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 * 19 Feb 98 - Version 1.2 by Jareth Hein (Support for user specified I/O) *
12 ******************************************************************************/
21 #define PROGRAM_NAME "GIFLIB"
24 static void DGifGetWord(GifFileType *GifFile, int *Word);
25 static void DGifSetupDecompress(GifFileType *GifFile);
26 static void DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
28 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
29 static void DGifDecompressInput(GifFileType *GifFile, int *Code);
30 static void DGifBufferedInput(GifFileType *GifFile, GifByteType *NextByte);
32 /******************************************************************************
33 * Open a new gif file for read, given by its name. *
34 * Returns GifFileType pointer dynamically allocated which serves as the gif *
36 ******************************************************************************/
37 void DGifOpenFileName(GifFileType *GifFile, const char *FileName)
41 if ((f = fopen(FileName,
46 #endif /* WIN32_NATIVE */
48 GifInternError(GifFile, D_GIF_ERR_OPEN_FAILED);
50 GifStdIOInit(GifFile, f, -1);
51 DGifInitRead(GifFile);
54 /******************************************************************************
55 * Update a new gif file, given its file handle. *
56 * Returns GifFileType pointer dynamically allocated which serves as the gif *
58 ******************************************************************************/
59 void DGifOpenFileHandle(GifFileType *GifFile, int FileHandle)
64 setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
65 f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
66 setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/
68 f = fdopen(FileHandle, "r"); /* Make it into a stream: */
69 #endif /* WIN32_NATIVE */
71 GifStdIOInit(GifFile, f, -1);
72 DGifInitRead(GifFile);
75 /******************************************************************************
76 * Update a new gif file, given its file handle. *
77 * Returns GifFileType pointer dynamically allocated which serves as the gif *
78 * info record. _GifError is cleared if succesfull. *
79 ******************************************************************************/
80 void DGifInitRead(GifFileType *GifFile)
82 GifByteType Buf[GIF_STAMP_LEN+1];
83 GifFilePrivateType *Private;
85 if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType)))
87 GifInternError(GifFile, D_GIF_ERR_NOT_ENOUGH_MEM);
89 memset(Private, '\0', sizeof(GifFilePrivateType));
90 GifFile->Private = (VoidPtr) Private;
92 Private->FileState = 0; /* Make sure bit 0 = 0 (File open for read). */
94 /* Lets see if this is a GIF file: */
95 GifRead(Buf, GIF_STAMP_LEN, GifFile);
97 /* The GIF Version number is ignored at this time. Maybe we should do */
98 /* something more useful with it. */
99 Buf[GIF_STAMP_LEN] = 0;
100 if (strncmp(GIF_STAMP, (const char *) Buf, GIF_VERSION_POS) != 0) {
101 GifInternError(GifFile, D_GIF_ERR_NOT_GIF_FILE);
104 DGifGetScreenDesc(GifFile);
107 /******************************************************************************
108 * This routine should be called before any other DGif calls. Note that *
109 * this routine is called automatically from DGif file open routines. *
110 ******************************************************************************/
111 void DGifGetScreenDesc(GifFileType *GifFile)
115 GifFilePrivateType *Private = (GifFilePrivateType*) GifFile->Private;
117 if (!IS_READABLE(Private)) {
118 /* This file was NOT open for reading: */
119 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
122 /* Put the screen descriptor into the file: */
123 DGifGetWord(GifFile, &GifFile->SWidth);
124 DGifGetWord(GifFile, &GifFile->SHeight);
126 GifRead(Buf, 3, GifFile);
127 GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
128 BitsPerPixel = (Buf[0] & 0x07) + 1;
129 GifFile->SBackGroundColor = Buf[1];
130 if (Buf[0] & 0x80) { /* Do we have global color map? */
132 GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
134 /* Get the global color map: */
135 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
136 GifRead(Buf, 3, GifFile);
137 GifFile->SColorMap->Colors[i].Red = Buf[0];
138 GifFile->SColorMap->Colors[i].Green = Buf[1];
139 GifFile->SColorMap->Colors[i].Blue = Buf[2];
142 /* We should always have a colormap */
143 GifFile->SColorMap = MakeMapObject(2, NULL);
144 GifFile->SColorMap->Colors[0].Red = 0;
145 GifFile->SColorMap->Colors[0].Green = 0;
146 GifFile->SColorMap->Colors[0].Blue = 0;
147 GifFile->SColorMap->Colors[1].Red = 0xff;
148 GifFile->SColorMap->Colors[1].Green = 0xff;
149 GifFile->SColorMap->Colors[1].Blue = 0xff;
153 /******************************************************************************
154 * This routine should be called before any attemp to read an image. *
155 ******************************************************************************/
156 void DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
159 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
161 if (!IS_READABLE(Private)) {
162 /* This file was NOT open for reading: */
163 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
166 GifRead(&Buf, 1, GifFile);
170 *Type = IMAGE_DESC_RECORD_TYPE;
173 *Type = EXTENSION_RECORD_TYPE;
176 *Type = TERMINATE_RECORD_TYPE;
179 *Type = UNDEFINED_RECORD_TYPE;
180 GifInternError(GifFile, D_GIF_ERR_WRONG_RECORD);
184 /******************************************************************************
185 * This routine should be called before any attemp to read an image. *
186 * Note it is assumed the Image desc. header (',') has been read. *
187 ******************************************************************************/
188 void DGifGetImageDesc(GifFileType *GifFile)
192 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
194 if (!IS_READABLE(Private)) {
195 /* This file was NOT open for reading: */
196 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
199 DGifGetWord(GifFile, &GifFile->Image.Left);
200 DGifGetWord(GifFile, &GifFile->Image.Top);
201 DGifGetWord(GifFile, &GifFile->Image.Width);
202 DGifGetWord(GifFile, &GifFile->Image.Height);
204 GifRead(Buf, 1, GifFile);
205 BitsPerPixel = (Buf[0] & 0x07) + 1;
206 GifFile->Image.Interlace = (Buf[0] & 0x40);
207 if (Buf[0] & 0x80) { /* Does this image have local color map? */
209 if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
210 FreeMapObject(GifFile->Image.ColorMap);
212 GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
214 /* Get the image local color map: */
215 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
216 GifRead(Buf, 3, GifFile);
217 GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
218 GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
219 GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
223 if (GifFile->SavedImages) {
226 if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
227 sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) {
228 GifInternError(GifFile, D_GIF_ERR_NOT_ENOUGH_MEM);
231 sp = &GifFile->SavedImages[GifFile->ImageCount];
232 memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
233 if (GifFile->Image.ColorMap)
235 sp->ImageDesc.ColorMap =
236 MakeMapObject (GifFile->Image.ColorMap->ColorCount,
237 GifFile->Image.ColorMap->Colors);
239 sp->RasterBits = NULL;
240 sp->ExtensionBlockCount = 0;
241 sp->ExtensionBlocks = (ExtensionBlock *)NULL;
244 GifFile->ImageCount++;
246 Private->PixelCount = (long) GifFile->Image.Width *
247 (long) GifFile->Image.Height;
249 DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
252 /******************************************************************************
253 * Get one full scanned line (Line) of length LineLen from GIF file. *
254 ******************************************************************************/
255 void DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
258 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
260 if (!IS_READABLE(Private)) {
261 /* This file was NOT open for reading: */
262 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
265 if (!LineLen) LineLen = GifFile->Image.Width;
267 #if defined(WIN32_NATIVE) || defined(__GNUC__)
268 if ((Private->PixelCount -= LineLen) > 0xffff0000UL)
270 if ((Private->PixelCount -= LineLen) > 0xffff0000)
271 #endif /* WIN32_NATIVE */
273 GifInternError(GifFile, D_GIF_ERR_DATA_TOO_BIG);
276 DGifDecompressLine(GifFile, Line, LineLen);
277 if (Private->PixelCount == 0) {
278 /* We probably would not be called any more, so lets clean */
279 /* everything before we return: need to flush out all rest of */
280 /* image until empty block (size 0) detected. We use GetCodeNext.*/
282 DGifGetCodeNext(GifFile, &Dummy);
283 while (Dummy != NULL);
287 /******************************************************************************
288 * Put one pixel (Pixel) into GIF file. *
289 ******************************************************************************/
290 void DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
293 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
295 if (!IS_READABLE(Private)) {
296 /* This file was NOT open for reading: */
297 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
300 #if defined(WIN32_NATIVE) || defined(__GNUC__)
301 if (--Private->PixelCount > 0xffff0000UL)
303 if (--Private->PixelCount > 0xffff0000)
304 #endif /* WIN32_NATIVE */
306 GifInternError(GifFile, D_GIF_ERR_DATA_TOO_BIG);
309 DGifDecompressLine(GifFile, &Pixel, 1);
310 if (Private->PixelCount == 0) {
311 /* We probably would not be called any more, so lets clean */
312 /* everything before we return: need to flush out all rest of */
313 /* image until empty block (size 0) detected. We use GetCodeNext.*/
315 DGifGetCodeNext(GifFile, &Dummy);
316 while (Dummy != NULL);
320 /******************************************************************************
321 * Get an extension block (see GIF manual) from gif file. This routine only *
322 * returns the first data block, and DGifGetExtensionNext shouldbe called *
323 * after this one until NULL extension is returned. *
324 * The Extension should NOT be freed by the user (not dynamically allocated).*
325 * Note it is assumed the Extension desc. header ('!') has been read. *
326 ******************************************************************************/
327 void DGifGetExtension(GifFileType *GifFile, int *ExtCode,
328 GifByteType **Extension)
331 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
333 if (!IS_READABLE(Private)) {
334 /* This file was NOT open for reading: */
335 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
338 GifRead(&Buf, 1, GifFile);
341 DGifGetExtensionNext(GifFile, Extension);
344 /******************************************************************************
345 * Get a following extension block (see GIF manual) from gif file. This *
346 * routine sould be called until NULL Extension is returned. *
347 * The Extension should NOT be freed by the user (not dynamically allocated).*
348 ******************************************************************************/
349 void DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension)
352 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
354 GifRead(&Buf, 1, GifFile);
356 *Extension = Private->Buf; /* Use private unused buffer. */
357 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
358 GifRead(&((*Extension)[1]), Buf, GifFile);
364 /******************************************************************************
365 * This routine should be called second to last, to close the GIF file. *
366 ******************************************************************************/
367 int DGifCloseFile(GifFileType *GifFile)
369 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
371 if (GifFile == NULL) return -1;
373 if (!IS_READABLE(Private))
375 /* This file was NOT open for reading: */
376 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
379 if (GifClose (GifFile))
381 GifInternError(GifFile, D_GIF_ERR_CLOSE_FAILED);
386 /******************************************************************************
387 * Get 2 bytes (word) from the given file: *
388 ******************************************************************************/
389 static void DGifGetWord(GifFileType *GifFile, int *Word)
393 GifRead(c, 2, GifFile);
395 *Word = (((unsigned int) c[1]) << 8) + c[0];
398 /******************************************************************************
399 * Get the image code in compressed form. his routine can be called if the *
400 * information needed to be piped out as is. Obviously this is much faster *
401 * than decoding and encoding again. This routine should be followed by calls *
402 * to DGifGetCodeNext, until NULL block is returned. *
403 * The block should NOT be freed by the user (not dynamically allocated). *
404 ******************************************************************************/
405 void DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
407 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
409 if (!IS_READABLE(Private)) {
410 /* This file was NOT open for reading: */
411 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
414 *CodeSize = Private->BitsPerPixel;
416 DGifGetCodeNext(GifFile, CodeBlock);
419 /******************************************************************************
420 * Continue to get the image code in compressed form. This routine should be *
421 * called until NULL block is returned. *
422 * The block should NOT be freed by the user (not dynamically allocated). *
423 ******************************************************************************/
424 void DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
427 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
429 GifRead(&Buf, 1, GifFile);
432 *CodeBlock = Private->Buf; /* Use private unused buffer. */
433 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
434 GifRead(&((*CodeBlock)[1]), Buf, GifFile);
438 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
439 Private->PixelCount = 0; /* And local info. indicate image read. */
444 /******************************************************************************
445 * Setup the LZ decompression for this image: *
446 ******************************************************************************/
447 static void DGifSetupDecompress(GifFileType *GifFile)
450 GifByteType CodeSize;
451 unsigned int *Prefix;
452 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
454 GifRead(&CodeSize, 1, GifFile); /* Read Code size from file. */
455 BitsPerPixel = CodeSize;
457 Private->Buf[0] = 0; /* Input Buffer empty. */
458 Private->BitsPerPixel = BitsPerPixel;
459 Private->ClearCode = (1 << BitsPerPixel);
460 Private->EOFCode = Private->ClearCode + 1;
461 Private->RunningCode = Private->EOFCode + 1;
462 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
463 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
464 Private->StackPtr = 0; /* No pixels on the pixel stack. */
465 Private->LastCode = NO_SUCH_CODE;
466 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
467 Private->CrntShiftDWord = 0;
469 Prefix = Private->Prefix;
470 for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
473 /******************************************************************************
474 * The LZ decompression routine: *
475 * This version decompress the given gif file into Line of length LineLen. *
476 * This routine can be called few times (one per scan line, for example), in *
477 * order the complete the whole image. *
478 ******************************************************************************/
479 static void DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
482 int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
483 GifByteType *Stack, *Suffix;
484 unsigned int *Prefix;
485 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
487 StackPtr = Private->StackPtr;
488 Prefix = Private->Prefix;
489 Suffix = Private->Suffix;
490 Stack = Private->Stack;
491 EOFCode = Private->EOFCode;
492 ClearCode = Private->ClearCode;
493 LastCode = Private->LastCode;
497 /* Let pop the stack off before continueing to read the gif file: */
498 while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
501 while (i < LineLen) { /* Decode LineLen items. */
502 DGifDecompressInput(GifFile, &CrntCode);
504 if (CrntCode == EOFCode) {
505 /* Note however that usually we will not be here as we will stop */
506 /* decoding as soon as we got all the pixel, or EOF code will */
507 /* not be read at all, and DGifGetLine/Pixel clean everything. */
508 if (i != LineLen - 1 || Private->PixelCount != 0) {
509 GifInternError(GifFile, D_GIF_ERR_EOF_TOO_SOON);
513 else if (CrntCode == ClearCode) {
514 /* We need to start over again: */
515 for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
516 Private->RunningCode = Private->EOFCode + 1;
517 Private->RunningBits = Private->BitsPerPixel + 1;
518 Private->MaxCode1 = 1 << Private->RunningBits;
519 LastCode = Private->LastCode = NO_SUCH_CODE;
522 /* Its regular code - if in pixel range simply add it to output */
523 /* stream, otherwise trace to codes linked list until the prefix */
524 /* is in pixel range: */
525 if (CrntCode < ClearCode) {
526 /* This is simple - its pixel scalar, so add it to output: */
527 Line[i++] = CrntCode;
530 /* Its a code to needed to be traced: trace the linked list */
531 /* until the prefix is a pixel, while pushing the suffix */
532 /* pixels on our stack. If we done, pop the stack in reverse */
533 /* (thats what stack is good for!) order to output. */
534 if (Prefix[CrntCode] == NO_SUCH_CODE) {
535 /* Only allowed if CrntCode is exactly the running code: */
536 /* In that case CrntCode = XXXCode, CrntCode or the */
537 /* prefix code is last code and the suffix char is */
538 /* exactly the prefix of last code! */
539 if (CrntCode == Private->RunningCode - 2) {
540 CrntPrefix = LastCode;
541 Suffix[Private->RunningCode - 2] =
542 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
543 LastCode, ClearCode);
546 GifInternError(GifFile, D_GIF_ERR_IMAGE_DEFECT);
550 CrntPrefix = CrntCode;
552 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */
553 /* During the trace. As we might loop forever, in case of */
554 /* defective image, we count the number of loops we trace */
555 /* and stop if we got LZ_MAX_CODE. obviously we can not */
556 /* loop more than that. */
558 while (j++ <= LZ_MAX_CODE &&
559 CrntPrefix > ClearCode &&
560 CrntPrefix <= LZ_MAX_CODE) {
561 Stack[StackPtr++] = Suffix[CrntPrefix];
562 CrntPrefix = Prefix[CrntPrefix];
564 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
565 GifInternError(GifFile, D_GIF_ERR_IMAGE_DEFECT);
567 /* Push the last character on stack: */
568 Stack[StackPtr++] = CrntPrefix;
570 /* Now lets pop all the stack into output: */
571 while (StackPtr != 0 && i < LineLen)
572 Line[i++] = Stack[--StackPtr];
574 if (LastCode != NO_SUCH_CODE) {
575 Prefix[Private->RunningCode - 2] = LastCode;
577 if (CrntCode == Private->RunningCode - 2) {
578 /* Only allowed if CrntCode is exactly the running code: */
579 /* In that case CrntCode = XXXCode, CrntCode or the */
580 /* prefix code is last code and the suffix char is */
581 /* exactly the prefix of last code! */
582 Suffix[Private->RunningCode - 2] =
583 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
586 Suffix[Private->RunningCode - 2] =
587 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
594 Private->LastCode = LastCode;
595 Private->StackPtr = StackPtr;
598 /******************************************************************************
599 * Routine to trace the Prefixes linked list until we get a prefix which is *
600 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
601 * If image is defective, we might loop here forever, so we limit the loops to *
602 * the maximum possible if image O.k. - LZ_MAX_CODE times. *
603 ******************************************************************************/
604 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
608 while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
612 /******************************************************************************
613 * Interface for accessing the LZ codes directly. Set Code to the real code *
614 * (12bits), or to -1 if EOF code is returned. *
615 ******************************************************************************/
616 void DGifGetLZCodes(GifFileType *GifFile, int *Code)
618 GifByteType *CodeBlock;
619 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
621 if (!IS_READABLE(Private)) {
622 /* This file was NOT open for reading: */
623 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
626 DGifDecompressInput(GifFile, Code);
628 if (*Code == Private->EOFCode) {
629 /* Skip rest of codes (hopefully only NULL terminating block): */
631 DGifGetCodeNext(GifFile, &CodeBlock);
632 while (CodeBlock != NULL);
636 else if (*Code == Private->ClearCode) {
637 /* We need to start over again: */
638 Private->RunningCode = Private->EOFCode + 1;
639 Private->RunningBits = Private->BitsPerPixel + 1;
640 Private->MaxCode1 = 1 << Private->RunningBits;
644 /******************************************************************************
645 * The LZ decompression input routine: *
646 * This routine is responsable for the decompression of the bit stream from *
647 * 8 bits (bytes) packets, into the real codes. *
648 * Returns GIF_OK if read succesfully. *
649 ******************************************************************************/
650 static void DGifDecompressInput(GifFileType *GifFile, int *Code)
652 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
653 GifByteType NextByte;
654 static unsigned int CodeMasks[] = {
655 0x0000, 0x0001, 0x0003, 0x0007,
656 0x000f, 0x001f, 0x003f, 0x007f,
657 0x00ff, 0x01ff, 0x03ff, 0x07ff,
661 while (Private->CrntShiftState < Private->RunningBits) {
662 /* Needs to get more bytes from input stream for next code: */
663 DGifBufferedInput(GifFile, &NextByte);
664 Private->CrntShiftDWord |=
665 ((unsigned long) NextByte) << Private->CrntShiftState;
666 Private->CrntShiftState += 8;
668 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
670 Private->CrntShiftDWord >>= Private->RunningBits;
671 Private->CrntShiftState -= Private->RunningBits;
673 /* If code cannt fit into RunningBits bits, must raise its size. Note */
674 /* however that codes above 4095 are used for special signaling. */
675 if (++Private->RunningCode > Private->MaxCode1 &&
676 Private->RunningBits < LZ_BITS) {
677 Private->MaxCode1 <<= 1;
678 Private->RunningBits++;
682 /******************************************************************************
683 * This routines read one gif data block at a time and buffers it internally *
684 * so that the decompression routine could access it. *
685 * The routine returns the next byte from its internal buffer (or read next *
686 * block in if buffer empty) *
687 ******************************************************************************/
688 static void DGifBufferedInput(GifFileType *GifFile, GifByteType *NextByte)
690 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
691 GifByteType *Buf = Private->Buf;
694 /* Needs to read the next buffer - this one is empty: */
695 GifRead(Buf, 1, GifFile);
696 GifRead((Buf + 1), Buf[0], GifFile);
698 Buf[1] = 2; /* We use now the second place as last char read! */
702 *NextByte = Buf[Buf[1]++];
707 /******************************************************************************
708 * This routine reads an entire GIF into core, hanging all its state info off *
709 * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() *
710 * first to initialize I/O. Its inverse is EGifSpew(). *
711 ******************************************************************************/
712 void DGifSlurp(GifFileType *GifFile)
715 GifRecordType RecordType;
717 GifByteType *ExtData;
719 /* Some versions of malloc dislike 0-length requests */
720 GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
721 memset(GifFile->SavedImages, 0, sizeof(SavedImage));
722 sp = &GifFile->SavedImages[0];
725 DGifGetRecordType(GifFile, &RecordType);
727 switch (RecordType) {
728 case IMAGE_DESC_RECORD_TYPE:
729 DGifGetImageDesc(GifFile);
731 sp = &GifFile->SavedImages[GifFile->ImageCount-1];
732 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
735 = (GifPixelType*) malloc (ImageSize * sizeof(GifPixelType));
737 DGifGetLine(GifFile, sp->RasterBits, ImageSize);
740 case EXTENSION_RECORD_TYPE:
741 DGifGetExtension(GifFile,&sp->Function,&ExtData);
744 if (AddExtensionBlock(sp, ExtData[0], ExtData+1) == GIF_ERROR)
745 GifInternError(GifFile, D_GIF_ERR_NOT_ENOUGH_MEM);
746 DGifGetExtensionNext(GifFile, &ExtData);
747 } while (ExtData != NULL);
750 case TERMINATE_RECORD_TYPE:
753 default: /* Should be trapped by DGifGetRecordType */
756 } while (RecordType != TERMINATE_RECORD_TYPE);
759 /******************************************************************************
760 * Extension record functions *
761 ******************************************************************************/
763 void MakeExtension(SavedImage *New, int Function)
765 New->Function = Function;
767 * Someday we might have to deal with multiple extensions.
771 int AddExtensionBlock(SavedImage *New, int Len, GifByteType *data)
776 if (New->ExtensionBlocks == NULL)
777 New->ExtensionBlocks = (ExtensionBlock *)malloc(sizeof(ExtensionBlock));
779 New->ExtensionBlocks =
780 (ExtensionBlock *)realloc(New->ExtensionBlocks,
781 sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1));
783 if (New->ExtensionBlocks == NULL)
786 ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
788 size = Len * sizeof(GifByteType);
789 ep->Bytes = (GifByteType *)malloc(size);
790 memcpy(ep->Bytes, data, size);
794 void FreeExtension(SavedImage *Image)
798 for (ep = Image->ExtensionBlocks;
799 ep < Image->ExtensionBlocks + Image->ExtensionBlockCount;
801 (void) free((char *)ep->Bytes);
802 free((char *)Image->ExtensionBlocks);
803 Image->ExtensionBlocks = NULL;
806 /******************************************************************************
807 * Image block allocation functions *
808 ******************************************************************************/
809 SavedImage *MakeSavedImage(GifFileType *GifFile, SavedImage *CopyFrom)
811 * Append an image block to the SavedImages array
816 if (GifFile->SavedImages == NULL)
817 GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
819 GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
820 sizeof(SavedImage) * (GifFile->ImageCount+1));
822 if (GifFile->SavedImages == NULL)
823 return((SavedImage *)NULL);
826 sp = &GifFile->SavedImages[GifFile->ImageCount++];
827 memset((char *)sp, '\0', sizeof(SavedImage));
831 memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
834 * Make our own allocated copies of the heap fields in the
835 * copied record. This guards against potential aliasing
839 /* first, the local color map */
840 if (sp->ImageDesc.ColorMap)
841 sp->ImageDesc.ColorMap =
842 MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount,
843 CopyFrom->ImageDesc.ColorMap->Colors);
845 /* next, the raster */
846 sp->RasterBits = (GifPixelType *) malloc(sizeof(GifPixelType)
847 * CopyFrom->ImageDesc.Height
848 * CopyFrom->ImageDesc.Width);
849 memcpy(sp->RasterBits,
850 CopyFrom->RasterBits,
852 * CopyFrom->ImageDesc.Height
853 * CopyFrom->ImageDesc.Width);
855 /* finally, the extension blocks */
856 if (sp->ExtensionBlocks)
859 = (ExtensionBlock*)malloc(sizeof(ExtensionBlock)
860 * CopyFrom->ExtensionBlockCount);
861 memcpy(sp->ExtensionBlocks,
862 CopyFrom->ExtensionBlocks,
863 sizeof(ExtensionBlock)
864 * CopyFrom->ExtensionBlockCount);
867 * For the moment, the actual blocks can take their
868 * chances with free(). We'll fix this later.
877 void FreeSavedImages(GifFileType *GifFile)
881 for (sp = GifFile->SavedImages;
882 sp < GifFile->SavedImages + GifFile->ImageCount;
885 if (sp->ImageDesc.ColorMap)
886 FreeMapObject(sp->ImageDesc.ColorMap);
889 free((char *)sp->RasterBits);
891 if (sp->ExtensionBlocks)
894 free((char *) GifFile->SavedImages);
897 /******************************************************************************
898 * Miscellaneous utility functions *
899 ******************************************************************************/
901 static int BitSize(int n)
902 /* return smallest bitfield size n will fit in */
906 for (i = 1; i <= 8; i++)
912 /******************************************************************************
913 * Color map object functions *
914 ******************************************************************************/
916 ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap)
918 * Allocate a color map of given size; initialize with contents of
919 * ColorMap if that pointer is non-NULL.
922 ColorMapObject *Object;
924 if (ColorCount != (1 << BitSize(ColorCount)))
925 return((ColorMapObject *)NULL);
927 Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
928 if (Object == (ColorMapObject *)NULL)
929 return((ColorMapObject *)NULL);
931 Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
932 if (Object->Colors == (GifColorType *)NULL)
933 return((ColorMapObject *)NULL);
935 Object->ColorCount = ColorCount;
936 Object->BitsPerPixel = BitSize(ColorCount);
939 memcpy((char *)Object->Colors,
940 (char *)ColorMap, ColorCount * sizeof(GifColorType));
945 void FreeMapObject(ColorMapObject *Object)
947 * Free a color map object
950 free(Object->Colors);