1 /* cgif.c -- a merge of some GIF-decoding files from giflib by E.S.Raymond
2 * by pts@fazekas.hu at Wed Feb 27 13:18:04 CET 2002
3
4 The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23 */
24
25 /*The creators of the GIF format require the following
26 acknowledgement:
27 The Graphics Interchange Format(c) is the Copyright property of
28 CompuServe Incorporated. GIF(sm) is a Service Mark property of
29 CompuServe Incorporated.
30 */
31
32 #ifdef __GNUC__
33 #ifndef __clang__
34 #pragma implementation
35 #endif
36 #endif
37
38 /**** pts: not an ANSI C function */
39 #undef EXTERN_C
40 #ifdef __cplusplus
41 #define EXTERN_C extern "C"
42 #define CGIFFF CGIF::
43 #else
44 #define EXTERN_C extern
45 #define CGIFFF
46 #endif
47 #if OBJDEP
48 # warning PROVIDES: cgif
49 #endif
50
51 #if 0
52 EXTERN_C FILE *fdopen (int fildes, const char *mode); /* GCC 3.0 SUXX */
53 #else
54 #undef _POSIX_SOURCE
55 #define _POSIX_SOURCE 1
56 #undef _POSIX_C_SOURCE
57 #define _POSIX_C_SOURCE 2
58 #endif
59
60 /* --- gifalloc.c */
61
62 /*****************************************************************************
63 * "Gif-Lib" - Yet another gif library. *
64 * *
65 * Written by: Gershon Elber Ver 0.1, Jun. 1989 *
66 * Extensively hacked by: Eric S. Raymond Ver 1.?, Sep 1992 *
67 ******************************************************************************
68 * GIF construction tools *
69 ******************************************************************************
70 * History: *
71 * 15 Sep 92 - Version 1.0 by Eric Raymond. *
72 *****************************************************************************/
73
74 // #undef __STRICT_ANSI__ /* for MINGW32 open() !! */
75 #include <stdio.h>
76 #include "cgif.h"
77
78 /**** pts ****/
79 #include <stdlib.h> /* malloc(), calloc(), free(), realloc() */
80 #include <string.h> /* memset() */
81
82
83 //#include <unistd.h>
84
85 #if USE_CGIF_FDOPEN
86 #include <fcntl.h> /* open() */
87 #include <sys/types.h>
88 #include <sys/stat.h>
89 # if defined(__MINGW32__) || defined(__CYGWIN__) || defined(_MSC_VER)
90 # undef __STRICT_ANSI__
91 # include <io.h>
92 /*#define open _open*/
93 # endif
94 #endif
95
96 /* --- gif_err.c */
97
98 /*****************************************************************************
99 * "Gif-Lib" - Yet another gif library. *
100 * *
101 * Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989 *
102 ******************************************************************************
103 * Handle error reporting for the GIF library. *
104 ******************************************************************************
105 * History: *
106 * 17 Jun 89 - Version 1.0 by Gershon Elber. *
107 *****************************************************************************/
108
109 /* #include <stdio.h> already */
110 /* #include "gif_lib.h" already */
111
112 /* --- dgif_lib.c */
113
114 /******************************************************************************
115 * "Gif-Lib" - Yet another gif library. *
116 * *
117 * Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 *
118 *******************************************************************************
119 * The kernel of the GIF Decoding process can be found here. *
120 *******************************************************************************
121 * History: *
122 * 16 Jun 89 - Version 1.0 by Gershon Elber. *
123 * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
124 ******************************************************************************/
125
126 #ifdef __MSDOS__
127 #include <io.h>
128 #include <alloc.h>
129 #include <stdlib.h>
130 #include <sys\stat.h>
131 #else
132 #include <sys/types.h>
133 #include <sys/stat.h>
134 #endif /* __MSDOS__ */
135
136 #include <fcntl.h>
137 /* #include <stdio.h> already */
138 /* #include <string.h> already */
139 /* #include "gif_lib.h" already */
140
141 /* #include <stdlib.h> already */ /* malloc(), free() */
142 #include <assert.h>
143
144 /* ---- */
145
146 /* --- gif_err.c */
147
148 /* #define PROGRAM_NAME "GIF_LIBRARY" */
149
150 int CGIFFF _GifError = 0;
151
152 /*****************************************************************************
153 * Return the last GIF error (0 if none) and reset the error. *
154 *****************************************************************************/
GifLastError(void)155 int CGIFFF GifLastError(void)
156 {
157 int i = _GifError;
158
159 _GifError = 0;
160
161 return i;
162 }
163
164 /**** pts ****/
165 /** May return NULL. */
GetGifError(void)166 PTS_const char *CGIFFF GetGifError(void)
167 {
168 PTS_const char *Err;
169
170 switch(_GifError) {
171 #if 0 /**** pts ****/
172 case E_GIF_ERR_OPEN_FAILED:
173 Err = "Failed to open given file";
174 break;
175 case E_GIF_ERR_WRITE_FAILED:
176 Err = "Failed to Write to given file";
177 break;
178 case E_GIF_ERR_HAS_SCRN_DSCR:
179 Err = "Screen Descriptor already been set";
180 break;
181 case E_GIF_ERR_HAS_IMAG_DSCR:
182 Err = "Image Descriptor is still active";
183 break;
184 case E_GIF_ERR_NO_COLOR_MAP:
185 Err = "Neither Global Nor Local color map";
186 break;
187 case E_GIF_ERR_DATA_TOO_BIG:
188 Err = "#Pixels bigger than Width * Height";
189 break;
190 case E_GIF_ERR_NOT_ENOUGH_MEM:
191 Err = "Fail to allocate required memory";
192 break;
193 case E_GIF_ERR_DISK_IS_FULL:
194 Err = "Write failed (disk full?)";
195 break;
196 case E_GIF_ERR_CLOSE_FAILED:
197 Err = "Failed to close given file";
198 break;
199 case E_GIF_ERR_NOT_WRITEABLE:
200 Err = "Given file was not opened for write";
201 break;
202 #endif
203 case D_GIF_ERR_OPEN_FAILED:
204 Err = "Failed to open given file";
205 break;
206 case D_GIF_ERR_READ_FAILED:
207 Err = "Failed to Read from given file";
208 break;
209 case D_GIF_ERR_NOT_GIF_FILE:
210 Err = "Given file is NOT GIF file";
211 break;
212 case D_GIF_ERR_NO_SCRN_DSCR:
213 Err = "No Screen Descriptor detected";
214 break;
215 case D_GIF_ERR_NO_IMAG_DSCR:
216 Err = "No Image Descriptor detected";
217 break;
218 case D_GIF_ERR_NO_COLOR_MAP:
219 Err = "Neither Global Nor Local color map";
220 break;
221 case D_GIF_ERR_WRONG_RECORD:
222 Err = "Wrong record type detected";
223 break;
224 case D_GIF_ERR_DATA_TOO_BIG:
225 Err = "#Pixels bigger than Width * Height";
226 break;
227 case D_GIF_ERR_NOT_ENOUGH_MEM:
228 Err = "Fail to allocate required memory";
229 break;
230 case D_GIF_ERR_CLOSE_FAILED:
231 Err = "Failed to close given file";
232 break;
233 case D_GIF_ERR_NOT_READABLE:
234 Err = "Given file was not opened for read";
235 break;
236 case D_GIF_ERR_IMAGE_DEFECT:
237 Err = "Image is defective, decoding aborted";
238 break;
239 case D_GIF_ERR_EOF_TOO_SOON:
240 Err = "Image EOF detected, before image complete";
241 break;
242 default:
243 Err = NULL;
244 break;
245 }
246 return Err;
247 }
248
249 /*****************************************************************************
250 * Print the last GIF error to stderr. *
251 *****************************************************************************/
PrintGifError(void)252 void CGIFFF PrintGifError(void)
253 {
254 PTS_const char *Err=GetGifError();
255 if (Err != NULL)
256 fprintf(stderr, "\nGIF-LIB error: %s.\n", Err);
257 else
258 fprintf(stderr, "\nGIF-LIB undefined error %d.\n", _GifError);
259 }
260
261 /* --- gifalloc.c */
262
263 #define MAXGIF(x, y) (((x) > (y)) ? (x) : (y))
264
265 /******************************************************************************
266 * Miscellaneous utility functions *
267 ******************************************************************************/
268
BitSize(int n)269 static int BitSize(int n)
270 /* return smallest bitfield size n will fit in */
271 {
272 register int i;
273
274 for (i = 1; i <= 8; i++)
275 if ((1 << i) >= n)
276 break;
277 return(i);
278 }
279
280
281 /******************************************************************************
282 * Color map object functions *
283 ******************************************************************************/
284
MakeMapObject(int ColorCount,GifColorType * ColorMap)285 CGIFFF ColorMapObject *CGIFFF MakeMapObject(int ColorCount, GifColorType *ColorMap)
286 /*
287 * Allocate a color map of given size; initialize with contents of
288 * ColorMap if that pointer is non-NULL.
289 */
290 {
291 ColorMapObject *Object;
292
293 if (ColorCount != (1 << BitSize(ColorCount)))
294 return((ColorMapObject *)NULL);
295
296 Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
297 if (Object == (ColorMapObject *)NULL)
298 return((ColorMapObject *)NULL);
299
300 Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
301 if (Object->Colors == (GifColorType *)NULL)
302 return((ColorMapObject *)NULL);
303
304 Object->ColorCount = ColorCount;
305 Object->BitsPerPixel = BitSize(ColorCount);
306
307 if (ColorMap)
308 memcpy((char *)Object->Colors,
309 (char *)ColorMap, ColorCount * sizeof(GifColorType));
310
311 return(Object);
312 }
313
FreeMapObject(CGIFFF ColorMapObject * Object)314 void CGIFFF FreeMapObject(CGIFFF ColorMapObject *Object)
315 /*
316 * Free a color map object
317 */
318 {
319 free(Object->Colors);
320 free(Object);
321 }
322
323 #if 0
324 void DumpColorMap(ColorMapObject *Object, FILE *fp)
325 {
326 if (Object)
327 {
328 int i, j, Len = Object->ColorCount;
329
330 for (i = 0; i < Len; i+=4) {
331 for (j = 0; j < 4 && j < Len; j++) {
332 fprintf(fp,
333 "%3d: %02x %02x %02x ", i + j,
334 Object->Colors[i + j].Red,
335 Object->Colors[i + j].Green,
336 Object->Colors[i + j].Blue);
337 }
338 fprintf(fp, "\n");
339 }
340 }
341 }
342 #endif /* DEBUG */
343
344 #if 0
345 ColorMapObject *CGIFFF UnionColorMap(
346 ColorMapObject *ColorIn1,
347 ColorMapObject *ColorIn2,
348 GifPixelType ColorTransIn2[])
349 /*
350 * Compute the union of two given color maps and return it. If result can't
351 * fit into 256 colors, NULL is returned, the allocated union otherwise.
352 * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
353 * copied iff they didn't exist before. ColorTransIn2 maps the old
354 * ColorIn2 into ColorUnion color map table.
355 */
356 {
357 int i, j, CrntSlot, RoundUpTo, NewBitSize;
358 ColorMapObject *ColorUnion;
359
360 /*
361 * Allocate table which will hold the result for sure.
362 */
363 ColorUnion
364 = MakeMapObject(MAXGIF(ColorIn1->ColorCount,ColorIn2->ColorCount)*2,NULL);
365
366 if (ColorUnion == NULL)
367 return(NULL);
368
369 /* Copy ColorIn1 to ColorUnionSize; */
370 for (i = 0; i < ColorIn1->ColorCount; i++)
371 ColorUnion->Colors[i] = ColorIn1->Colors[i];
372 CrntSlot = ColorIn1->ColorCount;
373
374 /*
375 * Potentially obnoxious hack:
376 *
377 * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
378 * of table 1. This is very useful if your display is limited to
379 * 16 colors.
380 */
381 while (ColorIn1->Colors[CrntSlot-1].Red == 0
382 && ColorIn1->Colors[CrntSlot-1].Green == 0
383 && ColorIn1->Colors[CrntSlot-1].Red == 0)
384 CrntSlot--;
385
386 /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */
387 for (i = 0; i < ColorIn2->ColorCount && CrntSlot<=256; i++)
388 {
389 /* Let's see if this color already exists: */
390 for (j = 0; j < ColorIn1->ColorCount; j++)
391 if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0)
392 break;
393
394 if (j < ColorIn1->ColorCount)
395 ColorTransIn2[i] = j; /* color exists in Color1 */
396 else
397 {
398 /* Color is new - copy it to a new slot: */
399 ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
400 ColorTransIn2[i] = CrntSlot++;
401 }
402 }
403
404 if (CrntSlot > 256)
405 {
406 FreeMapObject(ColorUnion);
407 return((ColorMapObject *)NULL);
408 }
409
410 NewBitSize = BitSize(CrntSlot);
411 RoundUpTo = (1 << NewBitSize);
412
413 if (RoundUpTo != ColorUnion->ColorCount)
414 {
415 register GifColorType *Map = ColorUnion->Colors;
416
417 /*
418 * Zero out slots up to next power of 2.
419 * We know these slots exist because of the way ColorUnion's
420 * start dimension was computed.
421 */
422 for (j = CrntSlot; j < RoundUpTo; j++)
423 Map[j].Red = Map[j].Green = Map[j].Blue = 0;
424
425 /* perhaps we can shrink the map? */
426 if (RoundUpTo < ColorUnion->ColorCount)
427 ColorUnion->Colors
428 = (GifColorType *)realloc(Map, sizeof(GifColorType)*RoundUpTo);
429 }
430
431 ColorUnion->ColorCount = RoundUpTo;
432 ColorUnion->BitsPerPixel = NewBitSize;
433
434 return(ColorUnion);
435 }
436 void ApplyTranslation(SavedImage *Image, GifPixelType Translation[])
437 /*
438 * Apply a given color translation to the raster bits of an image
439 */
440 {
441 register int i;
442 register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
443
444 for (i = 0; i < RasterSize; i++)
445 Image->RasterBits[i] = Translation[Image->RasterBits[i]];
446 }
447 #endif
448
449 /******************************************************************************
450 * Extension record functions *
451 ******************************************************************************/
452
453 #if 0 /**** pts ****/
454 void MakeExtension(SavedImage *New, int Function)
455 {
456 New->Function = Function;
457 /*
458 * Someday we might have to deal with multiple extensions.
459 */
460 }
461 #endif
462
AddExtensionBlock(CGIFFF SavedImage * New,int Len,CGIFFF GifByteType ExtData[])463 int CGIFFF AddExtensionBlock(CGIFFF SavedImage *New, int Len, CGIFFF GifByteType ExtData[])
464 {
465 ExtensionBlock *ep;
466
467 if (New->ExtensionBlocks == NULL)
468 New->ExtensionBlocks = (ExtensionBlock *)malloc(sizeof(ExtensionBlock));
469 else
470 New->ExtensionBlocks =
471 (ExtensionBlock *)realloc(New->ExtensionBlocks,
472 sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1));
473
474 if (New->ExtensionBlocks == NULL)
475 return(GIF_ERROR);
476
477 ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
478
479 if ((ep->Bytes = (GifByteType *)malloc(ep->ByteCount = Len)) == NULL)
480 return(GIF_ERROR);
481
482 if (ExtData)
483 memcpy(ep->Bytes, ExtData, Len);
484
485 return(GIF_OK);
486 }
487
FreeExtension(CGIFFF SavedImage * Image)488 void CGIFFF FreeExtension(CGIFFF SavedImage *Image)
489 {
490 ExtensionBlock *ep;
491
492 for (ep = Image->ExtensionBlocks;
493 ep < Image->ExtensionBlocks + Image->ExtensionBlockCount;
494 ep++)
495 (void) free((char *)ep->Bytes);
496 free((char *)Image->ExtensionBlocks);
497 Image->ExtensionBlocks = NULL;
498 }
499
500 /******************************************************************************
501 * Image block allocation functions *
502 ******************************************************************************/
MakeSavedImage(CGIFFF GifFileType * GifFile,CGIFFF SavedImage * CopyFrom)503 CGIFFF SavedImage *CGIFFF MakeSavedImage(CGIFFF GifFileType *GifFile, CGIFFF SavedImage *CopyFrom)
504 /*
505 * Append an image block to the SavedImages array
506 */
507 {
508 SavedImage *sp;
509
510 if (GifFile->SavedImages == NULL)
511 GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
512 else
513 GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
514 sizeof(SavedImage) * (GifFile->ImageCount+1));
515
516 if (GifFile->SavedImages == NULL)
517 return((SavedImage *)NULL);
518 else
519 {
520 sp = &GifFile->SavedImages[GifFile->ImageCount++];
521 memset((char *)sp, '\0', sizeof(SavedImage));
522
523 if (CopyFrom)
524 {
525 memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
526
527 /*
528 * Make our own allocated copies of the heap fields in the
529 * copied record. This guards against potential aliasing
530 * problems.
531 */
532
533 /* first, the local color map */
534 if (sp->ImageDesc.ColorMap)
535 sp->ImageDesc.ColorMap =
536 MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount,
537 CopyFrom->ImageDesc.ColorMap->Colors);
538
539 /* next, the raster */
540 sp->RasterBits = (GifPixelType *)malloc(sizeof(GifPixelType)
541 * CopyFrom->ImageDesc.Height
542 * CopyFrom->ImageDesc.Width);
543 memcpy(sp->RasterBits,
544 CopyFrom->RasterBits,
545 sizeof(GifPixelType)
546 * CopyFrom->ImageDesc.Height
547 * CopyFrom->ImageDesc.Width);
548
549 /* finally, the extension blocks */
550 if (sp->ExtensionBlocks)
551 {
552 sp->ExtensionBlocks
553 = (ExtensionBlock*)malloc(sizeof(ExtensionBlock)
554 * CopyFrom->ExtensionBlockCount);
555 memcpy(sp->ExtensionBlocks,
556 CopyFrom->ExtensionBlocks,
557 sizeof(ExtensionBlock)
558 * CopyFrom->ExtensionBlockCount);
559
560 /*
561 * For the moment, the actual blocks can take their
562 * chances with free(). We'll fix this later.
563 */
564 }
565 }
566
567 return(sp);
568 }
569 }
570
FreeSavedImages(CGIFFF GifFileType * GifFile)571 void CGIFFF FreeSavedImages(CGIFFF GifFileType *GifFile)
572 {
573 SavedImage *sp;
574
575 for (sp = GifFile->SavedImages;
576 sp < GifFile->SavedImages + GifFile->ImageCount;
577 sp++)
578 {
579 if (sp->ImageDesc.ColorMap)
580 FreeMapObject(sp->ImageDesc.ColorMap);
581
582 if (sp->RasterBits)
583 free((char *)sp->RasterBits);
584
585 if (sp->ExtensionBlocks)
586 FreeExtension(sp);
587 }
588 free((char *) GifFile->SavedImages);
589 }
590
591 /* --- dgif_lib.c */
592
593 #define GIF_FILE_BUFFER_SIZE 16384 /* Files uses bigger buffers than usual. */
594
595 /* #define PROGRAM_NAME "GIFLIB" */
596
597 #define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for comment. */
598 #define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */
599 #define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1
600 #define GIF_VERSION_POS 3 /* Version first character in stamp. */
601
602 #define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
603 #define LZ_BITS 12
604
605 #define FILE_STATE_READ 0x01/* 1 write, 0 read - EGIF_LIB compatible.*/
606
607 #define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */
608 #define FIRST_CODE 4097 /* Impossible code, to signal first. */
609 #define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */
610
611 #define IS_READABLE(Private) (!(Private->FileState & FILE_STATE_READ))
612
613 typedef struct GifFilePrivateType {
614 int FileState,
615 /*FileHandle,*/ /* Where all this data goes to! */
616 BitsPerPixel, /* Bits per pixel (Codes uses at list this + 1). */
617 ClearCode, /* The CLEAR LZ code. */
618 EOFCode, /* The EOF LZ code. */
619 RunningCode, /* The next code algorithm can generate. */
620 RunningBits,/* The number of bits required to represent RunningCode. */
621 MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */
622 LastCode, /* The code before the current code. */
623 CrntCode, /* Current algorithm code. */
624 StackPtr, /* For character stack (see below). */
625 CrntShiftState; /* Number of bits in CrntShiftDWord. */
626 unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */
627 unsigned long PixelCount; /* Number of pixels in image. */
628 FILE *File; /* File as stream. */
629 CGIFFF GifByteType Buf[256]; /* Compressed input is buffered here. */
630 CGIFFF GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */
631 CGIFFF GifByteType Suffix[LZ_MAX_CODE+1]; /* So we can trace the codes. */
632 unsigned int Prefix[LZ_MAX_CODE+1];
633 } GifFilePrivateType;
634
635 /* extern int _GifError; */
636
637 static int DGifGetWord(FILE *File, int *Word);
638 static int DGifSetupDecompress(CGIFFF GifFileType *GifFile);
639 static int DGifDecompressLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line,
640 int LineLen);
641 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
642 static int DGifDecompressInput(GifFilePrivateType *Private, int *Code);
643 static int DGifBufferedInput(FILE *File, CGIFFF GifByteType *Buf,
644 CGIFFF GifByteType *NextByte);
645
646 /******************************************************************************
647 * Open a new gif file for read, given by its name. *
648 * Returns GifFileType pointer dynamically allocated which serves as the gif *
649 * info record. _GifError is cleared if succesfull. *
650 ******************************************************************************/
DGifOpenFileName(const char * FileName)651 CGIFFF GifFileType *CGIFFF DGifOpenFileName(const char *FileName) {
652 #if 0 /**** pts ****/
653 CGIFFF GifFileType *CGIFFF DGifOpenFileName(const char *FileName)
654 {
655 int FileHandle;
656
657 if ((FileHandle = open(FileName, O_RDONLY
658 #ifdef __MSDOS__
659 | O_BINARY
660 #endif /* __MSDOS__ */
661 )) == -1) {
662 _GifError = D_GIF_ERR_OPEN_FAILED;
663 return NULL;
664 }
665
666 return DGifOpenFileHandle(FileHandle);
667 #else
668 FILE *f;
669 if (NULL==(f=fopen(FileName,"rb"))) { _GifError=D_GIF_ERR_OPEN_FAILED; return NULL; }
670 return DGifOpenFILE(f);
671 #endif
672 }
673
674 #if USE_CGIF_FDOPEN
675
676 /******************************************************************************
677 * Update a new gif file, given its file handle. *
678 * Returns GifFileType pointer dynamically allocated which serves as the gif *
679 * info record. _GifError is cleared if succesfull. *
680 ******************************************************************************/
681 CGIFFF GifFileType *CGIFFF DGifOpenFileHandle(int FileHandle)
682 {
683 FILE *f;
684
685 #ifdef __MSDOS__
686 setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
687 f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
688 setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/
689 #else
690 f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
691 #endif /* __MSDOS__ */
692 return DGifOpenFILE(f);
693 }
694 #endif
695
696 /**** pts ****/
697 CGIFFF GifFileType *CGIFFF DGifOpenFILE(void/*FILE*/ *f) {
698 char Buf[GIF_STAMP_LEN+1];
699 GifFileType *GifFile;
700 GifFilePrivateType *Private;
701 if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) {
702 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
703 return NULL;
704 }
705
706 memset(GifFile, '\0', sizeof(GifFileType));
707
708 if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType)))
709 == NULL) {
710 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
711 free((char *) GifFile);
712 return NULL;
713 }
714 GifFile->Private = (VoidPtr) Private;
715 /* Private->FileHandle = FileHandle; */
716 Private->File = (FILE*)f;
717 Private->FileState = 0; /* Make sure bit 0 = 0 (File open for read). */
718
719 /* Let's see if this is a GIF file: */
720 if (fread(Buf, 1, GIF_STAMP_LEN, Private->File) != GIF_STAMP_LEN) {
721 _GifError = D_GIF_ERR_READ_FAILED;
722 free((char *) Private);
723 free((char *) GifFile);
724 return NULL;
725 }
726
727 /* The GIF Version number is ignored at this time. Maybe we should do */
728 /* something more useful with it. */
729 Buf[GIF_STAMP_LEN] = 0;
730 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
731 _GifError = D_GIF_ERR_NOT_GIF_FILE;
732 free((char *) Private);
733 free((char *) GifFile);
734 return NULL;
735 }
736
737 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
738 free((char *) Private);
739 free((char *) GifFile);
740 return NULL;
741 }
742
743 _GifError = 0;
744
745 return GifFile;
746 }
747
748 /******************************************************************************
749 * This routine should be called before any other DGif calls. Note that *
750 * this routine is called automatically from DGif file open routines. *
751 ******************************************************************************/
752 int CGIFFF DGifGetScreenDesc(CGIFFF GifFileType *GifFile)
753 {
754 int i, BitsPerPixel;
755 GifByteType Buf[3];
756 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
757
758 if (!IS_READABLE(Private)) {
759 /* This file was NOT open for reading: */
760 _GifError = D_GIF_ERR_NOT_READABLE;
761 return GIF_ERROR;
762 }
763
764 /* Put the screen descriptor into the file: */
765 if (DGifGetWord(Private->File, &GifFile->SWidth) == GIF_ERROR ||
766 DGifGetWord(Private->File, &GifFile->SHeight) == GIF_ERROR)
767 return GIF_ERROR;
768
769 if (fread(Buf, 1, 3, Private->File) != 3) {
770 _GifError = D_GIF_ERR_READ_FAILED;
771 return GIF_ERROR;
772 }
773 GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
774 BitsPerPixel = (Buf[0] & 0x07) + 1;
775 GifFile->SBackGroundColor = Buf[1];
776 // fprintf(stderr, "colres=%d bpp=%d bgcol=%d\n", GifFile->SColorResolution, BitsPerPixel, GifFile->SBackGroundColor);
777 if (Buf[0] & 0x80) { /* Do we have global color map? */
778 // fprintf(stderr, "have gcolormap\n");
779 GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
780
781 /* Get the global color map: */
782 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
783 if (fread(Buf, 1, 3, Private->File) != 3) {
784 _GifError = D_GIF_ERR_READ_FAILED;
785 return GIF_ERROR;
786 }
787 GifFile->SColorMap->Colors[i].Red = Buf[0];
788 GifFile->SColorMap->Colors[i].Green = Buf[1];
789 GifFile->SColorMap->Colors[i].Blue = Buf[2];
790 }
791 }
792
793 return GIF_OK;
794 }
795
796 /******************************************************************************
797 * This routine should be called before any attemp to read an image. *
798 ******************************************************************************/
799 int CGIFFF DGifGetRecordType(CGIFFF GifFileType *GifFile, CGIFFF GifRecordType *Type)
800 {
801 GifByteType Buf;
802 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
803
804 if (!IS_READABLE(Private)) {
805 /* This file was NOT open for reading: */
806 _GifError = D_GIF_ERR_NOT_READABLE;
807 return GIF_ERROR;
808 }
809
810 if (fread(&Buf, 1, 1, Private->File) != 1) {
811 _GifError = D_GIF_ERR_READ_FAILED;
812 return GIF_ERROR;
813 }
814
815 // fprintf(stderr, "record %d at offset %ld\n", Buf&255, ftell(Private->File));
816 switch (Buf) {
817 case ',': *Type = IMAGE_DESC_RECORD_TYPE; break;
818 case '!': *Type = EXTENSION_RECORD_TYPE; break;
819 case ';': *Type = TERMINATE_RECORD_TYPE; break;
820 default: *Type = UNDEFINED_RECORD_TYPE;
821 // fprintf(stderr, "wrong record %d at offset %ld\n", Buf&255, ftell(Private->File));
822 _GifError = D_GIF_ERR_WRONG_RECORD;
823 return GIF_ERROR;
824 }
825
826 return GIF_OK;
827 }
828
829 /******************************************************************************
830 * This routine should be called before any attemp to read an image. *
831 * Note it is assumed the Image desc. header (',') has been read. *
832 ******************************************************************************/
833 int CGIFFF DGifGetImageDesc(CGIFFF GifFileType *GifFile)
834 {
835 int i, BitsPerPixel;
836 GifByteType Buf[3];
837 GifImageDesc Image;
838 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
839 memset(&Image, 0, sizeof(Image));
840
841 if (!IS_READABLE(Private)) {
842 /* This file was NOT open for reading: */
843 _GifError = D_GIF_ERR_NOT_READABLE;
844 return GIF_ERROR;
845 }
846
847 if (DGifGetWord(Private->File, &Image.Left) == GIF_ERROR ||
848 DGifGetWord(Private->File, &Image.Top) == GIF_ERROR ||
849 DGifGetWord(Private->File, &Image.Width) == GIF_ERROR ||
850 DGifGetWord(Private->File, &Image.Height) == GIF_ERROR)
851 return GIF_ERROR;
852 if (fread(Buf, 1, 1, Private->File) != 1) {
853 _GifError = D_GIF_ERR_READ_FAILED;
854 return GIF_ERROR;
855 }
856 BitsPerPixel = (Buf[0] & 0x07) + 1;
857 Image.Interlace = (Buf[0] & 0x40);
858 if (Buf[0] & 0x80) { /* Does this image have local color map? */
859
860 if (Image.ColorMap && GifFile->SavedImages == NULL)
861 FreeMapObject(Image.ColorMap);
862
863 Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
864
865 /* Get the image local color map: */
866 for (i = 0; i < Image.ColorMap->ColorCount; i++) {
867 if (fread(Buf, 1, 3, Private->File) != 3) {
868 _GifError = D_GIF_ERR_READ_FAILED;
869 return GIF_ERROR;
870 }
871 Image.ColorMap->Colors[i].Red = Buf[0];
872 Image.ColorMap->Colors[i].Green = Buf[1];
873 Image.ColorMap->Colors[i].Blue = Buf[2];
874 }
875 }
876
877 /**** pts ****/
878 if (NULL!=GifFile->SavedImages) {
879 GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
880 sizeof(SavedImage) * (GifFile->ImageCount + 1));
881 } else {
882 assert(GifFile->ImageCount==0);
883 GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
884 }
885 if (NULL==GifFile->SavedImages) {
886 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
887 return GIF_ERROR;
888 }
889
890 {
891 SavedImage *sp;
892 sp = &GifFile->SavedImages[GifFile->ImageCount];
893 memcpy(&sp->ImageDesc, &Image, sizeof(GifImageDesc));
894 sp->RasterBits = (GifPixelType *)NULL;
895 sp->ExtensionBlockCount = 0;
896 sp->ExtensionBlocks = (ExtensionBlock *)NULL;
897 sp->delay=0;
898 sp->dispose=0;
899 sp->iter=1;
900 sp->transp=(-1);
901 }
902
903 GifFile->ImageCount++;
904
905 Private->PixelCount = (long) Image.Width *
906 (long) Image.Height;
907
908 DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
909
910 return GIF_OK;
911 }
912
913 /******************************************************************************
914 * Get one full scanned line (Line) of length LineLen from GIF file. *
915 ******************************************************************************/
916 int CGIFFF DGifGetLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line, int LineLen)
917 {
918 GifByteType *Dummy;
919 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
920
921 if (!IS_READABLE(Private)) {
922 /* This file was NOT open for reading: */
923 _GifError = D_GIF_ERR_NOT_READABLE;
924 return GIF_ERROR;
925 }
926
927 /**** pts ****/
928 /* if (!LineLen) LineLen = GifFile->Image.Width; */
929
930 #if defined(__MSDOS__) || defined(__GNUC__)
931 if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
932 #else
933 if ((Private->PixelCount -= LineLen) > 0xffff0000) {
934 #endif /* __MSDOS__ */
935 _GifError = D_GIF_ERR_DATA_TOO_BIG;
936 return GIF_ERROR;
937 }
938
939 if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
940 if (Private->PixelCount == 0) {
941 /* We probably would not be called any more, so lets clean */
942 /* everything before we return: need to flush out all rest of */
943 /* image until empty block (size 0) detected. We use GetCodeNext.*/
944 do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
945 return GIF_ERROR;
946 while (Dummy != NULL);
947 }
948 return GIF_OK;
949 }
950 else
951 return GIF_ERROR;
952 }
953
954 /******************************************************************************
955 * Put one pixel (Pixel) into GIF file. *
956 ******************************************************************************/
957 int CGIFFF DGifGetPixel(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType Pixel)
958 {
959 GifByteType *Dummy;
960 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
961
962 if (!IS_READABLE(Private)) {
963 /* This file was NOT open for reading: */
964 _GifError = D_GIF_ERR_NOT_READABLE;
965 return GIF_ERROR;
966 }
967
968 #if defined(__MSDOS__) || defined(__GNUC__)
969 if (--Private->PixelCount > 0xffff0000UL)
970 #else
971 if (--Private->PixelCount > 0xffff0000)
972 #endif /* __MSDOS__ */
973 {
974 _GifError = D_GIF_ERR_DATA_TOO_BIG;
975 return GIF_ERROR;
976 }
977
978 if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
979 if (Private->PixelCount == 0) {
980 /* We probably would not be called any more, so lets clean */
981 /* everything before we return: need to flush out all rest of */
982 /* image until empty block (size 0) detected. We use GetCodeNext.*/
983 do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
984 return GIF_ERROR;
985 while (Dummy != NULL);
986 }
987 return GIF_OK;
988 }
989 else
990 return GIF_ERROR;
991 }
992
993 /******************************************************************************
994 * Get an extension block (see GIF manual) from gif file. This routine only *
995 * returns the first data block, and DGifGetExtensionNext shouldbe called *
996 * after this one until NULL extension is returned. *
997 * The Extension should NOT be freed by the user (not dynamically allocated).*
998 * Note it is assumed the Extension desc. header ('!') has been read. *
999 ******************************************************************************/
1000 int CGIFFF DGifGetExtension(CGIFFF GifFileType *GifFile, int *ExtCode,
1001 CGIFFF GifByteType **Extension)
1002 {
1003 GifByteType Buf;
1004 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1005
1006
1007 if (!IS_READABLE(Private)) {
1008 /* This file was NOT open for reading: */
1009 _GifError = D_GIF_ERR_NOT_READABLE;
1010 return GIF_ERROR;
1011 }
1012
1013 if (fread(&Buf, 1, 1, Private->File) != 1) {
1014 _GifError = D_GIF_ERR_READ_FAILED;
1015 return GIF_ERROR;
1016 }
1017 *ExtCode = Buf;
1018
1019 return DGifGetExtensionNext(GifFile, Extension);
1020 }
1021
1022 /******************************************************************************
1023 * Get a following extension block (see GIF manual) from gif file. This *
1024 * routine sould be called until NULL Extension is returned. *
1025 * The Extension should NOT be freed by the user (not dynamically allocated).*
1026 ******************************************************************************/
1027 int CGIFFF DGifGetExtensionNext(CGIFFF GifFileType *GifFile, CGIFFF GifByteType **Extension)
1028 {
1029 GifByteType Buf;
1030 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1031
1032 if (fread(&Buf, 1, 1, Private->File) != 1) {
1033 _GifError = D_GIF_ERR_READ_FAILED;
1034 return GIF_ERROR;
1035 }
1036 if (Buf > 0) {
1037 *Extension = Private->Buf; /* Use private unused buffer. */
1038 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
1039 if (fread(&((*Extension)[1]), 1, Buf, Private->File) != Buf) {
1040 _GifError = D_GIF_ERR_READ_FAILED;
1041 return GIF_ERROR;
1042 }
1043 }
1044 else
1045 *Extension = NULL;
1046
1047 return GIF_OK;
1048 }
1049
1050 /******************************************************************************
1051 * This routine should be called last, to close the GIF file. *
1052 ******************************************************************************/
1053 int CGIFFF DGifCloseFile(CGIFFF GifFileType *GifFile)
1054 {
1055 GifFilePrivateType *Private;
1056
1057 if (GifFile == NULL) return GIF_ERROR;
1058
1059 Private = (GifFilePrivateType *) GifFile->Private;
1060
1061 if (!IS_READABLE(Private)) {
1062 /* This file was NOT open for reading: */
1063 _GifError = D_GIF_ERR_NOT_READABLE;
1064 return GIF_ERROR;
1065 }
1066
1067 #if 0 /**** pts ****/
1068 if (GifFile->Image.ColorMap)
1069 FreeMapObject(GifFile->Image.ColorMap);
1070 #endif
1071 if (GifFile->SColorMap)
1072 FreeMapObject(GifFile->SColorMap);
1073 if (Private)
1074 free((char *) Private);
1075 if (GifFile->SavedImages)
1076 FreeSavedImages(GifFile);
1077 free(GifFile);
1078
1079 #if 0 /**** pts ****/
1080 if (fclose(File) != 0) {
1081 _GifError = D_GIF_ERR_CLOSE_FAILED;
1082 return GIF_ERROR;
1083 }
1084 #endif
1085 return GIF_OK;
1086 }
1087
1088 /******************************************************************************
1089 * Get 2 bytes (word) from the given file: *
1090 ******************************************************************************/
1091 static int DGifGetWord(FILE *File, int *Word)
1092 {
1093 unsigned char c[2];
1094
1095 if (fread(c, 1, 2, File) != 2) {
1096 CGIFFF _GifError = D_GIF_ERR_READ_FAILED;
1097 return GIF_ERROR;
1098 }
1099
1100 *Word = (((unsigned int) c[1]) << 8) + c[0];
1101 return GIF_OK;
1102 }
1103
1104 /******************************************************************************
1105 * Get the image code in compressed form. his routine can be called if the *
1106 * information needed to be piped out as is. Obviously this is much faster *
1107 * than decoding and encoding again. This routine should be followed by calls *
1108 * to DGifGetCodeNext, until NULL block is returned. *
1109 * The block should NOT be freed by the user (not dynamically allocated). *
1110 ******************************************************************************/
1111 int CGIFFF DGifGetCode(CGIFFF GifFileType *GifFile, int *CodeSize, CGIFFF GifByteType **CodeBlock)
1112 {
1113 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1114
1115 if (!IS_READABLE(Private)) {
1116 /* This file was NOT open for reading: */
1117 _GifError = D_GIF_ERR_NOT_READABLE;
1118 return GIF_ERROR;
1119 }
1120
1121 *CodeSize = Private->BitsPerPixel;
1122
1123 return DGifGetCodeNext(GifFile, CodeBlock);
1124 }
1125
1126 /******************************************************************************
1127 * Continue to get the image code in compressed form. This routine should be *
1128 * called until NULL block is returned. *
1129 * The block should NOT be freed by the user (not dynamically allocated). *
1130 ******************************************************************************/
1131 int CGIFFF DGifGetCodeNext(CGIFFF GifFileType *GifFile, CGIFFF GifByteType **CodeBlock)
1132 {
1133 GifByteType Buf;
1134 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1135
1136 if (fread(&Buf, 1, 1, Private->File) != 1) {
1137 _GifError = D_GIF_ERR_READ_FAILED;
1138 return GIF_ERROR;
1139 }
1140
1141 if (Buf > 0) {
1142 *CodeBlock = Private->Buf; /* Use private unused buffer. */
1143 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
1144 if (fread(&((*CodeBlock)[1]), 1, Buf, Private->File) != Buf) {
1145 _GifError = D_GIF_ERR_READ_FAILED;
1146 return GIF_ERROR;
1147 }
1148 }
1149 else {
1150 *CodeBlock = NULL;
1151 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
1152 Private->PixelCount = 0; /* And local info. indicate image read. */
1153 }
1154
1155 return GIF_OK;
1156 }
1157
1158 /******************************************************************************
1159 * Setup the LZ decompression for this image: *
1160 ******************************************************************************/
1161 static int DGifSetupDecompress(CGIFFF GifFileType *GifFile)
1162 {
1163 int i, BitsPerPixel;
1164 CGIFFF GifByteType CodeSize;
1165 unsigned int *Prefix;
1166 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1167
1168 if (fread(&CodeSize, 1, 1, Private->File) != 1) /* Read Code size from file. */
1169 return GIF_ERROR;
1170 BitsPerPixel = CodeSize;
1171
1172 Private->Buf[0] = 0; /* Input Buffer empty. */
1173 Private->BitsPerPixel = BitsPerPixel;
1174 Private->ClearCode = (1 << BitsPerPixel);
1175 Private->EOFCode = Private->ClearCode + 1;
1176 Private->RunningCode = Private->EOFCode + 1;
1177 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
1178 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
1179 Private->StackPtr = 0; /* No pixels on the pixel stack. */
1180 Private->LastCode = NO_SUCH_CODE;
1181 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
1182 Private->CrntShiftDWord = 0;
1183
1184 Prefix = Private->Prefix;
1185 for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
1186
1187 return GIF_OK;
1188 }
1189
1190 /******************************************************************************
1191 * The LZ decompression routine: *
1192 * This version decompress the given gif file into Line of length LineLen. *
1193 * This routine can be called few times (one per scan line, for example), in *
1194 * order the complete the whole image. *
1195 ******************************************************************************/
1196 static int DGifDecompressLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line,
1197 int LineLen)
1198 {
1199 int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
1200 CGIFFF GifByteType *Stack, *Suffix;
1201 unsigned int *Prefix;
1202 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1203
1204 StackPtr = Private->StackPtr;
1205 Prefix = Private->Prefix;
1206 Suffix = Private->Suffix;
1207 Stack = Private->Stack;
1208 EOFCode = Private->EOFCode;
1209 ClearCode = Private->ClearCode;
1210 LastCode = Private->LastCode;
1211
1212 if (StackPtr != 0) {
1213 /* Let pop the stack off before continueing to read the gif file: */
1214 while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
1215 }
1216
1217 while (i < LineLen) { /* Decode LineLen items. */
1218 if (DGifDecompressInput(Private, &CrntCode) == GIF_ERROR)
1219 return GIF_ERROR;
1220
1221 /*fprintf(stderr,"CrntCode=0x%x\n",CrntCode);*/
1222 if (CrntCode == EOFCode) {
1223 /* Note however that usually we will not be here as we will stop */
1224 /* decoding as soon as we got all the pixel, or EOF code will */
1225 /* not be read at all, and DGifGetLine/Pixel clean everything. */
1226 if (i != LineLen - 1 || Private->PixelCount != 0) {
1227 CGIFFF _GifError = D_GIF_ERR_EOF_TOO_SOON;
1228 return GIF_ERROR;
1229 }
1230 i++;
1231 }
1232 else if (CrntCode == ClearCode) {
1233 /* We need to start over again: */
1234 for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
1235 Private->RunningCode = Private->EOFCode + 1;
1236 Private->RunningBits = Private->BitsPerPixel + 1;
1237 Private->MaxCode1 = 1 << Private->RunningBits;
1238 LastCode = Private->LastCode = NO_SUCH_CODE;
1239 }
1240 else {
1241 /* Its regular code - if in pixel range simply add it to output */
1242 /* stream, otherwise trace to codes linked list until the prefix */
1243 /* is in pixel range: */
1244 if (CrntCode < ClearCode) {
1245 /* This is simple - its pixel scalar, so add it to output: */
1246 Line[i++] = CrntCode;
1247 }
1248 else {
1249 /* Its a code to needed to be traced: trace the linked list */
1250 /* until the prefix is a pixel, while pushing the suffix */
1251 /* pixels on our stack. If we done, pop the stack in reverse */
1252 /* (thats what stack is good for!) order to output. */
1253 if (Prefix[CrntCode] == NO_SUCH_CODE) {
1254 /* Only allowed if CrntCode is exactly the running code: */
1255 /* In that case CrntCode = XXXCode, CrntCode or the */
1256 /* prefix code is last code and the suffix char is */
1257 /* exactly the prefix of last code! */
1258 if (CrntCode == Private->RunningCode - 2) {
1259 CrntPrefix = LastCode;
1260 Suffix[Private->RunningCode - 2] =
1261 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
1262 LastCode, ClearCode);
1263 }
1264 else {
1265 CGIFFF _GifError = D_GIF_ERR_IMAGE_DEFECT;
1266 return GIF_ERROR;
1267 }
1268 }
1269 else
1270 CrntPrefix = CrntCode;
1271
1272 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */
1273 /* During the trace. As we might loop forever, in case of */
1274 /* defective image, we count the number of loops we trace */
1275 /* and stop if we got LZ_MAX_CODE. obviously we can not */
1276 /* loop more than that. */
1277 j = 0;
1278 while (j++ <= LZ_MAX_CODE &&
1279 CrntPrefix > ClearCode &&
1280 CrntPrefix <= LZ_MAX_CODE) {
1281 Stack[StackPtr++] = Suffix[CrntPrefix];
1282 CrntPrefix = Prefix[CrntPrefix];
1283 }
1284 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
1285 CGIFFF _GifError = D_GIF_ERR_IMAGE_DEFECT;
1286 return GIF_ERROR;
1287 }
1288 /* Push the last character on stack: */
1289 Stack[StackPtr++] = CrntPrefix;
1290
1291 /* Now lets pop all the stack into output: */
1292 while (StackPtr != 0 && i < LineLen)
1293 Line[i++] = Stack[--StackPtr];
1294 }
1295 if (LastCode != NO_SUCH_CODE) {
1296 Prefix[Private->RunningCode - 2] = LastCode;
1297
1298 if (CrntCode == Private->RunningCode - 2) {
1299 /* Only allowed if CrntCode is exactly the running code: */
1300 /* In that case CrntCode = XXXCode, CrntCode or the */
1301 /* prefix code is last code and the suffix char is */
1302 /* exactly the prefix of last code! */
1303 Suffix[Private->RunningCode - 2] =
1304 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
1305 }
1306 else {
1307 Suffix[Private->RunningCode - 2] =
1308 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
1309 }
1310 }
1311 LastCode = CrntCode;
1312 }
1313 }
1314
1315 Private->LastCode = LastCode;
1316 Private->StackPtr = StackPtr;
1317
1318 return GIF_OK;
1319 }
1320
1321 /******************************************************************************
1322 * Routine to trace the Prefixes linked list until we get a prefix which is *
1323 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
1324 * If image is defective, we might loop here forever, so we limit the loops to *
1325 * the maximum possible if image O.k. - LZ_MAX_CODE times. *
1326 ******************************************************************************/
1327 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
1328 {
1329 int i = 0;
1330
1331 while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
1332 return Code;
1333 }
1334
1335 /******************************************************************************
1336 * Interface for accessing the LZ codes directly. Set Code to the real code *
1337 * (12bits), or to -1 if EOF code is returned. *
1338 ******************************************************************************/
1339 int CGIFFF DGifGetLZCodes(CGIFFF GifFileType *GifFile, int *Code)
1340 {
1341 GifByteType *CodeBlock;
1342 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1343
1344 if (!IS_READABLE(Private)) {
1345 /* This file was NOT open for reading: */
1346 _GifError = D_GIF_ERR_NOT_READABLE;
1347 return GIF_ERROR;
1348 }
1349
1350 if (DGifDecompressInput(Private, Code) == GIF_ERROR)
1351 return GIF_ERROR;
1352
1353 if (*Code == Private->EOFCode) {
1354 /* Skip rest of codes (hopefully only NULL terminating block): */
1355 do if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
1356 return GIF_ERROR;
1357 while (CodeBlock != NULL);
1358
1359 *Code = -1;
1360 }
1361 else if (*Code == Private->ClearCode) {
1362 /* We need to start over again: */
1363 Private->RunningCode = Private->EOFCode + 1;
1364 Private->RunningBits = Private->BitsPerPixel + 1;
1365 Private->MaxCode1 = 1 << Private->RunningBits;
1366 }
1367
1368 return GIF_OK;
1369 }
1370
1371 /******************************************************************************
1372 * The LZ decompression input routine: *
1373 * This routine is responsable for the decompression of the bit stream from *
1374 * 8 bits (bytes) packets, into the real codes. *
1375 * Returns GIF_OK if read succesfully. *
1376 ******************************************************************************/
1377 static int DGifDecompressInput(GifFilePrivateType *Private, int *Code)
1378 {
1379 CGIFFF GifByteType NextByte;
1380 static unsigned int CodeMasks[] = {
1381 0x0000, 0x0001, 0x0003, 0x0007,
1382 0x000f, 0x001f, 0x003f, 0x007f,
1383 0x00ff, 0x01ff, 0x03ff, 0x07ff,
1384 0x0fff
1385 };
1386
1387 while (Private->CrntShiftState < Private->RunningBits) {
1388 /* Needs to get more bytes from input stream for next code: */
1389 if (DGifBufferedInput(Private->File, Private->Buf, &NextByte)
1390 == GIF_ERROR) {
1391 return GIF_ERROR;
1392 }
1393 Private->CrntShiftDWord |=
1394 ((unsigned long) NextByte) << Private->CrntShiftState;
1395 Private->CrntShiftState += 8;
1396 }
1397 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1398
1399 Private->CrntShiftDWord >>= Private->RunningBits;
1400 Private->CrntShiftState -= Private->RunningBits;
1401
1402 /* If code cannt fit into RunningBits bits, must raise its size. Note */
1403 /* however that codes above 4095 are used for special signaling. */
1404 if (++Private->RunningCode > Private->MaxCode1 &&
1405 Private->RunningBits < LZ_BITS) {
1406 Private->MaxCode1 <<= 1;
1407 Private->RunningBits++;
1408 }
1409 return GIF_OK;
1410 }
1411
1412 /******************************************************************************
1413 * This routines read one gif data block at a time and buffers it internally *
1414 * so that the decompression routine could access it. *
1415 * The routine returns the next byte from its internal buffer (or read next *
1416 * block in if buffer empty) and returns GIF_OK if succesful. *
1417 ******************************************************************************/
1418 static int DGifBufferedInput(FILE *File, CGIFFF GifByteType *Buf,
1419 CGIFFF GifByteType *NextByte)
1420 {
1421 if (Buf[0] == 0) {
1422 /* Needs to read the next buffer - this one is empty: */
1423 if (fread(Buf, 1, 1, File) != 1)
1424 {
1425 CGIFFF _GifError = D_GIF_ERR_READ_FAILED;
1426 return GIF_ERROR;
1427 }
1428 if (fread(&Buf[1], 1, Buf[0], File) != Buf[0])
1429 {
1430 CGIFFF _GifError = D_GIF_ERR_READ_FAILED;
1431 return GIF_ERROR;
1432 }
1433 *NextByte = Buf[1];
1434 Buf[1] = 2; /* We use now the second place as last char read! */
1435 Buf[0]--;
1436 }
1437 else {
1438 *NextByte = Buf[Buf[1]++];
1439 Buf[0]--;
1440 }
1441
1442 return GIF_OK;
1443 }
1444
1445 /******************************************************************************
1446 * This routine reads an entire GIF into core, hanging all its state info off *
1447 * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() *
1448 * first to initialize I/O. Its inverse is EGifSpew(). *
1449 ******************************************************************************/
1450 int CGIFFF DGifSlurp(CGIFFF GifFileType *GifFile)
1451 {
1452 static unsigned InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
1453 InterlacedJumps[] = { 8, 8, 4, 2 }; /* be read - offsets and jumps... */
1454 /**** pts: unused vars ****/
1455 /* int i, j, Error, ImageSize; */
1456 int ext_code;
1457
1458 GifRecordType RecordType;
1459 /**** pts ****/
1460 SavedImage *sp=0; /**** pts: avoid gcc warning */
1461 /** Extension info of next SavedImage */
1462 SavedImage ext;
1463 /** No-extension info */
1464 SavedImage noext;
1465
1466 GifByteType *ExtData;
1467
1468 /**** pts ****/
1469 memset(&noext, 0, sizeof(noext));
1470 noext.delay=0;
1471 noext.dispose=0;
1472 noext.iter=1;
1473 noext.transp=(-1);
1474 noext.ExtensionBlocks=NULL;
1475 noext.ExtensionBlockCount=0;
1476 ext=noext;
1477
1478 /**** pts ****/
1479 GifFile->SavedImages=0;
1480
1481 do {
1482 if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1483 return(GIF_ERROR);
1484
1485 switch (RecordType) {
1486 case IMAGE_DESC_RECORD_TYPE:
1487 if (DGifGetImageDesc(GifFile) == GIF_ERROR)
1488 return(GIF_ERROR);
1489
1490 /**** pts: DGifGetImageDesc has already allocated the mem ****/
1491 sp = &GifFile->SavedImages[GifFile->ImageCount-1];
1492 /**** pts: apply extensions to the image just read */
1493 ext.RasterBits=sp->RasterBits;
1494 ext.ImageDesc=sp->ImageDesc;
1495 *sp=ext;
1496 ext=noext;
1497
1498 /**** pts ****/
1499 sp->RasterBits = (GifPixelType*) malloc((0L+sp->ImageDesc.Width) * sp->ImageDesc.Height * sizeof(GifPixelType));
1500 if (sp->RasterBits==NULL) { _GifError=D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; }
1501 if (sp->ImageDesc.Interlace) {
1502 unsigned i, j, Height=sp->ImageDesc.Height, Width=sp->ImageDesc.Width;
1503 /* Need to perform 4 passes on the images: */
1504 for (i = 0; i < 4; i++)
1505 for (j = InterlacedOffset[i]; j < Height; j += InterlacedJumps[i])
1506 if (DGifGetLine(GifFile, sp->RasterBits+Width*j, Width) != GIF_OK) return GIF_ERROR;
1507 } else {
1508 if (DGifGetLine(GifFile, sp->RasterBits, (0L+sp->ImageDesc.Width) * sp->ImageDesc.Height)
1509 == GIF_ERROR)
1510 return(GIF_ERROR);
1511 }
1512 break;
1513
1514 case EXTENSION_RECORD_TYPE:
1515
1516 if (DGifGetExtension(GifFile,&ext_code,&ExtData)==GIF_ERROR)
1517 return(GIF_ERROR);
1518 if (ExtData!=NULL) {
1519 #if 0 /**** pts ****/
1520 ep = &ext.ExtensionBlocks[ext.ExtensionBlockCount++];
1521 ep->ByteCount = ExtData[0];
1522 ep->Bytes = (GifByteType *)malloc(ep->ByteCount * sizeof(GifByteType));
1523 memcpy(ep->Bytes, ExtData, ep->ByteCount * sizeof(char));
1524 #else
1525 /**** pts ****/
1526 if (0xf9==(unsigned char)(ext_code)) {
1527 assert(ExtData[0]>=4);
1528 ext.dispose=ExtData[1]>>2;
1529 ext.delay=(ExtData[3] << 8) | ExtData[2];
1530 if ((ExtData[1] & 0x01) == 1) ext.transp=ExtData[4];
1531 } else if (0xff==(unsigned char)(ext_code)) {
1532 assert(ExtData[0]>=3);
1533 ext.iter=(ExtData[3] << 8) | ExtData[2];
1534 } else {
1535 AddExtensionBlock(&ext, ExtData[0], ExtData+1);
1536 ext.ExtensionBlocks[ext.ExtensionBlockCount-1].code=ext_code;
1537 }
1538 #endif
1539 while (1) {
1540 if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1541 return(GIF_ERROR);
1542 #if 0 /**** pts ****/
1543 ep = &ext.ExtensionBlocks[ext.ExtensionBlockCount++];
1544 ep->ByteCount = ExtData[0];
1545 ep->Bytes = (GifByteType *)malloc(ep->ByteCount * sizeof(GifByteType));
1546 memcpy(ep->Bytes,ExtData,ep->ByteCount * sizeof(char));
1547 #else
1548 if (ExtData==NULL) break;
1549 AddExtensionBlock(sp, ExtData[0], ExtData+1);
1550 #endif
1551 }
1552 }
1553 break;
1554
1555 case TERMINATE_RECORD_TYPE:
1556 break;
1557
1558 default: /* Should be trapped by DGifGetRecordType */
1559 break;
1560 }
1561 }
1562 while
1563 (RecordType != TERMINATE_RECORD_TYPE);
1564
1565 return(GIF_OK);
1566 }
1567
1568 /* __END__ */
1569