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