comparison src/dgif_lib.c @ 308:33bdb3d4b97f r21-0b52

Import from CVS: tag r21-0b52
author cvs
date Mon, 13 Aug 2007 10:42:44 +0200
parents
children 19dcec799385 d883f39b8495
comparison
equal deleted inserted replaced
307:42d630fd9bd8 308:33bdb3d4b97f
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 * 19 Feb 98 - Version 1.2 by Jareth Hein (Support for user specified I/O) *
12 ******************************************************************************/
13
14 #ifdef __MSDOS__
15 #include <io.h>
16 #include <alloc.h>
17 #include <stdlib.h>
18 #include <sys\stat.h>
19 #else
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #endif /* __MSDOS__ */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #ifdef HAVE_FCNTL_H
29 #include <fcntl.h>
30 #endif
31
32 #include "gifrlib.h"
33
34 #define PROGRAM_NAME "GIFLIB"
35
36
37 static void DGifGetWord(GifFileType *GifFile, int *Word);
38 static void DGifSetupDecompress(GifFileType *GifFile);
39 static void DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
40 int LineLen);
41 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
42 static void DGifDecompressInput(GifFileType *GifFile, int *Code);
43 static void DGifBufferedInput(GifFileType *GifFile, GifByteType *NextByte);
44
45 /******************************************************************************
46 * Open a new gif file for read, given by its name. *
47 * Returns GifFileType pointer dynamically allocated which serves as the gif *
48 * info record. *
49 ******************************************************************************/
50 void DGifOpenFileName(GifFileType *GifFile, const char *FileName)
51 {
52 FILE *f;
53
54 if ((f = fopen(FileName,
55 #ifdef __MSDOS__
56 "rb"
57 #else
58 "r"
59 #endif /* __MSDOS__ */
60 )) == NULL)
61 GifInternError(GifFile, D_GIF_ERR_OPEN_FAILED);
62
63 GifStdIOInit(GifFile, f, -1);
64 DGifInitRead(GifFile);
65 }
66
67 /******************************************************************************
68 * Update a new gif file, given its file handle. *
69 * Returns GifFileType pointer dynamically allocated which serves as the gif *
70 * info record. *
71 ******************************************************************************/
72 void DGifOpenFileHandle(GifFileType *GifFile, int FileHandle)
73 {
74 FILE *f;
75
76 #ifdef __MSDOS__
77 setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
78 f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
79 setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/
80 #else
81 f = fdopen(FileHandle, "r"); /* Make it into a stream: */
82 #endif /* __MSDOS__ */
83
84 GifStdIOInit(GifFile, f, -1);
85 DGifInitRead(GifFile);
86 }
87
88 /******************************************************************************
89 * Update a new gif file, given its file handle. *
90 * Returns GifFileType pointer dynamically allocated which serves as the gif *
91 * info record. _GifError is cleared if succesfull. *
92 ******************************************************************************/
93 void DGifInitRead(GifFileType *GifFile)
94 {
95 GifByteType Buf[GIF_STAMP_LEN+1];
96 GifFilePrivateType *Private;
97
98 if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType)))
99 == NULL) {
100 GifInternError(GifFile, D_GIF_ERR_NOT_ENOUGH_MEM);
101 }
102 memset(Private, '\0', sizeof(GifFilePrivateType));
103 GifFile->Private = (VoidPtr) Private;
104
105 Private->FileState = 0; /* Make sure bit 0 = 0 (File open for read). */
106
107 /* Lets see if this is a GIF file: */
108 GifRead(Buf, GIF_STAMP_LEN, GifFile);
109
110 /* The GIF Version number is ignored at this time. Maybe we should do */
111 /* something more useful with it. */
112 Buf[GIF_STAMP_LEN] = 0;
113 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
114 GifInternError(GifFile, D_GIF_ERR_NOT_GIF_FILE);
115 }
116
117 DGifGetScreenDesc(GifFile);
118 }
119
120 /******************************************************************************
121 * This routine should be called before any other DGif calls. Note that *
122 * this routine is called automatically from DGif file open routines. *
123 ******************************************************************************/
124 void DGifGetScreenDesc(GifFileType *GifFile)
125 {
126 int i, BitsPerPixel;
127 GifByteType Buf[3];
128 GifFilePrivateType *Private = (GifFilePrivateType*) GifFile->Private;
129
130 if (!IS_READABLE(Private)) {
131 /* This file was NOT open for reading: */
132 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
133 }
134
135 /* Put the screen descriptor into the file: */
136 DGifGetWord(GifFile, &GifFile->SWidth);
137 DGifGetWord(GifFile, &GifFile->SHeight);
138
139 GifRead(Buf, 3, GifFile);
140 GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
141 BitsPerPixel = (Buf[0] & 0x07) + 1;
142 GifFile->SBackGroundColor = Buf[1];
143 if (Buf[0] & 0x80) { /* Do we have global color map? */
144
145 GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
146
147 /* Get the global color map: */
148 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
149 GifRead(Buf, 3, GifFile);
150 GifFile->SColorMap->Colors[i].Red = Buf[0];
151 GifFile->SColorMap->Colors[i].Green = Buf[1];
152 GifFile->SColorMap->Colors[i].Blue = Buf[2];
153 }
154 } else {
155 /* We should always have a colormap */
156 GifFile->SColorMap = MakeMapObject(2, NULL);
157 GifFile->SColorMap->Colors[0].Red = 0;
158 GifFile->SColorMap->Colors[0].Green = 0;
159 GifFile->SColorMap->Colors[0].Blue = 0;
160 GifFile->SColorMap->Colors[1].Red = 0xff;
161 GifFile->SColorMap->Colors[1].Green = 0xff;
162 GifFile->SColorMap->Colors[1].Blue = 0xff;
163 }
164 }
165
166 /******************************************************************************
167 * This routine should be called before any attemp to read an image. *
168 ******************************************************************************/
169 void DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
170 {
171 GifByteType Buf;
172 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
173
174 if (!IS_READABLE(Private)) {
175 /* This file was NOT open for reading: */
176 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
177 }
178
179 GifRead(&Buf, 1, GifFile);
180
181 switch (Buf) {
182 case ',':
183 *Type = IMAGE_DESC_RECORD_TYPE;
184 break;
185 case '!':
186 *Type = EXTENSION_RECORD_TYPE;
187 break;
188 case ';':
189 *Type = TERMINATE_RECORD_TYPE;
190 break;
191 default:
192 *Type = UNDEFINED_RECORD_TYPE;
193 GifInternError(GifFile, D_GIF_ERR_WRONG_RECORD);
194 }
195 }
196
197 /******************************************************************************
198 * This routine should be called before any attemp to read an image. *
199 * Note it is assumed the Image desc. header (',') has been read. *
200 ******************************************************************************/
201 void DGifGetImageDesc(GifFileType *GifFile)
202 {
203 int i, BitsPerPixel;
204 GifByteType Buf[3];
205 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
206
207 if (!IS_READABLE(Private)) {
208 /* This file was NOT open for reading: */
209 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
210 }
211
212 DGifGetWord(GifFile, &GifFile->Image.Left);
213 DGifGetWord(GifFile, &GifFile->Image.Top);
214 DGifGetWord(GifFile, &GifFile->Image.Width);
215 DGifGetWord(GifFile, &GifFile->Image.Height);
216
217 GifRead(Buf, 1, GifFile);
218 BitsPerPixel = (Buf[0] & 0x07) + 1;
219 GifFile->Image.Interlace = (Buf[0] & 0x40);
220 if (Buf[0] & 0x80) { /* Does this image have local color map? */
221
222 if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
223 FreeMapObject(GifFile->Image.ColorMap);
224
225 GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
226
227 /* Get the image local color map: */
228 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
229 GifRead(Buf, 3, GifFile);
230 GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
231 GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
232 GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
233 }
234 }
235
236 if (GifFile->SavedImages) {
237 SavedImage *sp;
238
239 if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
240 sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) {
241 GifInternError(GifFile, D_GIF_ERR_NOT_ENOUGH_MEM);
242 }
243
244 sp = &GifFile->SavedImages[GifFile->ImageCount];
245 memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
246 if (GifFile->Image.ColorMap)
247 {
248 sp->ImageDesc.ColorMap =
249 MakeMapObject (GifFile->Image.ColorMap->ColorCount,
250 GifFile->Image.ColorMap->Colors);
251 }
252 sp->RasterBits = (GifPixelType *)NULL;
253 sp->ExtensionBlockCount = 0;
254 sp->ExtensionBlocks = (ExtensionBlock *)NULL;
255 }
256
257 GifFile->ImageCount++;
258
259 Private->PixelCount = (long) GifFile->Image.Width *
260 (long) GifFile->Image.Height;
261
262 DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
263 }
264
265 /******************************************************************************
266 * Get one full scanned line (Line) of length LineLen from GIF file. *
267 ******************************************************************************/
268 void DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
269 {
270 GifByteType *Dummy;
271 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
272
273 if (!IS_READABLE(Private)) {
274 /* This file was NOT open for reading: */
275 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
276 }
277
278 if (!LineLen) LineLen = GifFile->Image.Width;
279
280 #if defined(__MSDOS__) || defined(__GNUC__)
281 if ((Private->PixelCount -= LineLen) > 0xffff0000UL)
282 #else
283 if ((Private->PixelCount -= LineLen) > 0xffff0000)
284 #endif /* __MSDOS__ */
285 {
286 GifInternError(GifFile, D_GIF_ERR_DATA_TOO_BIG);
287 }
288
289 DGifDecompressLine(GifFile, Line, LineLen);
290 if (Private->PixelCount == 0) {
291 /* We probably would not be called any more, so lets clean */
292 /* everything before we return: need to flush out all rest of */
293 /* image until empty block (size 0) detected. We use GetCodeNext.*/
294 do
295 DGifGetCodeNext(GifFile, &Dummy);
296 while (Dummy != NULL);
297 }
298 }
299
300 /******************************************************************************
301 * Put one pixel (Pixel) into GIF file. *
302 ******************************************************************************/
303 void DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
304 {
305 GifByteType *Dummy;
306 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
307
308 if (!IS_READABLE(Private)) {
309 /* This file was NOT open for reading: */
310 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
311 }
312
313 #if defined(__MSDOS__) || defined(__GNUC__)
314 if (--Private->PixelCount > 0xffff0000UL)
315 #else
316 if (--Private->PixelCount > 0xffff0000)
317 #endif /* __MSDOS__ */
318 {
319 GifInternError(GifFile, D_GIF_ERR_DATA_TOO_BIG);
320 }
321
322 DGifDecompressLine(GifFile, &Pixel, 1);
323 if (Private->PixelCount == 0) {
324 /* We probably would not be called any more, so lets clean */
325 /* everything before we return: need to flush out all rest of */
326 /* image until empty block (size 0) detected. We use GetCodeNext.*/
327 do
328 DGifGetCodeNext(GifFile, &Dummy);
329 while (Dummy != NULL);
330 }
331 }
332
333 /******************************************************************************
334 * Get an extension block (see GIF manual) from gif file. This routine only *
335 * returns the first data block, and DGifGetExtensionNext shouldbe called *
336 * after this one until NULL extension is returned. *
337 * The Extension should NOT be freed by the user (not dynamically allocated).*
338 * Note it is assumed the Extension desc. header ('!') has been read. *
339 ******************************************************************************/
340 void DGifGetExtension(GifFileType *GifFile, int *ExtCode,
341 GifByteType **Extension)
342 {
343 GifByteType Buf;
344 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
345
346 if (!IS_READABLE(Private)) {
347 /* This file was NOT open for reading: */
348 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
349 }
350
351 GifRead(&Buf, 1, GifFile);
352 *ExtCode = Buf;
353
354 DGifGetExtensionNext(GifFile, Extension);
355 }
356
357 /******************************************************************************
358 * Get a following extension block (see GIF manual) from gif file. This *
359 * routine sould be called until NULL Extension is returned. *
360 * The Extension should NOT be freed by the user (not dynamically allocated).*
361 ******************************************************************************/
362 void DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension)
363 {
364 GifByteType Buf;
365 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
366
367 GifRead(&Buf, 1, GifFile);
368 if (Buf > 0) {
369 *Extension = Private->Buf; /* Use private unused buffer. */
370 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
371 GifRead(&((*Extension)[1]), Buf, GifFile);
372 }
373 else
374 *Extension = NULL;
375 }
376
377 /******************************************************************************
378 * This routine should be called second to last, to close the GIF file. *
379 ******************************************************************************/
380 int DGifCloseFile(GifFileType *GifFile)
381 {
382 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
383
384 if (GifFile == NULL) return -1;
385
386 if (!IS_READABLE(Private))
387 {
388 /* This file was NOT open for reading: */
389 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
390 }
391
392 if (GifClose (GifFile))
393 {
394 GifInternError(GifFile, D_GIF_ERR_CLOSE_FAILED);
395 }
396 return 0;
397 }
398
399 /******************************************************************************
400 * Get 2 bytes (word) from the given file: *
401 ******************************************************************************/
402 static void DGifGetWord(GifFileType *GifFile, int *Word)
403 {
404 unsigned char c[2];
405
406 GifRead(c, 2, GifFile);
407
408 *Word = (((unsigned int) c[1]) << 8) + c[0];
409 }
410
411 /******************************************************************************
412 * Get the image code in compressed form. his routine can be called if the *
413 * information needed to be piped out as is. Obviously this is much faster *
414 * than decoding and encoding again. This routine should be followed by calls *
415 * to DGifGetCodeNext, until NULL block is returned. *
416 * The block should NOT be freed by the user (not dynamically allocated). *
417 ******************************************************************************/
418 void DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
419 {
420 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
421
422 if (!IS_READABLE(Private)) {
423 /* This file was NOT open for reading: */
424 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
425 }
426
427 *CodeSize = Private->BitsPerPixel;
428
429 DGifGetCodeNext(GifFile, CodeBlock);
430 }
431
432 /******************************************************************************
433 * Continue to get the image code in compressed form. This routine should be *
434 * called until NULL block is returned. *
435 * The block should NOT be freed by the user (not dynamically allocated). *
436 ******************************************************************************/
437 void DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
438 {
439 GifByteType Buf;
440 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
441
442 GifRead(&Buf, 1, GifFile);
443
444 if (Buf > 0) {
445 *CodeBlock = Private->Buf; /* Use private unused buffer. */
446 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
447 GifRead(&((*CodeBlock)[1]), Buf, GifFile);
448 }
449 else {
450 *CodeBlock = NULL;
451 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
452 Private->PixelCount = 0; /* And local info. indicate image read. */
453 }
454
455 }
456
457 /******************************************************************************
458 * Setup the LZ decompression for this image: *
459 ******************************************************************************/
460 static void DGifSetupDecompress(GifFileType *GifFile)
461 {
462 int i, BitsPerPixel;
463 GifByteType CodeSize;
464 unsigned int *Prefix;
465 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
466
467 GifRead(&CodeSize, 1, GifFile); /* Read Code size from file. */
468 BitsPerPixel = CodeSize;
469
470 Private->Buf[0] = 0; /* Input Buffer empty. */
471 Private->BitsPerPixel = BitsPerPixel;
472 Private->ClearCode = (1 << BitsPerPixel);
473 Private->EOFCode = Private->ClearCode + 1;
474 Private->RunningCode = Private->EOFCode + 1;
475 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
476 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
477 Private->StackPtr = 0; /* No pixels on the pixel stack. */
478 Private->LastCode = NO_SUCH_CODE;
479 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
480 Private->CrntShiftDWord = 0;
481
482 Prefix = Private->Prefix;
483 for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
484 }
485
486 /******************************************************************************
487 * The LZ decompression routine: *
488 * This version decompress the given gif file into Line of length LineLen. *
489 * This routine can be called few times (one per scan line, for example), in *
490 * order the complete the whole image. *
491 ******************************************************************************/
492 static void DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
493 int LineLen)
494 {
495 int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
496 GifByteType *Stack, *Suffix;
497 unsigned int *Prefix;
498 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
499
500 StackPtr = Private->StackPtr;
501 Prefix = Private->Prefix;
502 Suffix = Private->Suffix;
503 Stack = Private->Stack;
504 EOFCode = Private->EOFCode;
505 ClearCode = Private->ClearCode;
506 LastCode = Private->LastCode;
507
508 CrntPrefix = 0;
509 if (StackPtr != 0) {
510 /* Let pop the stack off before continueing to read the gif file: */
511 while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
512 }
513
514 while (i < LineLen) { /* Decode LineLen items. */
515 DGifDecompressInput(GifFile, &CrntCode);
516
517 if (CrntCode == EOFCode) {
518 /* Note however that usually we will not be here as we will stop */
519 /* decoding as soon as we got all the pixel, or EOF code will */
520 /* not be read at all, and DGifGetLine/Pixel clean everything. */
521 if (i != LineLen - 1 || Private->PixelCount != 0) {
522 GifInternError(GifFile, D_GIF_ERR_EOF_TOO_SOON);
523 }
524 i++;
525 }
526 else if (CrntCode == ClearCode) {
527 /* We need to start over again: */
528 for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
529 Private->RunningCode = Private->EOFCode + 1;
530 Private->RunningBits = Private->BitsPerPixel + 1;
531 Private->MaxCode1 = 1 << Private->RunningBits;
532 LastCode = Private->LastCode = NO_SUCH_CODE;
533 }
534 else {
535 /* Its regular code - if in pixel range simply add it to output */
536 /* stream, otherwise trace to codes linked list until the prefix */
537 /* is in pixel range: */
538 if (CrntCode < ClearCode) {
539 /* This is simple - its pixel scalar, so add it to output: */
540 Line[i++] = CrntCode;
541 }
542 else {
543 /* Its a code to needed to be traced: trace the linked list */
544 /* until the prefix is a pixel, while pushing the suffix */
545 /* pixels on our stack. If we done, pop the stack in reverse */
546 /* (thats what stack is good for!) order to output. */
547 if (Prefix[CrntCode] == NO_SUCH_CODE) {
548 /* Only allowed if CrntCode is exactly the running code: */
549 /* In that case CrntCode = XXXCode, CrntCode or the */
550 /* prefix code is last code and the suffix char is */
551 /* exactly the prefix of last code! */
552 if (CrntCode == Private->RunningCode - 2) {
553 CrntPrefix = LastCode;
554 Suffix[Private->RunningCode - 2] =
555 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
556 LastCode, ClearCode);
557 }
558 else {
559 GifInternError(GifFile, D_GIF_ERR_IMAGE_DEFECT);
560 }
561 }
562 else
563 CrntPrefix = CrntCode;
564
565 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */
566 /* During the trace. As we might loop forever, in case of */
567 /* defective image, we count the number of loops we trace */
568 /* and stop if we got LZ_MAX_CODE. obviously we can not */
569 /* loop more than that. */
570 j = 0;
571 while (j++ <= LZ_MAX_CODE &&
572 CrntPrefix > ClearCode &&
573 CrntPrefix <= LZ_MAX_CODE) {
574 Stack[StackPtr++] = Suffix[CrntPrefix];
575 CrntPrefix = Prefix[CrntPrefix];
576 }
577 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
578 GifInternError(GifFile, D_GIF_ERR_IMAGE_DEFECT);
579 }
580 /* Push the last character on stack: */
581 Stack[StackPtr++] = CrntPrefix;
582
583 /* Now lets pop all the stack into output: */
584 while (StackPtr != 0 && i < LineLen)
585 Line[i++] = Stack[--StackPtr];
586 }
587 if (LastCode != NO_SUCH_CODE) {
588 Prefix[Private->RunningCode - 2] = LastCode;
589
590 if (CrntCode == Private->RunningCode - 2) {
591 /* Only allowed if CrntCode is exactly the running code: */
592 /* In that case CrntCode = XXXCode, CrntCode or the */
593 /* prefix code is last code and the suffix char is */
594 /* exactly the prefix of last code! */
595 Suffix[Private->RunningCode - 2] =
596 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
597 }
598 else {
599 Suffix[Private->RunningCode - 2] =
600 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
601 }
602 }
603 LastCode = CrntCode;
604 }
605 }
606
607 Private->LastCode = LastCode;
608 Private->StackPtr = StackPtr;
609 }
610
611 /******************************************************************************
612 * Routine to trace the Prefixes linked list until we get a prefix which is *
613 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
614 * If image is defective, we might loop here forever, so we limit the loops to *
615 * the maximum possible if image O.k. - LZ_MAX_CODE times. *
616 ******************************************************************************/
617 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
618 {
619 int i = 0;
620
621 while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
622 return Code;
623 }
624
625 /******************************************************************************
626 * Interface for accessing the LZ codes directly. Set Code to the real code *
627 * (12bits), or to -1 if EOF code is returned. *
628 ******************************************************************************/
629 void DGifGetLZCodes(GifFileType *GifFile, int *Code)
630 {
631 GifByteType *CodeBlock;
632 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
633
634 if (!IS_READABLE(Private)) {
635 /* This file was NOT open for reading: */
636 GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
637 }
638
639 DGifDecompressInput(GifFile, Code);
640
641 if (*Code == Private->EOFCode) {
642 /* Skip rest of codes (hopefully only NULL terminating block): */
643 do
644 DGifGetCodeNext(GifFile, &CodeBlock);
645 while (CodeBlock != NULL);
646
647 *Code = -1;
648 }
649 else if (*Code == Private->ClearCode) {
650 /* We need to start over again: */
651 Private->RunningCode = Private->EOFCode + 1;
652 Private->RunningBits = Private->BitsPerPixel + 1;
653 Private->MaxCode1 = 1 << Private->RunningBits;
654 }
655 }
656
657 /******************************************************************************
658 * The LZ decompression input routine: *
659 * This routine is responsable for the decompression of the bit stream from *
660 * 8 bits (bytes) packets, into the real codes. *
661 * Returns GIF_OK if read succesfully. *
662 ******************************************************************************/
663 static void DGifDecompressInput(GifFileType *GifFile, int *Code)
664 {
665 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
666 GifByteType NextByte;
667 static unsigned int CodeMasks[] = {
668 0x0000, 0x0001, 0x0003, 0x0007,
669 0x000f, 0x001f, 0x003f, 0x007f,
670 0x00ff, 0x01ff, 0x03ff, 0x07ff,
671 0x0fff
672 };
673
674 while (Private->CrntShiftState < Private->RunningBits) {
675 /* Needs to get more bytes from input stream for next code: */
676 DGifBufferedInput(GifFile, &NextByte);
677 Private->CrntShiftDWord |=
678 ((unsigned long) NextByte) << Private->CrntShiftState;
679 Private->CrntShiftState += 8;
680 }
681 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
682
683 Private->CrntShiftDWord >>= Private->RunningBits;
684 Private->CrntShiftState -= Private->RunningBits;
685
686 /* If code cannt fit into RunningBits bits, must raise its size. Note */
687 /* however that codes above 4095 are used for special signaling. */
688 if (++Private->RunningCode > Private->MaxCode1 &&
689 Private->RunningBits < LZ_BITS) {
690 Private->MaxCode1 <<= 1;
691 Private->RunningBits++;
692 }
693 }
694
695 /******************************************************************************
696 * This routines read one gif data block at a time and buffers it internally *
697 * so that the decompression routine could access it. *
698 * The routine returns the next byte from its internal buffer (or read next *
699 * block in if buffer empty) *
700 ******************************************************************************/
701 static void DGifBufferedInput(GifFileType *GifFile, GifByteType *NextByte)
702 {
703 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
704 GifByteType *Buf = Private->Buf;
705
706 if (Buf[0] == 0) {
707 /* Needs to read the next buffer - this one is empty: */
708 GifRead(Buf, 1, GifFile);
709 GifRead((Buf + 1), Buf[0], GifFile);
710 *NextByte = Buf[1];
711 Buf[1] = 2; /* We use now the second place as last char read! */
712 Buf[0]--;
713 }
714 else {
715 *NextByte = Buf[Buf[1]++];
716 Buf[0]--;
717 }
718 }
719
720 /******************************************************************************
721 * This routine reads an entire GIF into core, hanging all its state info off *
722 * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() *
723 * first to initialize I/O. Its inverse is EGifSpew(). *
724 ******************************************************************************/
725 void DGifSlurp(GifFileType *GifFile)
726 {
727 int ImageSize;
728 GifRecordType RecordType;
729 SavedImage *sp;
730 GifByteType *ExtData;
731
732 /* Some versions of malloc dislike 0-length requests */
733 GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
734 memset(GifFile->SavedImages, 0, sizeof(SavedImage));
735 sp = &GifFile->SavedImages[0];
736
737 do {
738 DGifGetRecordType(GifFile, &RecordType);
739
740 switch (RecordType) {
741 case IMAGE_DESC_RECORD_TYPE:
742 DGifGetImageDesc(GifFile);
743
744 sp = &GifFile->SavedImages[GifFile->ImageCount-1];
745 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
746
747 sp->RasterBits
748 = (GifPixelType*) malloc(ImageSize * sizeof(GifPixelType));
749
750 DGifGetLine(GifFile, sp->RasterBits, ImageSize);
751 break;
752
753 case EXTENSION_RECORD_TYPE:
754 DGifGetExtension(GifFile,&sp->Function,&ExtData);
755
756 do {
757 if (AddExtensionBlock(sp, ExtData[0], ExtData+1) == GIF_ERROR)
758 GifInternError(GifFile, D_GIF_ERR_NOT_ENOUGH_MEM);
759 DGifGetExtensionNext(GifFile, &ExtData);
760 } while (ExtData != NULL);
761 break;
762
763 case TERMINATE_RECORD_TYPE:
764 break;
765
766 default: /* Should be trapped by DGifGetRecordType */
767 break;
768 }
769 } while (RecordType != TERMINATE_RECORD_TYPE);
770 }
771
772 /******************************************************************************
773 * Extension record functions *
774 ******************************************************************************/
775
776 void MakeExtension(SavedImage *New, int Function)
777 {
778 New->Function = Function;
779 /*
780 * Someday we might have to deal with multiple extensions.
781 */
782 }
783
784 int AddExtensionBlock(SavedImage *New, int Len, GifByteType *data)
785 {
786 int size;
787 ExtensionBlock *ep;
788
789 if (New->ExtensionBlocks == NULL)
790 New->ExtensionBlocks = (ExtensionBlock *)malloc(sizeof(ExtensionBlock));
791 else
792 New->ExtensionBlocks =
793 (ExtensionBlock *)realloc(New->ExtensionBlocks,
794 sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1));
795
796 if (New->ExtensionBlocks == NULL)
797 return(GIF_ERROR);
798
799 ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
800 ep->ByteCount = Len;
801 size = Len * sizeof(GifByteType);
802 ep->Bytes = (GifByteType *)malloc(size);
803 memcpy(ep->Bytes, data, size);
804 return(GIF_OK);
805 }
806
807 void FreeExtension(SavedImage *Image)
808 {
809 ExtensionBlock *ep;
810
811 for (ep = Image->ExtensionBlocks;
812 ep < Image->ExtensionBlocks + Image->ExtensionBlockCount;
813 ep++)
814 (void) free((char *)ep->Bytes);
815 free((char *)Image->ExtensionBlocks);
816 Image->ExtensionBlocks = NULL;
817 }
818
819 /******************************************************************************
820 * Image block allocation functions *
821 ******************************************************************************/
822 SavedImage *MakeSavedImage(GifFileType *GifFile, SavedImage *CopyFrom)
823 /*
824 * Append an image block to the SavedImages array
825 */
826 {
827 SavedImage *sp;
828
829 if (GifFile->SavedImages == NULL)
830 GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
831 else
832 GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
833 sizeof(SavedImage) * (GifFile->ImageCount+1));
834
835 if (GifFile->SavedImages == NULL)
836 return((SavedImage *)NULL);
837 else
838 {
839 sp = &GifFile->SavedImages[GifFile->ImageCount++];
840 memset((char *)sp, '\0', sizeof(SavedImage));
841
842 if (CopyFrom)
843 {
844 memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
845
846 /*
847 * Make our own allocated copies of the heap fields in the
848 * copied record. This guards against potential aliasing
849 * problems.
850 */
851
852 /* first, the local color map */
853 if (sp->ImageDesc.ColorMap)
854 sp->ImageDesc.ColorMap =
855 MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount,
856 CopyFrom->ImageDesc.ColorMap->Colors);
857
858 /* next, the raster */
859 sp->RasterBits = (char *)malloc(sizeof(GifPixelType)
860 * CopyFrom->ImageDesc.Height
861 * CopyFrom->ImageDesc.Width);
862 memcpy(sp->RasterBits,
863 CopyFrom->RasterBits,
864 sizeof(GifPixelType)
865 * CopyFrom->ImageDesc.Height
866 * CopyFrom->ImageDesc.Width);
867
868 /* finally, the extension blocks */
869 if (sp->ExtensionBlocks)
870 {
871 sp->ExtensionBlocks
872 = (ExtensionBlock*)malloc(sizeof(ExtensionBlock)
873 * CopyFrom->ExtensionBlockCount);
874 memcpy(sp->ExtensionBlocks,
875 CopyFrom->ExtensionBlocks,
876 sizeof(ExtensionBlock)
877 * CopyFrom->ExtensionBlockCount);
878
879 /*
880 * For the moment, the actual blocks can take their
881 * chances with free(). We'll fix this later.
882 */
883 }
884 }
885
886 return(sp);
887 }
888 }
889
890 void FreeSavedImages(GifFileType *GifFile)
891 {
892 SavedImage *sp;
893
894 for (sp = GifFile->SavedImages;
895 sp < GifFile->SavedImages + GifFile->ImageCount;
896 sp++)
897 {
898 if (sp->ImageDesc.ColorMap)
899 FreeMapObject(sp->ImageDesc.ColorMap);
900
901 if (sp->RasterBits)
902 free((char *)sp->RasterBits);
903
904 if (sp->ExtensionBlocks)
905 FreeExtension(sp);
906 }
907 free((char *) GifFile->SavedImages);
908 }
909
910 /******************************************************************************
911 * Miscellaneous utility functions *
912 ******************************************************************************/
913
914 int BitSize(int n)
915 /* return smallest bitfield size n will fit in */
916 {
917 register int i;
918
919 for (i = 1; i <= 8; i++)
920 if ((1 << i) >= n)
921 break;
922 return(i);
923 }
924
925 /******************************************************************************
926 * Color map object functions *
927 ******************************************************************************/
928
929 ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap)
930 /*
931 * Allocate a color map of given size; initialize with contents of
932 * ColorMap if that pointer is non-NULL.
933 */
934 {
935 ColorMapObject *Object;
936
937 if (ColorCount != (1 << BitSize(ColorCount)))
938 return((ColorMapObject *)NULL);
939
940 Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
941 if (Object == (ColorMapObject *)NULL)
942 return((ColorMapObject *)NULL);
943
944 Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
945 if (Object->Colors == (GifColorType *)NULL)
946 return((ColorMapObject *)NULL);
947
948 Object->ColorCount = ColorCount;
949 Object->BitsPerPixel = BitSize(ColorCount);
950
951 if (ColorMap)
952 memcpy((char *)Object->Colors,
953 (char *)ColorMap, ColorCount * sizeof(GifColorType));
954
955 return(Object);
956 }
957
958 void FreeMapObject(ColorMapObject *Object)
959 /*
960 * Free a color map object
961 */
962 {
963 free(Object->Colors);
964 free(Object);
965 }