home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / GIFDEV.ZIP / GIFSCN.C < prev    next >
C/C++ Source or Header  |  1989-02-11  |  17KB  |  627 lines

  1. /* GIFSCAN - scans through a GIF file and reports all parameters */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5.  
  6. /************************************************************************/
  7.  
  8. /* COLORMAP - reads color information in from the GIF file and displays */
  9. /*            it in a user selected method.  This display may be in :   */
  10. /*            hexidecimal (default), percentage, or decimal.  User      */
  11. /*            selects output method by placing a switch (-d, -p, -h)    */
  12. /*            between the program name and GIF filename at request time.*/
  13.  
  14. colormap(out, dev, times, file_byte_cnt)
  15. FILE *dev;                  
  16. int times;
  17. int out;
  18. int *file_byte_cnt;
  19.  
  20. #define DECIMAL 1
  21. #define PERCENT 2
  22. #define HEXIDEC 3
  23. #define MAX 255
  24.  
  25. {
  26.     unsigned int red;
  27.     unsigned int green;
  28.     unsigned int blue;
  29.  
  30.     int print_cnt;
  31.     int i;
  32.  
  33.             /* Start of procedure */
  34.  
  35.     if (out == DECIMAL)
  36.         printf ("\nColor definitions in decimal   (index #, R, G, B)\n");
  37.  
  38.     if (out == PERCENT)
  39.         printf ("\nColor definitions by percentage   (index #, R, G, B)\n");
  40.  
  41.     if (out == HEXIDEC)
  42.         printf ("\nColor definitions in hexidecimal    (index #, R, G, B)\n");
  43.  
  44.             /* read and print the color definitions */
  45.  
  46.     print_cnt = 0;
  47.  
  48.     for (i = 0; (i < times); i++)
  49.     {
  50.         red = getc(dev);
  51.         green = getc(dev);
  52.         blue = getc(dev);
  53.  
  54.         *file_byte_cnt += 3;
  55.  
  56.         switch (out)
  57.         {
  58.             case DECIMAL :
  59.                 printf ("%3d - %3d %3d %3d  ", i, red, green, blue);
  60.                 break;
  61.  
  62.             case PERCENT :
  63.                 red = (red * 100) / MAX;
  64.                 green = (green * 100) / MAX;
  65.                 blue = (blue * 100) / MAX;
  66.                 printf ("%3d - %3d %3d %3d  ", i, red, green, blue);
  67.                 break;
  68.  
  69.             case HEXIDEC :
  70.                 printf ("%3d - %2x %2x %2x   ", i, red, green, blue);
  71.                 break;
  72.         }
  73.   
  74.         print_cnt++;
  75.  
  76.         if (print_cnt == 4)
  77.         {
  78.             printf ("\n");
  79.             print_cnt = 0;
  80.         }
  81.     }
  82.     if ((times % 4) != 0)
  83.         printf ("\n");
  84. }
  85.  
  86. /************************************************************************/
  87.  
  88. /* GETBYTES - routine to retrieve two bytes of information from the GIF */
  89. /*            file and then shift them into correct byte order.  The    */
  90. /*            information is stored in Least Significant Byte order.    */
  91.  
  92. unsigned int getbytes(dev, file_byte_cnt)
  93.  
  94. FILE *dev;
  95. int *file_byte_cnt;
  96.  
  97. {
  98.     int byte1;
  99.     int byte2;
  100.     int result;
  101.  
  102.             /* read bytes and shift over */
  103.  
  104.     byte1 = getc(dev);
  105.     byte2 = getc(dev);
  106.  
  107.     *file_byte_cnt += 2;
  108.  
  109.     result = (byte2 << 8) | byte1;
  110.  
  111.     return result;
  112.  
  113. }
  114.  
  115. /***********************************************************************/
  116.  
  117. /* IMAGEINF - routine to read the GIF image information and display it */
  118. /*            to the user's screen in an orderly fasion.  If there are */
  119. /*            multiple images then IMAGEINF will be called to display  */
  120. /*            multiple screens.                                        */
  121.  
  122. imageinf(dev, bits_to_use, color_style, file_byte_cnt)
  123. FILE *dev;
  124. int bits_to_use;
  125. int color_style;
  126. int *file_byte_cnt;
  127.  
  128. {
  129.     int byte1;
  130.     int byte2;
  131.     int byte3;
  132.     int image_left;
  133.     int image_top;
  134.     int data_byte_cnt;
  135.     int bits_per_pix;
  136.     int color_res;
  137.     int colors;
  138.     int i;
  139.     int local;
  140.     int unexpected;
  141.  
  142.     unsigned int width;
  143.     unsigned int height;
  144.  
  145.     unsigned long bytetot;
  146.     unsigned long possbytes;
  147.  
  148.             /* determine the image left value */
  149.  
  150.     image_left = getbytes(dev, file_byte_cnt);
  151.  
  152.             /* determine the image top value */
  153.  
  154.     image_top = getbytes(dev, file_byte_cnt);
  155.     printf ("\nImage Left:     %5d\t\tImage Top:     %5d", image_left,
  156.                                                            image_top);
  157.  
  158.             /* determine the image width */
  159.  
  160.     width = getbytes(dev, file_byte_cnt);
  161.  
  162.             /* determine the image height */
  163.  
  164.     height = getbytes(dev, file_byte_cnt);
  165.     printf ("\nImage Width:    %5d\t\tImage Height:  %5d", width, height);
  166.  
  167.             /* check for interlaced image */
  168.  
  169.     byte1 = getc(dev);
  170.     (*file_byte_cnt)++;
  171.  
  172.     byte2 = byte1 & 0x40;
  173.     if (byte2 == 0x40)
  174.         printf ("\nInterlaced: Yes");
  175.     else
  176.         printf ("\nInterlaced: No");
  177.  
  178.             /* check for a local map */
  179.  
  180.     byte2 = byte1 & 0x80;
  181.     if (byte2 == 0x80)
  182.     {
  183.         local = 1;
  184.         printf ("\nLocal Color Map: Yes");
  185.     }
  186.     else
  187.     {
  188.         local = 0;
  189.         printf ("\nLocal Color Map: No");
  190.     }
  191.  
  192.             /* check for the 3 zero bits */
  193.  
  194.     byte2 = byte1 & 0x38;
  195.     if (byte2 != 0)
  196.         printf ("\n? -- Reserved zero bits in image not zeros.\n");
  197.  
  198.             /* determine the # of color bits in local map */
  199.  
  200.     bits_per_pix = byte1 & 0x07;
  201.     bits_per_pix++;
  202.     colors = 1 << bits_per_pix;
  203.  
  204.     if (local == 1)
  205.     {
  206.         bits_to_use = bits_per_pix;
  207.         printf ("\nBits per pixel: %5d\t\t# colors :     %5d", bits_per_pix,
  208.                                                                colors);
  209.         colormap (color_style, dev, colors, file_byte_cnt);
  210.     }
  211.  
  212.             /* retrieve the code size */
  213.  
  214.     byte1 = getc(dev);
  215.     (*file_byte_cnt)++;
  216.  
  217.     if ((byte1 < 2) || (byte1 > 8))
  218.     {
  219.         printf ("\n? -- Code size %d at start of image");
  220.         printf ("\n     is out of range (2-8).\n");
  221.     }
  222.     else
  223.         printf ("\nLZW min code size (bits):  %3d", byte1);
  224.  
  225.             /* tally up the total bytes and read past each data block */
  226.  
  227.     bytetot = 0;
  228.     possbytes = 0;
  229.  
  230.     while ((data_byte_cnt = getc(dev)) > 0)
  231.     {
  232.         (*file_byte_cnt)++;
  233.         bytetot = bytetot + data_byte_cnt;
  234.         for (i = 0; (i < data_byte_cnt); i++)
  235.         {
  236.             byte2 = getc(dev);
  237.             (*file_byte_cnt)++;
  238.             if (byte2 == EOF)
  239.             {
  240.                 (*file_byte_cnt)--;
  241.                 printf ("\n? -- EOF reached inside image data block.\n");
  242.                 printf ("\n     Located %d bytes into file.",*file_byte_cnt);
  243.                 exit (2);
  244.             }
  245.         }
  246.     }
  247.  
  248.     (*file_byte_cnt)++;
  249.                     
  250.     possbytes = (unsigned long) width * height;
  251.     i = 8 / bits_to_use;
  252.     possbytes = possbytes / i;
  253.     printf ("\nTotal number of bytes in image:  %ld out of possible  %ld\n",
  254.                                                        bytetot, possbytes);
  255.  
  256.     if (data_byte_cnt == EOF)
  257.     {
  258.         (*file_byte_cnt)--;
  259.         printf ("\n? -- EOF reached before zero byte count");
  260.         printf ("\n     of image was read.\n");
  261.         printf ("\n     Located %d bytes into file.",*file_byte_cnt);
  262.         exit (3);
  263.     }
  264. }
  265.  
  266. /************************************************************************/
  267.  
  268. /* EXTNINFO - routine to read the GIF file for extension data and       */
  269. /*            display it to the screen in an orderly fasion.  This      */
  270. /*            extension information may be located before, between, or  */
  271. /*            after any of the image data.                              */
  272.  
  273. extninfo(dev, file_byte_cnt)
  274. FILE *dev;
  275. int *file_byte_cnt;
  276.  
  277. {
  278.     int byte1;
  279.     int byte2;
  280.     int i;
  281.     int data_byte_cnt;
  282.  
  283.     unsigned long bytetot;
  284.  
  285.             /* retrieve the function code */
  286.  
  287.     byte1 = getc(dev);
  288.     (*file_byte_cnt)++;
  289.     printf ("\nGIF extension code %d located at byte %d", byte1,
  290.                                                           *file_byte_cnt);
  291.  
  292.             /* tally up the total bytes and read past each data block */
  293.  
  294.     bytetot = 0;
  295.  
  296.     while ((data_byte_cnt = getc(dev)) > 0)
  297.     {                
  298.         (*file_byte_cnt)++;
  299.         bytetot = bytetot + data_byte_cnt;
  300.         for (i = 0; (i < data_byte_cnt); i++)
  301.         {
  302.             byte2 = getc(dev);
  303.             (*file_byte_cnt)++;
  304.             if (byte2 == EOF)
  305.             {
  306.                 (*file_byte_cnt)--;
  307.                 printf ("\n? -- EOF was reached inside extension data block.\n");
  308.                 printf ("\n     Located %d bytes into file.",*file_byte_cnt);
  309.                 exit (2);
  310.             }
  311.         }
  312.     }
  313.  
  314.     (*file_byte_cnt)++;
  315.     printf ("\nTotal number of bytes in extension:  %ld\n", bytetot);
  316.  
  317.     if (data_byte_cnt == EOF)
  318.     {
  319.         (*file_byte_cnt)--;
  320.         printf ("\n? -- EOF was reached before zero byte count");
  321.         printf ("\n     of extension was read.\n");
  322.         printf ("\n     Located %d bytes into file.",*file_byte_cnt);
  323.         exit (3);
  324.     }
  325. }
  326.  
  327. /************************************************************************/
  328.  
  329. /* CHKUNEXP - routine to check for any unexpected nonzero data found    */
  330. /*            within the GIF file.  This routine will help determine    */
  331. /*            where the unexpected data may reside in the file.         */
  332.  
  333. chkunexp (unexpected, determiner)
  334. int *unexpected;
  335. int determiner;
  336.  
  337. {
  338.  
  339.             /* Determine place in the GIF file */
  340.  
  341.     if (determiner > 0)
  342.     {
  343.         printf ("\n? -- %d bytes of unexpected data found before",
  344.                                                       *unexpected);
  345.         printf ("\n     image %d.\n", determiner);
  346.     }
  347.     else if (determiner == -1)
  348.     {
  349.         printf ("\n? -- %d bytes of unexpected data found before",
  350.                                                       *unexpected);
  351.         printf ("\n     GIF file terminator.\n");
  352.     }
  353.     else if (determiner == -2)
  354.     {
  355.         printf ("\n? -- %d bytes of unexpected data found after",
  356.                                                       *unexpected);
  357.         printf ("\n     GIF file terminator.\n");
  358.     }
  359.     else
  360.     {
  361.         printf ("\n? -- %d bytes of unexpected data found at",
  362.                                                       *unexpected);
  363.         printf ("\n     or after expected GIF terminator byte.\n");
  364.     }
  365.  
  366.             /* Zero out the unexpected variable for */
  367.             /* the next group that may be encountered */
  368.  
  369.     *unexpected = 0;
  370. }
  371.  
  372. /************************************************************************/
  373.  
  374. /* MAIN - the main routine reads the GIF file for the global GIF        */
  375. /*        information which it displays to the user's screen.  This     */
  376. /*        routine also determines which subroutine to call and which    */
  377. /*        information to process.                                       */
  378.  
  379.  
  380. main(argc, argv)
  381. char *argv[];
  382. int argc;
  383.  
  384. #define DEC "-d"
  385. #define HEX "-h"
  386. #define PCT "-p"
  387. #define DECIMAL 1
  388. #define PERCENT 2
  389. #define HEXIDEC 3
  390.  
  391. {
  392.     char filename[15];
  393.     char version[7];
  394.     char style[5];
  395.  
  396.     int byte1;
  397.     int byte2;
  398.     int byte3;
  399.     int image_left;
  400.     int image_top;
  401.     int data_byte_cnt;
  402.     int image_cnt;
  403.     int bits_per_pix;
  404.     int bits_to_use;
  405.     int color_res;
  406.     int colors;
  407.     int i;
  408.     int globl;
  409.     int end_gif_fnd;
  410.     int unexpected;
  411.     int color_style;
  412.     int switch_present;
  413.     int file_byte_cnt;
  414.  
  415.     unsigned int width;
  416.     unsigned int height;
  417.  
  418.     FILE *in;
  419.  
  420.             /* Start of Processing */
  421.  
  422.             /* If just one argument then display the message */
  423.  
  424.     if (argc == 1)
  425.     {
  426.         printf ("\nUSAGE:    gifscan  color_opt  filename\n");
  427.         printf ("\ncolor_opt   specifies how color lookup table");
  428.         printf ("\n            definitions are displayed");
  429.         printf ("\n  -h  :     output as hexidecimal (0 - FF) (default)");
  430.         printf ("\n  -d  :     output as decimal (0 - 255)");
  431.         printf ("\n  -p  :     output as percentage (0 - 100)\n");
  432.         exit ();
  433.     }
  434.  
  435.     color_style = 0;
  436.     switch_present = 0;
  437.  
  438.     if ((strnicmp (argv[1], "-", 1) == 0))
  439.     {
  440.         switch_present = 1;
  441.         strcpy (style, argv[1]);
  442.     }
  443.     else
  444.         switch_present = 0;
  445.  
  446.     do
  447.     {
  448.         if ((strnicmp (style, DEC, 2) == 0))
  449.             color_style = DECIMAL;
  450.         else if ((strnicmp (style, PCT, 2) == 0))
  451.             color_style = PERCENT;
  452.         else
  453.             color_style = HEXIDEC;
  454.  
  455. /*        else if ((strnicmp (style, HEX, 2) == 0))
  456.             color_style = HEXIDEC;
  457.         else
  458.         {
  459.             printf ("\nEnter Colormap style (-h, -p, -d) : ");
  460.             gets (style);
  461.         } */
  462.     }
  463.     while (color_style == 0);
  464.  
  465.             /* Check for GIF filename */
  466.  
  467.     do
  468.     {
  469.         if ((argc == 1) || ((argc == 2) && (switch_present == 1)))
  470.         {
  471.             printf ("\nEnter GIF filename:  ");
  472.             gets (filename);
  473.         }
  474.         else
  475.             if (argc == 3)
  476.                 strcpy (filename, argv[2]);
  477.             else
  478.                 strcpy (filename, argv[1]);
  479.  
  480.         in = fopen (filename, "rb");
  481.         argc = 1;
  482.     }
  483.     while (in == NULL);
  484.  
  485.     image_cnt = 0;
  486.     end_gif_fnd = 0;
  487.     unexpected = 0;
  488.     file_byte_cnt = 0;
  489.  
  490.             /* get version from file */
  491.  
  492.     if ((version[0] = getc(in)) == 0x47)
  493.     {
  494.         for (i = 1; (i < 6); i++)
  495.             version[i] = getc(in);
  496.         version[6] = '\0';
  497.         printf ("\nVersion: %s", version);
  498.     }
  499.     else
  500.     {
  501.         printf ("\n? -- NOT a GIF file\n");
  502.         exit(1);
  503.     }
  504.  
  505.     file_byte_cnt += 6;
  506.  
  507.             /* determine screen width */
  508.  
  509.     width = getbytes(in, &file_byte_cnt);
  510.  
  511.             /* determine screen height */
  512.  
  513.     height = getbytes(in, &file_byte_cnt);
  514.     printf ("\nScreen Width:      %5d\tScreen Height:     %5d", width,
  515.                                                                 height);
  516.  
  517.             /* check for a Global Map */
  518.  
  519.     byte1 = getc(in);
  520.     file_byte_cnt++;
  521.  
  522.     byte2 = byte1 & 0x80;
  523.     if (byte2 == 0x80)
  524.     {
  525.         printf ("\nGlobal Color Map: Yes");
  526.         globl = 1;
  527.     }
  528.     else
  529.     {
  530.         printf ("\nGlobal Color Map: No");
  531.         globl = 0;
  532.     }
  533.  
  534.             /* Check for the 0 bit */
  535.  
  536.     byte2 = byte1 & 0x08;
  537.     if (byte2 != 0)
  538.         printf ("\n? -- Reserved zero bit is not zero.\n");
  539.  
  540.             /* determine the color resolution */
  541.  
  542.     byte2 = byte1 & 0x70;
  543.     color_res = byte2 >> 4;
  544.  
  545.             /* get the background index */
  546.  
  547.     byte3 = getc(in);
  548.     file_byte_cnt++;
  549.     printf ("\nColor resolution:  %5d\tBackground index:  %5d",
  550.                                                      ++color_res,
  551.                                                           byte3);
  552.  
  553.             /* determine the bits per pixel */
  554.  
  555.     bits_per_pix = byte1 & 0x07;
  556.     bits_per_pix++;
  557.     bits_to_use = bits_per_pix;
  558.  
  559.             /* determine # of colors in global map */
  560.  
  561.     colors = 1 << bits_per_pix;
  562.     printf ("\nBits per pixel:    %5d\t# colors:          %5d\n", bits_per_pix,
  563.                                                                 colors);
  564.  
  565.             /* check for the 0 byte */
  566.  
  567.     byte1 = getc(in);
  568.     file_byte_cnt++;
  569.     if (byte1 != 0)
  570.         printf ("\n? -- Reserved byte after Background index is not zero.\n");
  571.  
  572.     if (globl == 1)
  573.         colormap (color_style, in, colors, &file_byte_cnt);
  574.  
  575.             /* check for the zero byte count, a new image, or */
  576.             /* the end marker for the gif file */
  577.  
  578.     while ((byte1 = getc(in)) != EOF)
  579.     {
  580.         file_byte_cnt++;
  581.         if (byte1 == ',')
  582.         {
  583.             image_cnt++;
  584.             if (unexpected != 0)
  585.                 chkunexp (&unexpected, image_cnt);
  586.             printf ("\nImage # %2d separator located at byte %d.",
  587.                                              image_cnt, file_byte_cnt);
  588.  
  589.             imageinf (in, bits_to_use, color_style, &file_byte_cnt);
  590.         }
  591.  
  592.         else if (byte1 == '!')
  593.  
  594.             /* Extension data found */
  595.  
  596.             extninfo (in, &file_byte_cnt);
  597.  
  598.         else if (byte1 == ';')
  599.  
  600.             /* GIF terminator located, check for any */
  601.             /* unexpected data found before terminator */
  602.  
  603.         {
  604.             if (unexpected != 0)
  605.                 chkunexp (&unexpected, -1);
  606.             end_gif_fnd = 1;
  607.             printf ("\nGIF terminator located at byte %d.\n",
  608.                                                  file_byte_cnt);
  609.         }
  610.  
  611.         else
  612.             unexpected++;
  613.     }
  614.  
  615.             /* EOF has been reached - check last bytes read */
  616.  
  617.     if (end_gif_fnd == 0)
  618.     {
  619.         printf ("\n? -- GIF file terminator ';' was not found.");
  620.         printf ("\n     Expected at byte %d in file.\n",file_byte_cnt);
  621.     }
  622.     if ((unexpected != 0) && (end_gif_fnd == 0))
  623.         chkunexp (&unexpected, -3);
  624.     else if (unexpected != 0)
  625.         chkunexp (&unexpected, -2);
  626. }
  627.