summaryrefslogtreecommitdiff
path: root/apps/plugins/imageviewer/gif/dgif_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/imageviewer/gif/dgif_lib.c')
-rw-r--r--apps/plugins/imageviewer/gif/dgif_lib.c1169
1 files changed, 1169 insertions, 0 deletions
diff --git a/apps/plugins/imageviewer/gif/dgif_lib.c b/apps/plugins/imageviewer/gif/dgif_lib.c
new file mode 100644
index 0000000000..6dc52991a5
--- /dev/null
+++ b/apps/plugins/imageviewer/gif/dgif_lib.c
@@ -0,0 +1,1169 @@
1/******************************************************************************
2
3dgif_lib.c - GIF decoding
4
5The functions here and in egif_lib.c are partitioned carefully so that
6if you only require one of read and write capability, only one of these
7two modules will be linked. Preserve this property!
8
9*****************************************************************************/
10
11#include <stdlib.h>
12#include <limits.h>
13#include <stdint.h>
14#include <fcntl.h>
15/* #include <unistd.h> */
16/* #include <stdio.h> */
17#include <string.h>
18
19#ifdef _WIN32
20#include <io.h>
21#endif /* _WIN32 */
22
23#include "gif_lib.h"
24#include "gif_lib_private.h"
25
26/* compose unsigned little endian value */
27#define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
28
29/* avoid extra function call in case we use fread (TVT) */
30#define READ(_gif,_buf,_len) \
31 (((GifFilePrivateType*)_gif->Private)->Read ? \
32 ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \
33 fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File))
34
35static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
36static int DGifSetupDecompress(GifFileType *GifFile);
37static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
38 int LineLen);
39static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode);
40static int DGifDecompressInput(GifFileType *GifFile, int *Code);
41static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
42 GifByteType *NextByte);
43
44/******************************************************************************
45 Open a new GIF file for read, given by its name.
46 Returns dynamically allocated GifFileType pointer which serves as the GIF
47 info record.
48******************************************************************************/
49GifFileType *
50DGifOpenFileName(const char *FileName, int *Error)
51{
52 int FileHandle;
53 GifFileType *GifFile;
54
55 if ((FileHandle = rb->open(FileName, O_RDONLY)) == -1) {
56 if (Error != NULL)
57 *Error = D_GIF_ERR_OPEN_FAILED;
58 return NULL;
59 }
60
61 GifFile = DGifOpenFileHandle(FileHandle, Error);
62 // cppcheck-suppress resourceLeak
63 return GifFile;
64}
65
66/******************************************************************************
67 Update a new GIF file, given its file handle.
68 Returns dynamically allocated GifFileType pointer which serves as the GIF
69 info record.
70******************************************************************************/
71GifFileType *
72DGifOpenFileHandle(int FileHandle, int *Error)
73{
74 char Buf[GIF_STAMP_LEN + 1];
75 GifFileType *GifFile;
76 GifFilePrivateType *Private;
77 int f;
78
79 GifFile = (GifFileType *)malloc(sizeof(GifFileType));
80 if (GifFile == NULL) {
81 if (Error != NULL)
82 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
83 (void)rb->close(FileHandle);
84 return NULL;
85 }
86
87 /*@i1@*/memset(GifFile, '\0', sizeof(GifFileType));
88
89 /* Belt and suspenders, in case the null pointer isn't zero */
90 GifFile->SavedImages = NULL;
91 GifFile->SColorMap = NULL;
92
93 Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
94 if (Private == NULL) {
95 if (Error != NULL)
96 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
97 (void)rb->close(FileHandle);
98 free((char *)GifFile);
99 return NULL;
100 }
101#ifdef _WIN32
102 _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
103#endif /* _WIN32 */
104
105 f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
106
107 /*@-mustfreeonly@*/
108 GifFile->Private = (void *)Private;
109 Private->FileHandle = FileHandle;
110 Private->File = f;
111 Private->FileState = FILE_STATE_READ;
112 Private->Read = NULL; /* don't use alternate input method (TVT) */
113 GifFile->UserData = NULL; /* TVT */
114 /*@=mustfreeonly@*/
115
116 /* Let's see if this is a GIF file: */
117 if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
118 if (Error != NULL)
119 *Error = D_GIF_ERR_READ_FAILED;
120 (void)fclose(f);
121 free((char *)Private);
122 free((char *)GifFile);
123 return NULL;
124 }
125
126 /* Check for GIF prefix at start of file */
127 Buf[GIF_STAMP_LEN] = 0;
128 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
129 if (Error != NULL)
130 *Error = D_GIF_ERR_NOT_GIF_FILE;
131 (void)fclose(f);
132 free((char *)Private);
133 free((char *)GifFile);
134 return NULL;
135 }
136
137 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
138 (void)fclose(f);
139 free((char *)Private);
140 free((char *)GifFile);
141 return NULL;
142 }
143
144 GifFile->Error = 0;
145
146 /* What version of GIF? */
147 Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
148
149 return GifFile;
150}
151
152/******************************************************************************
153 GifFileType constructor with user supplied input function (TVT)
154******************************************************************************/
155GifFileType *
156DGifOpen(void *userData, InputFunc readFunc, int *Error)
157{
158 char Buf[GIF_STAMP_LEN + 1];
159 GifFileType *GifFile;
160 GifFilePrivateType *Private;
161
162 GifFile = (GifFileType *)malloc(sizeof(GifFileType));
163 if (GifFile == NULL) {
164 if (Error != NULL)
165 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
166 return NULL;
167 }
168
169 memset(GifFile, '\0', sizeof(GifFileType));
170
171 /* Belt and suspenders, in case the null pointer isn't zero */
172 GifFile->SavedImages = NULL;
173 GifFile->SColorMap = NULL;
174
175 Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
176 if (!Private) {
177 if (Error != NULL)
178 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
179 free((char *)GifFile);
180 return NULL;
181 }
182
183 GifFile->Private = (void *)Private;
184 Private->FileHandle = 0;
185 Private->File = 0; /* NULL */
186 Private->FileState = FILE_STATE_READ;
187
188 Private->Read = readFunc; /* TVT */
189 GifFile->UserData = userData; /* TVT */
190
191 /* Lets see if this is a GIF file: */
192 if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
193 if (Error != NULL)
194 *Error = D_GIF_ERR_READ_FAILED;
195 free((char *)Private);
196 free((char *)GifFile);
197 return NULL;
198 }
199
200 /* Check for GIF prefix at start of file */
201 Buf[GIF_STAMP_LEN] = '\0';
202 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
203 if (Error != NULL)
204 *Error = D_GIF_ERR_NOT_GIF_FILE;
205 free((char *)Private);
206 free((char *)GifFile);
207 return NULL;
208 }
209
210 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
211 free((char *)Private);
212 free((char *)GifFile);
213 return NULL;
214 }
215
216 GifFile->Error = 0;
217
218 /* What version of GIF? */
219 Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
220
221 return GifFile;
222}
223
224/******************************************************************************
225 This routine should be called before any other DGif calls. Note that
226 this routine is called automatically from DGif file open routines.
227******************************************************************************/
228int
229DGifGetScreenDesc(GifFileType *GifFile)
230{
231 int BitsPerPixel;
232 bool SortFlag;
233 GifByteType Buf[3];
234 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
235
236 if (!IS_READABLE(Private)) {
237 /* This file was NOT open for reading: */
238 GifFile->Error = D_GIF_ERR_NOT_READABLE;
239 return GIF_ERROR;
240 }
241
242 /* Put the screen descriptor into the file: */
243 if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
244 DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
245 return GIF_ERROR;
246
247 if (READ(GifFile, Buf, 3) != 3) {
248 GifFile->Error = D_GIF_ERR_READ_FAILED;
249 GifFreeMapObject(GifFile->SColorMap);
250 GifFile->SColorMap = NULL;
251 return GIF_ERROR;
252 }
253 GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
254 SortFlag = (Buf[0] & 0x08) != 0;
255 BitsPerPixel = (Buf[0] & 0x07) + 1;
256 GifFile->SBackGroundColor = Buf[1];
257 GifFile->AspectByte = Buf[2];
258 if (Buf[0] & 0x80) { /* Do we have global color map? */
259 int i;
260
261 GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
262 if (GifFile->SColorMap == NULL) {
263 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
264 return GIF_ERROR;
265 }
266
267 /* Get the global color map: */
268 GifFile->SColorMap->SortFlag = SortFlag;
269 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
270 if (READ(GifFile, Buf, 3) != 3) {
271 GifFreeMapObject(GifFile->SColorMap);
272 GifFile->SColorMap = NULL;
273 GifFile->Error = D_GIF_ERR_READ_FAILED;
274 return GIF_ERROR;
275 }
276 GifFile->SColorMap->Colors[i].Red = Buf[0];
277 GifFile->SColorMap->Colors[i].Green = Buf[1];
278 GifFile->SColorMap->Colors[i].Blue = Buf[2];
279 }
280 } else {
281 GifFile->SColorMap = NULL;
282 }
283
284 return GIF_OK;
285}
286
287/******************************************************************************
288 This routine should be called before any attempt to read an image.
289******************************************************************************/
290int
291DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type)
292{
293 GifByteType Buf;
294 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
295
296 if (!IS_READABLE(Private)) {
297 /* This file was NOT open for reading: */
298 GifFile->Error = D_GIF_ERR_NOT_READABLE;
299 return GIF_ERROR;
300 }
301
302 if (READ(GifFile, &Buf, 1) != 1) {
303 GifFile->Error = D_GIF_ERR_READ_FAILED;
304 return GIF_ERROR;
305 }
306
307 switch (Buf) {
308 case DESCRIPTOR_INTRODUCER:
309 *Type = IMAGE_DESC_RECORD_TYPE;
310 break;
311 case EXTENSION_INTRODUCER:
312 *Type = EXTENSION_RECORD_TYPE;
313 break;
314 default:
315 *Type = TERMINATE_RECORD_TYPE;
316 break;
317 }
318
319 return GIF_OK;
320}
321
322/******************************************************************************
323 This routine should be called before any attempt to read an image.
324 Note it is assumed the Image desc. header has been read.
325******************************************************************************/
326int
327DGifGetImageDesc(GifFileType *GifFile)
328{
329 unsigned int BitsPerPixel;
330 GifByteType Buf[3];
331 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
332/* SavedImage *sp; */
333
334 if (!IS_READABLE(Private)) {
335 /* This file was NOT open for reading: */
336 GifFile->Error = D_GIF_ERR_NOT_READABLE;
337 return GIF_ERROR;
338 }
339
340 if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
341 DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
342 DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
343 DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
344 return GIF_ERROR;
345 if (READ(GifFile, Buf, 1) != 1) {
346 GifFile->Error = D_GIF_ERR_READ_FAILED;
347 GifFreeMapObject(GifFile->Image.ColorMap);
348 GifFile->Image.ColorMap = NULL;
349 return GIF_ERROR;
350 }
351 BitsPerPixel = (Buf[0] & 0x07) + 1;
352 GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false;
353
354 /* Setup the colormap */
355 if (GifFile->Image.ColorMap) {
356 GifFreeMapObject(GifFile->Image.ColorMap);
357 GifFile->Image.ColorMap = NULL;
358 }
359 /* Does this image have local color map? */
360 if (Buf[0] & 0x80) {
361 int i;
362
363 GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
364 if (GifFile->Image.ColorMap == NULL) {
365 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
366 return GIF_ERROR;
367 }
368
369 /* Get the image local color map: */
370 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
371 if (READ(GifFile, Buf, 3) != 3) {
372 GifFreeMapObject(GifFile->Image.ColorMap);
373 GifFile->Error = D_GIF_ERR_READ_FAILED;
374 GifFile->Image.ColorMap = NULL;
375 return GIF_ERROR;
376 }
377 GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
378 GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
379 GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
380 }
381 }
382
383#if 0
384 if (GifFile->SavedImages) {
385 if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
386 sizeof(SavedImage) *
387 (GifFile->ImageCount + 1))) == NULL) {
388 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
389 return GIF_ERROR;
390 }
391 } else {
392 if ((GifFile->SavedImages =
393 (SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
394 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
395 return GIF_ERROR;
396 }
397 }
398
399 sp = &GifFile->SavedImages[GifFile->ImageCount];
400 memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
401 if (GifFile->Image.ColorMap != NULL) {
402 sp->ImageDesc.ColorMap = GifMakeMapObject(
403 GifFile->Image.ColorMap->ColorCount,
404 GifFile->Image.ColorMap->Colors);
405 if (sp->ImageDesc.ColorMap == NULL) {
406 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
407 return GIF_ERROR;
408 }
409 }
410 sp->RasterBits = (unsigned char *)NULL;
411 sp->ExtensionBlockCount = 0;
412 sp->ExtensionBlocks = (ExtensionBlock *) NULL;
413
414 GifFile->ImageCount++;
415#endif
416 Private->PixelCount = (long)GifFile->Image.Width *
417 (long)GifFile->Image.Height;
418
419 /* Reset decompress algorithm parameters. */
420 (void)DGifSetupDecompress(GifFile);
421
422 return GIF_OK;
423}
424
425/******************************************************************************
426 Get one full scanned line (Line) of length LineLen from GIF file.
427******************************************************************************/
428int
429DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
430{
431 GifByteType *Dummy;
432 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
433
434 if (!IS_READABLE(Private)) {
435 /* This file was NOT open for reading: */
436 GifFile->Error = D_GIF_ERR_NOT_READABLE;
437 return GIF_ERROR;
438 }
439
440 if (!LineLen)
441 LineLen = GifFile->Image.Width;
442
443 if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
444 GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
445 return GIF_ERROR;
446 }
447
448 if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
449 if (Private->PixelCount == 0) {
450 /* We probably won't be called any more, so let's clean up
451 * everything before we return: need to flush out all the
452 * rest of image until an empty block (size 0)
453 * detected. We use GetCodeNext.
454 */
455 do
456 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
457 return GIF_ERROR;
458 while (Dummy != NULL) ;
459 }
460 return GIF_OK;
461 } else
462 return GIF_ERROR;
463}
464
465/******************************************************************************
466 Put one pixel (Pixel) into GIF file.
467******************************************************************************/
468int
469DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
470{
471 GifByteType *Dummy;
472 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
473
474 if (!IS_READABLE(Private)) {
475 /* This file was NOT open for reading: */
476 GifFile->Error = D_GIF_ERR_NOT_READABLE;
477 return GIF_ERROR;
478 }
479 if (--Private->PixelCount > 0xffff0000UL)
480 {
481 GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
482 return GIF_ERROR;
483 }
484
485 if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
486 if (Private->PixelCount == 0) {
487 /* We probably won't be called any more, so let's clean up
488 * everything before we return: need to flush out all the
489 * rest of image until an empty block (size 0)
490 * detected. We use GetCodeNext.
491 */
492 do
493 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
494 return GIF_ERROR;
495 while (Dummy != NULL) ;
496 }
497 return GIF_OK;
498 } else
499 return GIF_ERROR;
500}
501
502/******************************************************************************
503 Get an extension block (see GIF manual) from GIF file. This routine only
504 returns the first data block, and DGifGetExtensionNext should be called
505 after this one until NULL extension is returned.
506 The Extension should NOT be freed by the user (not dynamically allocated).
507 Note it is assumed the Extension description header has been read.
508******************************************************************************/
509int
510DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
511{
512 GifByteType Buf;
513 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
514
515 if (!IS_READABLE(Private)) {
516 /* This file was NOT open for reading: */
517 GifFile->Error = D_GIF_ERR_NOT_READABLE;
518 return GIF_ERROR;
519 }
520
521 if (READ(GifFile, &Buf, 1) != 1) {
522 GifFile->Error = D_GIF_ERR_READ_FAILED;
523 return GIF_ERROR;
524 }
525 *ExtCode = Buf;
526
527 return DGifGetExtensionNext(GifFile, Extension);
528}
529
530/******************************************************************************
531 Get a following extension block (see GIF manual) from GIF file. This
532 routine should be called until NULL Extension is returned.
533 The Extension should NOT be freed by the user (not dynamically allocated).
534******************************************************************************/
535int
536DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension)
537{
538 GifByteType Buf;
539 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
540
541 if (READ(GifFile, &Buf, 1) != 1) {
542 GifFile->Error = D_GIF_ERR_READ_FAILED;
543 return GIF_ERROR;
544 }
545 if (Buf > 0) {
546 *Extension = Private->Buf; /* Use private unused buffer. */
547 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
548 /* coverity[tainted_data] */
549 if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
550 GifFile->Error = D_GIF_ERR_READ_FAILED;
551 return GIF_ERROR;
552 }
553 } else
554 *Extension = NULL;
555
556 return GIF_OK;
557}
558
559/******************************************************************************
560 Extract a Graphics Control Block from raw extension data
561******************************************************************************/
562
563int DGifExtensionToGCB(const size_t GifExtensionLength,
564 const GifByteType *GifExtension,
565 GraphicsControlBlock *GCB)
566{
567 if (GifExtensionLength != 4) {
568 return GIF_ERROR;
569 }
570
571 GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
572 GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
573 GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
574 if (GifExtension[0] & 0x01)
575 GCB->TransparentColor = (int)GifExtension[3];
576 else
577 GCB->TransparentColor = NO_TRANSPARENT_COLOR;
578
579 return GIF_OK;
580}
581
582/******************************************************************************
583 Extract the Graphics Control Block for a saved image, if it exists.
584******************************************************************************/
585
586int DGifSavedExtensionToGCB(GifFileType *GifFile,
587 int ImageIndex, GraphicsControlBlock *GCB)
588{
589 int i;
590
591 if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1)
592 return GIF_ERROR;
593
594 GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
595 GCB->UserInputFlag = false;
596 GCB->DelayTime = 0;
597 GCB->TransparentColor = NO_TRANSPARENT_COLOR;
598
599 for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
600 ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
601 if (ep->Function == GRAPHICS_EXT_FUNC_CODE)
602 return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB);
603 }
604
605 return GIF_ERROR;
606}
607
608/******************************************************************************
609 This routine should be called last, to close the GIF file.
610******************************************************************************/
611int
612DGifCloseFile(GifFileType *GifFile)
613{
614 GifFilePrivateType *Private;
615
616 if (GifFile == NULL || GifFile->Private == NULL)
617 return GIF_ERROR;
618
619 if (GifFile->Image.ColorMap) {
620 GifFreeMapObject(GifFile->Image.ColorMap);
621 GifFile->Image.ColorMap = NULL;
622 }
623
624 if (GifFile->Image.GCB) {
625 free(GifFile->Image.GCB);
626 GifFile->Image.GCB = NULL;
627 }
628
629 if (GifFile->SColorMap) {
630 GifFreeMapObject(GifFile->SColorMap);
631 GifFile->SColorMap = NULL;
632 }
633
634 if (GifFile->SavedImages) {
635 GifFreeSavedImages(GifFile);
636 GifFile->SavedImages = NULL;
637 }
638
639 GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks);
640
641 Private = (GifFilePrivateType *) GifFile->Private;
642
643 if (!IS_READABLE(Private)) {
644 /* This file was NOT open for reading: */
645 GifFile->Error = D_GIF_ERR_NOT_READABLE;
646 return GIF_ERROR;
647 }
648
649 if (Private->File && (fclose(Private->File) != 0)) {
650 GifFile->Error = D_GIF_ERR_CLOSE_FAILED;
651 return GIF_ERROR;
652 }
653
654 free((char *)GifFile->Private);
655
656 /*
657 * Without the #ifndef, we get spurious warnings because Coverity mistakenly
658 * thinks the GIF structure is freed on an error return.
659 */
660#ifndef __COVERITY__
661 free(GifFile);
662#endif /* __COVERITY__ */
663
664 return GIF_OK;
665}
666
667/******************************************************************************
668 Get 2 bytes (word) from the given file:
669******************************************************************************/
670static int
671DGifGetWord(GifFileType *GifFile, GifWord *Word)
672{
673 unsigned char c[2];
674
675 if (READ(GifFile, c, 2) != 2) {
676 GifFile->Error = D_GIF_ERR_READ_FAILED;
677 return GIF_ERROR;
678 }
679
680 *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]);
681 return GIF_OK;
682}
683
684/******************************************************************************
685 Get the image code in compressed form. This routine can be called if the
686 information needed to be piped out as is. Obviously this is much faster
687 than decoding and encoding again. This routine should be followed by calls
688 to DGifGetCodeNext, until NULL block is returned.
689 The block should NOT be freed by the user (not dynamically allocated).
690******************************************************************************/
691int
692DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
693{
694 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
695
696 if (!IS_READABLE(Private)) {
697 /* This file was NOT open for reading: */
698 GifFile->Error = D_GIF_ERR_NOT_READABLE;
699 return GIF_ERROR;
700 }
701
702 *CodeSize = Private->BitsPerPixel;
703
704 return DGifGetCodeNext(GifFile, CodeBlock);
705}
706
707/******************************************************************************
708 Continue to get the image code in compressed form. This routine should be
709 called until NULL block is returned.
710 The block should NOT be freed by the user (not dynamically allocated).
711******************************************************************************/
712int
713DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
714{
715 GifByteType Buf;
716 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
717
718 /* coverity[tainted_data_argument] */
719 if (READ(GifFile, &Buf, 1) != 1) {
720 GifFile->Error = D_GIF_ERR_READ_FAILED;
721 return GIF_ERROR;
722 }
723
724 /* coverity[lower_bounds] */
725 if (Buf > 0) {
726 *CodeBlock = Private->Buf; /* Use private unused buffer. */
727 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
728 /* coverity[tainted_data] */
729 if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
730 GifFile->Error = D_GIF_ERR_READ_FAILED;
731 return GIF_ERROR;
732 }
733 } else {
734 *CodeBlock = NULL;
735 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
736 Private->PixelCount = 0; /* And local info. indicate image read. */
737 }
738
739 return GIF_OK;
740}
741
742/******************************************************************************
743 Setup the LZ decompression for this image:
744******************************************************************************/
745static int
746DGifSetupDecompress(GifFileType *GifFile)
747{
748 int i, BitsPerPixel;
749 GifByteType CodeSize;
750 GifPrefixType *Prefix;
751 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
752
753 READ(GifFile, &CodeSize, 1); /* Read Code size from file. */
754 BitsPerPixel = CodeSize;
755
756 Private->Buf[0] = 0; /* Input Buffer empty. */
757 Private->BitsPerPixel = BitsPerPixel;
758 Private->ClearCode = (1 << BitsPerPixel);
759 Private->EOFCode = Private->ClearCode + 1;
760 Private->RunningCode = Private->EOFCode + 1;
761 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
762 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
763 Private->StackPtr = 0; /* No pixels on the pixel stack. */
764 Private->LastCode = NO_SUCH_CODE;
765 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
766 Private->CrntShiftDWord = 0;
767
768 Prefix = Private->Prefix;
769 for (i = 0; i <= LZ_MAX_CODE; i++)
770 Prefix[i] = NO_SUCH_CODE;
771
772 return GIF_OK;
773}
774
775/******************************************************************************
776 The LZ decompression routine:
777 This version decompress the given GIF file into Line of length LineLen.
778 This routine can be called few times (one per scan line, for example), in
779 order the complete the whole image.
780******************************************************************************/
781static int
782DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
783{
784 int i = 0;
785 int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
786 GifByteType *Stack, *Suffix;
787 GifPrefixType *Prefix;
788 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
789
790 StackPtr = Private->StackPtr;
791 Prefix = Private->Prefix;
792 Suffix = Private->Suffix;
793 Stack = Private->Stack;
794 EOFCode = Private->EOFCode;
795 ClearCode = Private->ClearCode;
796 LastCode = Private->LastCode;
797
798 if (StackPtr > LZ_MAX_CODE) {
799 return GIF_ERROR;
800 }
801
802 if (StackPtr != 0) {
803 /* Let pop the stack off before continueing to read the GIF file: */
804 while (StackPtr != 0 && i < LineLen)
805 Line[i++] = Stack[--StackPtr];
806 }
807
808 while (i < LineLen) { /* Decode LineLen items. */
809 if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
810 return GIF_ERROR;
811
812 if (CrntCode == EOFCode) {
813 /* Note however that usually we will not be here as we will stop
814 * decoding as soon as we got all the pixel, or EOF code will
815 * not be read at all, and DGifGetLine/Pixel clean everything. */
816 GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
817 return GIF_ERROR;
818 } else if (CrntCode == ClearCode) {
819 /* We need to start over again: */
820 for (j = 0; j <= LZ_MAX_CODE; j++)
821 Prefix[j] = NO_SUCH_CODE;
822 Private->RunningCode = Private->EOFCode + 1;
823 Private->RunningBits = Private->BitsPerPixel + 1;
824 Private->MaxCode1 = 1 << Private->RunningBits;
825 LastCode = Private->LastCode = NO_SUCH_CODE;
826 } else {
827 /* Its regular code - if in pixel range simply add it to output
828 * stream, otherwise trace to codes linked list until the prefix
829 * is in pixel range: */
830 if (CrntCode < ClearCode) {
831 /* This is simple - its pixel scalar, so add it to output: */
832 Line[i++] = CrntCode;
833 } else {
834 /* Its a code to needed to be traced: trace the linked list
835 * until the prefix is a pixel, while pushing the suffix
836 * pixels on our stack. If we done, pop the stack in reverse
837 * (thats what stack is good for!) order to output. */
838 if (Prefix[CrntCode] == NO_SUCH_CODE) {
839 /* Only allowed if CrntCode is exactly the running code:
840 * In that case CrntCode = XXXCode, CrntCode or the
841 * prefix code is last code and the suffix char is
842 * exactly the prefix of last code! */
843 if (CrntCode == Private->RunningCode - 2) {
844 CrntPrefix = LastCode;
845 Suffix[Private->RunningCode - 2] =
846 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
847 LastCode,
848 ClearCode);
849 } else {
850 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
851 return GIF_ERROR;
852 }
853 } else
854 CrntPrefix = CrntCode;
855
856 /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
857 * during the trace. As we might loop forever, in case of
858 * defective image, we use StackPtr as loop counter and stop
859 * before overflowing Stack[]. */
860 while (StackPtr < LZ_MAX_CODE &&
861 CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
862 Stack[StackPtr++] = Suffix[CrntPrefix];
863 CrntPrefix = Prefix[CrntPrefix];
864 }
865 if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
866 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
867 return GIF_ERROR;
868 }
869 /* Push the last character on stack: */
870 Stack[StackPtr++] = CrntPrefix;
871
872 /* Now lets pop all the stack into output: */
873 while (StackPtr != 0 && i < LineLen)
874 Line[i++] = Stack[--StackPtr];
875 }
876 if (LastCode != NO_SUCH_CODE) {
877 Prefix[Private->RunningCode - 2] = LastCode;
878
879 if (CrntCode == Private->RunningCode - 2) {
880 /* Only allowed if CrntCode is exactly the running code:
881 * In that case CrntCode = XXXCode, CrntCode or the
882 * prefix code is last code and the suffix char is
883 * exactly the prefix of last code! */
884 Suffix[Private->RunningCode - 2] =
885 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
886 } else {
887 Suffix[Private->RunningCode - 2] =
888 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
889 }
890 }
891 LastCode = CrntCode;
892 }
893 }
894
895 Private->LastCode = LastCode;
896 Private->StackPtr = StackPtr;
897
898 return GIF_OK;
899}
900
901/******************************************************************************
902 Routine to trace the Prefixes linked list until we get a prefix which is
903 not code, but a pixel value (less than ClearCode). Returns that pixel value.
904 If image is defective, we might loop here forever, so we limit the loops to
905 the maximum possible if image O.k. - LZ_MAX_CODE times.
906******************************************************************************/
907static int
908DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode)
909{
910 int i = 0;
911
912 while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
913 if (Code > LZ_MAX_CODE) {
914 return NO_SUCH_CODE;
915 }
916 Code = Prefix[Code];
917 }
918 return Code;
919}
920
921/******************************************************************************
922 Interface for accessing the LZ codes directly. Set Code to the real code
923 (12bits), or to -1 if EOF code is returned.
924******************************************************************************/
925int
926DGifGetLZCodes(GifFileType *GifFile, int *Code)
927{
928 GifByteType *CodeBlock;
929 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
930
931 if (!IS_READABLE(Private)) {
932 /* This file was NOT open for reading: */
933 GifFile->Error = D_GIF_ERR_NOT_READABLE;
934 return GIF_ERROR;
935 }
936
937 if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)
938 return GIF_ERROR;
939
940 if (*Code == Private->EOFCode) {
941 /* Skip rest of codes (hopefully only NULL terminating block): */
942 do {
943 if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
944 return GIF_ERROR;
945 } while (CodeBlock != NULL) ;
946
947 *Code = -1;
948 } else if (*Code == Private->ClearCode) {
949 /* We need to start over again: */
950 Private->RunningCode = Private->EOFCode + 1;
951 Private->RunningBits = Private->BitsPerPixel + 1;
952 Private->MaxCode1 = 1 << Private->RunningBits;
953 }
954
955 return GIF_OK;
956}
957
958/******************************************************************************
959 The LZ decompression input routine:
960 This routine is responsable for the decompression of the bit stream from
961 8 bits (bytes) packets, into the real codes.
962 Returns GIF_OK if read successfully.
963******************************************************************************/
964static int
965DGifDecompressInput(GifFileType *GifFile, int *Code)
966{
967 static const unsigned short CodeMasks[] = {
968 0x0000, 0x0001, 0x0003, 0x0007,
969 0x000f, 0x001f, 0x003f, 0x007f,
970 0x00ff, 0x01ff, 0x03ff, 0x07ff,
971 0x0fff
972 };
973
974 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
975
976 GifByteType NextByte;
977
978 /* The image can't contain more than LZ_BITS per code. */
979 if (Private->RunningBits > LZ_BITS) {
980 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
981 return GIF_ERROR;
982 }
983
984 while (Private->CrntShiftState < Private->RunningBits) {
985 /* Needs to get more bytes from input stream for next code: */
986 if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
987 return GIF_ERROR;
988 }
989 Private->CrntShiftDWord |=
990 ((unsigned long)NextByte) << Private->CrntShiftState;
991 Private->CrntShiftState += 8;
992 }
993 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
994
995 Private->CrntShiftDWord >>= Private->RunningBits;
996 Private->CrntShiftState -= Private->RunningBits;
997
998 /* If code cannot fit into RunningBits bits, must raise its size. Note
999 * however that codes above 4095 are used for special signaling.
1000 * If we're using LZ_BITS bits already and we're at the max code, just
1001 * keep using the table as it is, don't increment Private->RunningCode.
1002 */
1003 if (Private->RunningCode < LZ_MAX_CODE + 2 &&
1004 ++Private->RunningCode > Private->MaxCode1 &&
1005 Private->RunningBits < LZ_BITS) {
1006 Private->MaxCode1 <<= 1;
1007 Private->RunningBits++;
1008 }
1009 return GIF_OK;
1010}
1011
1012/******************************************************************************
1013 This routines read one GIF data block at a time and buffers it internally
1014 so that the decompression routine could access it.
1015 The routine returns the next byte from its internal buffer (or read next
1016 block in if buffer empty) and returns GIF_OK if succesful.
1017******************************************************************************/
1018static int
1019DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
1020{
1021 if (Buf[0] == 0) {
1022 /* Needs to read the next buffer - this one is empty: */
1023 if (READ(GifFile, Buf, 1) != 1) {
1024 GifFile->Error = D_GIF_ERR_READ_FAILED;
1025 return GIF_ERROR;
1026 }
1027 /* There shouldn't be any empty data blocks here as the LZW spec
1028 * says the LZW termination code should come first. Therefore we
1029 * shouldn't be inside this routine at that point.
1030 */
1031 if (Buf[0] == 0) {
1032 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1033 return GIF_ERROR;
1034 }
1035 /* There shouldn't be any empty data blocks here as the LZW spec
1036 * says the LZW termination code should come first. Therefore we
1037 * shouldn't be inside this routine at that point.
1038 */
1039 if (Buf[0] == 0) {
1040 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1041 return GIF_ERROR;
1042 }
1043 if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
1044 GifFile->Error = D_GIF_ERR_READ_FAILED;
1045 return GIF_ERROR;
1046 }
1047 *NextByte = Buf[1];
1048 Buf[1] = 2; /* We use now the second place as last char read! */
1049 Buf[0]--;
1050 } else {
1051 *NextByte = Buf[Buf[1]++];
1052 Buf[0]--;
1053 }
1054
1055 return GIF_OK;
1056}
1057
1058#if 0
1059/******************************************************************************
1060 This routine reads an entire GIF into core, hanging all its state info off
1061 the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle()
1062 first to initialize I/O. Its inverse is EGifSpew().
1063*******************************************************************************/
1064int
1065DGifSlurp(GifFileType *GifFile)
1066{
1067 size_t ImageSize;
1068 GifRecordType RecordType;
1069 SavedImage *sp;
1070 GifByteType *ExtData;
1071 int ExtFunction;
1072
1073 GifFile->ExtensionBlocks = NULL;
1074 GifFile->ExtensionBlockCount = 0;
1075
1076 do {
1077 if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1078 return (GIF_ERROR);
1079
1080 switch (RecordType) {
1081 case IMAGE_DESC_RECORD_TYPE:
1082 if (DGifGetImageDesc(GifFile) == GIF_ERROR)
1083 return (GIF_ERROR);
1084
1085 sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
1086 /* Allocate memory for the image */
1087 if (sp->ImageDesc.Width < 0 && sp->ImageDesc.Height < 0 &&
1088 sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) {
1089 return GIF_ERROR;
1090 }
1091 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1092
1093 if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
1094 return GIF_ERROR;
1095 }
1096 sp->RasterBits = (unsigned char *)malloc(ImageSize *
1097 sizeof(GifPixelType));
1098
1099 if (sp->RasterBits == NULL) {
1100 return GIF_ERROR;
1101 }
1102
1103 if (sp->ImageDesc.Interlace) {
1104 int i, j;
1105 /*
1106 * The way an interlaced image should be read -
1107 * offsets and jumps...
1108 */
1109 int InterlacedOffset[] = { 0, 4, 2, 1 };
1110 int InterlacedJumps[] = { 8, 8, 4, 2 };
1111 /* Need to perform 4 passes on the image */
1112 for (i = 0; i < 4; i++)
1113 for (j = InterlacedOffset[i];
1114 j < sp->ImageDesc.Height;
1115 j += InterlacedJumps[i]) {
1116 if (DGifGetLine(GifFile,
1117 sp->RasterBits+j*sp->ImageDesc.Width,
1118 sp->ImageDesc.Width) == GIF_ERROR)
1119 return GIF_ERROR;
1120 }
1121 }
1122 else {
1123 if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR)
1124 return (GIF_ERROR);
1125 }
1126
1127 if (GifFile->ExtensionBlocks) {
1128 sp->ExtensionBlocks = GifFile->ExtensionBlocks;
1129 sp->ExtensionBlockCount = GifFile->ExtensionBlockCount;
1130
1131 GifFile->ExtensionBlocks = NULL;
1132 GifFile->ExtensionBlockCount = 0;
1133 }
1134 break;
1135
1136 case EXTENSION_RECORD_TYPE:
1137 if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR)
1138 return (GIF_ERROR);
1139 /* Create an extension block with our data */
1140 if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1141 &GifFile->ExtensionBlocks,
1142 ExtFunction, ExtData[0], &ExtData[1])
1143 == GIF_ERROR)
1144 return (GIF_ERROR);
1145 while (ExtData != NULL) {
1146 if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1147 return (GIF_ERROR);
1148 /* Continue the extension block */
1149 if (ExtData != NULL)
1150 if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1151 &GifFile->ExtensionBlocks,
1152 CONTINUE_EXT_FUNC_CODE,
1153 ExtData[0], &ExtData[1]) == GIF_ERROR)
1154 return (GIF_ERROR);
1155 }
1156 break;
1157
1158 case TERMINATE_RECORD_TYPE:
1159 break;
1160
1161 default: /* Should be trapped by DGifGetRecordType */
1162 break;
1163 }
1164 } while (RecordType != TERMINATE_RECORD_TYPE);
1165
1166 return (GIF_OK);
1167}
1168#endif
1169/* end */