Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* gifread.c given a filename.gif, alpha, returns width, height, rgb pixels */
- /* int width, height; int alpha=0 to 255, or -1 for just rgb */
- /* unsigned char pixels[4*width*height]; or 3*width*height for alpha=-1 */
- /* call: status = gifread("your-filename", alpha, &width, &height, pixels);*/
- /* status==0 for OK */
- #include "gif.h"
- #include <stdio.h>
- #include <stdlib.h>
- static FILE *fpGif; /* Pointer to the input FILE stream, global for decoder */
- static int bad_code_count; /* set by decoder */
- static int gifReadHead(char gifFileName[], BYTE rgbpix[]);
- static short int gif_decode(short int linewidth, BYTE rgbpix[]);
- static int nrgbpix;
- static int debug = 0; /* set to 1 for full debug printout */
- static int line_num;
- static int ipass;
- static int rgba=0;
- static int alph;
- static GIFHEAD gifHead; /* GIF Header structure */
- static GIFIMAGEDESC gifImageDesc; /* Logical Image Descriptor struct */
- #define OUT_OF_MEMORY -10
- #define BAD_CODE_SIZE -20
- #define READ_ERROR -1
- #define WRITE_ERROR -2
- #define OPEN_ERROR -3
- #define CREATE_ERROR -4
- int gifread(char filename[], int alpha, int *width, int *height, BYTE rgbpix[])
- {
- int status;
- line_num = 0; /* needed for multiple calls in one program */
- nrgbpix = 0;
- ipass = 1; /* pass number of interlace */
- rgba = 0;
- if(alpha>=0 && alpha<=255) { rgba = 1; alph = alpha; } /* 4 bytes per pixel */
- status = gifReadHead(filename, rgbpix);
- *width = gifImageDesc.ImageWidth;
- *height = gifImageDesc.ImageHeight;
- return status;
- } /* end gifread */
- static int gifReadHead(char gifFileName[], BYTE rgbpix[])
- {
- WORD i, j; /* 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 */
- int blkSize; /* Data block byte count, (int) of above */
- BYTE dataBlock[256]; /* Hold a data block */
- BYTE *ptr; /* Scratch pointer variable */
- BYTE code_size;
- short int err;
- GIFPLAINTEXT gifPlainText; /* Plain Text Extension structure */
- GIFAPPLICATION gifApplication; /* Application Extension structure */
- GIFCOMMENT gifComment; /* Comment Extension structure */
- GIFGRAPHICCONTROL gifGraphicControl; /* Graphic Control Extension strct */
- if(debug)printf("gifhead - Display the header info within a GIF image file \n");
- /* Open the GIF image file */
- if ((fpGif = fopen(gifFileName, "rb")) == (FILE *) NULL)
- {
- printf("gifhead: Cannot open file %s\n", gifFileName);
- return -1;
- }
- /* Read the GIF image file header information */
- ReadGifHeader(&gifHead, fpGif);
- /* Check for FILE stream error */
- if (ferror(fpGif))
- {
- printf("gifhead: Error reading header information!\n");
- return -1;
- }
- if(debug)printf(" Signature: %.*s\n",
- sizeof(gifHead.Signature), gifHead.Signature);
- if(debug)printf(" Version: %.*s\n",
- sizeof(gifHead.Version), gifHead.Version);
- if(debug)printf(" ScreenWidth: %u\n", gifHead.ScreenWidth);
- if(debug)printf(" ScreenHeight: %u\n", gifHead.ScreenHeight);
- if(debug)printf(" Global Color Table is: %s\n",
- gifHead.PackedField & 0x80 ? "Present" : "Not Present");
- if(debug)printf(" Original Resolution: %u (%u bits per primary color)\n",
- (gifHead.PackedField & 0x70) >> 4,
- ((gifHead.PackedField & 0x70) >> 4) + 1);
- if(debug)printf(" Global Color Table is: %s\n",
- gifHead.PackedField & 0x08 ? "Sorted" : "Not Sorted");
- if(debug)printf(" Size of Global Color Table: %lu entries (%lu bytes)\n",
- 1L << ((gifHead.PackedField & 0x07) + 1),
- 3L * (1L << ((gifHead.PackedField & 0x07) + 1)));
- if(debug)printf("Size of Global Color Table Entry: %u bits per pixel\n",
- (gifHead.PackedField & 0x07) + 1);
- if(debug)printf(" Background Color Index: %u\n", gifHead.ColorIndex);
- if(debug)printf(" Pixel Aspect Ratio: %u\n", gifHead.AspectRatio);
- /*
- ** Read and display the global color table if present.
- */
- if (gifHead.PackedField & 0x80)
- {
- lineCount = 0; /* Count of the number of lines displayed */
- tableSize = (WORD) (1L << ((gifHead.PackedField & 0x07) + 1));
- if(debug)puts("\n\n\t\t\t\tGlobal Color Table\n");
- if(debug)printf("Color Red Grn Blu Color Red Grn Blu Color");
- if(debug)printf(" Red Grn Blu Color Red Grn Blu\n");
- /* Display the palette values */
- for (i = 0; i < tableSize; i++)
- {
- if(debug)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)
- {
- if(debug)putchar('\n');
- lineCount++;
- }
- else
- if(debug)fputs(" ", stdout);
- if (lineCount == 22)
- {
- if(debug)printf("\n\nColor Red Grn Blu Color Red Grn Blu");
- if(debug)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 */
- if(debug)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++;
- if(debug)printf("\n\nImage Descriptor for Image %d\n\n",
- imageCount);
- if(debug)printf(" Image Left Position: %u\n",
- gifImageDesc.ImageLeft);
- if(debug)printf(" Image Top Position: %u\n",
- gifImageDesc.ImageTop);
- if(debug)printf(" Image Width: %u\n",
- gifImageDesc.ImageWidth);
- if(debug)printf(" Image Height: %u\n",
- gifImageDesc.ImageHeight);
- if(debug)printf(" Local Color Table is: %s\n",
- gifImageDesc.PackedField & 0x80 ? "Present" : "Not Present");
- if(debug)printf(" Local Color Table Entries are: %s\n",
- gifImageDesc.PackedField & 0x20 ? "Sorted" : "Not Sorted");
- if(debug)printf(" Image is: %sInterlaced\n",
- gifImageDesc.PackedField & 0x40 ? "" : "Not ");
- if(debug)printf(" Reserved: %u\n",
- (gifImageDesc.PackedField & 0x18) >> 3);
- if(debug)printf(" Size of Local Color Table: %lu entries (%lu bytes)\n",
- 1L << ((gifImageDesc.PackedField & 0x07) + 1),
- 3L * (1L << ((gifImageDesc.PackedField & 0x07) + 1)));
- if(debug)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)
- {
- lineCount = 0; /* Count of the number of lines displayed */
- tableSize =
- (WORD) (1L << ((gifImageDesc.PackedField & 0x07) + 1));
- if(debug)puts("\n\n\t\t\t\tLocal Color Table\n");
- if(debug)printf("Color Red Grn Blu Color Red Grn Blu");
- if(debug)printf(" Color Red Grn Blu Color Red Grn Blu\n");
- /* Display the palette values */
- for (i = 0; i < tableSize; i++)
- {
- if(debug)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)
- {
- if(debug)putchar('\n');
- lineCount++;
- }
- else
- if(debug)fputs(" ", stdout);
- if (lineCount == 22)
- {
- if(debug)printf("\n\nColor Red Grn Blu Color Red Grn Blu");
- if(debug)printf(" Color Red Grn Blu Color Red Grn Blu\n");
- lineCount = 0;
- }
- }
- if(debug)puts("\n");
- }
- /*
- ** Skip past the encoded image data.
- */
- if(debug)printf(" Image data: doing via gif_decode.c \n");
- err=gif_decode(gifImageDesc.ImageWidth, rgbpix);
- err=GetByte(fpGif); /* final zero block */
- if(debug)printf("gif_decode returned err=%d, bad_code_count=%d\n",
- (int)err, (int)bad_code_count);
- break;
- case 0x21: /* Extension Block */
- Label = GetByte(fpGif);
- switch (Label)
- {
- case 0x01: /* Plain Text Extension */
- if(debug)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");
- if(debug)printf(" Block Size: %u\n",
- gifPlainText.BlockSize);
- if(debug)printf(" Text Grid Left Position: %u\n",
- gifPlainText.TextGridLeft);
- if(debug)printf(" Text Grid Right Position: %u\n",
- gifPlainText.TextGridTop);
- if(debug)printf(" Text Grid Width: %u\n",
- gifPlainText.TextGridWidth);
- if(debug)printf(" Text Grid Height: %u\n",
- gifPlainText.TextGridHeight);
- if(debug)printf(" Character Cell Width: %u\n",
- gifPlainText.CellWidth);
- if(debug)printf(" Character Cell Height: %u\n",
- gifPlainText.CellHeight);
- if(debug)printf(" Text Foreground Color Index: %u\n",
- gifPlainText.TextFgColorIndex);
- if(debug)printf(" Text Background Color Index: %u\n",
- gifPlainText.TextBgColorIndex);
- /* Display Plain Text Data */
- ptr = gifPlainText.PlainTextData;
- while ((dataSize = *ptr++) != 0)
- {
- if(debug)printf("\nSize of Plain Text sub-block: %u\n",
- dataSize);
- if(debug)puts("\nText:");
- while (dataSize--)
- if(debug)fputc(*ptr++, stdout);
- if(debug)putchar('\n');
- }
- break;
- case 0xFE: /* Comment Extension */
- if(debug)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)
- {
- if(debug)printf("\nSize of Comment sub-block: %u\n", dataSize);
- if(debug)puts("\nComment:");
- while (dataSize--)
- if(debug)fputc(*ptr++, stdout);
- if(debug)putchar('\n');
- }
- break;
- case 0xF9: /* Graphic Control Extension */
- if(debug)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");
- if(debug)printf(" Block Size: %u\n",
- gifGraphicControl.BlockSize);
- if(debug)printf(" Reserved: %u\n",
- (gifGraphicControl.PackedField & 0xE0) >> 5);
- if(debug)printf(" Disposal Method: %u ",
- (gifGraphicControl.PackedField & 0x1D) >> 2);
- switch((gifGraphicControl.PackedField & 0x1D) >> 2)
- {
- case 0x00:
- if(debug)puts("(No Disposal Method Defined)");
- break;
- case 0x01:
- if(debug)puts("(Do Not Dispose)");
- break;
- case 0x02:
- if(debug)puts("(Restore to Background Color)");
- break;
- case 0x03:
- if(debug)puts("(Restore to Previous Graphic)");
- break;
- default:
- if(debug)puts("(To Be Defined)");
- }
- if(debug)printf(" User Input Flag: User Input is %sExpected\n",
- gifGraphicControl.PackedField & 0x02 ? "" : "Not ");
- if(debug)printf(" Transparent Color Flag: Color Index Is %sPresent\n",
- gifGraphicControl.PackedField & 0x01 ? "" : "Not ");
- if(debug)printf(" Delay Time: %u\n",
- gifGraphicControl.DelayTime);
- if(debug)printf("Transparent Color Index: %u\n",
- gifGraphicControl.ColorIndex);
- /* Display Graphic Control Information */
- while ((dataSize = GetByte(fpGif)) != 0)
- {
- if(debug)printf("\nSize of Graphic Control sub-block: %u\n",
- dataSize);
- if(debug)puts("Graphic Control Information:");
- for (i = 0; i < dataSize; i++)
- if(debug)fputc(GetByte(fpGif), stdout);
- if(debug)putchar('\n');
- }
- break;
- case 0xFF: /* Application Extension */
- if(debug)puts("\n\nApplication Extension\n");
- gifApplication.Introducer = Identifier;
- gifApplication.Label = Label;
- if (ReadGifApplication(&gifApplication, fpGif))
- fprintf(stderr,
- "Error reading Application Extension information\n");
- if(debug)printf("Block Size: %u\n", gifApplication.BlockSize);
- if(debug)printf("Application Identifier: %*u\n",
- sizeof(gifApplication.Identifier),
- gifApplication.Identifier);
- if(debug)printf("Authentication Code: %*u\n",
- sizeof(gifApplication.AuthentCode),
- gifApplication.AuthentCode);
- /* Display Application Data */
- ptr = gifApplication.ApplicationData;
- while ((dataSize = *ptr++) != 0)
- {
- if(debug)printf("\nSize of Application sub-block: %u\n", dataSize);
- if(debug)puts("\nApplication Data:");
- while (dataSize--)
- if(debug)fputc(*ptr++, stdout);
- if(debug)putchar('\n');
- }
- break;
- default:
- if(debug)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);
- }
- }
- } /* end gifHead */
- /* gif_decode.c - An LZW decoder for GIF JSS mods */
- /* Copyright (C) 1987, by Steven A. Bennett */
- /* Permission is given by the author to freely redistribute and include */
- /* this code in any program as long as this credit is given where due. */
- /* In accordance with the above, I want to credit Steve Wilhite who wrote */
- /* the code which this is heavily inspired by... */
- /* */
- /* GIF and 'Graphics Interchange Format' are trademarks (tm) of */
- /* Compuserve, Incorporated, an H&R Block Company. */
- /* */
- /* Release Notes: This file contains a decoder routine for GIF images */
- /* which is similar, structurally, to the original routine by Steve Wilhite*/
- /* It is, however, somewhat noticably faster in most cases. */
- /* Various error codes used by decode.c */
- /* extern int get_byte(); replaced by getc(fpGif) */
- /* This external (machine specific) function is expected to return */
- /* either the next byte from the GIF file, or a negative number, as */
- /* defined in above errors */
- /* extern int out_line(BYTE pixels[], int linelen, BYTE rgbpix[]); Now here. */
- /* This function takes a full line of pixels (one byte per pixel) and */
- /* displays them (or does whatever your program wants with them...). It */
- /* should return zero, or negative if an error or some other event occurs */
- /* which would require aborting the decode process... Note that the length */
- /* passed will almost always be equal to the line length passed to the */
- /* decoder function, with the sole exception occurring when an ending code */
- /* occurs in an odd place in the GIF file... In any case, linelen will be */
- /* equal to the number of pixels passed... */
- int out_line(BYTE pixels[], int linelen, BYTE rgbpix[]) /* JSS */
- {
- int i, j;
- BYTE r, g, b;
- int enough=26;
- int w, h, hw, x, y;
- w = gifImageDesc.ImageWidth;
- h = gifImageDesc.ImageHeight;
- if(rgba) { hw = 4*h*w; x = 4*w; }
- else { hw = 3*h*w; x = 3*w; }
- line_num++; /* number, not subscript */
- for(i=0; i<linelen; i++)
- {
- if(i%enough==0) if(debug)printf("\n");
- if(debug)printf("%d ", (int)pixels[i]);
- }
- if(debug)printf("\n");
- y = hw-x*(2*(nrgbpix/x)+1); /* invert image y */
- if(debug)printf("out_line %d with length=%d, nrgbpix=%d, y=%d \n",
- line_num, linelen, nrgbpix, y);
- for(i=0; i<linelen; i++)
- {
- j = (int)pixels[i];
- /* have index into color table, now get colors */
- r = gifHead.GlobalCT[j].Red;
- g = gifHead.GlobalCT[j].Green;
- b = gifHead.GlobalCT[j].Blue;
- if(debug)printf("r=%03u, g=%03u, b=%03u, row=%d, col=%d, inv=%d \n",
- r, g, b, line_num, i, y+nrgbpix);
- rgbpix[y+nrgbpix] = r; /* invert y */
- rgbpix[y+nrgbpix+1] = g;
- rgbpix[y+nrgbpix+2] = b;
- if(rgba) { rgbpix[y+nrgbpix+3] = alph; nrgbpix += 4; }
- else { nrgbpix += 3; }
- }
- if(gifImageDesc.PackedField & 0x40)
- {
- if(ipass==4)
- {
- nrgbpix = nrgbpix + x; /* every other */
- }
- if(ipass==3)
- {
- nrgbpix = nrgbpix + (4-1)*x; /* every fourth */
- if(nrgbpix>=hw)
- {
- ipass = 4;
- nrgbpix = x; /* start row 1 */
- }
- }
- if(ipass==2)
- {
- nrgbpix = nrgbpix + (8-1)*x; /* every eighth */
- if(nrgbpix>=hw)
- {
- ipass = 3;
- nrgbpix = 2*x; /* start row 2 */
- }
- }
- if(ipass==1)
- {
- nrgbpix = nrgbpix + (8-1)*x; /* every eighth */
- if(nrgbpix>=hw)
- {
- ipass = 2;
- nrgbpix = 4*x; /* start row 4 */
- }
- }
- }
- return 0;
- } /* end out_line */
- /* extern int bad_code_count; */
- /* This value is the only other global required by the using program, and */
- /* is incremented each time an out of range code is read by the decoder. */
- /* When this value is non-zero after a decode, your GIF file is probably */
- /* corrupt in some way... */
- #define MAX_CODES 4095
- /* Static variables */
- static WORD curr_size; /* The current code size */
- static WORD clear; /* Value for a clear code */
- static WORD ending; /* Value for a ending code */
- static WORD newcodes; /* First available code */
- static WORD top_slot; /* Highest code for current size */
- static WORD slot; /* Last read code */
- /* The following static variables are used */
- /* for separating out codes */
- static WORD navail_bytes = 0; /* # bytes left in block */
- static WORD nbits_left = 0; /* # bits left in current byte */
- static BYTE b1; /* Current byte */
- static BYTE byte_buff[257]; /* Current block */
- static BYTE *pbytes; /* Pointer to next byte in block */
- static int code_mask[13] = {
- 0,
- 0x0001, 0x0003,
- 0x0007, 0x000F,
- 0x001F, 0x003F,
- 0x007F, 0x00FF,
- 0x01FF, 0x03FF,
- 0x07FF, 0x0FFF
- };
- /* This function initializes the decoder for reading a new image. */
- static WORD init_exp(WORD size)
- {
- if(debug)printf("gif_decode.c init_exp size=%d\n", (int)size);
- curr_size = size + 1;
- top_slot = 1 << curr_size;
- clear = 1 << size;
- ending = clear + 1;
- slot = newcodes = ending + 1;
- navail_bytes = nbits_left = 0;
- return(0);
- } /* end init_exp */
- /* get_next_code() */
- /* - gets the next code from the GIF file. Returns the code, or else */
- /* a negative number in case of file errors... */
- static WORD get_next_code()
- {
- WORD i, x;
- int ret;
- if (nbits_left == 0)
- {
- if (navail_bytes <= 0)
- {
- /* Out of bytes in current block, so read next block */
- pbytes = byte_buff;
- if ((navail_bytes = getc(fpGif)) < 0)
- {
- printf("gif_decode.c get_next_code bad block size=%d\n",
- (int)navail_bytes);
- return navail_bytes;
- }
- else if (navail_bytes)
- {
- if(debug)printf("gif_decode.c get_next_code block size=%d\n",
- (int)navail_bytes);
- for (i = 0; i < navail_bytes; ++i)
- {
- if ((x = getc(fpGif)) < 0) return x;
- byte_buff[i] = x;
- }
- }
- else
- {
- printf("gif_decode.c get_next_code zero block size=%d\n",
- (int)navail_bytes);
- }
- }
- b1 = *pbytes++;
- nbits_left = 8;
- --navail_bytes;
- }
- ret = b1 >> (8 - nbits_left);
- while (curr_size > nbits_left)
- {
- if (navail_bytes <= 0)
- {
- /* Out of bytes in current block, so read next block */
- pbytes = byte_buff;
- if ((navail_bytes = getc(fpGif)) < 0) return(navail_bytes);
- else if (navail_bytes)
- {
- for (i = 0; i < navail_bytes; ++i)
- {
- if ((x = getc(fpGif)) < 0) return x;
- byte_buff[i] = x;
- }
- }
- }
- b1 = *pbytes++;
- ret |= b1 << nbits_left;
- nbits_left += 8;
- --navail_bytes;
- }
- nbits_left -= curr_size;
- ret &= code_mask[curr_size];
- /* printf("gif_decode.c get_next_code code=%d\n", (int)ret); */
- return (WORD)ret;
- } /* end get_next_code */
- /* The reason we have these seperated like this instead of using */
- /* a structure like the original Wilhite code did, is because this */
- /* stuff generally produces significantly faster code when compiled... */
- /* This code is full of similar speedups... (For a good book on writing */
- /* C for speed or for space optomisation, see Efficient C by Tom Plum, */
- /* published by Plum-Hall Associates...) */
- static BYTE stack[MAX_CODES + 1]; /* Stack for storing pixels */
- static BYTE suffix[MAX_CODES + 1]; /* Suffix table */
- static unsigned int prefix[MAX_CODES + 1]; /* Prefix linked list */
- /* - This function decodes an LZW image, according to the method used */
- /* in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded */
- /* will generate a call to out_line(), which is a user specific function */
- /* to display a line of pixels. The function gets it's codes from */
- /* get_next_code() which is responsible for reading blocks of data and */
- /* seperating them into the proper size codes. Finally, getc(fpGif) is*/
- /* the global routine to read the next byte from the GIF file. */
- /* It is generally a good idea to have linewidth correspond to the actual */
- /* width of a line (as specified in the Image header) to make your own */
- /* code a bit simpler, but it isn't absolutely necessary. */
- /* Returns: 0 if successful, else negative. (See ERRS.H) */
- static short int gif_decode(short int linewidth, BYTE rgbpix[])
- /* call with width, LZW initial code size, return is error code */
- {
- register BYTE *sp, *bufptr;
- BYTE *buf;
- register WORD code, fc, oc, bufcnt;
- WORD c, size, ret;
- if(debug)printf("gif_decode.c linewidth=%d\n", (int)linewidth);
- /* Initialize for decoding a new image... */
- if ((size = getc(fpGif)) < 0) return size;
- if (size < 2 || 9 < size) return BAD_CODE_SIZE;
- init_exp(size);
- /* Initialize in case they forgot to put in a clear code. */
- /* (This shouldn't happen, but we'll try and decode it anyway...) */
- oc = fc = 0;
- /* Allocate space for the decode buffer */
- if ((buf = (BYTE *)malloc(linewidth + 1)) == NULL) return OUT_OF_MEMORY;
- /* Set up the stack pointer and decode buffer pointer */
- sp = stack;
- bufptr = buf;
- bufcnt = linewidth;
- /* This is the main loop. For each code we get we pass through the */
- /* linked list of prefix codes, pushing the corresponding "character" for */
- /* each code onto the stack. When the list reaches a single "character" */
- /* we push that on the stack too, and then start unstacking each */
- /* character for output in the correct order. Special handling is */
- /* included for the clear code, and the whole thing ends when we get */
- /* an ending code. */
- while ((c = get_next_code()) != ending)
- {
- /* If we had a file error, return without completing the decode */
- if (c < 0)
- {
- free(buf);
- return 0;
- }
- /* If the code is a clear code, reinitialize all necessary items. */
- if (c == clear)
- {
- curr_size = size + 1;
- slot = newcodes;
- top_slot = 1 << curr_size;
- /* Continue reading codes until we get a non-clear code */
- /* (Another unlikely, but possible case...) */
- while ((c = get_next_code()) == clear) ;
- /* If we get an ending code immediately after a clear code */
- /* (Yet another unlikely case), then break out of the loop. */
- if (c == ending) break;
- /* Finally, if the code is beyond the range of already set codes, */
- /* (This one had better NOT happen... I have no idea what will */
- /* result from this, but I doubt it will look good...) then set it */
- /* to color zero. */
- if (c >= slot) c = 0;
- oc = fc = c;
- /* And let us not forget to put the char into the buffer... And */
- /* if, on the off chance, we were exactly one pixel from the end */
- /* of the line, we have to send the buffer to the out_line() */
- /* routine... */
- *bufptr++ = c;
- if (--bufcnt == 0)
- {
- if ((ret = out_line(buf, linewidth, rgbpix)) < 0)
- {
- free(buf);
- return(ret);
- }
- bufptr = buf;
- bufcnt = linewidth;
- }
- }
- else
- {
- /* In this case, it's not a clear code or an ending code, so */
- /* it must be a code code... So we can now decode the code into */
- /* a stack of character codes. (Clear as mud, right?) */
- code = c;
- /* Here we go again with one of those off chances... If, on the */
- /* off chance, the code we got is beyond the range of those already */
- /* set up (Another thing which had better NOT happen...) we trick */
- /* the decoder into thinking it actually got the last code read. */
- /* (Hmmn... I'm not sure why this works... But it does...) */
- if (code >= slot)
- {
- if (code > slot) ++bad_code_count;
- code = oc;
- *sp++ = fc;
- }
- /* Here we scan back along the linked list of prefixes, pushing */
- /* helpless characters (ie. suffixes) onto the stack as we do so. */
- while (code >= newcodes)
- {
- *sp++ = suffix[code];
- code = prefix[code];
- }
- /* Push the last character on the stack, and set up the new */
- /* prefix and suffix, and if the required slot number is greater */
- /* than that allowed by the current bit size, increase the bit */
- /* size. (NOTE - If we are all full, we *don't* save the new */
- /* suffix and prefix... I'm not certain if this is correct... */
- /* it might be more proper to overwrite the last code... */
- *sp++ = code;
- if (slot < top_slot)
- {
- suffix[slot] = fc = code;
- prefix[slot++] = oc;
- oc = c;
- }
- if (slot >= top_slot)
- if (curr_size < 12)
- {
- top_slot <<= 1;
- ++curr_size;
- }
- /* Now that we've pushed the decoded string (in reverse order) */
- /* onto the stack, lets pop it off and put it into our decode */
- /* buffer... And when the decode buffer is full, write another*/
- /* line... */
- while (sp > stack)
- {
- *bufptr++ = *(--sp);
- if (--bufcnt == 0)
- {
- if ((ret = out_line(buf, linewidth, rgbpix)) < 0)
- {
- free(buf);
- return ret;
- }
- bufptr = buf;
- bufcnt = linewidth;
- }
- }
- }
- }
- ret = 0;
- if (bufcnt != linewidth) ret = out_line(buf, (linewidth - bufcnt), rgbpix);
- free(buf);
- return(ret);
- } /* end gif_decode */
- /* gif_io.c implement low level I/O for Gif */
- WORD GetWord(FILE *FpGif) /* little endian */
- {
- int low, high; /* native machine */
- WORD word;
- low = getc(FpGif);
- high = getc(FpGif);
- word = low;
- word = word+ (high<<8);
- return word;
- } /* end GetWord */
- BYTE GetByte(FILE *FpGif)
- {
- return getc(FpGif);
- } /* end GetByte */
- DWORD GetDword(FILE *FpGif)
- {
- int b1, b2, b3, b4; /* native machine */
- WORD word;
- b1 = getc(FpGif);
- b2 = getc(FpGif);
- b3 = getc(FpGif);
- b4 = getc(FpGif);
- word = b1;
- word = word + (b2<<8) + (b3<<16) + (b4<24);
- return word;
- } /* end GetDword */
- void GetString(char * str, int len, FILE *FpGif)
- {
- int i;
- for(i=0; i<len; i++)
- {
- str[i] = (BYTE)getc(FpGif);
- }
- } /* end GetString */
- VOID PutByte(BYTE x, FILE *FpGif)
- {
- putc(x, FpGif);
- } /* end PutByte */
- void PutWord(WORD x, FILE *FpGif)
- {
- BYTE low, high;
- low = (BYTE)(x & 0xFF);
- high = (BYTE)(x>>8);
- putc(low, FpGif);
- putc(high, FpGif);
- } /* end PutWord */
- void PutDword(DWORD x, FILE *FpGif)
- {
- BYTE b1, b2, b3, b4;
- b1 = (BYTE)(x & 0xFF);
- b2 = (BYTE)( (x>>8) & 0xFF);
- b3 = (BYTE)( (x>>16) * 0xFF);
- b4 = (BYTE)(x>>24);
- putc(b1, FpGif);
- putc(b2, FpGif);
- putc(b3, FpGif);
- putc(b4, FpGif);
- } /* end PutDword */
- void PutString(char * str, int len, FILE *FpGif)
- {
- int i;
- for(i=0; i<len; i++)
- {
- putc(str[i],FpGif);
- }
- } /* end PutString */
- /****************************************************************************\
- ** 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. **
- \****************************************************************************/
- /* Local function prototype */
- BYTE *ReadDataSubBlocks(FILE *FpGif);
- /*
- ** 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 *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 *GifImageDesc, /* Pointer to GIF image descriptor structure */
- FILE *FpGif) /* GIF image file input FILE stream */
- {
- 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 *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 *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 *GifApplication, /* Pointer to Application Extension struct */
- 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 *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.
- */
- BYTE *
- ReadDataSubBlocks(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 */
- }
- /* 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 "gif.h"
- VOID
- WriteGifHeader(GIFHEAD *GifHead, /* Pointer to GIF header structure */
- FILE *FpGif) /* GIF image file output FILE stream */
- {
- /* PutWord = PutLittleWord; write 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);
- }
- /* gifdecode.c GIF LZW Decoder */
- /****************************************************************************\
- ** 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 **
- ** **
- ** Decompress 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 "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(
- 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;
- }
- /* gifencode.c GIF LZW Encoder */
- /****************************************************************************\
- ** 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 "gif.h"
- WORD
- GifEncodeScanLine(
- 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 */
- {
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement