1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 #include <stdio.h>
14 #include <stdlib.h>
15 
16 #include "gif.h"
17 
18 WORD iWIDE, iHIGH, eWIDE, eHIGH, expand, numcols, strip, nostrip;
19 unsigned long  cols[256];
20 char *cmd;
21 
22 FILE *fp;
23 
24 static WORD
25     XC = 0, YC = 0,         /* Output X and Y coords of current pixel       */
26     InitCodeSize,           /* Starting code size, used during Clear        */
27     CodeSize,               /* Code size, read from GIF header              */
28     BytesPerScanline,       /* Bytes per scanline in output raster          */
29     IWidth, IHeight;        /* image dimensions                             */
30 static int
31     BitOffset = 0,          /* Bit Offset of next code                      */
32     Pass = 0,               /* Used by output routine if WORDerlaced pic    */
33     OutCount = 0,           /* Decompressor output 'stack count'            */
34     Code,                   /* Value returned by ReadCode                   */
35     MaxCode,                /* limiting value for current code size         */
36     ClearCode,              /* GIF clear code                               */
37     EOFCode,                /* GIF end-of-information code                  */
38     CurCode, OldCode, InCode,   /* Decompressor variables                   */
39     FirstFree,              /* First free code, generated per GIF spec      */
40     FreeCode,               /* Decompressor, next free slot in hash table   */
41     FinChar,                /* Decompressor variable                        */
42     DataMask,               /* AND mask for data size                       */
43     ReadMask;               /* Code AND mask for current code size          */
44 
45 /*MODIFICATIONS*/
46 BYTE tempbyte[10];
47 BYTE * tempBYTEptr[10];
48 WORD tempint[10];
49 WORD ImageCount = 0;
50 /*END MODIFICATION*/
51 
52 boolean Interlace, HasColormap;
53 
54 BYTE *Image;                /* The result array                             */
55 BYTE *RawGIF;               /* The heap array to hold it, raw               */
56 BYTE *Raster;               /* The raster data stream, unblocked            */
57 
58 /* The hash table used by the decompressor */
59 
60 int Prefix[4096];
61 int Suffix[4096];
62 
63 /* An output array used by the decompressor */
64 
65 int OutCode[1025];
66 
67 /* The color map, read from the GIF header */
68 
69 int  numused;
70 
71 /*
72  * Fetch the next code from the raster data stream.  The codes can be any
73  * length from 3 to 12 bits, packed WORDo 8-bit BYTEs, so we have to maWORDain
74  * our location in the Raster array as a BIT Offset.  We compute the BYTE
75  * Offset WORDo the raster array by dividing this by 8, pick up three BYTEs,
76  * compute the bit Offset WORDo our 24-bit chunk, shift to bring the desired
77  * code to the bottom, then mask it off and return it.
78  */
79 static int
ReadCode(void)80 ReadCode(void)
81 {
82     int RawCode, ByteOffset;
83 
84     ByteOffset = BitOffset / 8;
85     RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
86 
87     if (CodeSize >= 8)
88         RawCode += (0x10000 * Raster[ByteOffset + 2]);
89 
90     RawCode >>= (BitOffset % 8);
91     BitOffset += (int)CodeSize;
92     return (RawCode & ReadMask);
93 }
94 
95 static void
AddToPixel(BYTE Index)96 AddToPixel(BYTE Index)
97 {
98     if (YC<IHeight)
99     *(Image + YC * BytesPerScanline + XC) = Index;
100 
101 
102 
103     /* Update the X-coordinate, and if it overflows, update the
104      * Y-coordinate */
105     if (++XC == IWidth) {
106         /*
107          * If a non-WORDerlaced picture, just increment YC to the next scan
108          * line.  If it's WORDerlaced, deal with the WORDerlace as described
109          * in the GIF spec.  Put the decoded scan line out to the screen if we
110          * haven't gone past the bottom of it.
111          */
112         XC = 0;
113 
114         if (!Interlace) {
115             YC++;
116         } else {
117             switch (Pass) {
118             case 0:
119                 YC += 8;
120 
121                 if (YC >= IHeight) {
122                     Pass++;
123                     YC = 4;
124                 }
125 
126                 break;
127             case 1:
128                 YC += 8;
129 
130                 if (YC >= IHeight) {
131                     Pass++;
132                     YC = 2;
133                 }
134 
135                 break;
136             case 2:
137                 YC += 4;
138 
139                 if (YC >= IHeight) {
140                     Pass++;
141                     YC = 1;
142                 }
143 
144                 break;
145             case 3:
146                 YC += 2;
147                 break;
148             default:
149                 break;
150             }
151         }
152     }
153 }
154 
155 /* Main routine.  Convert a GIF image to an HDF image */
156 
157 BYTE *
Decompress(GIFIMAGEDESC * GifImageDesc,GIFHEAD * GifHead)158 Decompress(GIFIMAGEDESC *GifImageDesc, GIFHEAD *GifHead)
159 {
160     int i;
161 
162     XC = 0;
163     YC = 0;
164     Pass = 0;
165     OutCount = 0;
166     BitOffset = 0;
167 
168     DataMask = (1 << ((GifHead->PackedField & 0x07) +1)) -1;
169     Raster = GifImageDesc->GIFImage;
170 
171     /* Check for image seperator */
172 
173     /* Now read in values from the image descriptor */
174     IWidth = GifImageDesc->ImageWidth;
175     IHeight = GifImageDesc->ImageHeight;
176     Interlace = GifImageDesc->PackedField & 0x40;
177 
178     /*
179      * Note that I ignore the possible existence of a local color map.  I'm
180      * told there aren't many files around that use them, and the spec says
181      * it's defined for future use.  This could lead to an error reading some
182      * files.
183      */
184 
185     /*
186      * Start reading the raster data. First we get the WORDial code size and
187      * compute decompressor constant values, based on this code size.
188      */
189 
190     CodeSize = GifImageDesc->CodeSize;
191     ClearCode = (1 << CodeSize);
192     EOFCode = ClearCode + 1;
193     FreeCode = FirstFree = ClearCode + 2;
194 
195     /*
196      * The GIF spec has it that the code size is the code size used to compute
197      * the above values is the code size given in the file, but the code size
198      * used in compression/decompression is the code size given in the file
199      * plus one. (thus the ++).
200      */
201 
202     CodeSize++;
203     InitCodeSize = CodeSize;
204     MaxCode = (1 << CodeSize);
205     ReadMask = MaxCode - 1;
206 
207     /*
208      * Read the raster data.  Here we just transpose it from the GIF array to
209      * the Raster array, turning it from a series of blocks WORDo one long
210      * data stream, which makes life much easier for ReadCode().
211      */
212 
213     /* Allocate the Image */
214 
215     if (!(Image = (BYTE *)malloc((size_t)IWidth*(size_t)IHeight))) {
216         printf("Out of memory");
217         exit(EXIT_FAILURE);
218     }
219 
220     BytesPerScanline = IWidth;
221 
222     /*
223      * Decompress the file, continuing until you see the GIF EOF code.  One
224      * obvious enhancement is to add checking for corrupt files here.
225      */
226 
227     Code = ReadCode();
228 
229     while (Code != EOFCode) {
230         /*
231          * Clear code sets everything back to its initial value, then reads
232          * the immediately subsequent code as uncompressed data.
233          */
234         if (Code == ClearCode) {
235             CodeSize = InitCodeSize;
236             MaxCode = (1 << CodeSize);
237             ReadMask = MaxCode - 1;
238             FreeCode = FirstFree;
239             CurCode = OldCode = Code = ReadCode();
240             FinChar = CurCode & DataMask;
241             AddToPixel((BYTE)FinChar);
242         } else {
243             /*
244              * If not a clear code, then must be data: save same as CurCode
245              * and InCode
246              */
247             CurCode = InCode = Code;
248 
249             /*
250              * If greater or equal to FreeCode, not in the hash table yet;
251              * repeat the last character decoded
252              */
253             if (CurCode >= FreeCode) {
254                 CurCode = OldCode;
255                 OutCode[OutCount++] = FinChar;
256             }
257 
258             /*
259              * Unless this code is raw data, pursue the chain poWORDed to by
260              * CurCode through the hash table to its end; each code in the
261              * chain puts its associated output code on the output queue.
262              */
263             while (CurCode > DataMask) {
264                 if (OutCount >= 1024) {
265                     /*return error message*/
266                 }
267 
268                 OutCode[OutCount++] = Suffix[CurCode];
269                 CurCode = Prefix[CurCode];
270             }
271 
272             /* The last code in the chain is treated as raw data. */
273             FinChar = CurCode & DataMask;
274             OutCode[OutCount++] = FinChar;
275 
276             /*
277              * Now we put the data out to the Output routine. It's been
278              * stacked LIFO, so deal with it that way...
279              */
280             for (i = OutCount - 1; i >= 0; i--)
281                 AddToPixel((BYTE)OutCode[i]);
282 
283             OutCount = 0;
284 
285             /*
286              * Build the hash table on-the-fly. No table is stored in the
287              * file.
288              */
289             Prefix[FreeCode] = OldCode;
290             Suffix[FreeCode] = FinChar;
291             OldCode = InCode;
292 
293             /*
294              * PoWORD to the next slot in the table.  If we exceed the current
295              * MaxCode value, increment the code size unless it's already 12.
296              * If it is, do nothing: the next code decompressed better be
297              * CLEAR
298              */
299             FreeCode++;
300 
301             if (FreeCode >= MaxCode)
302                 if (CodeSize < 12) {
303                     CodeSize++;
304                     MaxCode *= 2;
305                     ReadMask = (1 << CodeSize) - 1;
306                 }
307         }
308 
309         Code = ReadCode();
310     }
311 
312     return Image;
313 }
314