home *** CD-ROM | disk | FTP | other *** search
- /* GIFSCAN - scans through a GIF file and reports all parameters */
-
- #ifndef lint
- static char *SCCSid = "@(#)gifscn.c v1.2 changed 5/16/91 13:35:03";
- #endif
-
- #include <stdio.h>
- #include <stdlib.h>
-
- /* global values */
- int Quiet = 0; /* don't print detail */
- int Debug = 0; /* print debug/trace info */
- extern int optind, opterr;
- extern char *optarg;
-
- /************************************************************************/
-
- /* COLORMAP - reads color information in from the GIF file and displays */
- /* it in a user selected method. This display may be in : */
- /* hexidecimal (default), percentage, or decimal. User */
- /* selects output method by placing a switch (-d, -p, -h) */
- /* between the program name and GIF filename at request time.*/
-
- colormap(out, dev, times, file_byte_cnt)
- FILE *dev;
- int times;
- int out;
- int *file_byte_cnt;
-
- #define DECIMAL 1
- #define PERCENT 2
- #define HEXIDEC 3
- #define MAX 255
-
- {
- unsigned int red;
- unsigned int green;
- unsigned int blue;
-
- int print_cnt;
- int i;
-
- /* Start of procedure */
-
- if (!Quiet) {
- if (out == DECIMAL)
- printf ("\nColor definitions in decimal (index #, R, G, B)\n");
-
- if (out == PERCENT)
- printf ("\nColor definitions by percentage (index #, R, G, B)\n");
-
- if (out == HEXIDEC)
- printf ("\nColor definitions in hexidecimal (index #, R, G, B)\n");
- }
-
- /* read and print the color definitions */
-
- print_cnt = 0;
-
- for (i = 0; (i < times); i++)
- {
- red = getc(dev);
- green = getc(dev);
- blue = getc(dev);
-
- *file_byte_cnt += 3;
-
- if (!Quiet) switch (out)
- {
- case DECIMAL :
- printf ("%3d - %3d %3d %3d ", i, red, green, blue);
- break;
-
- case PERCENT :
- red = (red * 100) / MAX;
- green = (green * 100) / MAX;
- blue = (blue * 100) / MAX;
- printf ("%3d - %3d %3d %3d ", i, red, green, blue);
- break;
-
- case HEXIDEC :
- printf ("%3d - %2x %2x %2x ", i, red, green, blue);
- break;
- }
-
- print_cnt++;
-
- if (!Quiet && print_cnt == 4)
- {
- printf ("\n");
- print_cnt = 0;
- }
- }
- if (!Quiet && (times % 4) != 0)
- printf ("\n");
- }
-
- /************************************************************************/
-
- /* GETBYTES - routine to retrieve two bytes of information from the GIF */
- /* file and then shift them into correct byte order. The */
- /* information is stored in Least Significant Byte order. */
-
- unsigned int getbytes(dev, file_byte_cnt)
-
- FILE *dev;
- int *file_byte_cnt;
-
- {
- int byte1;
- int byte2;
- int result;
-
- /* read bytes and shift over */
-
- byte1 = getc(dev);
- byte2 = getc(dev);
-
- *file_byte_cnt += 2;
-
- result = (byte2 << 8) | byte1;
-
- return result;
-
- }
-
- /***********************************************************************/
-
- /* IMAGEINF - routine to read the GIF image information and display it */
- /* to the user's screen in an orderly fasion. If there are */
- /* multiple images then IMAGEINF will be called to display */
- /* multiple screens. */
-
- imageinf(dev, bits_to_use, color_style, file_byte_cnt)
- FILE *dev;
- int bits_to_use;
- int color_style;
- int *file_byte_cnt;
-
- {
- int byte1;
- int byte2;
- int byte3;
- int image_left;
- int image_top;
- int data_byte_cnt;
- int bits_per_pix;
- int color_res;
- int colors;
- int i;
- int local;
- int unexpected;
-
- unsigned int width;
- unsigned int height;
-
- unsigned long bytetot;
- unsigned long possbytes;
-
- /* determine the image left value */
-
- image_left = getbytes(dev, file_byte_cnt);
-
- /* determine the image top value */
-
- image_top = getbytes(dev, file_byte_cnt);
- printf ("\nImage Left: %5d\t\tImage Top: %5d", image_left,
- image_top);
-
- /* determine the image width */
-
- width = getbytes(dev, file_byte_cnt);
-
- /* determine the image height */
-
- height = getbytes(dev, file_byte_cnt);
- printf ("\nImage Width: %5d\t\tImage Height: %5d", width, height);
-
- /* check for interlaced image */
-
- byte1 = getc(dev);
- (*file_byte_cnt)++;
-
- byte2 = byte1 & 0x40;
- if (byte2 == 0x40)
- printf ("\nInterlaced: Yes");
- else
- printf ("\nInterlaced: No");
-
- /* check for a local map */
-
- byte2 = byte1 & 0x80;
- if (byte2 == 0x80)
- {
- local = 1;
- printf ("\nLocal Color Map: Yes");
- }
- else
- {
- local = 0;
- printf ("\nLocal Color Map: No");
- }
-
- /* check for the 3 zero bits */
-
- byte2 = byte1 & 0x38;
- if (byte2 != 0)
- printf ("\n? -- Reserved zero bits in image not zeros.\n");
-
- /* determine the # of color bits in local map */
-
- bits_per_pix = byte1 & 0x07;
- bits_per_pix++;
- colors = 1 << bits_per_pix;
-
- if (local == 1)
- {
- bits_to_use = bits_per_pix;
- printf ("\nBits per pixel: %5d\t\t# colors : %5d", bits_per_pix,
- colors);
- colormap (color_style, dev, colors, file_byte_cnt);
- }
-
- /* retrieve the code size */
-
- byte1 = getc(dev);
- (*file_byte_cnt)++;
-
- if ((byte1 < 2) || (byte1 > 8))
- {
- printf ("\n? -- Code size %d at start of image");
- printf ("\n is out of range (2-8).\n");
- }
- else
- printf ("\nLZW min code size (bits): %3d", byte1);
-
- /* tally up the total bytes and read past each data block */
-
- bytetot = 0;
- possbytes = 0;
-
- while ((data_byte_cnt = getc(dev)) > 0)
- {
- (*file_byte_cnt)++;
- bytetot = bytetot + data_byte_cnt;
- if (!Quiet) printf("\n Record size %d",data_byte_cnt);
- for (i = 0; (i < data_byte_cnt); i++)
- {
- byte2 = getc(dev);
- (*file_byte_cnt)++;
- if (byte2 == EOF)
- {
- (*file_byte_cnt)--;
- printf ("\n? -- EOF reached inside image data block.\n");
- printf ("\n Located %d bytes into file.",*file_byte_cnt);
- exit (2);
- }
- }
- }
-
- (*file_byte_cnt)++;
-
- possbytes = (unsigned long) width * height;
- i = 8 / bits_to_use;
- possbytes = possbytes / i;
- printf ("\nTotal number of bytes in image: %ld out of possible %ld\n",
- bytetot, possbytes);
-
- if (data_byte_cnt == EOF)
- {
- (*file_byte_cnt)--;
- printf ("\n? -- EOF reached before zero byte count");
- printf ("\n of image was read.\n");
- printf ("\n Located %d bytes into file.",*file_byte_cnt);
- exit (3);
- }
- }
-
- /************************************************************************/
-
- /* EXTNINFO - routine to read the GIF file for extension data and */
- /* display it to the screen in an orderly fasion. This */
- /* extension information may be located before, between, or */
- /* after any of the image data. */
-
- extninfo(dev, file_byte_cnt)
- FILE *dev;
- int *file_byte_cnt;
-
- {
- int byte1;
- int byte2;
- int i;
- int data_byte_cnt;
-
- unsigned long bytetot;
-
- /* retrieve the function code */
-
- byte1 = getc(dev);
- (*file_byte_cnt)++;
- printf ("\nGIF extension code %d located at byte %d", byte1,
- *file_byte_cnt);
-
- /* tally up the total bytes and read past each data block */
-
- bytetot = 0;
-
- while ((data_byte_cnt = getc(dev)) > 0)
- {
- (*file_byte_cnt)++;
- bytetot = bytetot + data_byte_cnt;
- for (i = 0; (i < data_byte_cnt); i++)
- {
- byte2 = getc(dev);
- (*file_byte_cnt)++;
- if (byte2 == EOF)
- {
- (*file_byte_cnt)--;
- printf ("\n? -- EOF was reached inside extension data block.\n");
- printf ("\n Located %d bytes into file.",*file_byte_cnt);
- exit (2);
- }
- }
- }
-
- (*file_byte_cnt)++;
- printf ("\nTotal number of bytes in extension: %ld\n", bytetot);
-
- if (data_byte_cnt == EOF)
- {
- (*file_byte_cnt)--;
- printf ("\n? -- EOF was reached before zero byte count");
- printf ("\n of extension was read.\n");
- printf ("\n Located %d bytes into file.",*file_byte_cnt);
- exit (3);
- }
- }
-
- /************************************************************************/
-
- /* CHKUNEXP - routine to check for any unexpected nonzero data found */
- /* within the GIF file. This routine will help determine */
- /* where the unexpected data may reside in the file. */
-
- chkunexp (unexpected, determiner)
- int *unexpected;
- int determiner;
-
- {
-
- /* Determine place in the GIF file */
-
- if (determiner > 0)
- {
- printf ("\n? -- %d bytes of unexpected data found before",
- *unexpected);
- printf ("\n image %d.\n", determiner);
- }
- else if (determiner == -1)
- {
- printf ("\n? -- %d bytes of unexpected data found before",
- *unexpected);
- printf ("\n GIF file terminator.\n");
- }
- else if (determiner == -2)
- {
- printf ("\n? -- %d bytes of unexpected data found after",
- *unexpected);
- printf ("\n GIF file terminator.\n");
- }
- else
- {
- printf ("\n? -- %d bytes of unexpected data found at",
- *unexpected);
- printf ("\n or after expected GIF terminator byte.\n");
- }
-
- /* Zero out the unexpected variable for */
- /* the next group that may be encountered */
-
- *unexpected = 0;
- }
-
- /************************************************************************/
-
- /* MAIN - the main routine reads the GIF file for the global GIF */
- /* information which it displays to the user's screen. This */
- /* routine also determines which subroutine to call and which */
- /* information to process. */
-
-
- main(argc, argv)
- char *argv[];
- int argc;
-
- #define DECIMAL 1
- #define PERCENT 2
- #define HEXIDEC 3
-
- {
- char filename[15];
- char version[7];
- char style[5];
-
- int byte1;
- int byte2;
- int byte3;
- int image_left;
- int image_top;
- int data_byte_cnt;
- int image_cnt;
- int bits_per_pix;
- int bits_to_use;
- int color_res;
- int colors;
- int i;
- int globl;
- int end_gif_fnd;
- int unexpected;
- int color_style;
- int switch_present;
- int file_byte_cnt;
-
- unsigned int width;
- unsigned int height;
-
- FILE *in;
-
- /* Start of Processing */
-
- /* If just one argument then display the message */
-
- if (argc == 1)
- {
- printf ("\nUSAGE: gifscan color_opt filename\n");
- printf ("\ncolor_opt specifies how color lookup table");
- printf ("\n definitions are displayed");
- printf ("\n -h : output as hexidecimal (0 - FF) (default)");
- printf ("\n -d : output as decimal (0 - 255)");
- printf ("\n -p : output as percentage (0 - 100)\n");
- exit (0);
- }
-
- color_style = 0;
- switch_present = 0;
-
- while ((i = getopt(argc, argv, "dhpqD")) != EOF) {
- switch (i) {
- case 'd': /* decimal */
- color_style = DECIMAL;
- break;
- case 'p': /* percent */
- color_style = PERCENT;
- break;
- case 'h': /* hexadecimal */
- color_style = HEXIDEC;
- break;
- case 'q': /* set quiet flag */
- Quiet = 1;
- break;
- case 'D': /* debug (undoc) */
- Debug = 1;
- break;
- default:
- exit(1);
- }
- }
-
- /* Check for GIF filename */
-
- if (argc == optind) {
- fprintf(stderr, "Missing filename(s)\nType gifscn for help\n");
- exit(1);
- }
- else {
- if (Debug) fprintf(stderr, "Filename: %s\n", argv[optind]);
- /* copy the filename and open it */
- strcpy(filename, argv[optind]);
- in = fopen(filename, "rb");
- if (in == NULL) {
- fprintf(stderr, "Can't open file %s\n", filename);
- exit(1);
- }
- }
-
- image_cnt = 0;
- end_gif_fnd = 0;
- unexpected = 0;
- file_byte_cnt = 0;
-
- /* get version from file */
-
- if ((version[0] = getc(in)) == 0x47)
- {
- for (i = 1; (i < 6); i++)
- version[i] = getc(in);
- version[6] = '\0';
- printf ("\nVersion: %s", version);
- }
- else
- {
- printf ("\n? -- NOT a GIF file\n");
- exit(1);
- }
-
- file_byte_cnt += 6;
-
- /* determine screen width */
-
- width = getbytes(in, &file_byte_cnt);
-
- /* determine screen height */
-
- height = getbytes(in, &file_byte_cnt);
- printf ("\nScreen Width: %5d\tScreen Height: %5d", width,
- height);
-
- /* check for a Global Map */
-
- byte1 = getc(in);
- file_byte_cnt++;
-
- byte2 = byte1 & 0x80;
- if (byte2 == 0x80)
- {
- printf ("\nGlobal Color Map: Yes");
- globl = 1;
- }
- else
- {
- printf ("\nGlobal Color Map: No");
- globl = 0;
- }
-
- /* Check for the 0 bit */
-
- byte2 = byte1 & 0x08;
- if (byte2 != 0)
- printf ("\n? -- Reserved zero bit is not zero.\n");
-
- /* determine the color resolution */
-
- byte2 = byte1 & 0x70;
- color_res = byte2 >> 4;
-
- /* get the background index */
-
- byte3 = getc(in);
- file_byte_cnt++;
- printf ("\nColor resolution: %5d\tBackground index: %5d",
- ++color_res,
- byte3);
-
- /* determine the bits per pixel */
-
- bits_per_pix = byte1 & 0x07;
- bits_per_pix++;
- bits_to_use = bits_per_pix;
-
- /* determine # of colors in global map */
-
- colors = 1 << bits_per_pix;
- printf ("\nBits per pixel: %5d\t# colors: %5d\n", bits_per_pix,
- colors);
-
- /* check for the 0 byte */
-
- byte1 = getc(in);
- file_byte_cnt++;
- if (byte1 != 0)
- printf ("\n? -- Reserved byte after Background index is not zero.\n");
-
- if (globl == 1)
- colormap (color_style, in, colors, &file_byte_cnt);
-
- /* check for the zero byte count, a new image, or */
- /* the end marker for the gif file */
-
- while ((byte1 = getc(in)) != EOF)
- {
- file_byte_cnt++;
- if (byte1 == ',')
- {
- image_cnt++;
- if (unexpected != 0)
- chkunexp (&unexpected, image_cnt);
- printf ("\nImage # %2d separator located at byte %d.",
- image_cnt, file_byte_cnt);
-
- imageinf (in, bits_to_use, color_style, &file_byte_cnt);
- }
-
- else if (byte1 == '!')
-
- /* Extension data found */
-
- extninfo (in, &file_byte_cnt);
-
- else if (byte1 == ';')
-
- /* GIF terminator located, check for any */
- /* unexpected data found before terminator */
-
- {
- if (unexpected != 0)
- chkunexp (&unexpected, -1);
- end_gif_fnd = 1;
- printf ("\nGIF terminator located at byte %d.\n",
- file_byte_cnt);
- }
-
- else
- unexpected++;
- }
-
- /* EOF has been reached - check last bytes read */
-
- if (end_gif_fnd == 0)
- {
- printf ("\n? -- GIF file terminator ';' was not found.");
- printf ("\n Expected at byte %d in file.\n",file_byte_cnt);
- }
- if ((unexpected != 0) && (end_gif_fnd == 0))
- chkunexp (&unexpected, -3);
- else if (unexpected != 0)
- chkunexp (&unexpected, -2);
- }
-