This file contains examples of GIF header structures and how to read, write, display, decode, and encode a GIF file. GIF Header File GIF.H /****************************************************************************\ ** Title: GIF.H ** ** Purpose: GIF Header file ** ** Version: 1.0 ** ** Date: March 1992 ** ** Author: James D. Murray, Anaheim, CA, USA ** ** C Compilers: Borland C++ v2.0, Microsoft C v6.00a ** ** ** ** This file contains the header structures for the GIF image ** ** file format. ** ** ** ** ** ** Copyright (C) 1991 by Graphics Software Labs. All rights reserved. ** \****************************************************************************/ #ifndef GIF_H #define GIF_H 1 #include "datatype.h" /* Data type definitions */ /* ** The GIF Global Color Table. ** ** The size of a color table may be any power of two from 2 to 256. ** We specify the maximum size here for clarity. */ typedef struct _GifGlobalColorTable { BYTE Red; /* Red Global Color Table Data */ BYTE Green; /* Green Global Color Table Data */ BYTE Blue; /* Blue Global Color Table Data */ } GIFGLOBALCT[256]; /* ** The GIF Local Color Table. ** ** The size of a color table may be any power of two from 2 to 256. ** We specify the maximum size here for clarity. */ typedef struct _GifLocalColorTable { BYTE Red; /* Red Global Color Table Data */ BYTE Green; /* Green Global Color Table Data */ BYTE Blue; /* Blue Global Color Table Data */ } GIFLOCALCT[256]; /* ** The GIF header format. ** ** This structure actually contains the header, logical screen ** descriptor, and the global color table for the GIF image. */ typedef struct _GifHeader /* Offset Description */ { BYTE Signature[3]; /* 00h ID Signature */ BYTE Version[3]; /* 03h Version Number */ WORD ScreenWidth; /* 06h Logical Screen Width */ WORD ScreenHeight; /* 08h Logical Screen Height */ BYTE PackedField; /* 0Ah Color Information */ BYTE ColorIndex; /* 0Bh Background Color Index */ BYTE AspectRatio; /* 0Ch Pixel Aspect Ratio */ GIFGLOBALCT GlobalCT; /* 0Dh Global Color Table */ } GIFHEAD; /* ** The GIF Image Descriptor. */ typedef struct _GifImageDescriptor { BYTE ImageSeparator; /* Image Descriptor identifier */ WORD ImageLeft; /* X position of image on the display */ WORD ImageTop; /* Y position of image on the display */ WORD ImageWidth; /* Width of the image in pixels */ WORD ImageHeight; /* Height of the image in pixels */ BYTE PackedField; /* Image and Color Table Data Information */ GIFLOCALCT LocalCT; /* Local Color Table */ } GIFIMAGEDESC; /* ** GIF 89a Graphic Control Extension Block */ typedef struct _GifGraphicControlExtension { BYTE Introducer; /* Extension Introducer (always 21h) */ BYTE Label; /* Extension Label (always F9h) */ BYTE BlockSize; /* Size of Extension Block (always 04h) */ BYTE PackedField; /* Graphic Data Information */ WORD DelayTime; /* Delay time in hundredths of a second */ BYTE ColorIndex; /* Transparent Color Index */ BYTE Terminator; /* Block Terminator (always 0) */ } GIFGRAPHICCONTROL; /* ** GIF 89a Plain Text Extension Block */ typedef struct _GifPlainTextExtension { BYTE Introducer; /* Extension Introducer (always 21h) */ BYTE Label; /* Extension Label (always 01h) */ BYTE BlockSize; /* Size of Extension Block (always 0Ch) */ WORD TextGridLeft; /* X position of text grid in pixels */ WORD TextGridTop; /* Y position of text grid in pixels */ WORD TextGridWidth; /* Width of the text grid in pixels */ WORD TextGridHeight; /* Height of the text grid in pixels */ BYTE CellWidth; /* Width of a grid cell in pixels */ BYTE CellHeight; /* Height of a grid cell in pixels */ BYTE TextFgColorIndex; /* Text foreground color index value */ BYTE TextBgColorIndex; /* Text background color index value */ BYTE *PlainTextData; /* Plain Text data sub-blocks */ BYTE Terminator; /* Block Terminator (always 0) */ } GIFPLAINTEXT; /* ** GIF 89a Application Extension Block */ typedef struct _GifApplicationExtension { BYTE Introducer; /* Extension Introducer (always 21h) */ BYTE Label; /* Extension Label (always FFh) */ BYTE BlockSize; /* Size of Extension Block (always 0Bh) */ BYTE Identifier[8]; /* Application Identifier */ BYTE AuthentCode[3]; /* Application Authentication Code */ BYTE *ApplicationData; /* Application data sub-blocks */ BYTE Terminator; /* Block Terminator (always 0) */ } GIFAPPLICATION; /* ** GIF 89a Comment Extension Block */ typedef struct _GifCommentExtension { BYTE Introducer; /* Extension Introducer (always 21h) */ BYTE Label; /* Comment Label (always FEh) */ BYTE *CommentData; /* Comment data sub-blocks */ BYTE Terminator; /* Block Terminator (always 0) */ } GIFCOMMENT; /* ** Function Prototypes */ /* GIFREAD.C */ int ReadGifHeader(GIFHEAD *, FILE *); int ReadGifImageDesc(GIFIMAGEDESC *, FILE *); int ReadGifGraphicControl(GIFGRAPHICCONTROL *, FILE *); int ReadGifPlainText(GIFPLAINTEXT *, FILE *); int ReadGifApplication(GIFAPPLICATION *, FILE *); int ReadGifComment(GIFCOMMENT *, FILE *); #endif /* GIF_H */ } GIF File Reader GIFREAD.C /****************************************************************************\ ** Title: GIFREAD.C ** ** Purpose: Read the information from a GIF file. ** ** Version: 1.0 ** ** Date: March 1992 ** ** Author: James D. Murray, Anaheim, CA USA ** ** C Compilers: Borland C++ v2.0, Microsoft C v6.00a ** ** ** ** This module contains six functions which read various data structures ** ** stored in GIF 87a and 89a-format files. ** ** ** ** This module contains the following functions: ** ** ** ** ReadGifHeader - Read a GIF image file Header ** ** ReadGifImageDesc - Read a GIF Local Image Descriptor ** ** ReadGifGraphicControl - Read a GIF Graphic Control Extension block ** ** ReadGifPlainText - Read a GIF Plain Text Extension block ** ** ReadGifApplication - Read a GIF Application Extension block ** ** ReadGifComment - Read a GIF Comment Extension block ** ** ReadDataSubBlocks - Read one or more GIF data sub-blocks ** ** ** ** Copyright (C) 1991,92 by Graphics Software Labs. All rights reserved. ** \****************************************************************************/ #include #include #include "endianio.h" #include "gif.h" /* External global variables */ WORD (*GetWord)(FILE *); DWORD (*GetDword)(FILE *); /* Local function prototype */ static BYTE *ReadDataSubBlocks(FILE *); /* ** Read a GIF image file Header. ** ** This function reads the Header, Logical Screen Descriptor, and ** Global Color Table (if any) from a GIF image file. The information ** is stored in a GIFHEAD structure. ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifHeader(GifHead, FpGif) GIFHEAD *GifHead; /* Pointer to GIF header structure */ FILE *FpGif; /* GIF image file input FILE stream */ { register WORD i; /* Loop counter */ WORD tableSize; /* Number of entires in the Global Color Table */ GetWord = GetLittleWord; /* Read using little-endian byte order */ GetString(GifHead->Signature, sizeof(GifHead->Signature), FpGif); GetString(GifHead->Version, sizeof(GifHead->Version), FpGif); GifHead->ScreenWidth = GetWord(FpGif); GifHead->ScreenHeight = GetWord(FpGif); GifHead->PackedField = GetByte(FpGif); GifHead->ColorIndex = GetByte(FpGif); GifHead->AspectRatio = GetByte(FpGif); /* Check if a Global Color Table is present */ if (GifHead->PackedField & 0x80) { /* Read number of color table entries */ tableSize = (WORD) (1L << ((GifHead->PackedField & 0x07) + 1)); /* Read the Global Color Table */ for (i = 0; i < tableSize; i++) { GifHead->GlobalCT[i].Red = GetByte(FpGif); GifHead->GlobalCT[i].Green = GetByte(FpGif); GifHead->GlobalCT[i].Blue = GetByte(FpGif); } } /* Check for a FILE stream error */ if (ferror(FpGif)) return(-1); /* FILE stream error occured during read */ return(0); /* No FILE stream error occured */ } /* ** Read a GIF Local Image Descriptor. ** ** This function reads the Local Image Descriptor, and Local Color ** Table (if any) from a GIF image file. The information is stored ** in a GIFIMAGEDESC structure. ** ** Note that the ImageSeparator field value in the GIFIMAGEDESC ** structure is assigned by the function calling ReadGifImageDesc(). ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifImageDesc(GifImageDesc, FpGif) GIFIMAGEDESC *GifImageDesc; /* Pointer to GIF image descriptor structure */ FILE *FpGif; /* GIF image file input FILE stream */ { register WORD i; /* Loop counter */ WORD tableSize; /* Number of entries in the Local Color Table */ GetWord = GetLittleWord; /* Read using little-endian byte order */ GifImageDesc->ImageLeft = GetWord(FpGif); GifImageDesc->ImageTop = GetWord(FpGif); GifImageDesc->ImageWidth = GetWord(FpGif); GifImageDesc->ImageHeight = GetWord(FpGif); GifImageDesc->PackedField = GetByte(FpGif); /* Check if a Local Color Table is present */ if (GifImageDesc->PackedField & 0x80) { /* Read number of color table entries */ tableSize = (WORD) (1L << ((GifImageDesc->PackedField & 0x07) + 1)); /* Read the Local Color Table */ for (i = 0; i < tableSize; i++) { GifImageDesc->LocalCT[i].Red = GetByte(FpGif); GifImageDesc->LocalCT[i].Green = GetByte(FpGif); GifImageDesc->LocalCT[i].Blue = GetByte(FpGif); } } /* Check for a FILE stream error */ if (ferror(FpGif)) return(-1); /* FILE stream error occured during read */ return(0); /* No FILE stream error occured */ } /* ** Read a GIF Graphic Control Extension block. ** ** Note that the Introducer and Label field values in the GIFGRAPHICCONTROL ** structure are assigned by the function calling ReadGifGraphicControl(). ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifGraphicControl(GifGraphicControl, FpGif) GIFGRAPHICCONTROL *GifGraphicControl; /* Pointer to GC Extension structure */ FILE *FpGif; /* GIF image file input FILE stream */ { GetWord = GetLittleWord; /* Read using little-endian byte order */ GifGraphicControl->BlockSize = GetByte(FpGif); GifGraphicControl->PackedField = GetByte(FpGif); GifGraphicControl->DelayTime = GetWord(FpGif); GifGraphicControl->ColorIndex = GetByte(FpGif); /* Check for a FILE stream error */ if (ferror(FpGif)) return(-1); /* FILE stream error occured during read */ return(0); /* No FILE stream error occured */ } /* ** Read a GIF Plain Text Extension block. ** ** Note that the Introducer and Label field values in the GIFLPLAINTEXT ** structure are assigned by the function calling ReadGifPlainText(). ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifPlainText(GifPlainText, FpGif) GIFPLAINTEXT *GifPlainText; /* Pointer to Plain Text Extension structure */ FILE *FpGif; /* GIF image file input FILE stream */ { GetWord = GetLittleWord; /* Read using little-endian byte order */ GifPlainText->BlockSize = GetByte(FpGif); GifPlainText->TextGridLeft = GetWord(FpGif); GifPlainText->TextGridTop = GetWord(FpGif); GifPlainText->TextGridWidth = GetWord(FpGif); GifPlainText->TextGridHeight = GetWord(FpGif); GifPlainText->CellWidth = GetByte(FpGif); GifPlainText->CellHeight = GetByte(FpGif); GifPlainText->TextFgColorIndex = GetByte(FpGif); GifPlainText->TextBgColorIndex = GetByte(FpGif); /* Read in the Plain Text data sub-blocks */ if (!(GifPlainText->PlainTextData = ReadDataSubBlocks(FpGif))) return(1); GifPlainText->Terminator = 0; /* Check for a FILE stream error */ if (ferror(FpGif)) return(-1); /* FILE stream error occured during read */ return(0); /* No FILE stream error occured */ } /* ** Read a GIF Application Extension block. ** ** Note that the Introducer and Label field values in the GIFAPPLICATION ** structure are assigned by the function calling ReadGifApplication(). ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifApplication(GifApplication, FpGif) GIFAPPLICATION *GifApplication; /* Pointer to Application Extension structure */ FILE *FpGif; /* GIF image file input FILE stream */ { GifApplication->BlockSize = GetByte(FpGif); GifApplication->Identifier[0] = GetByte(FpGif); GifApplication->Identifier[1] = GetByte(FpGif); GifApplication->Identifier[2] = GetByte(FpGif); GifApplication->Identifier[3] = GetByte(FpGif); GifApplication->Identifier[4] = GetByte(FpGif); GifApplication->Identifier[5] = GetByte(FpGif); GifApplication->Identifier[6] = GetByte(FpGif); GifApplication->Identifier[7] = GetByte(FpGif); GifApplication->AuthentCode[0] = GetByte(FpGif); GifApplication->AuthentCode[1] = GetByte(FpGif); GifApplication->AuthentCode[2] = GetByte(FpGif); /* Read in the Plain Text data sub-blocks */ if (!(GifApplication->ApplicationData = ReadDataSubBlocks(FpGif))) return(1); GifApplication->Terminator = 0; /* Check for a FILE stream error */ if (ferror(FpGif)) return(-1); /* FILE stream error occured during read */ return(0); /* No FILE stream error occured */ } /* ** Read a GIF Comment Extension block. ** ** Note that the Introducer and Label field values in the GIFCOMMENT ** structure are assigned by the function calling ReadGifComment(). ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifComment(GifComment, FpGif) GIFCOMMENT *GifComment; /* Pointer to GIF Comment Extension structure */ FILE *FpGif; /* GIF image file input FILE stream */ { /* Read in the Plain Text data sub-blocks */ if (!(GifComment->CommentData = ReadDataSubBlocks(FpGif))) return(1); GifComment->Terminator = 0; /* Check for a FILE stream error */ if (ferror(FpGif)) return(-1); /* FILE stream error occured during read */ return(0); /* No FILE stream error occured */ } /* ** Read one or more GIF data sub-blocks and write the information ** to a buffer. ** ** A GIF "sub-block" is a single count byte followed by 1 to 255 ** additional data bytes. ** ** Returns: A NULL pointer if a memory allocation error occured, ** otherwise a valid pointer if no error occured. */ static BYTE * ReadDataSubBlocks(FpGif) FILE *FpGif; /* GIF image file input FILE stream */ { BYTE *ptr1; /* Pointer used to "walk the heap" */ BYTE *ptr2; /* Pointer used to mark the top of the heap */ BYTE dataSize; /* Size of the current data sub-block being read */ WORD bufSize; /* Total size of the Plain Text data buffer */ bufSize = 0; /* The output buffer is empty */ dataSize = GetByte(FpGif); /* Get the size of the first sub-block */ /* Allocate initial data buffer */ if (!(ptr1 = ptr2 = (BYTE *) malloc(dataSize + 1))) return((BYTE *) NULL); for (;;) { bufSize += (dataSize + 1); /* Running total of the buffer size */ *ptr1++ = dataSize; /* Write the data count */ while (dataSize--) /* Read/write the Plain Text data */ *ptr1++ = GetByte(FpGif); /* Check if there is another data sub-block */ if ((dataSize = GetByte(FpGif)) == 0) break; /* Block Terminator encountered */ /* Increase the buffer size to accomodate the next sub-block */ if (!(ptr1 = ptr2 = (BYTE *) realloc(ptr2, dataSize + 1))) return((BYTE *) NULL); ptr1 += bufSize; /* Move pointer to the end of the data */ } *ptr1++ = (BYTE) NULL; /* Add NULL to simulate Terminator value */ return(ptr2); /* Return a pointer to the sub-block data */ } } GIF File Writer GIFWRITE.C These functions are the complement of the reader functions in GIFREAD.C. They are used to write the header and data blocks found within the GIF image file format. /****************************************************************************\ ** Title: GIFWRITE.C ** ** Purpose: Write GIF header information to a file. ** ** Version: 1.0 ** ** Date: May 1991 ** ** Author: James D. Murray, Anaheim, CA USA ** ** C Compilers: Borland C++ v2.0, Microsoft C v6.00a ** ** ** ** Write the information contained within a GIFHEADER structure ** ** to a file. Used to construct GIF-format files. ** ** ** ** This module contains the following functions: ** ** ** ** WriteGifHeader - Write a GIF header to a file stream ** ** ** ** Copyright (C) 1991 by Graphics Software Labs. All rights reserved. ** \****************************************************************************/ #include #include "endianio.h" #include "gif.h" /* External global variables */ VOID (*PutWord)(WORD, FILE *); VOID (*PutDword)(DWORD, FILE *); VOID WriteGifHeader(GifHead, FpGif) GIFHEAD *GifHead; /* Pointer to GIF header structure */ FILE *FpGif; /* GIF image file output FILE stream */ { PutWord = PutLittleWord; /* Read using little-endian byte order */ PutString(GifHead->Signature, sizeof(GifHead->Signature), FpGif); PutString(GifHead->Version, sizeof(GifHead->Version), FpGif); PutWord(GifHead->ScreenWidth, FpGif); PutWord(GifHead->ScreenHeight, FpGif); PutByte(GifHead->PackedField, FpGif); PutByte(GifHead->ColorIndex, FpGif); PutByte(GifHead->AspectRatio, FpGif); } } GIF File Information Lister GIFHEAD.C /****************************************************************************\ ** Title: GIFHEAD.C ** ** Purpose: Display the data in a GIF image file. ** ** Version: 1.0 ** ** Date: March 1992 ** ** Author: James D. Murray, Anaheim, CA, USA ** ** C Compilers: Borland C++ v2.0, Microsoft C v6.00a ** ** ** ** GIFHEAD displays all real information contained within a GIF image ** ** file, including all color tables and extension block information. ** ** GIFHEAD reads both GIF 87a abd 89a-format files. ** ** ** ** Copyright (C) 1991-92 by Graphics Software Labs. All rights reserved. ** \****************************************************************************/ #include #include #include #include #include #include "datatype.h" #include "endianio.h" #include "gif.h" #define VERSION "1.00" int main(argc, argv) int argc; char *argv[]; { register WORD i; /* Loop counter */ WORD tableSize; /* Number of entires in the global color table */ WORD lineCount; /* Count of the number of table lines displayed */ WORD imageCount; /* Count of the number of images in the file */ WORD blockCount; /* Running count of the number of data blocks */ BYTE Identifier; /* Extension block identifier holder */ BYTE Label; /* Extension block label holder */ BYTE dataSize; /* Size of data sub-block holder */ BYTE *ptr; /* Scratch pointer variable */ FILE *fpGif; /* Pointer to the input FILE stream */ CHAR gifFileName[80]; /* Holder for the GIF image file name */ GIFHEAD gifHead; /* GIF Header structure */ GIFIMAGEDESC gifImageDesc; /* Logical Image Descriptor struct */ GIFPLAINTEXT gifPlainText; /* Plain Text Extension structure */ GIFAPPLICATION gifApplication; /* Application Extension structure */ GIFCOMMENT gifComment; /* Comment Extension structure */ GIFGRAPHICCONTROL gifGraphicControl; /* Graphic Control Extension strct */ printf("GIFHEAD - Display the header info within a GIF image file (v%s)\n\n", VERSION); /* Check for proper number of command line arguments */ if (argc < 2) { fputs("Usage: GIFHEAD filename.gif\n\n", stderr); exit(-1); } /* Add the .gif extension to the file name if no extension exists */ strncpy(gifFileName, argv[1], 76); if (!strrchr(gifFileName, '.')) strcat(gifFileName, ".gif"); /* Open the GIF image file */ if ((fpGif = fopen(gifFileName, "rb")) == (FILE *) NULL) { fprintf(stderr, "GIFHEAD: Cannot open file %s\n", gifFileName); exit(-2); } /* Read the GIF image file header information */ ReadGifHeader(&gifHead, fpGif); /* Check for FILE stream error */ if (ferror(fpGif)) { fputs("GIFHEAD: Error reading header information!\n", stderr); exit(-3); } printf(" Signature: %.*s\n", sizeof(gifHead.Signature), gifHead.Signature); printf(" Version: %.*s\n", sizeof(gifHead.Version), gifHead.Version); printf(" ScreenWidth: %u\n", gifHead.ScreenWidth); printf(" ScreenHeight: %u\n", gifHead.ScreenHeight); printf(" Global Color Table is: %s\n", gifHead.PackedField & 0x80 ? "Present" : "Not Present"); printf(" Original Resolution: %u (%u bits per primary color)\n", (gifHead.PackedField & 0x70) >> 4, ((gifHead.PackedField & 0x70) >> 4) + 1); printf(" Global Color Table is: %s\n", gifHead.PackedField & 0x08 ? "Sorted" : "Not Sorted"); printf(" Size of Global Color Table: %lu entries (%lu bytes)\n", 1L << ((gifHead.PackedField & 0x07) + 1), 3L * (1L << ((gifHead.PackedField & 0x07) + 1))); printf("Size of Global Color Table Entry: %u bits per pixel\n", (gifHead.PackedField & 0x07) + 1); printf(" Background Color Index: %u\n", gifHead.ColorIndex); printf(" Pixel Aspect Ratio: %u\n", gifHead.AspectRatio); /* ** Read and display the global color table if present. */ if (gifHead.PackedField & 0x80) { fputs("\nHit Enter for Global Color Table information...", stdout); getch(); lineCount = 0; /* Count of the number of lines displayed */ tableSize = (WORD) (1L << ((gifHead.PackedField & 0x07) + 1)); puts("\n\n\t\t\t\tGlobal Color Table\n"); printf("Color Red Grn Blu Color Red Grn Blu Color"); printf(" Red Grn Blu Color Red Grn Blu\n"); /* Display the palette values */ for (i = 0; i < tableSize; i++) { printf(" %3d %03u %03u %03u", i, gifHead.GlobalCT[i].Red, gifHead.GlobalCT[i].Green, gifHead.GlobalCT[i].Blue); /* Four entries per row */ if (i && i % 4 == 3) { putchar('\n'); lineCount++; } else fputs(" ", stdout); if (lineCount == 22) { fputs("Hit Enter for next page...", stdout); getch(); printf("\n\nColor Red Grn Blu Color Red Grn Blu"); printf(" Color Red Grn Blu Color Red Grn Blu\n"); lineCount = 0; } } } /* ** Identify, read, and display block information. */ imageCount = 0; /* Clear the image counter */ for (;;) { Identifier = GetByte(fpGif); switch (Identifier) { case 0x3B: /* Trailer */ printf("\n\nGIF Trailer found (end of GIF image file).\n\n"); fclose(fpGif); return(0); case 0x2C: /* Image Descriptor */ gifImageDesc.ImageSeparator = Identifier; if (ReadGifImageDesc(&gifImageDesc, fpGif) == -1) fputs("Error reading Image Descriptor information\n", stderr); imageCount++; printf("\n\nImage Descriptor for Image %d\n\n", imageCount); printf(" Image Left Position: %u\n", gifImageDesc.ImageLeft); printf(" Image Top Position: %u\n", gifImageDesc.ImageTop); printf(" Image Width: %u\n", gifImageDesc.ImageWidth); printf(" Image Height: %u\n", gifImageDesc.ImageHeight); printf(" Local Color Table is: %s\n", gifImageDesc.PackedField & 0x80 ? "Present" : "Not Present"); printf(" Local Color Table Entries are: %s\n", gifImageDesc.PackedField & 0x20 ? "Sorted" : "Not Sorted"); printf(" Image is: %sInterlaced\n", gifImageDesc.PackedField & 0x40 ? "" : "Not "); printf(" Reserved: %u\n", (gifImageDesc.PackedField & 0x18) >> 3); printf(" Size of Local Color Table: %lu entries (%lu bytes)\n", 1L << ((gifImageDesc.PackedField & 0x07) + 1), 3L * (1L << ((gifImageDesc.PackedField & 0x07) + 1))); printf("Size of Local Color Table Entry: %u bits per pixel\n", (gifImageDesc.PackedField & 0x07) + 1); /* ** Read and display local color table, if present. */ if (gifImageDesc.PackedField & 0x80) { fputs("\nHit Enter for Local Color Table information...", stdout); getch(); lineCount = 0; /* Count of the number of lines displayed */ tableSize = (WORD) (1L << ((gifImageDesc.PackedField & 0x07) + 1)); puts("\n\n\t\t\t\tLocal Color Table\n"); printf("Color Red Grn Blu Color Red Grn Blu"); printf(" Color Red Grn Blu Color Red Grn Blu\n"); /* Display the palette values */ for (i = 0; i < tableSize; i++) { printf(" %3d %03u %03u %03u", i, gifImageDesc.LocalCT[i].Red, gifImageDesc.LocalCT[i].Green, gifImageDesc.LocalCT[i].Blue); /* Four entries per row */ if (i && i % 4 == 3) { putchar('\n'); lineCount++; } else fputs(" ", stdout); if (lineCount == 22) { fputs("Hit Enter for next page...", stdout); getch(); printf("\n\nColor Red Grn Blu Color Red Grn Blu"); printf(" Color Red Grn Blu Color Red Grn Blu\n"); lineCount = 0; } } puts("\n"); } /* ** Skip past the encoded image data. */ printf(" LZW Minimum Code Size Value: %u\n", GetByte(fpGif)); printf(" Number of blocks of image data:"); blockCount = 0; while ((dataSize = GetByte(fpGif)) != 0) { blockCount++; fseek(fpGif, (long) dataSize, SEEK_CUR); } printf(" %u\n", blockCount); break; case 0x21: /* Extension Block */ Label = GetByte(fpGif); switch (Label) { case 0x01: /* Plain Text Extension */ puts("\n\nPlain Text Extension\n"); gifPlainText.Introducer = Identifier; gifPlainText.Label = Label; if (ReadGifPlainText(&gifPlainText, fpGif)) fprintf(stderr, "Error reading Plain Text Extension information.\n"); printf(" Block Size: %u\n", gifPlainText.BlockSize); printf(" Text Grid Left Position: %u\n", gifPlainText.TextGridLeft); printf(" Text Grid Right Position: %u\n", gifPlainText.TextGridTop); printf(" Text Grid Width: %u\n", gifPlainText.TextGridWidth); printf(" Text Grid Height: %u\n", gifPlainText.TextGridHeight); printf(" Character Cell Width: %u\n", gifPlainText.CellWidth); printf(" Character Cell Height: %u\n", gifPlainText.CellHeight); printf(" Text Foreground Color Index: %u\n", gifPlainText.TextFgColorIndex); printf(" Text Background Color Index: %u\n", gifPlainText.TextBgColorIndex); /* Display Plain Text Data */ ptr = gifPlainText.PlainTextData; while ((dataSize = *ptr++) != 0) { printf("\nSize of Plain Text sub-block: %u\n", dataSize); puts("\nText:"); while (dataSize--) fputc(*ptr++, stdout); putchar('\n'); } break; case 0xFE: /* Comment Extension */ puts("\n\nComment Extension"); gifComment.Introducer = Identifier; gifComment.Label = Label; if (ReadGifComment(&gifComment, fpGif)) fprintf(stderr, "Error reading Comment Extension information\n"); /* Display Comment Data */ ptr = gifComment.CommentData; while ((dataSize = *ptr++) != 0) { printf("\nSize of Comment sub-block: %u\n", dataSize); puts("\nComment:"); while (dataSize--) fputc(*ptr++, stdout); putchar('\n'); } break; case 0xF9: /* Graphic Control Extension */ puts("\n\nGraphics Control Extension\n"); gifGraphicControl.Introducer = Identifier; gifGraphicControl.Label = Label; if (ReadGifGraphicControl(&gifGraphicControl, fpGif)) fprintf(stderr, "Error reading Graphic Control Extension information\n"); printf(" Block Size: %u\n", gifGraphicControl.BlockSize); printf(" Reserved: %u\n", (gifGraphicControl.PackedField & 0xE0) >> 5); printf(" Disposal Method: %u ", (gifGraphicControl.PackedField & 0x1D) >> 2); switch((gifGraphicControl.PackedField & 0x1D) >> 2) { case 0x00: puts("(No Disposal Method Defined)"); break; case 0x01: puts("(Do Not Dispose)"); break; case 0x02: puts("(Restore to Background Color)"); break; case 0x03: puts("(Restore to Previous Graphic)"); break; default: puts("(To Be Defined)"); } printf(" User Input Flag: User Input is %sExpected\n", gifGraphicControl.PackedField & 0x02 ? "" : "Not "); printf(" Transparent Color Flag: Color Index Is %sPresent\n", gifGraphicControl.PackedField & 0x01 ? "" : "Not "); printf(" Delay Time: %u\n", gifGraphicControl.DelayTime); printf("Transparent Color Index: %u\n", gifGraphicControl.ColorIndex); /* Display Graphic Control Information */ while ((dataSize = GetByte(fpGif)) != 0) { printf("\nSize of Graphic Control sub-block: %u\n", dataSize); puts("Graphic Control Information:"); for (i = 0; i < dataSize; i++) fputc(GetByte(fpGif), stdout); putchar('\n'); } break; case 0xFF: /* Application Extension */ puts("\n\nApplication Extension\n"); gifApplication.Introducer = Identifier; gifApplication.Label = Label; if (ReadGifApplication(&gifApplication, fpGif)) fprintf(stderr, "Error reading Application Extension information\n"); printf("Block Size: %u\n", gifApplication.BlockSize); printf("Application Identifier: %*u\n", sizeof(gifApplication.Identifier), gifApplication.Identifier); printf("Authentication Code: %*u\n", sizeof(gifApplication.AuthentCode), gifApplication.AuthentCode); /* Display Application Data */ ptr = gifApplication.ApplicationData; while ((dataSize = *ptr++) != 0) { printf("\nSize of Application sub-block: %u\n", dataSize); puts("\nApplication Data:"); while (dataSize--) fputc(*ptr++, stdout); putchar('\n'); } break; default: printf("\n\nUnknown Extension Label: 0x%02x\n", Label); break; } break; default: fprintf(stderr, "\n\nUnknown Block Separator Character: 0x%02x\n\n", Identifier); fclose(fpGif); return(-1); } } } } GIF File Reader and Writer GIFCODE.C /****************************************************************************\ ** Title: GIFCODE.C ** ** Purpose: Decode/Encode a GIF image file. ** ** Version: 1.0 ** ** Date: March 1992 ** ** Author: James D. Murray, Anaheim, CA USA ** ** C Compilers: Borland C++ v2.0, Microsoft C v6.00a ** ** ** ** This code is an example of several functions that work with GIF ** ** image files. GIFCODE reads a GIF image file, decodes the image ** ** data, re-encodes it, and writes it out to a second GIF file. ** ** While this program is only a working example, it can be used to ** ** possibly repair GIF files that have been previously encoded ** ** incorrectly and fail to display properly. ** ** ** ** This module contains the following functions: ** ** ** ** GifEncodeScanLine - Encode a raw scan line using LZW ** ** GifDecodeScanLine - Decode a LZW-encoded scan line ** ** ** ** Copyright (C) 1991,92 by Graphics Software Labs. All rights reserved. ** \****************************************************************************/ #include #include #include #include "endianio.h" #include "gif.h" int main(argc, argv) int argc; /* Number of command line arguments */ char *argv[]; /* Array of command line arguments */ { FILE *fpGifIn; FILE *fpGifOut; GIFHEAD *gifHead; puts("GIFCODE - Decode and recode a GIF image file (v1.00)\n"); /* Check for proper number of command line arguments */ if (argc < 3) { fputs("Usage: GIFCODE input_filename.gif output_filename.gif\n\n", stderr); exit(-1); } /* Open the input GIF image file */ if ((fpGifIn = fopen(argv[1], "rb")) == (FILE *) NULL) { fprintf(stderr, "GIFCODE: Cannot open input file %s\n", argv[1]); exit(-2); } /* Open the output GIF image file */ if ((fpGifOut = fopen(argv[2], "wb")) == (FILE *) NULL) { fprintf(stderr, "GIFCODE: Cannot open output file %s\n", argv[2]); exit(-3); } /* Read the GIF image file header information */ ReadGifHeader(&gifHead, fpGifIn); /* Check for FILE stream error */ if (ferror(fpGifIn)) { fputs("GIFCODE: Error reading header information!\n", stderr); exit(-4); } return(0); /* Successful termination */ } } GIF LZW Decoder GIFDECODE.C /****************************************************************************\ ** Title: GIFDECODE.C ** ** Purpose: Decode a GIF image file scan line. ** ** Version: 1.0 ** ** Date: May 1991 ** ** Author: James D. Murray, Anaheim, CA USA ** ** C Compilers: Borland C++ v2.0, Microsoft C v6.00a ** ** ** ** Compress an image scan line using the Lez-Zempel Welch (LZW) encoding ** ** algorithm. Decoded data is returned in a buffer. Useful for ** ** algorithms that need to work on images one scan line at a time. ** ** ** ** This module contains the following functions: ** ** ** ** GifDecodeScanLine - Decode an LZW-encoded scan line ** ** ** ** Copyright (C) 1991 by Graphics Software Labs. All rights reserved. ** \****************************************************************************/ #include #include "endianio.h" #include "gif.h" /* ** Decode (uncompress) a GIF image file scan line. ** ** The LZW-encoded data stored in a GIF file is arranged as a series ** of sub-blocks. Each sub-lock consists of a single count byte followed ** by 1 to 255 data bytes. This function reads the sub-blocks, sends ** the LZW data to the LZWDecode() function, and then returns a parameter ** pointer to a buffer filled with the decoded image data. */ SHORT GIFDecodeScanLine(DecodedBuffer, BufferSize, MinCodeSize, FpGif) BYTE *DecodedBuffer; /* Pointer to buffer to hold decoded data */ WORD BufferSize; /* Size of buffer to hold decoded data */ BYTE MinCodeSize; /* */ FILE *FpGif; /* FILE pointer to the open input GIF image file */ { #if 0 if (!(DecodedBuffer = LZWDecoder(buffer, bufferSize, MinCodeSize))) return(-1); #endif return(0); } } GIF LZW Encoder GIFENCOD.C /****************************************************************************\ ** Title: GIFENCOD.C ** ** Purpose: Encode a GIF image file scan line. ** ** Version: 1.0 ** ** Date: May 1991 ** ** Author: James D. Murray, Anaheim, CA USA ** ** C Compilers: Borland C++ v2.0, Microsoft C v6.00a ** ** ** ** Compress an image scan line using the Lev-Zempel Welch (LZW) encoding ** ** algorithm. Useful for algorithms that need to work on images ** ** one scan line at a time. ** ** ** ** This module contains the following functions: ** ** ** ** GifEncodeScanLine - Encode a raw scan line using LZW. ** ** ** ** Copyright (C) 1991 by Graphics Software Labs. All rights reserved. ** \****************************************************************************/ #include #include "endianio.h" #include "gif.h" WORD GifEncodeScanLine(DecodedBuffer, BufferSize, EncodedBuffer) BYTE *DecodedBuffer; /* Pointer to buffer holding unencoded data */ WORD BufferSize; /* Size of buffer holding unencoded data */ BYTE *EncodedBuffer; /* Pointer to buffer to hold encodeded scan line */ { }