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