1 /******************************************************************************
2 * "Gif-Lib" - Yet another gif library. *
4 * Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 *
5 *******************************************************************************
6 * The kernel of the GIF Decoding process can be found here. *
7 *******************************************************************************
9 * 16 Jun 89 - Version 1.0 by Gershon Elber. *
10 * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
11 ******************************************************************************/
17 #if defined (__MSDOS__) && !defined(__DJGPP__) && !defined(__GNUC__)
23 #include <sys/types.h>
25 #endif /* __MSDOS__ */
38 #include "gif_lib_private.h"
40 #define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for comment. */
42 /* avoid extra function call in case we use fread (TVT) */
43 #define READ(_gif,_buf,_len) \
44 (((GifFilePrivateType*)_gif->Private)->Read ? \
45 ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \
46 fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File))
48 static int DGifGetWord(GifFileType *GifFile, int *Word);
49 static int DGifSetupDecompress(GifFileType *GifFile);
50 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
52 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
53 static int DGifDecompressInput(GifFileType *GifFile, int *Code);
54 static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
55 GifByteType *NextByte);
57 /******************************************************************************
58 * Open a new gif file for read, given by its name. *
59 * Returns GifFileType pointer dynamically allocated which serves as the gif *
60 * info record. _GifError is cleared if succesfull. *
61 ******************************************************************************/
62 GifFileType *DGifOpenFileName(const char *FileName)
67 if ((FileHandle = open(FileName, O_RDONLY
68 #if defined(__MSDOS__) || defined(_OPEN_BINARY)
70 #endif /* __MSDOS__ || _OPEN_BINARY */
72 _GifError = D_GIF_ERR_OPEN_FAILED;
76 GifFile = DGifOpenFileHandle(FileHandle);
77 #if !defined(__EMSCRIPTEN__)
78 if (GifFile == (GifFileType *)NULL)
84 /******************************************************************************
85 * Update a new gif file, given its file handle. *
86 * Returns GifFileType pointer dynamically allocated which serves as the gif *
87 * info record. _GifError is cleared if succesfull. *
88 ******************************************************************************/
89 GifFileType *DGifOpenFileHandle(int FileHandle)
91 char Buf[GIF_STAMP_LEN+1];
93 GifFilePrivateType *Private;
96 GifFile = (GifFileType *) malloc(sizeof(GifFileType));
97 if (GifFile == NULL) {
98 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
102 memset(GifFile, '\0', sizeof(GifFileType));
104 Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType));
105 if (Private == NULL) {
106 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
107 free((char *) GifFile);
112 setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
113 #endif /* __MSDOS__ */
115 f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
118 setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/
119 #endif /* __MSDOS__ */
121 GifFile->Private = (VoidPtr) Private;
122 Private->FileHandle = FileHandle;
124 Private->FileState = FILE_STATE_READ;
125 Private->Read = 0; /* don't use alternate input method (TVT) */
126 GifFile->UserData = 0; /* TVT */
128 /* Lets see if this is a GIF file: */
129 if (READ(GifFile,Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
130 _GifError = D_GIF_ERR_READ_FAILED;
132 free((char *) Private);
133 free((char *) GifFile);
137 /* The GIF Version number is ignored at this time. Maybe we should do */
138 /* something more useful with it. */
139 Buf[GIF_STAMP_LEN] = 0;
140 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
141 _GifError = D_GIF_ERR_NOT_GIF_FILE;
143 free((char *) Private);
144 free((char *) GifFile);
148 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
150 free((char *) Private);
151 free((char *) GifFile);
160 /******************************************************************************
161 * GifFileType constructor with user supplied input function (TVT) *
163 ******************************************************************************/
164 GifFileType *DGifOpen( void* userData, InputFunc readFunc )
166 char Buf[GIF_STAMP_LEN+1];
167 GifFileType *GifFile;
168 GifFilePrivateType *Private;
170 GifFile = (GifFileType *) malloc(sizeof(GifFileType));
171 if (GifFile == NULL) {
172 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
176 memset(GifFile, '\0', sizeof(GifFileType));
178 Private = (GifFilePrivateType*) malloc(sizeof(GifFilePrivateType));
180 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
181 free((char *) GifFile);
185 GifFile->Private = (VoidPtr) Private;
186 Private->FileHandle = 0;
188 Private->FileState = FILE_STATE_READ;
190 Private->Read = readFunc; /* TVT */
191 GifFile->UserData = userData; /* TVT */
193 /* Lets see if this is a GIF file: */
194 if ( READ( GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
195 _GifError = D_GIF_ERR_READ_FAILED;
196 free((char *) Private);
197 free((char *) GifFile);
201 /* The GIF Version number is ignored at this time. Maybe we should do */
202 /* something more useful with it. */
203 Buf[GIF_STAMP_LEN] = 0;
204 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
205 _GifError = D_GIF_ERR_NOT_GIF_FILE;
206 free((char *) Private);
207 free((char *) GifFile);
211 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
212 free((char *) Private);
213 free((char *) GifFile);
222 /******************************************************************************
223 * This routine should be called before any other DGif calls. Note that *
224 * this routine is called automatically from DGif file open routines. *
225 ******************************************************************************/
226 int DGifGetScreenDesc(GifFileType *GifFile)
230 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
232 if (!IS_READABLE(Private)) {
233 /* This file was NOT open for reading: */
234 _GifError = D_GIF_ERR_NOT_READABLE;
238 /* Put the screen descriptor into the file: */
239 if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
240 DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
243 if (READ( GifFile, Buf, 3) != 3) {
244 _GifError = D_GIF_ERR_READ_FAILED;
247 GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
248 BitsPerPixel = (Buf[0] & 0x07) + 1;
249 GifFile->SBackGroundColor = Buf[1];
250 if (Buf[0] & 0x80) { /* Do we have global color map? */
252 GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
254 /* Get the global color map: */
255 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
256 if (READ(GifFile, Buf, 3) != 3) {
257 _GifError = D_GIF_ERR_READ_FAILED;
260 GifFile->SColorMap->Colors[i].Red = Buf[0];
261 GifFile->SColorMap->Colors[i].Green = Buf[1];
262 GifFile->SColorMap->Colors[i].Blue = Buf[2];
269 /******************************************************************************
270 * This routine should be called before any attemp to read an image. *
271 ******************************************************************************/
272 int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
275 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
277 if (!IS_READABLE(Private)) {
278 /* This file was NOT open for reading: */
279 _GifError = D_GIF_ERR_NOT_READABLE;
283 if (READ( GifFile, &Buf, 1) != 1) {
284 _GifError = D_GIF_ERR_READ_FAILED;
290 *Type = IMAGE_DESC_RECORD_TYPE;
293 *Type = EXTENSION_RECORD_TYPE;
296 *Type = TERMINATE_RECORD_TYPE;
299 *Type = UNDEFINED_RECORD_TYPE;
300 _GifError = D_GIF_ERR_WRONG_RECORD;
307 /******************************************************************************
308 * This routine should be called before any attemp to read an image. *
309 * Note it is assumed the Image desc. header (',') has been read. *
310 ******************************************************************************/
311 int DGifGetImageDesc(GifFileType *GifFile)
315 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
318 if (!IS_READABLE(Private)) {
319 /* This file was NOT open for reading: */
320 _GifError = D_GIF_ERR_NOT_READABLE;
324 if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
325 DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
326 DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
327 DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
329 if (READ(GifFile,Buf, 1) != 1) {
330 _GifError = D_GIF_ERR_READ_FAILED;
333 BitsPerPixel = (Buf[0] & 0x07) + 1;
334 GifFile->Image.Interlace = (Buf[0] & 0x40);
335 if (Buf[0] & 0x80) { /* Does this image have local color map? */
337 if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
338 FreeMapObject(GifFile->Image.ColorMap);
340 GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
342 /* Get the image local color map: */
343 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
344 if (READ(GifFile,Buf, 3) != 3) {
345 _GifError = D_GIF_ERR_READ_FAILED;
348 GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
349 GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
350 GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
353 else if (GifFile->Image.ColorMap)
355 FreeMapObject(GifFile->Image.ColorMap);
356 GifFile->Image.ColorMap = NULL;
359 if (GifFile->SavedImages) {
360 if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
361 sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) {
362 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
366 if ((GifFile->SavedImages =
367 (SavedImage *)malloc(sizeof(SavedImage))) == NULL) {
368 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
373 sp = &GifFile->SavedImages[GifFile->ImageCount];
374 memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
375 if (GifFile->Image.ColorMap != NULL) {
376 sp->ImageDesc.ColorMap = MakeMapObject(
377 GifFile->Image.ColorMap->ColorCount,
378 GifFile->Image.ColorMap->Colors);
380 sp->RasterBits = (char *)NULL;
381 sp->ExtensionBlockCount = 0;
382 sp->ExtensionBlocks = (ExtensionBlock *)NULL;
384 GifFile->ImageCount++;
386 Private->PixelCount = (long) GifFile->Image.Width *
387 (long) GifFile->Image.Height;
389 DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
394 /******************************************************************************
395 * Get one full scanned line (Line) of length LineLen from GIF file. *
396 ******************************************************************************/
397 int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
400 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
402 if (!IS_READABLE(Private)) {
403 /* This file was NOT open for reading: */
404 _GifError = D_GIF_ERR_NOT_READABLE;
408 if (!LineLen) LineLen = GifFile->Image.Width;
410 #if defined(__MSDOS__) || defined(__GNUC__)
411 if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
413 if ((Private->PixelCount -= LineLen) > 0xffff0000) {
414 #endif /* __MSDOS__ */
415 _GifError = D_GIF_ERR_DATA_TOO_BIG;
419 if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
420 if (Private->PixelCount == 0) {
421 /* We probably would not be called any more, so lets clean */
422 /* everything before we return: need to flush out all rest of */
423 /* image until empty block (size 0) detected. We use GetCodeNext.*/
424 do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
426 while (Dummy != NULL);
434 /******************************************************************************
435 * Put one pixel (Pixel) into GIF file. *
436 ******************************************************************************/
437 int DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
440 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
442 if (!IS_READABLE(Private)) {
443 /* This file was NOT open for reading: */
444 _GifError = D_GIF_ERR_NOT_READABLE;
448 #if defined(__MSDOS__) || defined(__GNUC__)
449 if (--Private->PixelCount > 0xffff0000UL)
451 if (--Private->PixelCount > 0xffff0000)
452 #endif /* __MSDOS__ */
454 _GifError = D_GIF_ERR_DATA_TOO_BIG;
458 if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
459 if (Private->PixelCount == 0) {
460 /* We probably would not be called any more, so lets clean */
461 /* everything before we return: need to flush out all rest of */
462 /* image until empty block (size 0) detected. We use GetCodeNext.*/
463 do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
465 while (Dummy != NULL);
473 /******************************************************************************
474 * Get an extension block (see GIF manual) from gif file. This routine only *
475 * returns the first data block, and DGifGetExtensionNext shouldbe called *
476 * after this one until NULL extension is returned. *
477 * The Extension should NOT be freed by the user (not dynamically allocated).*
478 * Note it is assumed the Extension desc. header ('!') has been read. *
479 ******************************************************************************/
480 int DGifGetExtension(GifFileType *GifFile, int *ExtCode,
481 GifByteType **Extension)
484 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
486 if (!IS_READABLE(Private)) {
487 /* This file was NOT open for reading: */
488 _GifError = D_GIF_ERR_NOT_READABLE;
492 if (READ(GifFile,&Buf, 1) != 1) {
493 _GifError = D_GIF_ERR_READ_FAILED;
498 return DGifGetExtensionNext(GifFile, Extension);
501 /******************************************************************************
502 * Get a following extension block (see GIF manual) from gif file. This *
503 * routine should be called until NULL Extension is returned. *
504 * The Extension should NOT be freed by the user (not dynamically allocated).*
505 ******************************************************************************/
506 int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension)
509 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
511 if (READ(GifFile,&Buf, 1) != 1) {
512 _GifError = D_GIF_ERR_READ_FAILED;
516 *Extension = Private->Buf; /* Use private unused buffer. */
517 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
518 if (READ(GifFile,&((*Extension)[1]), Buf) != Buf) {
519 _GifError = D_GIF_ERR_READ_FAILED;
529 /******************************************************************************
530 * This routine should be called last, to close the GIF file. *
531 ******************************************************************************/
532 int DGifCloseFile(GifFileType *GifFile)
534 GifFilePrivateType *Private;
537 if (GifFile == NULL) return GIF_ERROR;
539 Private = (GifFilePrivateType *) GifFile->Private;
541 if (!IS_READABLE(Private)) {
542 /* This file was NOT open for reading: */
543 _GifError = D_GIF_ERR_NOT_READABLE;
547 File = Private->File;
549 if (GifFile->Image.ColorMap)
551 FreeMapObject(GifFile->Image.ColorMap);
552 GifFile->Image.ColorMap = NULL;
555 if (GifFile->SColorMap)
557 FreeMapObject(GifFile->SColorMap);
558 GifFile->SColorMap = NULL;
563 free((char *) Private);
567 if (GifFile->SavedImages)
569 FreeSavedImages(GifFile);
570 GifFile->SavedImages = NULL;
575 if ( File && (fclose(File) != 0)) {
576 _GifError = D_GIF_ERR_CLOSE_FAILED;
582 /******************************************************************************
583 * Get 2 bytes (word) from the given file: *
584 ******************************************************************************/
585 static int DGifGetWord(GifFileType *GifFile, int *Word)
589 if (READ(GifFile,c, 2) != 2) {
590 _GifError = D_GIF_ERR_READ_FAILED;
594 *Word = (((unsigned int) c[1]) << 8) + c[0];
598 /******************************************************************************
599 * Get the image code in compressed form. his routine can be called if the *
600 * information needed to be piped out as is. Obviously this is much faster *
601 * than decoding and encoding again. This routine should be followed by calls *
602 * to DGifGetCodeNext, until NULL block is returned. *
603 * The block should NOT be freed by the user (not dynamically allocated). *
604 ******************************************************************************/
605 int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
607 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
609 if (!IS_READABLE(Private)) {
610 /* This file was NOT open for reading: */
611 _GifError = D_GIF_ERR_NOT_READABLE;
615 *CodeSize = Private->BitsPerPixel;
617 return DGifGetCodeNext(GifFile, CodeBlock);
620 /******************************************************************************
621 * Continue to get the image code in compressed form. This routine should be *
622 * called until NULL block is returned. *
623 * The block should NOT be freed by the user (not dynamically allocated). *
624 ******************************************************************************/
625 int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
628 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
630 if (READ(GifFile,&Buf, 1) != 1) {
631 _GifError = D_GIF_ERR_READ_FAILED;
636 *CodeBlock = Private->Buf; /* Use private unused buffer. */
637 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
638 if (READ(GifFile,&((*CodeBlock)[1]), Buf) != Buf) {
639 _GifError = D_GIF_ERR_READ_FAILED;
645 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
646 Private->PixelCount = 0; /* And local info. indicate image read. */
652 /******************************************************************************
653 * Setup the LZ decompression for this image: *
654 ******************************************************************************/
655 static int DGifSetupDecompress(GifFileType *GifFile)
658 GifByteType CodeSize;
659 unsigned int *Prefix;
660 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
662 READ(GifFile,&CodeSize, 1); /* Read Code size from file. */
663 BitsPerPixel = CodeSize;
665 Private->Buf[0] = 0; /* Input Buffer empty. */
666 Private->BitsPerPixel = BitsPerPixel;
667 Private->ClearCode = (1 << BitsPerPixel);
668 Private->EOFCode = Private->ClearCode + 1;
669 Private->RunningCode = Private->EOFCode + 1;
670 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
671 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
672 Private->StackPtr = 0; /* No pixels on the pixel stack. */
673 Private->LastCode = NO_SUCH_CODE;
674 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
675 Private->CrntShiftDWord = 0;
677 Prefix = Private->Prefix;
678 for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
683 /******************************************************************************
684 * The LZ decompression routine: *
685 * This version decompress the given gif file into Line of length LineLen. *
686 * This routine can be called few times (one per scan line, for example), in *
687 * order the complete the whole image. *
688 ******************************************************************************/
689 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
692 int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
693 GifByteType *Stack, *Suffix;
694 unsigned int *Prefix;
695 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
697 StackPtr = Private->StackPtr;
698 Prefix = Private->Prefix;
699 Suffix = Private->Suffix;
700 Stack = Private->Stack;
701 EOFCode = Private->EOFCode;
702 ClearCode = Private->ClearCode;
703 LastCode = Private->LastCode;
706 /* Let pop the stack off before continueing to read the gif file: */
707 while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
710 while (i < LineLen) { /* Decode LineLen items. */
711 if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
714 if (CrntCode == EOFCode) {
715 /* Note however that usually we will not be here as we will stop */
716 /* decoding as soon as we got all the pixel, or EOF code will */
717 /* not be read at all, and DGifGetLine/Pixel clean everything. */
718 if (i != LineLen - 1 || Private->PixelCount != 0) {
719 _GifError = D_GIF_ERR_EOF_TOO_SOON;
724 else if (CrntCode == ClearCode) {
725 /* We need to start over again: */
726 for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
727 Private->RunningCode = Private->EOFCode + 1;
728 Private->RunningBits = Private->BitsPerPixel + 1;
729 Private->MaxCode1 = 1 << Private->RunningBits;
730 LastCode = Private->LastCode = NO_SUCH_CODE;
733 /* Its regular code - if in pixel range simply add it to output */
734 /* stream, otherwise trace to codes linked list until the prefix */
735 /* is in pixel range: */
736 if (CrntCode < ClearCode) {
737 /* This is simple - its pixel scalar, so add it to output: */
738 Line[i++] = CrntCode;
741 /* Its a code to needed to be traced: trace the linked list */
742 /* until the prefix is a pixel, while pushing the suffix */
743 /* pixels on our stack. If we done, pop the stack in reverse */
744 /* (thats what stack is good for!) order to output. */
745 if (Prefix[CrntCode] == NO_SUCH_CODE) {
746 /* Only allowed if CrntCode is exactly the running code: */
747 /* In that case CrntCode = XXXCode, CrntCode or the */
748 /* prefix code is last code and the suffix char is */
749 /* exactly the prefix of last code! */
750 if (CrntCode == Private->RunningCode - 2) {
751 CrntPrefix = LastCode;
752 Suffix[Private->RunningCode - 2] =
753 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
754 LastCode, ClearCode);
757 _GifError = D_GIF_ERR_IMAGE_DEFECT;
762 CrntPrefix = CrntCode;
764 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */
765 /* During the trace. As we might loop forever, in case of */
766 /* defective image, we count the number of loops we trace */
767 /* and stop if we got LZ_MAX_CODE. obviously we can not */
768 /* loop more than that. */
770 while (j++ <= LZ_MAX_CODE &&
771 CrntPrefix > ClearCode &&
772 CrntPrefix <= LZ_MAX_CODE) {
773 Stack[StackPtr++] = Suffix[CrntPrefix];
774 CrntPrefix = Prefix[CrntPrefix];
776 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
777 _GifError = D_GIF_ERR_IMAGE_DEFECT;
780 /* Push the last character on stack: */
781 Stack[StackPtr++] = CrntPrefix;
783 /* Now lets pop all the stack into output: */
784 while (StackPtr != 0 && i < LineLen)
785 Line[i++] = Stack[--StackPtr];
787 if (LastCode != NO_SUCH_CODE) {
788 Prefix[Private->RunningCode - 2] = LastCode;
790 if (CrntCode == Private->RunningCode - 2) {
791 /* Only allowed if CrntCode is exactly the running code: */
792 /* In that case CrntCode = XXXCode, CrntCode or the */
793 /* prefix code is last code and the suffix char is */
794 /* exactly the prefix of last code! */
795 Suffix[Private->RunningCode - 2] =
796 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
799 Suffix[Private->RunningCode - 2] =
800 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
807 Private->LastCode = LastCode;
808 Private->StackPtr = StackPtr;
813 /******************************************************************************
814 * Routine to trace the Prefixes linked list until we get a prefix which is *
815 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
816 * If image is defective, we might loop here forever, so we limit the loops to *
817 * the maximum possible if image O.k. - LZ_MAX_CODE times. *
818 ******************************************************************************/
819 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
823 while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
827 /******************************************************************************
828 * Interface for accessing the LZ codes directly. Set Code to the real code *
829 * (12bits), or to -1 if EOF code is returned. *
830 ******************************************************************************/
831 int DGifGetLZCodes(GifFileType *GifFile, int *Code)
833 GifByteType *CodeBlock;
834 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
836 if (!IS_READABLE(Private)) {
837 /* This file was NOT open for reading: */
838 _GifError = D_GIF_ERR_NOT_READABLE;
842 if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)
845 if (*Code == Private->EOFCode) {
846 /* Skip rest of codes (hopefully only NULL terminating block): */
847 do if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
849 while (CodeBlock != NULL);
853 else if (*Code == Private->ClearCode) {
854 /* We need to start over again: */
855 Private->RunningCode = Private->EOFCode + 1;
856 Private->RunningBits = Private->BitsPerPixel + 1;
857 Private->MaxCode1 = 1 << Private->RunningBits;
863 /******************************************************************************
864 * The LZ decompression input routine: *
865 * This routine is responsable for the decompression of the bit stream from *
866 * 8 bits (bytes) packets, into the real codes. *
867 * Returns GIF_OK if read succesfully. *
868 ******************************************************************************/
869 static int DGifDecompressInput(GifFileType *GifFile, int *Code)
871 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
873 GifByteType NextByte;
874 static unsigned int CodeMasks[] = {
875 0x0000, 0x0001, 0x0003, 0x0007,
876 0x000f, 0x001f, 0x003f, 0x007f,
877 0x00ff, 0x01ff, 0x03ff, 0x07ff,
881 while (Private->CrntShiftState < Private->RunningBits) {
882 /* Needs to get more bytes from input stream for next code: */
883 if (DGifBufferedInput(GifFile, Private->Buf, &NextByte)
887 Private->CrntShiftDWord |=
888 ((unsigned long) NextByte) << Private->CrntShiftState;
889 Private->CrntShiftState += 8;
891 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
893 Private->CrntShiftDWord >>= Private->RunningBits;
894 Private->CrntShiftState -= Private->RunningBits;
896 /* If code cannt fit into RunningBits bits, must raise its size. Note */
897 /* however that codes above 4095 are used for special signaling. */
898 if (++Private->RunningCode > Private->MaxCode1 &&
899 Private->RunningBits < LZ_BITS) {
900 Private->MaxCode1 <<= 1;
901 Private->RunningBits++;
906 /******************************************************************************
907 * This routines read one gif data block at a time and buffers it internally *
908 * so that the decompression routine could access it. *
909 * The routine returns the next byte from its internal buffer (or read next *
910 * block in if buffer empty) and returns GIF_OK if succesful. *
911 ******************************************************************************/
912 static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
913 GifByteType *NextByte)
916 /* Needs to read the next buffer - this one is empty: */
917 if (READ(GifFile, Buf, 1) != 1)
919 _GifError = D_GIF_ERR_READ_FAILED;
922 if (READ(GifFile,&Buf[1], Buf[0]) != Buf[0])
924 _GifError = D_GIF_ERR_READ_FAILED;
928 Buf[1] = 2; /* We use now the second place as last char read! */
932 *NextByte = Buf[Buf[1]++];
939 /******************************************************************************
940 * This routine reads an entire GIF into core, hanging all its state info off *
941 * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() *
942 * first to initialize I/O. Its inverse is EGifSpew(). *
944 ******************************************************************************/
945 int DGifSlurp(GifFileType *GifFile)
947 int i, j, Error, ImageSize;
948 GifRecordType RecordType;
950 GifByteType *ExtData;
951 SavedImage temp_save;
953 temp_save.ExtensionBlocks=NULL;
954 temp_save.ExtensionBlockCount=0;
957 if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
960 switch (RecordType) {
961 case IMAGE_DESC_RECORD_TYPE:
962 if (DGifGetImageDesc(GifFile) == GIF_ERROR)
965 sp = &GifFile->SavedImages[GifFile->ImageCount-1];
966 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
969 = (char *) malloc(ImageSize * sizeof(GifPixelType));
971 if (DGifGetLine(GifFile, sp->RasterBits, ImageSize)
975 if (temp_save.ExtensionBlocks) {
976 sp->ExtensionBlocks = temp_save.ExtensionBlocks;
977 sp->ExtensionBlockCount = temp_save.ExtensionBlockCount;
979 temp_save.ExtensionBlocks = NULL;
980 temp_save.ExtensionBlockCount=0;
982 /* FIXME: The following is wrong. It is left in only for backwards
983 * compatibility. Someday it should go away. Use the
984 * sp->ExtensionBlocks->Function variable instead.
986 sp->Function = sp->ExtensionBlocks[0].Function;
992 case EXTENSION_RECORD_TYPE:
993 if (DGifGetExtension(GifFile,&temp_save.Function,&ExtData)==GIF_ERROR)
995 while (ExtData != NULL) {
997 /* Create an extension block with our data */
998 if (AddExtensionBlock(&temp_save, ExtData[0], &ExtData[1])
1002 if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1004 temp_save.Function = 0;
1008 case TERMINATE_RECORD_TYPE:
1011 default: /* Should be trapped by DGifGetRecordType */
1014 } while (RecordType != TERMINATE_RECORD_TYPE);
1016 /* Just in case the Gif has an extension block without an associated
1017 * image... (Should we save this into a savefile structure with no image
1018 * instead? Have to check if the present writing code can handle that as
1021 if (temp_save.ExtensionBlocks)
1022 FreeExtension(&temp_save);