1 /******************************************************************************
2 * "Gif-Lib" - Yet another gif library. *
3 * *
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 *******************************************************************************
8 * History: *
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 ******************************************************************************/
12
13 #ifdef _WIN32
14 #include "../win32/config.h"
15 #else
16 #include "../config.h"
17 #endif
18
19 #if defined (__MSDOS__) && !defined(__DJGPP__) && !defined(__GNUC__)
20 #include <alloc.h>
21 #include <sys\stat.h>
22 #else
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #endif /* __MSDOS__ */
26
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30 #ifdef HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif
33 #include <fcntl.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include "gif_lib.h"
37 #include "gif_lib_private.h"
38
39 #define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for comment. */
40
41 /* avoid extra function call in case we use fread (TVT) */
42 #define READ(_gif,_buf,_len) \
43 (((GifFilePrivateType*)_gif->Private)->Read ? \
44 ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \
45 fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File))
46
47 static int DGifGetWord(GifFileType *GifFile, int *Word);
48 static int DGifSetupDecompress(GifFileType *GifFile);
49 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
50 int LineLen);
51 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
52 static int DGifDecompressInput(GifFileType *GifFile, int *Code);
53 static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
54 GifByteType *NextByte);
55
56 /******************************************************************************
57 * GifFileType constructor with user supplied input function (TVT) *
58 * *
59 ******************************************************************************/
DGifOpen(void * userData,InputFunc readFunc)60 GifFileType *DGifOpen( void* userData, InputFunc readFunc )
61 {
62 unsigned char Buf[GIF_STAMP_LEN+1];
63 GifFileType *GifFile;
64 GifFilePrivateType *Private;
65
66
67 if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) {
68 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
69 return NULL;
70 }
71
72 memset(GifFile, '\0', sizeof(GifFileType));
73
74 if (!(Private = (GifFilePrivateType*) malloc(sizeof(GifFilePrivateType)))){
75 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
76 free((char *) GifFile);
77 return NULL;
78 }
79
80 GifFile->Private = (VoidPtr) Private;
81 Private->FileHandle = 0;
82 Private->File = 0;
83 Private->FileState = FILE_STATE_READ;
84
85 Private->Read = readFunc; /* TVT */
86 GifFile->UserData = userData; /* TVT */
87
88 /* Lets see if this is a GIF file: */
89 if ( READ( GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
90 _GifError = D_GIF_ERR_READ_FAILED;
91 free((char *) Private);
92 free((char *) GifFile);
93 return NULL;
94 }
95
96 /* The GIF Version number is ignored at this time. Maybe we should do */
97 /* something more useful with it. */
98 Buf[GIF_STAMP_LEN] = 0;
99 if (strncmp(GIF_STAMP, (char*)Buf, GIF_VERSION_POS) != 0) {
100 _GifError = D_GIF_ERR_NOT_GIF_FILE;
101 free((char *) Private);
102 free((char *) GifFile);
103 return NULL;
104 }
105
106 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
107 free((char *) Private);
108 free((char *) GifFile);
109 return NULL;
110 }
111
112 _GifError = 0;
113
114 return GifFile;
115 }
116
117 /******************************************************************************
118 * This routine should be called before any other DGif calls. Note that *
119 * this routine is called automatically from DGif file open routines. *
120 ******************************************************************************/
DGifGetScreenDesc(GifFileType * GifFile)121 int DGifGetScreenDesc(GifFileType *GifFile)
122 {
123 int i, BitsPerPixel;
124 GifByteType Buf[3];
125 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
126
127 if (!IS_READABLE(Private)) {
128 /* This file was NOT open for reading: */
129 _GifError = D_GIF_ERR_NOT_READABLE;
130 return GIF_ERROR;
131 }
132
133 /* Put the screen descriptor into the file: */
134 if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
135 DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
136 return GIF_ERROR;
137
138 if (READ( GifFile, Buf, 3) != 3) {
139 _GifError = D_GIF_ERR_READ_FAILED;
140 return GIF_ERROR;
141 }
142 GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
143 BitsPerPixel = (Buf[0] & 0x07) + 1;
144 GifFile->SBackGroundColor = Buf[1];
145 if (Buf[0] & 0x80) { /* Do we have global color map? */
146
147 GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
148
149 /* Get the global color map: */
150 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
151 if (READ(GifFile, Buf, 3) != 3) {
152 _GifError = D_GIF_ERR_READ_FAILED;
153 return GIF_ERROR;
154 }
155 GifFile->SColorMap->Colors[i].Red = Buf[0];
156 GifFile->SColorMap->Colors[i].Green = Buf[1];
157 GifFile->SColorMap->Colors[i].Blue = Buf[2];
158 }
159 }
160
161 return GIF_OK;
162 }
163
164 /******************************************************************************
165 * This routine should be called before any attemp to read an image. *
166 ******************************************************************************/
DGifGetRecordType(GifFileType * GifFile,GifRecordType * Type)167 int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
168 {
169 GifByteType Buf;
170 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
171
172 if (!IS_READABLE(Private)) {
173 /* This file was NOT open for reading: */
174 _GifError = D_GIF_ERR_NOT_READABLE;
175 return GIF_ERROR;
176 }
177
178 if (READ( GifFile, &Buf, 1) != 1) {
179 _GifError = D_GIF_ERR_READ_FAILED;
180 return GIF_ERROR;
181 }
182
183 switch (Buf) {
184 case ',':
185 *Type = IMAGE_DESC_RECORD_TYPE;
186 break;
187 case '!':
188 *Type = EXTENSION_RECORD_TYPE;
189 break;
190 case ';':
191 *Type = TERMINATE_RECORD_TYPE;
192 break;
193 default:
194 *Type = UNDEFINED_RECORD_TYPE;
195 _GifError = D_GIF_ERR_WRONG_RECORD;
196 return GIF_ERROR;
197 }
198
199 return GIF_OK;
200 }
201
202 /******************************************************************************
203 * This routine should be called before any attemp to read an image. *
204 * Note it is assumed the Image desc. header (',') has been read. *
205 ******************************************************************************/
DGifGetImageDesc(GifFileType * GifFile)206 int DGifGetImageDesc(GifFileType *GifFile)
207 {
208 int i, BitsPerPixel;
209 GifByteType Buf[3];
210 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
211 SavedImage *sp;
212
213 if (!IS_READABLE(Private)) {
214 /* This file was NOT open for reading: */
215 _GifError = D_GIF_ERR_NOT_READABLE;
216 return GIF_ERROR;
217 }
218 if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
219 DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
220 DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
221 DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
222 return GIF_ERROR;
223 if (READ(GifFile,Buf, 1) != 1) {
224 _GifError = D_GIF_ERR_READ_FAILED;
225 return GIF_ERROR;
226 }
227 BitsPerPixel = (Buf[0] & 0x07) + 1;
228 GifFile->Image.Interlace = (Buf[0] & 0x40);
229 if (Buf[0] & 0x80) { /* Does this image have local color map? */
230
231 if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
232 FreeMapObject(GifFile->Image.ColorMap);
233
234 GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
235 /* Get the image local color map: */
236 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
237 if (READ(GifFile,Buf, 3) != 3) {
238 _GifError = D_GIF_ERR_READ_FAILED;
239 return GIF_ERROR;
240 }
241 GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
242 GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
243 GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
244 }
245 }
246 if (GifFile->SavedImages) {
247 if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
248 sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) {
249 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
250 return GIF_ERROR;
251 }
252 } else {
253 if ((GifFile->SavedImages =
254 (SavedImage *)malloc(sizeof(SavedImage))) == NULL) {
255 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
256 return GIF_ERROR;
257 }
258 }
259
260 sp = &GifFile->SavedImages[GifFile->ImageCount];
261 memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
262 if (GifFile->Image.ColorMap != NULL) {
263 sp->ImageDesc.ColorMap = MakeMapObject(
264 GifFile->Image.ColorMap->ColorCount,
265 GifFile->Image.ColorMap->Colors);
266 }
267 sp->RasterBits = (char *)NULL;
268 sp->ExtensionBlockCount = 0;
269 sp->ExtensionBlocks = (ExtensionBlock *)NULL;
270
271 GifFile->ImageCount++;
272
273 Private->PixelCount = (long) GifFile->Image.Width *
274 (long) GifFile->Image.Height;
275
276 DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
277
278 return GIF_OK;
279 }
280
281 /******************************************************************************
282 * Get one full scanned line (Line) of length LineLen from GIF file. *
283 ******************************************************************************/
DGifGetLine(GifFileType * GifFile,GifPixelType * Line,int LineLen)284 int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
285 {
286 GifByteType *Dummy;
287 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
288
289 if (!IS_READABLE(Private)) {
290 /* This file was NOT open for reading: */
291 _GifError = D_GIF_ERR_NOT_READABLE;
292 return GIF_ERROR;
293 }
294
295 if (!LineLen) LineLen = GifFile->Image.Width;
296
297 #if defined(__MSDOS__) || defined(__GNUC__)
298 if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
299 #else
300 if ((Private->PixelCount -= LineLen) > 0xffff0000) {
301 #endif /* __MSDOS__ */
302 _GifError = D_GIF_ERR_DATA_TOO_BIG;
303 return GIF_ERROR;
304 }
305
306 if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
307 if (Private->PixelCount == 0) {
308 /* We probably would not be called any more, so lets clean */
309 /* everything before we return: need to flush out all rest of */
310 /* image until empty block (size 0) detected. We use GetCodeNext.*/
311 do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
312 return GIF_ERROR;
313 while (Dummy != NULL);
314 }
315 return GIF_OK;
316 }
317 else
318 return GIF_ERROR;
319 }
320
321 /******************************************************************************
322 * Get an extension block (see GIF manual) from gif file. This routine only *
323 * returns the first data block, and DGifGetExtensionNext shouldbe called *
324 * after this one until NULL extension is returned. *
325 * The Extension should NOT be freed by the user (not dynamically allocated).*
326 * Note it is assumed the Extension desc. header ('!') has been read. *
327 ******************************************************************************/
328 int DGifGetExtension(GifFileType *GifFile, int *ExtCode,
329 GifByteType **Extension)
330 {
331 GifByteType Buf;
332 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
333
334 if (!IS_READABLE(Private)) {
335 /* This file was NOT open for reading: */
336 _GifError = D_GIF_ERR_NOT_READABLE;
337 return GIF_ERROR;
338 }
339
340 if (READ(GifFile,&Buf, 1) != 1) {
341 _GifError = D_GIF_ERR_READ_FAILED;
342 return GIF_ERROR;
343 }
344 *ExtCode = Buf;
345
346 return DGifGetExtensionNext(GifFile, Extension);
347 }
348
349 /******************************************************************************
350 * Get a following extension block (see GIF manual) from gif file. This *
351 * routine should be called until NULL Extension is returned. *
352 * The Extension should NOT be freed by the user (not dynamically allocated).*
353 ******************************************************************************/
354 int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension)
355 {
356 GifByteType Buf;
357 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
358
359 if (READ(GifFile,&Buf, 1) != 1) {
360 _GifError = D_GIF_ERR_READ_FAILED;
361 return GIF_ERROR;
362 }
363 if (Buf > 0) {
364 *Extension = Private->Buf; /* Use private unused buffer. */
365 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
366 if (READ(GifFile,&((*Extension)[1]), Buf) != Buf) {
367 _GifError = D_GIF_ERR_READ_FAILED;
368 return GIF_ERROR;
369 }
370 }
371 else
372 *Extension = NULL;
373
374 return GIF_OK;
375 }
376
377 /******************************************************************************
378 * This routine should be called last, to close the GIF file. *
379 ******************************************************************************/
380 int DGifCloseFile(GifFileType *GifFile)
381 {
382 GifFilePrivateType *Private;
383 FILE *File;
384 int ret = GIF_OK;
385
386 if (GifFile == NULL) return GIF_ERROR;
387
388 Private = (GifFilePrivateType *) GifFile->Private;
389
390 if (!IS_READABLE(Private)) {
391 /* This file was NOT open for reading: */
392 _GifError = D_GIF_ERR_NOT_READABLE;
393 ret = GIF_ERROR; /* we have to free everything regardless */
394 }
395
396 File = Private->File;
397
398 if (GifFile->Image.ColorMap)
399 {
400 FreeMapObject(GifFile->Image.ColorMap);
401 GifFile->Image.ColorMap = NULL;
402 }
403
404 if (GifFile->SColorMap)
405 {
406 FreeMapObject(GifFile->SColorMap);
407 GifFile->SColorMap = NULL;
408 }
409
410 if (Private)
411 {
412 free((char *) Private);
413 GifFile->Private = NULL;
414 }
415
416 if (GifFile->SavedImages)
417 {
418 FreeSavedImages(GifFile);
419 GifFile->SavedImages = NULL;
420 }
421
422 free(GifFile);
423
424 if ( File && (fclose(File) != 0))
425 {
426 _GifError = D_GIF_ERR_CLOSE_FAILED;
427 ret = GIF_ERROR;
428 }
429 return ret;
430 }
431
432 /******************************************************************************
433 * Get 2 bytes (word) from the given file: *
434 ******************************************************************************/
435 static int DGifGetWord(GifFileType *GifFile, int *Word)
436 {
437 unsigned char c[2];
438
439 if (READ(GifFile,c, 2) != 2) {
440 _GifError = D_GIF_ERR_READ_FAILED;
441 return GIF_ERROR;
442 }
443
444 *Word = (((unsigned int) c[1]) << 8) + c[0];
445 return GIF_OK;
446 }
447
448 /******************************************************************************
449 * Get the image code in compressed form. his routine can be called if the *
450 * information needed to be piped out as is. Obviously this is much faster *
451 * than decoding and encoding again. This routine should be followed by calls *
452 * to DGifGetCodeNext, until NULL block is returned. *
453 * The block should NOT be freed by the user (not dynamically allocated). *
454 ******************************************************************************/
455 int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
456 {
457 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
458
459 if (!IS_READABLE(Private)) {
460 /* This file was NOT open for reading: */
461 _GifError = D_GIF_ERR_NOT_READABLE;
462 return GIF_ERROR;
463 }
464
465 *CodeSize = Private->BitsPerPixel;
466
467 return DGifGetCodeNext(GifFile, CodeBlock);
468 }
469
470 /******************************************************************************
471 * Continue to get the image code in compressed form. This routine should be *
472 * called until NULL block is returned. *
473 * The block should NOT be freed by the user (not dynamically allocated). *
474 ******************************************************************************/
475 int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
476 {
477 GifByteType Buf;
478 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
479 if (READ(GifFile,&Buf, 1) != 1) {
480 _GifError = D_GIF_ERR_READ_FAILED;
481 return GIF_ERROR;
482 }
483 if (Buf > 0) {
484 int ret ;
485 *CodeBlock = Private->Buf; /* Use private unused buffer. */
486 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
487 ret = READ(GifFile,&((*CodeBlock)[1]), Buf);
488 if ( ret != Buf)
489 {
490 if( Buf == 59 )
491 {
492 fseek( GifFile->UserData, -1, SEEK_END );
493 *CodeBlock = NULL ;
494 return GIF_OK;
495 }
496 _GifError = D_GIF_ERR_READ_FAILED;
497 return GIF_ERROR;
498 }
499 }
500 else {
501 *CodeBlock = NULL;
502 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
503 Private->PixelCount = 0; /* And local info. indicate image read. */
504 }
505
506 return GIF_OK;
507 }
508
509 /******************************************************************************
510 * Setup the LZ decompression for this image: *
511 ******************************************************************************/
512 static int DGifSetupDecompress(GifFileType *GifFile)
513 {
514 int i, BitsPerPixel;
515 GifByteType CodeSize;
516 unsigned int *Prefix;
517 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
518
519 READ(GifFile,&CodeSize, 1); /* Read Code size from file. */
520 BitsPerPixel = CodeSize;
521
522 Private->Buf[0] = 0; /* Input Buffer empty. */
523 Private->BitsPerPixel = BitsPerPixel;
524 Private->ClearCode = (1 << BitsPerPixel);
525 Private->EOFCode = Private->ClearCode + 1;
526 Private->RunningCode = Private->EOFCode + 1;
527 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
528 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
529 Private->StackPtr = 0; /* No pixels on the pixel stack. */
530 Private->LastCode = NO_SUCH_CODE;
531 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
532 Private->CrntShiftDWord = 0;
533
534 Prefix = Private->Prefix;
535 for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
536
537 return GIF_OK;
538 }
539
540 /******************************************************************************
541 * The LZ decompression routine: *
542 * This version decompress the given gif file into Line of length LineLen. *
543 * This routine can be called few times (one per scan line, for example), in *
544 * order the complete the whole image. *
545 ******************************************************************************/
546 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
547 int LineLen)
548 {
549 int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
550 GifByteType *Stack, *Suffix;
551 unsigned int *Prefix;
552 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
553
554 StackPtr = Private->StackPtr;
555 Prefix = Private->Prefix;
556 Suffix = Private->Suffix;
557 Stack = Private->Stack;
558 EOFCode = Private->EOFCode;
559 ClearCode = Private->ClearCode;
560 LastCode = Private->LastCode;
561
562 if (StackPtr != 0) {
563 /* Let pop the stack off before continueing to read the gif file: */
564 while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
565 }
566
567 while (i < LineLen) { /* Decode LineLen items. */
568 if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
569 return GIF_ERROR;
570
571 if (CrntCode == EOFCode) {
572 /* Note however that usually we will not be here as we will stop */
573 /* decoding as soon as we got all the pixel, or EOF code will */
574 /* not be read at all, and DGifGetLine/Pixel clean everything. */
575 if (i != LineLen - 1 || Private->PixelCount != 0) {
576 _GifError = D_GIF_ERR_EOF_TOO_SOON;
577 return GIF_ERROR;
578 }
579 i++;
580 }
581 else if (CrntCode == ClearCode) {
582 /* We need to start over again: */
583 for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
584 Private->RunningCode = Private->EOFCode + 1;
585 Private->RunningBits = Private->BitsPerPixel + 1;
586 Private->MaxCode1 = 1 << Private->RunningBits;
587 LastCode = Private->LastCode = NO_SUCH_CODE;
588 }
589 else {
590 /* Its regular code - if in pixel range simply add it to output */
591 /* stream, otherwise trace to codes linked list until the prefix */
592 /* is in pixel range: */
593 if (CrntCode < ClearCode) {
594 /* This is simple - its pixel scalar, so add it to output: */
595 Line[i++] = CrntCode;
596 }
597 else {
598 /* Its a code to needed to be traced: trace the linked list */
599 /* until the prefix is a pixel, while pushing the suffix */
600 /* pixels on our stack. If we done, pop the stack in reverse */
601 /* (thats what stack is good for!) order to output. */
602 if (Prefix[CrntCode] == NO_SUCH_CODE) {
603 /* Only allowed if CrntCode is exactly the running code: */
604 /* In that case CrntCode = XXXCode, CrntCode or the */
605 /* prefix code is last code and the suffix char is */
606 /* exactly the prefix of last code! */
607 if (CrntCode == Private->RunningCode - 2) {
608 CrntPrefix = LastCode;
609 Suffix[Private->RunningCode - 2] =
610 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
611 LastCode, ClearCode);
612 }
613 else {
614 /*fprintf( stderr, "error at line %d, CrntCode = %d, Private->RunningCode - 2 = %d\n", __LINE__, CrntCode, Private->RunningCode - 2 ); */
615 _GifError = D_GIF_ERR_IMAGE_DEFECT;
616 return GIF_ERROR;
617 }
618 }
619 else
620 CrntPrefix = CrntCode;
621
622 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */
623 /* During the trace. As we might loop forever, in case of */
624 /* defective image, we count the number of loops we trace */
625 /* and stop if we got LZ_MAX_CODE. obviously we can not */
626 /* loop more than that. */
627 j = 0;
628 while (j++ <= LZ_MAX_CODE &&
629 CrntPrefix > ClearCode &&
630 CrntPrefix <= LZ_MAX_CODE) {
631 Stack[StackPtr++] = Suffix[CrntPrefix];
632 CrntPrefix = Prefix[CrntPrefix];
633 }
634 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
635 /* fprintf( stderr, "error at line %d, j = %d, CrntPrefix = %d\n", __LINE__, j, CrntPrefix ); */
636 _GifError = D_GIF_ERR_IMAGE_DEFECT;
637 return GIF_ERROR;
638 }
639 /* Push the last character on stack: */
640 Stack[StackPtr++] = CrntPrefix;
641
642 /* Now lets pop all the stack into output: */
643 while (StackPtr != 0 && i < LineLen)
644 Line[i++] = Stack[--StackPtr];
645 }
646 if (LastCode != NO_SUCH_CODE) {
647 Prefix[Private->RunningCode - 2] = LastCode;
648
649 if (CrntCode == Private->RunningCode - 2) {
650 /* Only allowed if CrntCode is exactly the running code: */
651 /* In that case CrntCode = XXXCode, CrntCode or the */
652 /* prefix code is last code and the suffix char is */
653 /* exactly the prefix of last code! */
654 Suffix[Private->RunningCode - 2] =
655 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
656 }
657 else {
658 Suffix[Private->RunningCode - 2] =
659 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
660 }
661 }
662 LastCode = CrntCode;
663 }
664 }
665
666 Private->LastCode = LastCode;
667 Private->StackPtr = StackPtr;
668
669 return GIF_OK;
670 }
671
672 /******************************************************************************
673 * Routine to trace the Prefixes linked list until we get a prefix which is *
674 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
675 * If image is defective, we might loop here forever, so we limit the loops to *
676 * the maximum possible if image O.k. - LZ_MAX_CODE times. *
677 ******************************************************************************/
678 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
679 {
680 int i = 0;
681
682 while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
683 return Code;
684 }
685
686 /******************************************************************************
687 * The LZ decompression input routine: *
688 * This routine is responsable for the decompression of the bit stream from *
689 * 8 bits (bytes) packets, into the real codes. *
690 * Returns GIF_OK if read succesfully. *
691 ******************************************************************************/
692 static int DGifDecompressInput(GifFileType *GifFile, int *Code)
693 {
694 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
695
696 GifByteType NextByte;
697 static unsigned int CodeMasks[] = {
698 0x0000, 0x0001, 0x0003, 0x0007,
699 0x000f, 0x001f, 0x003f, 0x007f,
700 0x00ff, 0x01ff, 0x03ff, 0x07ff,
701 0x0fff
702 };
703
704 while (Private->CrntShiftState < Private->RunningBits) {
705 /* Needs to get more bytes from input stream for next code: */
706 if (DGifBufferedInput(GifFile, Private->Buf, &NextByte)
707 == GIF_ERROR) {
708 return GIF_ERROR;
709 }
710 Private->CrntShiftDWord |=
711 ((unsigned long) NextByte) << Private->CrntShiftState;
712 Private->CrntShiftState += 8;
713 }
714 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
715
716 Private->CrntShiftDWord >>= Private->RunningBits;
717 Private->CrntShiftState -= Private->RunningBits;
718
719 /* If code cannt fit into RunningBits bits, must raise its size. Note */
720 /* however that codes above 4095 are used for special signaling. */
721 if (++Private->RunningCode > Private->MaxCode1 &&
722 Private->RunningBits < LZ_BITS) {
723 Private->MaxCode1 <<= 1;
724 Private->RunningBits++;
725 }
726 return GIF_OK;
727 }
728
729 /******************************************************************************
730 * This routines read one gif data block at a time and buffers it internally *
731 * so that the decompression routine could access it. *
732 * The routine returns the next byte from its internal buffer (or read next *
733 * block in if buffer empty) and returns GIF_OK if succesful. *
734 ******************************************************************************/
735 static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
736 GifByteType *NextByte)
737 {
738 if (Buf[0] == 0) {
739 /* Needs to read the next buffer - this one is empty: */
740 if (READ(GifFile, Buf, 1) != 1)
741 {
742 _GifError = D_GIF_ERR_READ_FAILED;
743 return GIF_ERROR;
744 }
745 if (READ(GifFile,&Buf[1], Buf[0]) != Buf[0])
746 {
747 _GifError = D_GIF_ERR_READ_FAILED;
748 return GIF_ERROR;
749 }
750 *NextByte = Buf[1];
751 Buf[1] = 2; /* We use now the second place as last char read! */
752 Buf[0]--;
753 }
754 else {
755 *NextByte = Buf[Buf[1]++];
756 Buf[0]--;
757 }
758
759 return GIF_OK;
760 }
761
762
763