1 /******************************************************************************
3 dgif_lib.c - GIF decoding
5 The functions here and in egif_lib.c are partitioned carefully so that
6 if you only require one of read and write capability, only one of these
7 two modules will be linked. Preserve this property!
9 SPDX-License-Identifier: MIT
11 *****************************************************************************/
27 #include "gif_lib_private.h"
29 /* compose unsigned little endian value */
30 #define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
32 /* avoid extra function call in case we use fread (TVT) */
33 static int InternalRead(GifFileType *gif, GifByteType *buf, int len) {
34 //fprintf(stderr, "### Read: %d\n", len);
36 (((GifFilePrivateType*)gif->Private)->Read ?
37 ((GifFilePrivateType*)gif->Private)->Read(gif,buf,len) :
38 fread(buf,1,len,((GifFilePrivateType*)gif->Private)->File));
41 static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
42 static int DGifSetupDecompress(GifFileType *GifFile);
43 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
45 static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode);
46 static int DGifDecompressInput(GifFileType *GifFile, int *Code);
47 static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
48 GifByteType *NextByte);
50 /******************************************************************************
51 Open a new GIF file for read, given by its name.
52 Returns dynamically allocated GifFileType pointer which serves as the GIF
54 ******************************************************************************/
56 DGifOpenFileName(const char *FileName, int *Error)
61 if ((FileHandle = open(FileName, O_RDONLY)) == -1) {
63 *Error = D_GIF_ERR_OPEN_FAILED;
67 GifFile = DGifOpenFileHandle(FileHandle, Error);
71 /******************************************************************************
72 Update a new GIF file, given its file handle.
73 Returns dynamically allocated GifFileType pointer which serves as the GIF
75 ******************************************************************************/
77 DGifOpenFileHandle(int FileHandle, int *Error)
79 char Buf[GIF_STAMP_LEN + 1];
81 GifFilePrivateType *Private;
84 GifFile = (GifFileType *)malloc(sizeof(GifFileType));
85 if (GifFile == NULL) {
87 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
88 (void)close(FileHandle);
92 /*@i1@*/memset(GifFile, '\0', sizeof(GifFileType));
94 /* Belt and suspenders, in case the null pointer isn't zero */
95 GifFile->SavedImages = NULL;
96 GifFile->SColorMap = NULL;
98 Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
99 if (Private == NULL) {
101 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
102 (void)close(FileHandle);
103 free((char *)GifFile);
107 /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
110 _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
113 f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
116 GifFile->Private = (void *)Private;
117 Private->FileHandle = FileHandle;
119 Private->FileState = FILE_STATE_READ;
120 Private->Read = NULL; /* don't use alternate input method (TVT) */
121 GifFile->UserData = NULL; /* TVT */
124 /* Let's see if this is a GIF file: */
125 /* coverity[check_return] */
126 if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
128 *Error = D_GIF_ERR_READ_FAILED;
130 free((char *)Private);
131 free((char *)GifFile);
135 /* Check for GIF prefix at start of file */
136 Buf[GIF_STAMP_LEN] = 0;
137 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
139 *Error = D_GIF_ERR_NOT_GIF_FILE;
141 free((char *)Private);
142 free((char *)GifFile);
146 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
148 free((char *)Private);
149 free((char *)GifFile);
155 /* What version of GIF? */
156 Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
161 /******************************************************************************
162 GifFileType constructor with user supplied input function (TVT)
163 ******************************************************************************/
165 DGifOpen(void *userData, InputFunc readFunc, int *Error)
167 char Buf[GIF_STAMP_LEN + 1];
168 GifFileType *GifFile;
169 GifFilePrivateType *Private;
171 GifFile = (GifFileType *)malloc(sizeof(GifFileType));
172 if (GifFile == NULL) {
174 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
178 memset(GifFile, '\0', sizeof(GifFileType));
180 /* Belt and suspenders, in case the null pointer isn't zero */
181 GifFile->SavedImages = NULL;
182 GifFile->SColorMap = NULL;
184 Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
187 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
188 free((char *)GifFile);
191 /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
193 GifFile->Private = (void *)Private;
194 Private->FileHandle = 0;
195 Private->File = NULL;
196 Private->FileState = FILE_STATE_READ;
198 Private->Read = readFunc; /* TVT */
199 GifFile->UserData = userData; /* TVT */
201 /* Lets see if this is a GIF file: */
202 /* coverity[check_return] */
203 if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
205 *Error = D_GIF_ERR_READ_FAILED;
206 free((char *)Private);
207 free((char *)GifFile);
211 /* Check for GIF prefix at start of file */
212 Buf[GIF_STAMP_LEN] = '\0';
213 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
215 *Error = D_GIF_ERR_NOT_GIF_FILE;
216 free((char *)Private);
217 free((char *)GifFile);
221 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
222 free((char *)Private);
223 free((char *)GifFile);
225 *Error = D_GIF_ERR_NO_SCRN_DSCR;
231 /* What version of GIF? */
232 Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
237 /******************************************************************************
238 This routine should be called before any other DGif calls. Note that
239 this routine is called automatically from DGif file open routines.
240 ******************************************************************************/
242 DGifGetScreenDesc(GifFileType *GifFile)
247 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
249 if (!IS_READABLE(Private)) {
250 /* This file was NOT open for reading: */
251 GifFile->Error = D_GIF_ERR_NOT_READABLE;
255 /* Put the screen descriptor into the file: */
256 if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
257 DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
260 if (InternalRead(GifFile, Buf, 3) != 3) {
261 GifFile->Error = D_GIF_ERR_READ_FAILED;
262 GifFreeMapObject(GifFile->SColorMap);
263 GifFile->SColorMap = NULL;
266 GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
267 SortFlag = (Buf[0] & 0x08) != 0;
268 BitsPerPixel = (Buf[0] & 0x07) + 1;
269 GifFile->SBackGroundColor = Buf[1];
270 GifFile->AspectByte = Buf[2];
271 if (Buf[0] & 0x80) { /* Do we have global color map? */
274 GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
275 if (GifFile->SColorMap == NULL) {
276 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
280 /* Get the global color map: */
281 GifFile->SColorMap->SortFlag = SortFlag;
282 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
283 /* coverity[check_return] */
284 if (InternalRead(GifFile, Buf, 3) != 3) {
285 GifFreeMapObject(GifFile->SColorMap);
286 GifFile->SColorMap = NULL;
287 GifFile->Error = D_GIF_ERR_READ_FAILED;
290 GifFile->SColorMap->Colors[i].Red = Buf[0];
291 GifFile->SColorMap->Colors[i].Green = Buf[1];
292 GifFile->SColorMap->Colors[i].Blue = Buf[2];
295 GifFile->SColorMap = NULL;
299 * No check here for whether the background color is in range for the
300 * screen color map. Possibly there should be.
307 DGifGetGifVersion(GifFileType *GifFile)
309 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
317 /******************************************************************************
318 This routine should be called before any attempt to read an image.
319 ******************************************************************************/
321 DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type)
324 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
326 if (!IS_READABLE(Private)) {
327 /* This file was NOT open for reading: */
328 GifFile->Error = D_GIF_ERR_NOT_READABLE;
332 /* coverity[check_return] */
333 if (InternalRead(GifFile, &Buf, 1) != 1) {
334 GifFile->Error = D_GIF_ERR_READ_FAILED;
338 //fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf);
340 case DESCRIPTOR_INTRODUCER:
341 *Type = IMAGE_DESC_RECORD_TYPE;
343 case EXTENSION_INTRODUCER:
344 *Type = EXTENSION_RECORD_TYPE;
346 case TERMINATOR_INTRODUCER:
347 *Type = TERMINATE_RECORD_TYPE;
350 *Type = UNDEFINED_RECORD_TYPE;
351 GifFile->Error = D_GIF_ERR_WRONG_RECORD;
359 DGifGetImageHeader(GifFileType *GifFile)
361 unsigned int BitsPerPixel;
363 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
365 if (!IS_READABLE(Private)) {
366 /* This file was NOT open for reading: */
367 GifFile->Error = D_GIF_ERR_NOT_READABLE;
371 if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
372 DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
373 DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
374 DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
376 if (InternalRead(GifFile, Buf, 1) != 1) {
377 GifFile->Error = D_GIF_ERR_READ_FAILED;
378 GifFreeMapObject(GifFile->Image.ColorMap);
379 GifFile->Image.ColorMap = NULL;
382 BitsPerPixel = (Buf[0] & 0x07) + 1;
383 GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false;
385 /* Setup the colormap */
386 if (GifFile->Image.ColorMap) {
387 GifFreeMapObject(GifFile->Image.ColorMap);
388 GifFile->Image.ColorMap = NULL;
390 /* Does this image have local color map? */
394 GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
395 if (GifFile->Image.ColorMap == NULL) {
396 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
400 /* Get the image local color map: */
401 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
402 /* coverity[check_return] */
403 if (InternalRead(GifFile, Buf, 3) != 3) {
404 GifFreeMapObject(GifFile->Image.ColorMap);
405 GifFile->Error = D_GIF_ERR_READ_FAILED;
406 GifFile->Image.ColorMap = NULL;
409 GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
410 GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
411 GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
415 Private->PixelCount = (long)GifFile->Image.Width *
416 (long)GifFile->Image.Height;
418 /* Reset decompress algorithm parameters. */
419 return DGifSetupDecompress(GifFile);
422 /******************************************************************************
423 This routine should be called before any attempt to read an image.
424 Note it is assumed the Image desc. header has been read.
425 ******************************************************************************/
427 DGifGetImageDesc(GifFileType *GifFile)
429 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
432 if (!IS_READABLE(Private)) {
433 /* This file was NOT open for reading: */
434 GifFile->Error = D_GIF_ERR_NOT_READABLE;
438 if (DGifGetImageHeader(GifFile) == GIF_ERROR) {
442 if (GifFile->SavedImages) {
443 SavedImage* new_saved_images =
444 (SavedImage *)reallocarray(GifFile->SavedImages,
445 (GifFile->ImageCount + 1), sizeof(SavedImage));
446 if (new_saved_images == NULL) {
447 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
450 GifFile->SavedImages = new_saved_images;
452 if ((GifFile->SavedImages =
453 (SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
454 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
459 sp = &GifFile->SavedImages[GifFile->ImageCount];
460 memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
461 if (GifFile->Image.ColorMap != NULL) {
462 sp->ImageDesc.ColorMap = GifMakeMapObject(
463 GifFile->Image.ColorMap->ColorCount,
464 GifFile->Image.ColorMap->Colors);
465 if (sp->ImageDesc.ColorMap == NULL) {
466 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
470 sp->RasterBits = (unsigned char *)NULL;
471 sp->ExtensionBlockCount = 0;
472 sp->ExtensionBlocks = (ExtensionBlock *) NULL;
474 GifFile->ImageCount++;
479 /******************************************************************************
480 Get one full scanned line (Line) of length LineLen from GIF file.
481 ******************************************************************************/
483 DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
486 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
488 if (!IS_READABLE(Private)) {
489 /* This file was NOT open for reading: */
490 GifFile->Error = D_GIF_ERR_NOT_READABLE;
495 LineLen = GifFile->Image.Width;
497 if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
498 GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
502 if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
503 if (Private->PixelCount == 0) {
504 /* We probably won't be called any more, so let's clean up
505 * everything before we return: need to flush out all the
506 * rest of image until an empty block (size 0)
507 * detected. We use GetCodeNext.
510 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
512 while (Dummy != NULL) ;
519 /******************************************************************************
520 Put one pixel (Pixel) into GIF file.
521 ******************************************************************************/
523 DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
526 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
528 if (!IS_READABLE(Private)) {
529 /* This file was NOT open for reading: */
530 GifFile->Error = D_GIF_ERR_NOT_READABLE;
533 if (--Private->PixelCount > 0xffff0000UL)
535 GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
539 if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
540 if (Private->PixelCount == 0) {
541 /* We probably won't be called any more, so let's clean up
542 * everything before we return: need to flush out all the
543 * rest of image until an empty block (size 0)
544 * detected. We use GetCodeNext.
547 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
549 while (Dummy != NULL) ;
556 /******************************************************************************
557 Get an extension block (see GIF manual) from GIF file. This routine only
558 returns the first data block, and DGifGetExtensionNext should be called
559 after this one until NULL extension is returned.
560 The Extension should NOT be freed by the user (not dynamically allocated).
561 Note it is assumed the Extension description header has been read.
562 ******************************************************************************/
564 DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
567 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
569 //fprintf(stderr, "### -> DGifGetExtension:\n");
570 if (!IS_READABLE(Private)) {
571 /* This file was NOT open for reading: */
572 GifFile->Error = D_GIF_ERR_NOT_READABLE;
576 /* coverity[check_return] */
577 if (InternalRead(GifFile, &Buf, 1) != 1) {
578 GifFile->Error = D_GIF_ERR_READ_FAILED;
582 //fprintf(stderr, "### <- DGifGetExtension: %02x, about to call next\n", Buf);
584 return DGifGetExtensionNext(GifFile, Extension);
587 /******************************************************************************
588 Get a following extension block (see GIF manual) from GIF file. This
589 routine should be called until NULL Extension is returned.
590 The Extension should NOT be freed by the user (not dynamically allocated).
591 ******************************************************************************/
593 DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension)
596 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
598 //fprintf(stderr, "### -> DGifGetExtensionNext\n");
599 if (InternalRead(GifFile, &Buf, 1) != 1) {
600 GifFile->Error = D_GIF_ERR_READ_FAILED;
603 //fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf);
606 *Extension = Private->Buf; /* Use private unused buffer. */
607 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
608 /* coverity[tainted_data,check_return] */
609 if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) {
610 GifFile->Error = D_GIF_ERR_READ_FAILED;
615 //fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension);
620 /******************************************************************************
621 Extract a Graphics Control Block from raw extension data
622 ******************************************************************************/
624 int DGifExtensionToGCB(const size_t GifExtensionLength,
625 const GifByteType *GifExtension,
626 GraphicsControlBlock *GCB)
628 if (GifExtensionLength != 4) {
632 GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
633 GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
634 GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
635 if (GifExtension[0] & 0x01)
636 GCB->TransparentColor = (int)GifExtension[3];
638 GCB->TransparentColor = NO_TRANSPARENT_COLOR;
643 /******************************************************************************
644 Extract the Graphics Control Block for a saved image, if it exists.
645 ******************************************************************************/
647 int DGifSavedExtensionToGCB(GifFileType *GifFile,
648 int ImageIndex, GraphicsControlBlock *GCB)
652 if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1)
655 GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
656 GCB->UserInputFlag = false;
658 GCB->TransparentColor = NO_TRANSPARENT_COLOR;
660 for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
661 ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
662 if (ep->Function == GRAPHICS_EXT_FUNC_CODE)
663 return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB);
669 /******************************************************************************
670 This routine should be called last, to close the GIF file.
671 ******************************************************************************/
673 DGifCloseFile(GifFileType *GifFile, int *ErrorCode)
675 GifFilePrivateType *Private;
677 if (GifFile == NULL || GifFile->Private == NULL)
680 if (GifFile->Image.ColorMap) {
681 GifFreeMapObject(GifFile->Image.ColorMap);
682 GifFile->Image.ColorMap = NULL;
685 if (GifFile->SColorMap) {
686 GifFreeMapObject(GifFile->SColorMap);
687 GifFile->SColorMap = NULL;
690 if (GifFile->SavedImages) {
691 GifFreeSavedImages(GifFile);
692 GifFile->SavedImages = NULL;
695 GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks);
697 Private = (GifFilePrivateType *) GifFile->Private;
699 if (!IS_READABLE(Private)) {
700 /* This file was NOT open for reading: */
701 if (ErrorCode != NULL)
702 *ErrorCode = D_GIF_ERR_NOT_READABLE;
703 free((char *)GifFile->Private);
708 if (Private->File && (fclose(Private->File) != 0)) {
709 if (ErrorCode != NULL)
710 *ErrorCode = D_GIF_ERR_CLOSE_FAILED;
711 free((char *)GifFile->Private);
716 free((char *)GifFile->Private);
718 if (ErrorCode != NULL)
719 *ErrorCode = D_GIF_SUCCEEDED;
723 /******************************************************************************
724 Get 2 bytes (word) from the given file:
725 ******************************************************************************/
727 DGifGetWord(GifFileType *GifFile, GifWord *Word)
731 /* coverity[check_return] */
732 if (InternalRead(GifFile, c, 2) != 2) {
733 GifFile->Error = D_GIF_ERR_READ_FAILED;
737 *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]);
741 /******************************************************************************
742 Get the image code in compressed form. This routine can be called if the
743 information needed to be piped out as is. Obviously this is much faster
744 than decoding and encoding again. This routine should be followed by calls
745 to DGifGetCodeNext, until NULL block is returned.
746 The block should NOT be freed by the user (not dynamically allocated).
747 ******************************************************************************/
749 DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
751 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
753 if (!IS_READABLE(Private)) {
754 /* This file was NOT open for reading: */
755 GifFile->Error = D_GIF_ERR_NOT_READABLE;
759 *CodeSize = Private->BitsPerPixel;
761 return DGifGetCodeNext(GifFile, CodeBlock);
764 /******************************************************************************
765 Continue to get the image code in compressed form. This routine should be
766 called until NULL block is returned.
767 The block should NOT be freed by the user (not dynamically allocated).
768 ******************************************************************************/
770 DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
773 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
775 /* coverity[tainted_data_argument] */
776 /* coverity[check_return] */
777 if (InternalRead(GifFile, &Buf, 1) != 1) {
778 GifFile->Error = D_GIF_ERR_READ_FAILED;
782 /* coverity[lower_bounds] */
784 *CodeBlock = Private->Buf; /* Use private unused buffer. */
785 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
786 /* coverity[tainted_data] */
787 if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
788 GifFile->Error = D_GIF_ERR_READ_FAILED;
793 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
794 Private->PixelCount = 0; /* And local info. indicate image read. */
800 /******************************************************************************
801 Setup the LZ decompression for this image:
802 ******************************************************************************/
804 DGifSetupDecompress(GifFileType *GifFile)
807 GifByteType CodeSize;
808 GifPrefixType *Prefix;
809 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
811 /* coverity[check_return] */
812 if (InternalRead(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */
813 return GIF_ERROR; /* Failed to read Code size. */
815 BitsPerPixel = CodeSize;
817 /* this can only happen on a severely malformed GIF */
818 if (BitsPerPixel > 8) {
819 GifFile->Error = D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */
820 return GIF_ERROR; /* Failed to read Code size. */
823 Private->Buf[0] = 0; /* Input Buffer empty. */
824 Private->BitsPerPixel = BitsPerPixel;
825 Private->ClearCode = (1 << BitsPerPixel);
826 Private->EOFCode = Private->ClearCode + 1;
827 Private->RunningCode = Private->EOFCode + 1;
828 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
829 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
830 Private->StackPtr = 0; /* No pixels on the pixel stack. */
831 Private->LastCode = NO_SUCH_CODE;
832 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
833 Private->CrntShiftDWord = 0;
835 Prefix = Private->Prefix;
836 for (i = 0; i <= LZ_MAX_CODE; i++)
837 Prefix[i] = NO_SUCH_CODE;
842 /******************************************************************************
843 The LZ decompression routine:
844 This version decompress the given GIF file into Line of length LineLen.
845 This routine can be called few times (one per scan line, for example), in
846 order the complete the whole image.
847 ******************************************************************************/
849 DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
852 int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
853 GifByteType *Stack, *Suffix;
854 GifPrefixType *Prefix;
855 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
857 StackPtr = Private->StackPtr;
858 Prefix = Private->Prefix;
859 Suffix = Private->Suffix;
860 Stack = Private->Stack;
861 EOFCode = Private->EOFCode;
862 ClearCode = Private->ClearCode;
863 LastCode = Private->LastCode;
865 if (StackPtr > LZ_MAX_CODE) {
870 /* Let pop the stack off before continueing to read the GIF file: */
871 while (StackPtr != 0 && i < LineLen)
872 Line[i++] = Stack[--StackPtr];
875 while (i < LineLen) { /* Decode LineLen items. */
876 if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
879 if (CrntCode == EOFCode) {
880 /* Note however that usually we will not be here as we will stop
881 * decoding as soon as we got all the pixel, or EOF code will
882 * not be read at all, and DGifGetLine/Pixel clean everything. */
883 GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
885 } else if (CrntCode == ClearCode) {
886 /* We need to start over again: */
887 for (j = 0; j <= LZ_MAX_CODE; j++)
888 Prefix[j] = NO_SUCH_CODE;
889 Private->RunningCode = Private->EOFCode + 1;
890 Private->RunningBits = Private->BitsPerPixel + 1;
891 Private->MaxCode1 = 1 << Private->RunningBits;
892 LastCode = Private->LastCode = NO_SUCH_CODE;
894 /* Its regular code - if in pixel range simply add it to output
895 * stream, otherwise trace to codes linked list until the prefix
896 * is in pixel range: */
897 if (CrntCode < ClearCode) {
898 /* This is simple - its pixel scalar, so add it to output: */
899 Line[i++] = CrntCode;
901 /* Its a code to needed to be traced: trace the linked list
902 * until the prefix is a pixel, while pushing the suffix
903 * pixels on our stack. If we done, pop the stack in reverse
904 * (thats what stack is good for!) order to output. */
905 if (Prefix[CrntCode] == NO_SUCH_CODE) {
906 CrntPrefix = LastCode;
908 /* Only allowed if CrntCode is exactly the running code:
909 * In that case CrntCode = XXXCode, CrntCode or the
910 * prefix code is last code and the suffix char is
911 * exactly the prefix of last code! */
912 if (CrntCode == Private->RunningCode - 2) {
913 Suffix[Private->RunningCode - 2] =
914 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
918 Suffix[Private->RunningCode - 2] =
919 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
924 CrntPrefix = CrntCode;
926 /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
927 * during the trace. As we might loop forever, in case of
928 * defective image, we use StackPtr as loop counter and stop
929 * before overflowing Stack[]. */
930 while (StackPtr < LZ_MAX_CODE &&
931 CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
932 Stack[StackPtr++] = Suffix[CrntPrefix];
933 CrntPrefix = Prefix[CrntPrefix];
935 if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
936 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
939 /* Push the last character on stack: */
940 Stack[StackPtr++] = CrntPrefix;
942 /* Now lets pop all the stack into output: */
943 while (StackPtr != 0 && i < LineLen)
944 Line[i++] = Stack[--StackPtr];
946 if (LastCode != NO_SUCH_CODE && Private->RunningCode - 2 < (LZ_MAX_CODE+1) && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
947 Prefix[Private->RunningCode - 2] = LastCode;
949 if (CrntCode == Private->RunningCode - 2) {
950 /* Only allowed if CrntCode is exactly the running code:
951 * In that case CrntCode = XXXCode, CrntCode or the
952 * prefix code is last code and the suffix char is
953 * exactly the prefix of last code! */
954 Suffix[Private->RunningCode - 2] =
955 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
957 Suffix[Private->RunningCode - 2] =
958 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
965 Private->LastCode = LastCode;
966 Private->StackPtr = StackPtr;
971 /******************************************************************************
972 Routine to trace the Prefixes linked list until we get a prefix which is
973 not code, but a pixel value (less than ClearCode). Returns that pixel value.
974 If image is defective, we might loop here forever, so we limit the loops to
975 the maximum possible if image O.k. - LZ_MAX_CODE times.
976 ******************************************************************************/
978 DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode)
982 while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
983 if (Code > LZ_MAX_CODE) {
991 /******************************************************************************
992 Interface for accessing the LZ codes directly. Set Code to the real code
993 (12bits), or to -1 if EOF code is returned.
994 ******************************************************************************/
996 DGifGetLZCodes(GifFileType *GifFile, int *Code)
998 GifByteType *CodeBlock;
999 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1001 if (!IS_READABLE(Private)) {
1002 /* This file was NOT open for reading: */
1003 GifFile->Error = D_GIF_ERR_NOT_READABLE;
1007 if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)
1010 if (*Code == Private->EOFCode) {
1011 /* Skip rest of codes (hopefully only NULL terminating block): */
1013 if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
1015 } while (CodeBlock != NULL) ;
1018 } else if (*Code == Private->ClearCode) {
1019 /* We need to start over again: */
1020 Private->RunningCode = Private->EOFCode + 1;
1021 Private->RunningBits = Private->BitsPerPixel + 1;
1022 Private->MaxCode1 = 1 << Private->RunningBits;
1028 /******************************************************************************
1029 The LZ decompression input routine:
1030 This routine is responsable for the decompression of the bit stream from
1031 8 bits (bytes) packets, into the real codes.
1032 Returns GIF_OK if read successfully.
1033 ******************************************************************************/
1035 DGifDecompressInput(GifFileType *GifFile, int *Code)
1037 static const unsigned short CodeMasks[] = {
1038 0x0000, 0x0001, 0x0003, 0x0007,
1039 0x000f, 0x001f, 0x003f, 0x007f,
1040 0x00ff, 0x01ff, 0x03ff, 0x07ff,
1044 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1046 GifByteType NextByte;
1048 /* The image can't contain more than LZ_BITS per code. */
1049 if (Private->RunningBits > LZ_BITS) {
1050 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1054 while (Private->CrntShiftState < Private->RunningBits) {
1055 /* Needs to get more bytes from input stream for next code: */
1056 if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
1059 Private->CrntShiftDWord |=
1060 ((unsigned long)NextByte) << Private->CrntShiftState;
1061 Private->CrntShiftState += 8;
1063 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1065 Private->CrntShiftDWord >>= Private->RunningBits;
1066 Private->CrntShiftState -= Private->RunningBits;
1068 /* If code cannot fit into RunningBits bits, must raise its size. Note
1069 * however that codes above 4095 are used for special signaling.
1070 * If we're using LZ_BITS bits already and we're at the max code, just
1071 * keep using the table as it is, don't increment Private->RunningCode.
1073 if (Private->RunningCode < LZ_MAX_CODE + 2 &&
1074 ++Private->RunningCode > Private->MaxCode1 &&
1075 Private->RunningBits < LZ_BITS) {
1076 Private->MaxCode1 <<= 1;
1077 Private->RunningBits++;
1082 /******************************************************************************
1083 This routines read one GIF data block at a time and buffers it internally
1084 so that the decompression routine could access it.
1085 The routine returns the next byte from its internal buffer (or read next
1086 block in if buffer empty) and returns GIF_OK if succesful.
1087 ******************************************************************************/
1089 DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
1092 /* Needs to read the next buffer - this one is empty: */
1093 /* coverity[check_return] */
1094 if (InternalRead(GifFile, Buf, 1) != 1) {
1095 GifFile->Error = D_GIF_ERR_READ_FAILED;
1098 /* There shouldn't be any empty data blocks here as the LZW spec
1099 * says the LZW termination code should come first. Therefore we
1100 * shouldn't be inside this routine at that point.
1103 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1106 if (InternalRead(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
1107 GifFile->Error = D_GIF_ERR_READ_FAILED;
1111 Buf[1] = 2; /* We use now the second place as last char read! */
1114 *NextByte = Buf[Buf[1]++];
1121 /******************************************************************************
1122 This routine reads an entire GIF into core, hanging all its state info off
1123 the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle()
1124 first to initialize I/O. Its inverse is EGifSpew().
1125 *******************************************************************************/
1127 DGifSlurp(GifFileType *GifFile)
1130 GifRecordType RecordType;
1132 GifByteType *ExtData;
1135 GifFile->ExtensionBlocks = NULL;
1136 GifFile->ExtensionBlockCount = 0;
1139 if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1142 switch (RecordType) {
1143 case IMAGE_DESC_RECORD_TYPE:
1144 if (DGifGetImageDesc(GifFile) == GIF_ERROR)
1147 sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
1148 /* Allocate memory for the image */
1149 if (sp->ImageDesc.Width <= 0 || sp->ImageDesc.Height <= 0 ||
1150 sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) {
1153 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1155 if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
1158 sp->RasterBits = (unsigned char *)reallocarray(NULL, ImageSize,
1159 sizeof(GifPixelType));
1161 if (sp->RasterBits == NULL) {
1165 if (sp->ImageDesc.Interlace) {
1168 * The way an interlaced image should be read -
1169 * offsets and jumps...
1171 int InterlacedOffset[] = { 0, 4, 2, 1 };
1172 int InterlacedJumps[] = { 8, 8, 4, 2 };
1173 /* Need to perform 4 passes on the image */
1174 for (i = 0; i < 4; i++)
1175 for (j = InterlacedOffset[i];
1176 j < sp->ImageDesc.Height;
1177 j += InterlacedJumps[i]) {
1178 if (DGifGetLine(GifFile,
1179 sp->RasterBits+j*sp->ImageDesc.Width,
1180 sp->ImageDesc.Width) == GIF_ERROR)
1185 if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR)
1189 if (GifFile->ExtensionBlocks) {
1190 sp->ExtensionBlocks = GifFile->ExtensionBlocks;
1191 sp->ExtensionBlockCount = GifFile->ExtensionBlockCount;
1193 GifFile->ExtensionBlocks = NULL;
1194 GifFile->ExtensionBlockCount = 0;
1198 case EXTENSION_RECORD_TYPE:
1199 if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR)
1201 /* Create an extension block with our data */
1202 if (ExtData != NULL) {
1203 if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1204 &GifFile->ExtensionBlocks,
1205 ExtFunction, ExtData[0], &ExtData[1])
1210 if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1212 if (ExtData == NULL)
1214 /* Continue the extension block */
1215 if (ExtData != NULL)
1216 if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1217 &GifFile->ExtensionBlocks,
1218 CONTINUE_EXT_FUNC_CODE,
1219 ExtData[0], &ExtData[1]) == GIF_ERROR)
1224 case TERMINATE_RECORD_TYPE:
1227 default: /* Should be trapped by DGifGetRecordType */
1230 } while (RecordType != TERMINATE_RECORD_TYPE);
1232 /* Sanity check for corrupted file */
1233 if (GifFile->ImageCount == 0) {
1234 GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;