diff options
Diffstat (limited to 'tools/gifconv/decompress.c')
-rw-r--r-- | tools/gifconv/decompress.c | 497 |
1 files changed, 257 insertions, 240 deletions
diff --git a/tools/gifconv/decompress.c b/tools/gifconv/decompress.c index abccb7f..a2682e5 100644 --- a/tools/gifconv/decompress.c +++ b/tools/gifconv/decompress.c @@ -1,38 +1,43 @@ +/* + * Copyright (C) 2001 National Center for Supercomputing Applications + * All rights reserved. + */ #include <stdio.h> #include <stdlib.h> + #include "gif.h" -#define NEXTBYTE (*ptr++) -#define IMAGESEP 0x2c -#define INTERLACEMASK 0x40 -#define COLORMAPMASK 0x80 -#define False 0 -#define True 1 +#define NEXTBYTE (*ptr++) + +#define IMAGESEP 0x2c +#define INTERLACEMASK 0x40 +#define COLORMAPMASK 0x80 -WORD iWIDE,iHIGH,eWIDE,eHIGH,expand,numcols,strip,nostrip; +WORD iWIDE, iHIGH, eWIDE, eHIGH, expand, numcols, strip, nostrip; unsigned long cols[256]; -char *cmd; +char *cmd; FILE *fp; -static int BitOffset = 0, /* Bit Offset of next code */ -XC = 0, YC = 0, /* Output X and Y coords of current pixel */ -Pass = 0, /* Used by output routine if WORDerlaced pic */ -OutCount = 0, /* Decompressor output 'stack count' */ -IWidth, IHeight, /* image dimensions */ -BytesPerScanline, /* Bytes per scanline in output raster */ -CodeSize, /* Code size, read from GIF header */ -InitCodeSize, /* Starting code size, used during Clear */ -Code, /* Value returned by ReadCode */ -MaxCode, /* limiting value for current code size */ -ClearCode, /* GIF clear code */ -EOFCode, /* GIF end-of-information code */ -CurCode, OldCode, InCode, /* Decompressor variables */ -FirstFree, /* First free code, generated per GIF spec */ -FreeCode, /* Decompressor, next free slot in hash table */ -FinChar, /* Decompressor variable */ -DataMask, /* AND mask for data size */ -ReadMask; /* Code AND mask for current code size */ +static int + BitOffset = 0, /* Bit Offset of next code */ + XC = 0, YC = 0, /* Output X and Y coords of current pixel */ + Pass = 0, /* Used by output routine if WORDerlaced pic */ + OutCount = 0, /* Decompressor output 'stack count' */ + IWidth, IHeight, /* image dimensions */ + BytesPerScanline, /* Bytes per scanline in output raster */ + CodeSize, /* Code size, read from GIF header */ + InitCodeSize, /* Starting code size, used during Clear */ + Code, /* Value returned by ReadCode */ + MaxCode, /* limiting value for current code size */ + ClearCode, /* GIF clear code */ + EOFCode, /* GIF end-of-information code */ + CurCode, OldCode, InCode, /* Decompressor variables */ + FirstFree, /* First free code, generated per GIF spec */ + FreeCode, /* Decompressor, next free slot in hash table */ + FinChar, /* Decompressor variable */ + DataMask, /* AND mask for data size */ + ReadMask; /* Code AND mask for current code size */ /*MODIFICATIONS*/ BYTE tempbyte[10]; @@ -43,10 +48,9 @@ WORD ImageCount = 0; boolean Interlace, HasColormap; - -BYTE *Image; /* The result array */ -BYTE *RawGIF; /* The heap array to hold it, raw */ -BYTE *Raster; /* The raster data stream, unblocked */ +BYTE *Image; /* The result array */ +BYTE *RawGIF; /* The heap array to hold it, raw */ +BYTE *Raster; /* The raster data stream, unblocked */ /* The hash table used by the decompressor */ @@ -61,233 +65,246 @@ int OutCode[1025]; int numused; -/* Fetch the next code from the raster data stream. The codes can be -* any length from 3 to 12 bits, packed WORDo 8-bit BYTEs, so we have to -* maWORDain our location in the Raster array as a BIT Offset. We compute -* the BYTE Offset WORDo the raster array by dividing this by 8, pick up -* three BYTEs, compute the bit Offset WORDo our 24-bit chunk, shift to -* bring the desired code to the bottom, then mask it off and return it. -*/ -static int ReadCode(void) +/* + * Fetch the next code from the raster data stream. The codes can be any + * length from 3 to 12 bits, packed WORDo 8-bit BYTEs, so we have to maWORDain + * our location in the Raster array as a BIT Offset. We compute the BYTE + * Offset WORDo the raster array by dividing this by 8, pick up three BYTEs, + * compute the bit Offset WORDo our 24-bit chunk, shift to bring the desired + * code to the bottom, then mask it off and return it. + */ +static int +ReadCode(void) { - int RawCode, ByteOffset; - + int RawCode, ByteOffset; + ByteOffset = BitOffset / 8; RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]); + if (CodeSize >= 8) - RawCode += (0x10000 * Raster[ByteOffset + 2]); + RawCode += (0x10000 * Raster[ByteOffset + 2]); + RawCode >>= (BitOffset % 8); BitOffset += CodeSize; - return(RawCode & ReadMask); + return (RawCode & ReadMask); } - -static void AddToPixel(BYTE Index) +static void +AddToPixel(BYTE Index) { if (YC<IHeight) - *(Image + YC * BytesPerScanline + XC) = Index; - + *(Image + YC * BytesPerScanline + XC) = Index; - - /* Update the X-coordinate, and if it overflows, update the Y-coordinate */ + + + /* Update the X-coordinate, and if it overflows, update the + * Y-coordinate */ if (++XC == IWidth) { - - /* If a non-WORDerlaced picture, just increment YC to the next scan line. - * If it's WORDerlaced, deal with the WORDerlace as described in the GIF - * spec. Put the decoded scan line out to the screen if we haven't gone - * past the bottom of it. - */ - - XC = 0; - if (!Interlace) YC++; - else { - switch (Pass) { - case 0: - YC += 8; - if (YC >= IHeight) { - Pass++; - YC = 4; - } - break; - case 1: - YC += 8; - if (YC >= IHeight) { - Pass++; - YC = 2; - } - break; - - case 2: - YC += 4; - if (YC >= IHeight) { - Pass++; - YC = 1; - } - break; - case 3: - YC += 2; - break; - default: - break; - } - } + /* + * If a non-WORDerlaced picture, just increment YC to the next scan + * line. If it's WORDerlaced, deal with the WORDerlace as described + * in the GIF spec. Put the decoded scan line out to the screen if we + * haven't gone past the bottom of it. + */ + XC = 0; + + if (!Interlace) { + YC++; + } else { + switch (Pass) { + case 0: + YC += 8; + + if (YC >= IHeight) { + Pass++; + YC = 4; + } + + break; + case 1: + YC += 8; + + if (YC >= IHeight) { + Pass++; + YC = 2; + } + + break; + case 2: + YC += 4; + + if (YC >= IHeight) { + Pass++; + YC = 1; + } + + break; + case 3: + YC += 2; + break; + default: + break; + } + } } } /* Main routine. Convert a GIF image to an HDF image */ -BYTE* Decompress(GifImageDesc , GifHead) -GIFIMAGEDESC *GifImageDesc; -GIFHEAD *GifHead; +BYTE * +Decompress(GIFIMAGEDESC *GifImageDesc, GIFHEAD *GifHead) { - int i; - - XC = 0; - YC = 0; - Pass = 0; - OutCount = 0; - BitOffset = 0; - - DataMask = (WORD)((1L << ((GifHead->PackedField & 0x07) +1)) -1); - Raster = GifImageDesc->GIFImage; - - - /* Check for image seperator */ - - /* Now read in values from the image descriptor */ - IWidth = GifImageDesc->ImageWidth; - IHeight = GifImageDesc->ImageHeight; - Interlace = GifImageDesc->PackedField & 0x40; - - /* Note that I ignore the possible existence of a local color map. - * I'm told there aren't many files around that use them, and the spec - * says it's defined for future use. This could lead to an error - * reading some files. - */ - - /* Start reading the raster data. First we get the WORDial code size - * and compute decompressor constant values, based on this code size. - */ - - CodeSize = GifImageDesc->CodeSize; - ClearCode = (1 << CodeSize); - EOFCode = ClearCode + 1; - FreeCode = FirstFree = ClearCode + 2; - - /* The GIF spec has it that the code size is the code size used to - * compute the above values is the code size given in the file, but the - * code size used in compression/decompression is the code size given in - * the file plus one. (thus the ++). - */ - - CodeSize++; - InitCodeSize = CodeSize; - MaxCode = (1 << CodeSize); - ReadMask = MaxCode - 1; - - /* Read the raster data. Here we just transpose it from the GIF array - * to the Raster array, turning it from a series of blocks WORDo one long - * data stream, which makes life much easier for ReadCode(). - */ - - - - /* free(RawGIF); We're not done just yet - change made */ - - /* Allocate the Image */ - - if (!(Image = (BYTE *)malloc((size_t)IWidth*(size_t)IHeight))) { - printf("Out of memory"); - exit(-1); - } - - BytesPerScanline = IWidth; - - /* Decompress the file, continuing until you see the GIF EOF code. - * One obvious enhancement is to add checking for corrupt files here. - */ - - Code = ReadCode(); - while (Code != EOFCode) { - - /* Clear code sets everything back to its initial value, then reads the - * immediately subsequent code as uncompressed data. - */ - - if (Code == ClearCode) { - CodeSize = InitCodeSize; - MaxCode = (1 << CodeSize); - ReadMask = MaxCode - 1; - FreeCode = FirstFree; - CurCode = OldCode = Code = ReadCode(); - FinChar = CurCode & DataMask; - AddToPixel(FinChar); - } - else { - - /* If not a clear code, then must be data: save same as CurCode and InCode */ - - CurCode = InCode = Code; - - /* If greater or equal to FreeCode, not in the hash table yet; - * repeat the last character decoded - */ - - if (CurCode >= FreeCode) { - CurCode = OldCode; - OutCode[OutCount++] = FinChar; - } - - /* Unless this code is raw data, pursue the chain poWORDed to by CurCode - * through the hash table to its end; each code in the chain puts its - * associated output code on the output queue. - */ - - while (CurCode > DataMask) { - if (OutCount > 1024) { - /*return error message*/ - } - OutCode[OutCount++] = Suffix[CurCode]; - CurCode = Prefix[CurCode]; - } - - /* The last code in the chain is treated as raw data. */ - - FinChar = CurCode & DataMask; - OutCode[OutCount++] = FinChar; - - /* Now we put the data out to the Output routine. - * It's been stacked LIFO, so deal with it that way... - */ - - for (i = OutCount - 1; i >= 0; i--) - AddToPixel(OutCode[i]); - OutCount = 0; - - /* Build the hash table on-the-fly. No table is stored in the file. */ - - Prefix[FreeCode] = OldCode; - Suffix[FreeCode] = FinChar; - OldCode = InCode; - - /* PoWORD to the next slot in the table. If we exceed the current - * MaxCode value, increment the code size unless it's already 12. If it - * is, do nothing: the next code decompressed better be CLEAR - */ - - FreeCode++; - if (FreeCode >= MaxCode) { - if (CodeSize < 12) { - CodeSize++; - MaxCode *= 2; - ReadMask = (1 << CodeSize) - 1; - } - } - } - Code = ReadCode(); - } - - return Image; -} + int i; + + XC = 0; + YC = 0; + Pass = 0; + OutCount = 0; + BitOffset = 0; + + DataMask = (WORD)((1L << ((GifHead->PackedField & 0x07) +1)) -1); + Raster = GifImageDesc->GIFImage; + + /* Check for image seperator */ + + /* Now read in values from the image descriptor */ + IWidth = GifImageDesc->ImageWidth; + IHeight = GifImageDesc->ImageHeight; + Interlace = GifImageDesc->PackedField & 0x40; + + /* + * Note that I ignore the possible existence of a local color map. I'm + * told there aren't many files around that use them, and the spec says + * it's defined for future use. This could lead to an error reading some + * files. + */ + + /* + * Start reading the raster data. First we get the WORDial code size and + * compute decompressor constant values, based on this code size. + */ + + CodeSize = GifImageDesc->CodeSize; + ClearCode = (1 << CodeSize); + EOFCode = ClearCode + 1; + FreeCode = FirstFree = ClearCode + 2; + + /* + * The GIF spec has it that the code size is the code size used to compute + * the above values is the code size given in the file, but the code size + * used in compression/decompression is the code size given in the file + * plus one. (thus the ++). + */ + + CodeSize++; + InitCodeSize = CodeSize; + MaxCode = (1 << CodeSize); + ReadMask = MaxCode - 1; + + /* + * Read the raster data. Here we just transpose it from the GIF array to + * the Raster array, turning it from a series of blocks WORDo one long + * data stream, which makes life much easier for ReadCode(). + */ + + /* Allocate the Image */ + + if (!(Image = (BYTE *)malloc((size_t)IWidth*(size_t)IHeight))) { + printf("Out of memory"); + exit(-1); + } + + BytesPerScanline = IWidth; + + /* + * Decompress the file, continuing until you see the GIF EOF code. One + * obvious enhancement is to add checking for corrupt files here. + */ + + Code = ReadCode(); + + while (Code != EOFCode) { + /* + * Clear code sets everything back to its initial value, then reads + * the immediately subsequent code as uncompressed data. + */ + if (Code == ClearCode) { + CodeSize = InitCodeSize; + MaxCode = (1 << CodeSize); + ReadMask = MaxCode - 1; + FreeCode = FirstFree; + CurCode = OldCode = Code = ReadCode(); + FinChar = CurCode & DataMask; + AddToPixel(FinChar); + } else { + /* + * If not a clear code, then must be data: save same as CurCode + * and InCode + */ + CurCode = InCode = Code; + /* + * If greater or equal to FreeCode, not in the hash table yet; + * repeat the last character decoded + */ + if (CurCode >= FreeCode) { + CurCode = OldCode; + OutCode[OutCount++] = FinChar; + } + /* + * Unless this code is raw data, pursue the chain poWORDed to by + * CurCode through the hash table to its end; each code in the + * chain puts its associated output code on the output queue. + */ + while (CurCode > DataMask) { + if (OutCount > 1024) { + /*return error message*/ + } + + OutCode[OutCount++] = Suffix[CurCode]; + CurCode = Prefix[CurCode]; + } + + /* The last code in the chain is treated as raw data. */ + FinChar = CurCode & DataMask; + OutCode[OutCount++] = FinChar; + + /* + * Now we put the data out to the Output routine. It's been + * stacked LIFO, so deal with it that way... + */ + for (i = OutCount - 1; i >= 0; i--) + AddToPixel(OutCode[i]); + + OutCount = 0; + + /* + * Build the hash table on-the-fly. No table is stored in the + * file. + */ + Prefix[FreeCode] = OldCode; + Suffix[FreeCode] = FinChar; + OldCode = InCode; + + /* + * PoWORD to the next slot in the table. If we exceed the current + * MaxCode value, increment the code size unless it's already 12. + * If it is, do nothing: the next code decompressed better be + * CLEAR + */ + FreeCode++; + + if (FreeCode >= MaxCode) + if (CodeSize < 12) { + CodeSize++; + MaxCode *= 2; + ReadMask = (1 << CodeSize) - 1; + } + } + + Code = ReadCode(); + } + + return Image; +} |