0
|
1 /* Synched up with: Not in FSF. */
|
|
2
|
|
3 /******************************************************************************
|
|
4 * "Gif-Lib" - Yet another gif library. *
|
|
5 * *
|
|
6 * Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 *
|
|
7 *******************************************************************************
|
|
8 * The kernel of the GIF Decoding process can be found here. *
|
|
9 *******************************************************************************
|
|
10 * History: *
|
|
11 * 16 Jun 89 - Version 1.0 by Gershon Elber. *
|
|
12 * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
|
|
13 ******************************************************************************/
|
|
14
|
16
|
15 #ifdef emacs
|
|
16 #include <config.h>
|
|
17 void *xmalloc (unsigned int size);
|
|
18 void *xrealloc (void *ptr, unsigned int size);
|
|
19 #ifdef ERROR_CHECK_MALLOC
|
|
20 void *xfree_1 (void *);
|
|
21 #define xfree xfree_1
|
|
22 #else
|
|
23 void *xfree (void *);
|
|
24 #endif
|
|
25 #endif /* emacs */
|
|
26
|
0
|
27 #ifdef __MSDOS__
|
|
28 #include <io.h>
|
|
29 #include <alloc.h>
|
|
30 #include <stdlib.h>
|
|
31 #include <sys\stat.h>
|
|
32 #else
|
|
33 #include <sys/types.h>
|
|
34 #include <sys/stat.h>
|
|
35 #endif /* __MSDOS__ */
|
|
36
|
|
37 #include <fcntl.h>
|
|
38 #include <stdio.h>
|
|
39 #include <string.h>
|
|
40
|
|
41 #include "gif_lib.h"
|
|
42 #ifndef emacs
|
|
43 #include "gif_hash.h"
|
|
44 #endif
|
|
45
|
|
46 #define PROGRAM_NAME "GIF_LIBRARY"
|
|
47
|
|
48 #define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for comment. */
|
|
49 #define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */
|
|
50 #define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1
|
|
51 #define GIF_VERSION_POS 3 /* Version first character in stamp. */
|
|
52
|
|
53 #define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
|
|
54 #define LZ_BITS 12
|
|
55
|
|
56 #define FILE_STATE_READ 0x01/* 1 write, 0 read - EGIF_LIB compatible.*/
|
|
57
|
|
58 #define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */
|
|
59 #define FIRST_CODE 4097 /* Impossible code, to signal first. */
|
|
60 #define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */
|
|
61
|
|
62 #define IS_READABLE(Private) (!(Private->FileState & FILE_STATE_READ))
|
|
63
|
|
64 typedef struct GifFilePrivateType {
|
|
65 int FileState,
|
|
66 FileHandle, /* Where all this data goes to! */
|
|
67 BitsPerPixel, /* Bits per pixel (Codes uses at list this + 1). */
|
|
68 ClearCode, /* The CLEAR LZ code. */
|
|
69 EOFCode, /* The EOF LZ code. */
|
|
70 RunningCode, /* The next code algorithm can generate. */
|
|
71 RunningBits,/* The number of bits required to represent RunningCode. */
|
|
72 MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */
|
|
73 LastCode, /* The code before the current code. */
|
|
74 CrntCode, /* Current algorithm code. */
|
|
75 StackPtr, /* For character stack (see below). */
|
|
76 CrntShiftState; /* Number of bits in CrntShiftDWord. */
|
|
77 unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */
|
|
78 long PixelCount; /* Number of pixels in image. */
|
|
79 FILE *File; /* File as stream. */
|
|
80 GifByteType Buf[256]; /* Compressed input is buffered here. */
|
|
81 GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */
|
|
82 GifByteType Suffix[LZ_MAX_CODE+1]; /* So we can trace the codes. */
|
|
83 unsigned int Prefix[LZ_MAX_CODE+1];
|
|
84 } GifFilePrivateType;
|
|
85
|
|
86 #ifndef emacs
|
|
87 #ifdef SYSV
|
|
88 static char *VersionStr =
|
|
89 "Gif library module,\t\tGershon Elber\n\
|
|
90 (C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
|
|
91 #else
|
|
92 static char *VersionStr =
|
|
93 PROGRAM_NAME
|
|
94 " IBMPC "
|
|
95 GIF_LIB_VERSION
|
|
96 " Gershon Elber, "
|
|
97 __DATE__ ", " __TIME__ "\n"
|
|
98 "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
|
|
99 #endif /* SYSV */
|
|
100 #endif /* !emacs */
|
|
101
|
|
102 extern int _GifError;
|
|
103
|
|
104 static int DGifGetWord(FILE *File, int *Word);
|
|
105 static int DGifSetupDecompress(GifFileType *GifFile);
|
|
106 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
|
|
107 int LineLen);
|
|
108 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
|
|
109 static int DGifDecompressInput(GifFilePrivateType *Private, int *Code);
|
|
110 static int DGifBufferedInput(FILE *File, GifByteType *Buf,
|
|
111 GifByteType *NextByte);
|
|
112
|
|
113 /******************************************************************************
|
|
114 * Open a new gif file for read, given by its name. *
|
|
115 * Returns GifFileType pointer dynamically allocated which serves as the gif *
|
|
116 * info record. _GifError is cleared if succesfull. *
|
|
117 ******************************************************************************/
|
|
118 GifFileType *DGifOpenFileName(const char *FileName)
|
|
119 {
|
|
120 int FileHandle;
|
|
121
|
|
122 if ((FileHandle = open(FileName, O_RDONLY
|
|
123 #ifdef __MSDOS__
|
|
124 | O_BINARY
|
|
125 #endif /* __MSDOS__ */
|
|
126 )) == -1) {
|
|
127 _GifError = D_GIF_ERR_OPEN_FAILED;
|
|
128 return NULL;
|
|
129 }
|
|
130
|
|
131 return DGifOpenFileHandle(FileHandle);
|
|
132 }
|
|
133
|
|
134 /******************************************************************************
|
|
135 * Update a new gif file, given its file handle. *
|
|
136 * Returns GifFileType pointer dynamically allocated which serves as the gif *
|
|
137 * info record. _GifError is cleared if succesfull. *
|
|
138 ******************************************************************************/
|
|
139 GifFileType *DGifOpenFileHandle(int FileHandle)
|
|
140 {
|
|
141 char Buf[GIF_STAMP_LEN+1];
|
|
142 GifFileType *GifFile;
|
|
143 GifFilePrivateType *Private;
|
|
144 FILE *f;
|
|
145
|
|
146 #ifdef __MSDOS__
|
|
147 setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
|
|
148 f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
|
|
149 setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/
|
|
150 #else
|
|
151 f = fdopen(FileHandle, "r"); /* Make it into a stream: */
|
|
152 #endif /* __MSDOS__ */
|
|
153
|
|
154 if ((GifFile = (GifFileType *) xmalloc(sizeof(GifFileType))) == NULL) {
|
|
155 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
|
|
156 return NULL;
|
|
157 }
|
|
158
|
|
159 memset(GifFile, '\0', sizeof(GifFileType));
|
|
160
|
|
161 if ((Private = (GifFilePrivateType *) xmalloc(sizeof(GifFilePrivateType)))
|
|
162 == NULL) {
|
|
163 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
|
|
164 xfree((char *) GifFile);
|
|
165 return NULL;
|
|
166 }
|
|
167 GifFile->Private = (VoidPtr) Private;
|
|
168 Private->FileHandle = FileHandle;
|
|
169 Private->File = f;
|
|
170 Private->FileState = 0; /* Make sure bit 0 = 0 (File open for read). */
|
|
171
|
|
172 /* Lets see if this is a GIF file: */
|
|
173 if (fread(Buf, 1, GIF_STAMP_LEN, Private->File) != GIF_STAMP_LEN) {
|
|
174 _GifError = D_GIF_ERR_READ_FAILED;
|
|
175 xfree((char *) Private);
|
|
176 xfree((char *) GifFile);
|
|
177 return NULL;
|
|
178 }
|
|
179
|
|
180 /* The GIF Version number is ignored at this time. Maybe we should do */
|
|
181 /* something more useful with it. */
|
|
182 Buf[GIF_STAMP_LEN] = 0;
|
|
183 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
|
|
184 _GifError = D_GIF_ERR_NOT_GIF_FILE;
|
|
185 xfree((char *) Private);
|
|
186 xfree((char *) GifFile);
|
|
187 return NULL;
|
|
188 }
|
|
189
|
|
190 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
|
|
191 xfree((char *) Private);
|
|
192 xfree((char *) GifFile);
|
|
193 return NULL;
|
|
194 }
|
|
195
|
|
196 _GifError = 0;
|
|
197
|
|
198 return GifFile;
|
|
199 }
|
|
200
|
|
201 /******************************************************************************
|
|
202 * This routine should be called before any other DGif calls. Note that *
|
|
203 * this routine is called automatically from DGif file open routines. *
|
|
204 ******************************************************************************/
|
|
205 int DGifGetScreenDesc(GifFileType *GifFile)
|
|
206 {
|
|
207 int i, BitsPerPixel;
|
|
208 GifByteType Buf[3];
|
|
209 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
210
|
|
211 if (!IS_READABLE(Private)) {
|
|
212 /* This file was NOT open for reading: */
|
|
213 _GifError = D_GIF_ERR_NOT_READABLE;
|
|
214 return GIF_ERROR;
|
|
215 }
|
|
216
|
|
217 /* Put the screen descriptor into the file: */
|
|
218 if (DGifGetWord(Private->File, &GifFile->SWidth) == GIF_ERROR ||
|
|
219 DGifGetWord(Private->File, &GifFile->SHeight) == GIF_ERROR)
|
|
220 return GIF_ERROR;
|
|
221
|
|
222 if (fread(Buf, 1, 3, Private->File) != 3) {
|
|
223 _GifError = D_GIF_ERR_READ_FAILED;
|
|
224 return GIF_ERROR;
|
|
225 }
|
|
226 GifFile->SColorResolution = ((int) ((Buf[0] & 0x70) + 1) >> 4) + 1;
|
|
227 BitsPerPixel = (Buf[0] & 0x07) + 1;
|
|
228 GifFile->SBackGroundColor = Buf[1];
|
|
229 if (Buf[0] & 0x80) { /* Do we have global color map? */
|
|
230
|
|
231 GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
|
|
232
|
|
233 /* Get the global color map: */
|
|
234 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
|
|
235 if (fread(Buf, 1, 3, Private->File) != 3) {
|
|
236 _GifError = D_GIF_ERR_READ_FAILED;
|
|
237 return GIF_ERROR;
|
|
238 }
|
|
239 GifFile->SColorMap->Colors[i].Red = Buf[0];
|
|
240 GifFile->SColorMap->Colors[i].Green = Buf[1];
|
|
241 GifFile->SColorMap->Colors[i].Blue = Buf[2];
|
|
242 }
|
|
243 }
|
|
244
|
|
245 return GIF_OK;
|
|
246 }
|
|
247
|
|
248 /******************************************************************************
|
|
249 * This routine should be called before any attemp to read an image. *
|
|
250 ******************************************************************************/
|
|
251 int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
|
|
252 {
|
|
253 GifByteType Buf;
|
|
254 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
255
|
|
256 if (!IS_READABLE(Private)) {
|
|
257 /* This file was NOT open for reading: */
|
|
258 _GifError = D_GIF_ERR_NOT_READABLE;
|
|
259 return GIF_ERROR;
|
|
260 }
|
|
261
|
|
262 if (fread(&Buf, 1, 1, Private->File) != 1) {
|
|
263 _GifError = D_GIF_ERR_READ_FAILED;
|
|
264 return GIF_ERROR;
|
|
265 }
|
|
266
|
|
267 switch (Buf) {
|
|
268 case ',':
|
|
269 *Type = IMAGE_DESC_RECORD_TYPE;
|
|
270 break;
|
|
271 case '!':
|
|
272 *Type = EXTENSION_RECORD_TYPE;
|
|
273 break;
|
|
274 case ';':
|
|
275 *Type = TERMINATE_RECORD_TYPE;
|
|
276 break;
|
|
277 default:
|
|
278 *Type = UNDEFINED_RECORD_TYPE;
|
|
279 _GifError = D_GIF_ERR_WRONG_RECORD;
|
|
280 return GIF_ERROR;
|
|
281 }
|
|
282
|
|
283 return GIF_OK;
|
|
284 }
|
|
285
|
|
286 /******************************************************************************
|
|
287 * This routine should be called before any attemp to read an image. *
|
|
288 * Note it is assumed the Image desc. header (',') has been read. *
|
|
289 ******************************************************************************/
|
|
290 int DGifGetImageDesc(GifFileType *GifFile)
|
|
291 {
|
|
292 int i, BitsPerPixel;
|
|
293 GifByteType Buf[3];
|
|
294 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
295
|
|
296 if (!IS_READABLE(Private)) {
|
|
297 /* This file was NOT open for reading: */
|
|
298 _GifError = D_GIF_ERR_NOT_READABLE;
|
|
299 return GIF_ERROR;
|
|
300 }
|
|
301
|
|
302 if (DGifGetWord(Private->File, &GifFile->Image.Left) == GIF_ERROR ||
|
|
303 DGifGetWord(Private->File, &GifFile->Image.Top) == GIF_ERROR ||
|
|
304 DGifGetWord(Private->File, &GifFile->Image.Width) == GIF_ERROR ||
|
|
305 DGifGetWord(Private->File, &GifFile->Image.Height) == GIF_ERROR)
|
|
306 return GIF_ERROR;
|
|
307 if (fread(Buf, 1, 1, Private->File) != 1) {
|
|
308 _GifError = D_GIF_ERR_READ_FAILED;
|
|
309 return GIF_ERROR;
|
|
310 }
|
|
311 BitsPerPixel = (Buf[0] & 0x07) + 1;
|
|
312 GifFile->Image.Interlace = (Buf[0] & 0x40);
|
|
313 if (Buf[0] & 0x80) { /* Does this image have local color map? */
|
|
314
|
|
315 if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
|
|
316 FreeMapObject(GifFile->Image.ColorMap);
|
|
317
|
|
318 GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
|
|
319
|
|
320 /* Get the image local color map: */
|
|
321 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
|
|
322 if (fread(Buf, 1, 3, Private->File) != 3) {
|
|
323 _GifError = D_GIF_ERR_READ_FAILED;
|
|
324 return GIF_ERROR;
|
|
325 }
|
|
326 GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
|
|
327 GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
|
|
328 GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
|
|
329 }
|
|
330 }
|
|
331
|
|
332 if (GifFile->SavedImages) {
|
|
333 SavedImage *sp;
|
|
334
|
|
335 if ((GifFile->SavedImages = (SavedImage *)xrealloc(GifFile->SavedImages,
|
|
336 sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) {
|
|
337 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
|
|
338 return GIF_ERROR;
|
|
339 }
|
|
340
|
|
341 sp = &GifFile->SavedImages[GifFile->ImageCount];
|
|
342 memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
|
|
343 if (GifFile->Image.ColorMap)
|
|
344 {
|
|
345 sp->ImageDesc.ColorMap =
|
|
346 MakeMapObject (GifFile->Image.ColorMap->ColorCount,
|
|
347 GifFile->Image.ColorMap->Colors);
|
|
348 }
|
|
349 sp->RasterBits = (GifPixelType *)NULL;
|
|
350 sp->ExtensionBlockCount = 0;
|
|
351 sp->ExtensionBlocks = (ExtensionBlock *)NULL;
|
|
352 }
|
|
353
|
|
354 GifFile->ImageCount++;
|
|
355
|
|
356 Private->PixelCount = (long) GifFile->Image.Width *
|
|
357 (long) GifFile->Image.Height;
|
|
358
|
|
359 DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
|
|
360
|
|
361 return GIF_OK;
|
|
362 }
|
|
363
|
|
364 /******************************************************************************
|
|
365 * Get one full scanned line (Line) of length LineLen from GIF file. *
|
|
366 ******************************************************************************/
|
|
367 int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
|
|
368 {
|
|
369 GifByteType *Dummy;
|
|
370 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
371
|
|
372 if (!IS_READABLE(Private)) {
|
|
373 /* This file was NOT open for reading: */
|
|
374 _GifError = D_GIF_ERR_NOT_READABLE;
|
|
375 return GIF_ERROR;
|
|
376 }
|
|
377
|
|
378 if (!LineLen) LineLen = GifFile->Image.Width;
|
|
379
|
|
380 #ifdef __MSDOS__
|
|
381 if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
|
|
382 #else
|
|
383 if ((unsigned) (Private->PixelCount -= LineLen) > 0xffff0000) {
|
|
384 #endif /* __MSDOS__ */
|
|
385 _GifError = D_GIF_ERR_DATA_TOO_BIG;
|
|
386 return GIF_ERROR;
|
|
387 }
|
|
388
|
|
389 if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
|
|
390 if (Private->PixelCount == 0) {
|
|
391 /* We probably would not be called any more, so lets clean */
|
|
392 /* everything before we return: need to flush out all rest of */
|
|
393 /* image until empty block (size 0) detected. We use GetCodeNext.*/
|
|
394 do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
|
|
395 return GIF_ERROR;
|
|
396 while (Dummy != NULL);
|
|
397 }
|
|
398 return GIF_OK;
|
|
399 }
|
|
400 else
|
|
401 return GIF_ERROR;
|
|
402 }
|
|
403
|
|
404 /******************************************************************************
|
|
405 * Put one pixel (Pixel) into GIF file. *
|
|
406 ******************************************************************************/
|
|
407 int DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
|
|
408 {
|
|
409 GifByteType *Dummy;
|
|
410 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
411
|
|
412 if (!IS_READABLE(Private)) {
|
|
413 /* This file was NOT open for reading: */
|
|
414 _GifError = D_GIF_ERR_NOT_READABLE;
|
|
415 return GIF_ERROR;
|
|
416 }
|
|
417
|
|
418 #ifdef __MSDOS__
|
|
419 if (--Private->PixelCount > 0xffff0000UL)
|
|
420 #else
|
|
421 if ((unsigned) --Private->PixelCount > 0xffff0000)
|
|
422 #endif /* __MSDOS__ */
|
|
423 {
|
|
424 _GifError = D_GIF_ERR_DATA_TOO_BIG;
|
|
425 return GIF_ERROR;
|
|
426 }
|
|
427
|
|
428 if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
|
|
429 if (Private->PixelCount == 0) {
|
|
430 /* We probably would not be called any more, so lets clean */
|
|
431 /* everything before we return: need to flush out all rest of */
|
|
432 /* image until empty block (size 0) detected. We use GetCodeNext.*/
|
|
433 do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
|
|
434 return GIF_ERROR;
|
|
435 while (Dummy != NULL);
|
|
436 }
|
|
437 return GIF_OK;
|
|
438 }
|
|
439 else
|
|
440 return GIF_ERROR;
|
|
441 }
|
|
442
|
|
443 /******************************************************************************
|
|
444 * Get an extension block (see GIF manual) from gif file. This routine only *
|
|
445 * returns the first data block, and DGifGetExtensionNext shouldbe called *
|
|
446 * after this one until NULL extension is returned. *
|
|
447 * The Extension should NOT be freed by the user (not dynamically allocated).*
|
|
448 * Note it is assumed the Extension desc. header ('!') has been read. *
|
|
449 ******************************************************************************/
|
|
450 int DGifGetExtension(GifFileType *GifFile, int *ExtCode,
|
|
451 GifByteType **Extension)
|
|
452 {
|
|
453 GifByteType Buf;
|
|
454 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
455
|
|
456 if (!IS_READABLE(Private)) {
|
|
457 /* This file was NOT open for reading: */
|
|
458 _GifError = D_GIF_ERR_NOT_READABLE;
|
|
459 return GIF_ERROR;
|
|
460 }
|
|
461
|
|
462 if (fread(&Buf, 1, 1, Private->File) != 1) {
|
|
463 _GifError = D_GIF_ERR_READ_FAILED;
|
|
464 return GIF_ERROR;
|
|
465 }
|
|
466 *ExtCode = Buf;
|
|
467
|
|
468 return DGifGetExtensionNext(GifFile, Extension);
|
|
469 }
|
|
470
|
|
471 /******************************************************************************
|
|
472 * Get a following extension block (see GIF manual) from gif file. This *
|
|
473 * routine sould be called until NULL Extension is returned. *
|
|
474 * The Extension should NOT be freed by the user (not dynamically allocated).*
|
|
475 ******************************************************************************/
|
|
476 int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension)
|
|
477 {
|
|
478 GifByteType Buf;
|
|
479 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
480
|
|
481 if (fread(&Buf, 1, 1, Private->File) != 1) {
|
|
482 _GifError = D_GIF_ERR_READ_FAILED;
|
|
483 return GIF_ERROR;
|
|
484 }
|
|
485 if (Buf > 0) {
|
|
486 *Extension = Private->Buf; /* Use private unused buffer. */
|
|
487 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
|
|
488 if (fread(&((*Extension)[1]), 1, Buf, Private->File) != Buf) {
|
|
489 _GifError = D_GIF_ERR_READ_FAILED;
|
|
490 return GIF_ERROR;
|
|
491 }
|
|
492 }
|
|
493 else
|
|
494 *Extension = NULL;
|
|
495
|
|
496 return GIF_OK;
|
|
497 }
|
|
498
|
|
499 /******************************************************************************
|
|
500 * This routine should be called last, to close the GIF file. *
|
|
501 ******************************************************************************/
|
|
502 int DGifCloseFile(GifFileType *GifFile)
|
|
503 {
|
|
504 GifFilePrivateType *Private;
|
|
505 FILE *File;
|
|
506
|
|
507 if (GifFile == NULL) return GIF_ERROR;
|
|
508
|
|
509 Private = (GifFilePrivateType *) GifFile->Private;
|
|
510
|
|
511 if (!IS_READABLE(Private)) {
|
|
512 /* This file was NOT open for reading: */
|
|
513 _GifError = D_GIF_ERR_NOT_READABLE;
|
|
514 return GIF_ERROR;
|
|
515 }
|
|
516
|
|
517 File = Private->File;
|
|
518
|
|
519 if (GifFile->Image.ColorMap)
|
|
520 {
|
|
521 FreeMapObject(GifFile->Image.ColorMap);
|
|
522 GifFile->Image.ColorMap = 0;
|
|
523 }
|
|
524 if (GifFile->SColorMap)
|
|
525 {
|
|
526 FreeMapObject(GifFile->SColorMap);
|
|
527 GifFile->SColorMap = 0;
|
|
528 }
|
|
529 if (Private)
|
|
530 {
|
|
531 xfree((char *) Private);
|
|
532 GifFile->Private = 0;
|
|
533 }
|
|
534 if (GifFile->SavedImages)
|
|
535 {
|
|
536 FreeSavedImages(GifFile);
|
|
537 GifFile->SavedImages = 0;
|
|
538 }
|
|
539 xfree(GifFile);
|
|
540
|
|
541 if (fclose(File) != 0) {
|
|
542 _GifError = D_GIF_ERR_CLOSE_FAILED;
|
|
543 return GIF_ERROR;
|
|
544 }
|
|
545 return GIF_OK;
|
|
546 }
|
|
547
|
|
548 /******************************************************************************
|
|
549 * Get 2 bytes (word) from the given file: *
|
|
550 ******************************************************************************/
|
|
551 static int DGifGetWord(FILE *File, int *Word)
|
|
552 {
|
|
553 unsigned char c[2];
|
|
554
|
|
555 if (fread(c, 1, 2, File) != 2) {
|
|
556 _GifError = D_GIF_ERR_READ_FAILED;
|
|
557 return GIF_ERROR;
|
|
558 }
|
|
559
|
|
560 *Word = (((unsigned int) c[1]) << 8) + c[0];
|
|
561 return GIF_OK;
|
|
562 }
|
|
563
|
|
564 /******************************************************************************
|
|
565 * Get the image code in compressed form. his routine can be called if the *
|
|
566 * information needed to be piped out as is. Obviously this is much faster *
|
|
567 * than decoding and encoding again. This routine should be followed by calls *
|
|
568 * to DGifGetCodeNext, until NULL block is returned. *
|
|
569 * The block should NOT be freed by the user (not dynamically allocated). *
|
|
570 ******************************************************************************/
|
|
571 int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
|
|
572 {
|
|
573 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
574
|
|
575 if (!IS_READABLE(Private)) {
|
|
576 /* This file was NOT open for reading: */
|
|
577 _GifError = D_GIF_ERR_NOT_READABLE;
|
|
578 return GIF_ERROR;
|
|
579 }
|
|
580
|
|
581 *CodeSize = Private->BitsPerPixel;
|
|
582
|
|
583 return DGifGetCodeNext(GifFile, CodeBlock);
|
|
584 }
|
|
585
|
|
586 /******************************************************************************
|
|
587 * Continue to get the image code in compressed form. This routine should be *
|
|
588 * called until NULL block is returned. *
|
|
589 * The block should NOT be freed by the user (not dynamically allocated). *
|
|
590 ******************************************************************************/
|
|
591 int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
|
|
592 {
|
|
593 GifByteType Buf;
|
|
594 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
595
|
|
596 if (fread(&Buf, 1, 1, Private->File) != 1) {
|
|
597 _GifError = D_GIF_ERR_READ_FAILED;
|
|
598 return GIF_ERROR;
|
|
599 }
|
|
600
|
|
601 if (Buf > 0) {
|
|
602 *CodeBlock = Private->Buf; /* Use private unused buffer. */
|
|
603 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
|
|
604 if (fread(&((*CodeBlock)[1]), 1, Buf, Private->File) != Buf) {
|
|
605 _GifError = D_GIF_ERR_READ_FAILED;
|
|
606 return GIF_ERROR;
|
|
607 }
|
|
608 }
|
|
609 else {
|
|
610 *CodeBlock = NULL;
|
|
611 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
|
|
612 Private->PixelCount = 0; /* And local info. indicate image read. */
|
|
613 }
|
|
614
|
|
615 return GIF_OK;
|
|
616 }
|
|
617
|
|
618 /******************************************************************************
|
|
619 * Setup the LZ decompression for this image: *
|
|
620 ******************************************************************************/
|
|
621 static int DGifSetupDecompress(GifFileType *GifFile)
|
|
622 {
|
|
623 int i, BitsPerPixel;
|
|
624 GifByteType CodeSize;
|
|
625 unsigned int *Prefix;
|
|
626 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
627
|
|
628 fread(&CodeSize, 1, 1, Private->File); /* Read Code size from file. */
|
|
629 BitsPerPixel = CodeSize;
|
|
630
|
|
631 Private->Buf[0] = 0; /* Input Buffer empty. */
|
|
632 Private->BitsPerPixel = BitsPerPixel;
|
|
633 Private->ClearCode = (1 << BitsPerPixel);
|
|
634 Private->EOFCode = Private->ClearCode + 1;
|
|
635 Private->RunningCode = Private->EOFCode + 1;
|
|
636 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
|
|
637 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
|
|
638 Private->StackPtr = 0; /* No pixels on the pixel stack. */
|
|
639 Private->LastCode = NO_SUCH_CODE;
|
|
640 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
|
|
641 Private->CrntShiftDWord = 0;
|
|
642
|
|
643 Prefix = Private->Prefix;
|
|
644 for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
|
|
645
|
|
646 return GIF_OK;
|
|
647 }
|
|
648
|
|
649 /******************************************************************************
|
|
650 * The LZ decompression routine: *
|
|
651 * This version decompress the given gif file into Line of length LineLen. *
|
|
652 * This routine can be called few times (one per scan line, for example), in *
|
|
653 * order the complete the whole image. *
|
|
654 ******************************************************************************/
|
|
655 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
|
|
656 int LineLen)
|
|
657 {
|
|
658 int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
|
|
659 GifByteType *Stack, *Suffix;
|
|
660 unsigned int *Prefix;
|
|
661 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
662
|
|
663 StackPtr = Private->StackPtr;
|
|
664 Prefix = Private->Prefix;
|
|
665 Suffix = Private->Suffix;
|
|
666 Stack = Private->Stack;
|
|
667 EOFCode = Private->EOFCode;
|
|
668 ClearCode = Private->ClearCode;
|
|
669 LastCode = Private->LastCode;
|
|
670
|
|
671 if (StackPtr != 0) {
|
|
672 /* Let pop the stack off before continueing to read the gif file: */
|
|
673 while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
|
|
674 }
|
|
675
|
|
676 while (i < LineLen) { /* Decode LineLen items. */
|
|
677 if (DGifDecompressInput(Private, &CrntCode) == GIF_ERROR)
|
|
678 return GIF_ERROR;
|
|
679
|
|
680 if (CrntCode == EOFCode) {
|
|
681 /* Note however that usually we will not be here as we will stop */
|
|
682 /* decoding as soon as we got all the pixel, or EOF code will */
|
|
683 /* not be read at all, and DGifGetLine/Pixel clean everything. */
|
|
684 if (i != LineLen - 1 || Private->PixelCount != 0) {
|
|
685 _GifError = D_GIF_ERR_EOF_TOO_SOON;
|
|
686 return GIF_ERROR;
|
|
687 }
|
|
688 i++;
|
|
689 }
|
|
690 else if (CrntCode == ClearCode) {
|
|
691 /* We need to start over again: */
|
|
692 for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
|
|
693 Private->RunningCode = Private->EOFCode + 1;
|
|
694 Private->RunningBits = Private->BitsPerPixel + 1;
|
|
695 Private->MaxCode1 = 1 << Private->RunningBits;
|
|
696 LastCode = Private->LastCode = NO_SUCH_CODE;
|
|
697 }
|
|
698 else {
|
|
699 /* Its regular code - if in pixel range simply add it to output */
|
|
700 /* stream, otherwise trace to codes linked list until the prefix */
|
|
701 /* is in pixel range: */
|
|
702 if (CrntCode < ClearCode) {
|
|
703 /* This is simple - its pixel scalar, so add it to output: */
|
|
704 Line[i++] = CrntCode;
|
|
705 }
|
|
706 else {
|
|
707 /* Its a code to needed to be traced: trace the linked list */
|
|
708 /* until the prefix is a pixel, while pushing the suffix */
|
|
709 /* pixels on our stack. If we done, pop the stack in reverse */
|
|
710 /* (thats what stack is good for!) order to output. */
|
|
711 if (Prefix[CrntCode] == NO_SUCH_CODE) {
|
|
712 /* Only allowed if CrntCode is exactly the running code: */
|
|
713 /* In that case CrntCode = XXXCode, CrntCode or the */
|
|
714 /* prefix code is last code and the suffix char is */
|
|
715 /* exactly the prefix of last code! */
|
|
716 if (CrntCode == Private->RunningCode - 2) {
|
|
717 CrntPrefix = LastCode;
|
|
718 Suffix[Private->RunningCode - 2] =
|
|
719 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
|
|
720 LastCode, ClearCode);
|
|
721 }
|
|
722 else {
|
|
723 _GifError = D_GIF_ERR_IMAGE_DEFECT;
|
|
724 return GIF_ERROR;
|
|
725 }
|
|
726 }
|
|
727 else
|
|
728 CrntPrefix = CrntCode;
|
|
729
|
|
730 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */
|
|
731 /* During the trace. As we might loop forever, in case of */
|
|
732 /* defective image, we count the number of loops we trace */
|
|
733 /* and stop if we got LZ_MAX_CODE. obviously we can not */
|
|
734 /* loop more than that. */
|
|
735 j = 0;
|
|
736 while (j++ <= LZ_MAX_CODE &&
|
|
737 CrntPrefix > ClearCode &&
|
|
738 CrntPrefix <= LZ_MAX_CODE) {
|
|
739 Stack[StackPtr++] = Suffix[CrntPrefix];
|
|
740 CrntPrefix = Prefix[CrntPrefix];
|
|
741 }
|
|
742 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
|
|
743 _GifError = D_GIF_ERR_IMAGE_DEFECT;
|
|
744 return GIF_ERROR;
|
|
745 }
|
|
746 /* Push the last character on stack: */
|
|
747 Stack[StackPtr++] = CrntPrefix;
|
|
748
|
|
749 /* Now lets pop all the stack into output: */
|
|
750 while (StackPtr != 0 && i < LineLen)
|
|
751 Line[i++] = Stack[--StackPtr];
|
|
752 }
|
|
753 if (LastCode != NO_SUCH_CODE) {
|
|
754 Prefix[Private->RunningCode - 2] = LastCode;
|
|
755
|
|
756 if (CrntCode == Private->RunningCode - 2) {
|
|
757 /* Only allowed if CrntCode is exactly the running code: */
|
|
758 /* In that case CrntCode = XXXCode, CrntCode or the */
|
|
759 /* prefix code is last code and the suffix char is */
|
|
760 /* exactly the prefix of last code! */
|
|
761 Suffix[Private->RunningCode - 2] =
|
|
762 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
|
|
763 }
|
|
764 else {
|
|
765 Suffix[Private->RunningCode - 2] =
|
|
766 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
|
|
767 }
|
|
768 }
|
|
769 LastCode = CrntCode;
|
|
770 }
|
|
771 }
|
|
772
|
|
773 Private->LastCode = LastCode;
|
|
774 Private->StackPtr = StackPtr;
|
|
775
|
|
776 return GIF_OK;
|
|
777 }
|
|
778
|
|
779 /******************************************************************************
|
|
780 * Routine to trace the Prefixes linked list until we get a prefix which is *
|
|
781 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
|
|
782 * If image is defective, we might loop here forever, so we limit the loops to *
|
|
783 * the maximum possible if image O.k. - LZ_MAX_CODE times. *
|
|
784 ******************************************************************************/
|
|
785 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
|
|
786 {
|
|
787 int i = 0;
|
|
788
|
|
789 while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
|
|
790 return Code;
|
|
791 }
|
|
792
|
|
793 /******************************************************************************
|
|
794 * Interface for accessing the LZ codes directly. Set Code to the real code *
|
|
795 * (12bits), or to -1 if EOF code is returned. *
|
|
796 ******************************************************************************/
|
|
797 int DGifGetLZCodes(GifFileType *GifFile, int *Code)
|
|
798 {
|
|
799 GifByteType *CodeBlock;
|
|
800 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
|
|
801
|
|
802 if (!IS_READABLE(Private)) {
|
|
803 /* This file was NOT open for reading: */
|
|
804 _GifError = D_GIF_ERR_NOT_READABLE;
|
|
805 return GIF_ERROR;
|
|
806 }
|
|
807
|
|
808 if (DGifDecompressInput(Private, Code) == GIF_ERROR)
|
|
809 return GIF_ERROR;
|
|
810
|
|
811 if (*Code == Private->EOFCode) {
|
|
812 /* Skip rest of codes (hopefully only NULL terminating block): */
|
|
813 do if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
|
|
814 return GIF_ERROR;
|
|
815 while (CodeBlock != NULL);
|
|
816
|
|
817 *Code = -1;
|
|
818 }
|
|
819 else if (*Code == Private->ClearCode) {
|
|
820 /* We need to start over again: */
|
|
821 Private->RunningCode = Private->EOFCode + 1;
|
|
822 Private->RunningBits = Private->BitsPerPixel + 1;
|
|
823 Private->MaxCode1 = 1 << Private->RunningBits;
|
|
824 }
|
|
825
|
|
826 return GIF_OK;
|
|
827 }
|
|
828
|
|
829 /******************************************************************************
|
|
830 * The LZ decompression input routine: *
|
|
831 * This routine is responsable for the decompression of the bit stream from *
|
|
832 * 8 bits (bytes) packets, into the real codes. *
|
|
833 * Returns GIF_OK if read succesfully. *
|
|
834 ******************************************************************************/
|
|
835 static int DGifDecompressInput(GifFilePrivateType *Private, int *Code)
|
|
836 {
|
|
837 GifByteType NextByte;
|
|
838 static unsigned int CodeMasks[] = {
|
|
839 0x0000, 0x0001, 0x0003, 0x0007,
|
|
840 0x000f, 0x001f, 0x003f, 0x007f,
|
|
841 0x00ff, 0x01ff, 0x03ff, 0x07ff,
|
|
842 0x0fff
|
|
843 };
|
|
844
|
|
845 while (Private->CrntShiftState < Private->RunningBits) {
|
|
846 /* Needs to get more bytes from input stream for next code: */
|
|
847 if (DGifBufferedInput(Private->File, Private->Buf, &NextByte)
|
|
848 == GIF_ERROR) {
|
|
849 return GIF_ERROR;
|
|
850 }
|
|
851 Private->CrntShiftDWord |=
|
|
852 ((unsigned long) NextByte) << Private->CrntShiftState;
|
|
853 Private->CrntShiftState += 8;
|
|
854 }
|
|
855 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
|
|
856
|
|
857 Private->CrntShiftDWord >>= Private->RunningBits;
|
|
858 Private->CrntShiftState -= Private->RunningBits;
|
|
859
|
|
860 /* If code cannt fit into RunningBits bits, must raise its size. Note */
|
|
861 /* however that codes above 4095 are used for special signaling. */
|
|
862 if (++Private->RunningCode > Private->MaxCode1 &&
|
|
863 Private->RunningBits < LZ_BITS) {
|
|
864 Private->MaxCode1 <<= 1;
|
|
865 Private->RunningBits++;
|
|
866 }
|
|
867 return GIF_OK;
|
|
868 }
|
|
869
|
|
870 /******************************************************************************
|
|
871 * This routines read one gif data block at a time and buffers it internally *
|
|
872 * so that the decompression routine could access it. *
|
|
873 * The routine returns the next byte from its internal buffer (or read next *
|
|
874 * block in if buffer empty) and returns GIF_OK if succesful. *
|
|
875 ******************************************************************************/
|
|
876 static int DGifBufferedInput(FILE *File, GifByteType *Buf,
|
|
877 GifByteType *NextByte)
|
|
878 {
|
|
879 if (Buf[0] == 0) {
|
|
880 /* Needs to read the next buffer - this one is empty: */
|
|
881 if (fread(Buf, 1, 1, File) != 1)
|
|
882 {
|
|
883 _GifError = D_GIF_ERR_READ_FAILED;
|
|
884 return GIF_ERROR;
|
|
885 }
|
|
886 if (fread(&Buf[1], 1, Buf[0], File) != Buf[0])
|
|
887 {
|
|
888 _GifError = D_GIF_ERR_READ_FAILED;
|
|
889 return GIF_ERROR;
|
|
890 }
|
|
891 *NextByte = Buf[1];
|
|
892 Buf[1] = 2; /* We use now the second place as last char read! */
|
|
893 Buf[0]--;
|
|
894 }
|
|
895 else {
|
|
896 *NextByte = Buf[Buf[1]++];
|
|
897 Buf[0]--;
|
|
898 }
|
|
899
|
|
900 return GIF_OK;
|
|
901 }
|
|
902
|
|
903 /******************************************************************************
|
|
904 * This routine reads an entire GIF into core, hanging all its state info off *
|
|
905 * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() *
|
|
906 * first to initialize I/O. Its inverse is EGifSpew(). *
|
|
907 ******************************************************************************/
|
|
908 int DGifSlurp(GifFileType *GifFile)
|
|
909 {
|
|
910 #if 0
|
|
911 int i, j, Error;
|
|
912 #endif /* 0 */
|
|
913 int ImageSize;
|
|
914 GifRecordType RecordType;
|
|
915 SavedImage *sp;
|
|
916 ExtensionBlock *ep;
|
|
917 GifByteType *ExtData;
|
36
|
918 int ExtCode;
|
0
|
919
|
|
920 /* Some versions of malloc dislike 0-length requests */
|
|
921 GifFile->SavedImages = (SavedImage *)xmalloc(sizeof(SavedImage));
|
|
922
|
|
923 do {
|
|
924 if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
|
|
925 return(GIF_ERROR);
|
|
926
|
|
927 switch (RecordType) {
|
|
928 case IMAGE_DESC_RECORD_TYPE:
|
|
929 if (DGifGetImageDesc(GifFile) == GIF_ERROR)
|
|
930 return(GIF_ERROR);
|
|
931
|
|
932 sp = &GifFile->SavedImages[GifFile->ImageCount-1];
|
|
933 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
|
|
934
|
|
935 sp->RasterBits
|
|
936 = (GifPixelType*) xmalloc(ImageSize * sizeof(GifPixelType));
|
|
937
|
|
938 if (DGifGetLine(GifFile, sp->RasterBits, ImageSize)
|
|
939 == GIF_ERROR)
|
|
940 return(GIF_ERROR);
|
|
941
|
|
942 break;
|
|
943
|
|
944 case EXTENSION_RECORD_TYPE:
|
36
|
945 /* This code fails if no image_desc record has been read
|
|
946 yet. I don't know if that's legal, but I've seen GIFs
|
|
947 that start with an extension record. XEmacs doesn't use
|
|
948 the extension records anyway, so we'll just ignore them.
|
|
949 - dkindred@cs.cmu.edu */
|
|
950 #if 0
|
0
|
951 if (DGifGetExtension(GifFile,&sp->Function,&ExtData)==GIF_ERROR)
|
|
952 return(GIF_ERROR);
|
|
953 else
|
|
954 {
|
|
955 ep = &sp->ExtensionBlocks[sp->ExtensionBlockCount++];
|
|
956
|
|
957 ep->ByteCount = ExtData[0];
|
|
958 ep->Bytes = (GifByteType *)xmalloc(ep->ByteCount * sizeof(GifByteType));
|
|
959 memcpy(ep->Bytes, ExtData, ep->ByteCount * sizeof(char));
|
|
960 }
|
|
961
|
|
962 while (ExtData != NULL) {
|
|
963 if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
|
|
964 return(GIF_ERROR);
|
|
965 else
|
|
966 {
|
|
967 ep = &sp->ExtensionBlocks[sp->ExtensionBlockCount++];
|
|
968
|
|
969 ep->ByteCount = ExtData[0];
|
|
970 ep->Bytes = (GifByteType *)xmalloc(ep->ByteCount * sizeof(GifByteType));
|
|
971 memcpy(ep->Bytes,ExtData,ep->ByteCount * sizeof(char));
|
|
972 }
|
|
973 }
|
36
|
974 #else
|
|
975 /* Skip any extension blocks in the file. */
|
|
976 if (DGifGetExtension (GifFile, &ExtCode, &ExtData)
|
|
977 == GIF_ERROR)
|
|
978 return GIF_ERROR;
|
|
979
|
|
980 while (ExtData != NULL) {
|
|
981 if (DGifGetExtensionNext (GifFile, &ExtData) == GIF_ERROR)
|
|
982 return GIF_ERROR;
|
|
983 }
|
|
984 #endif
|
0
|
985 break;
|
|
986
|
|
987 case TERMINATE_RECORD_TYPE:
|
|
988 break;
|
|
989
|
|
990 default: /* Should be trapped by DGifGetRecordType */
|
|
991 break;
|
|
992 }
|
|
993 }
|
|
994 while
|
|
995 (RecordType != TERMINATE_RECORD_TYPE);
|
|
996
|
|
997 return(GIF_OK);
|
|
998 }
|
|
999
|