home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / gifscan.c < prev    next >
C/C++ Source or Header  |  1989-05-05  |  12KB  |  529 lines

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