Back to index

im-sdk  12.3.91
dgif_lib.c
Go to the documentation of this file.
00001 /******************************************************************************
00002 *   "Gif-Lib" - Yet another gif library.                             *
00003 *                                                                    *
00004 * Written by:  Gershon Elber                     IBM PC Ver 1.1,      Aug. 1990     *
00005 *******************************************************************************
00006 * The kernel of the GIF Decoding process can be found here.                 *
00007 *******************************************************************************
00008 * History:                                                           *
00009 * 16 Jun 89 - Version 1.0 by Gershon Elber.                                 *
00010 *  3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
00011 ******************************************************************************/
00012 
00013 
00014 #ifdef __MSDOS__
00015 #include <io.h>
00016 #include <alloc.h>
00017 #include <stdlib.h>
00018 #include <sys\stat.h>
00019 #else
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 #endif /* __MSDOS__ */
00023 
00024 #include <fcntl.h>
00025 #include <stdio.h>
00026 #include <string.h>
00027 #include "gif_lib.h"
00028 #include "gif_hash.h"
00029 
00030 #define PROGRAM_NAME "GIFLIB"
00031 
00032 #define COMMENT_EXT_FUNC_CODE      0xfe /* Extension function code for comment. */
00033 #define GIF_STAMP    "GIFVER"       /* First chars in file - GIF stamp. */
00034 #define GIF_STAMP_LEN       sizeof(GIF_STAMP) - 1
00035 #define GIF_VERSION_POS     3             /* Version first character in stamp. */
00036 
00037 #define LZ_MAX_CODE  4095          /* Biggest code possible in 12 bits. */
00038 #define LZ_BITS             12
00039 
00040 #define FILE_STATE_READ            0x01/* 1 write, 0 read - EGIF_LIB compatible.*/
00041 
00042 #define FLUSH_OUTPUT        4096    /* Impossible code, to signal flush. */
00043 #define FIRST_CODE          4097    /* Impossible code, to signal first. */
00044 #define NO_SUCH_CODE        4098    /* Impossible code, to signal empty. */
00045 
00046 #define IS_READABLE(Private)       (!(Private->FileState & FILE_STATE_READ))
00047 
00048 typedef struct GifFilePrivateType {
00049     int FileState,
00050        FileHandle,                      /* Where all this data goes to! */
00051        BitsPerPixel,     /* Bits per pixel (Codes uses at list this + 1). */
00052        ClearCode,                                /* The CLEAR LZ code. */
00053        EOFCode,                                    /* The EOF LZ code. */
00054        RunningCode,             /* The next code algorithm can generate. */
00055        RunningBits,/* The number of bits required to represent RunningCode. */
00056        MaxCode1,  /* 1 bigger than max. possible code, in RunningBits bits. */
00057        LastCode,                    /* The code before the current code. */
00058        CrntCode,                            /* Current algorithm code. */
00059        StackPtr,                     /* For character stack (see below). */
00060        CrntShiftState;                     /* Number of bits in CrntShiftDWord. */
00061     unsigned long CrntShiftDWord;     /* For bytes decomposition into codes. */
00062     unsigned long PixelCount;                    /* Number of pixels in image. */
00063     FILE *File;                                           /* File as stream. */
00064     GifByteType Buf[256];          /* Compressed input is buffered here. */
00065     GifByteType Stack[LZ_MAX_CODE];        /* Decoded pixels are stacked here. */
00066     GifByteType Suffix[LZ_MAX_CODE+1];           /* So we can trace the codes. */
00067     unsigned int Prefix[LZ_MAX_CODE+1];
00068 } GifFilePrivateType;
00069 
00070 #ifdef SYSV
00071 static char *VersionStr =
00072         "Gif library module,\t\tGershon Elber\n\
00073        (C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
00074 #else
00075 static char *VersionStr =
00076        PROGRAM_NAME
00077        "      IBMPC "
00078        GIF_LIB_VERSION
00079        "      Gershon Elber,       "
00080        __DATE__ ",   " __TIME__ "\n"
00081        "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
00082 #endif /* SYSV */
00083 
00084 extern int _GifError;
00085 
00086 static int DGifGetWord(FILE *File, int *Word);
00087 static int DGifSetupDecompress(GifFileType *GifFile);
00088 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
00089                                                         int LineLen);
00090 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
00091 static int DGifDecompressInput(GifFilePrivateType *Private, int *Code);
00092 static int DGifBufferedInput(FILE *File, GifByteType *Buf,
00093                                                GifByteType *NextByte);
00094 
00095 /******************************************************************************
00096 *   Open a new gif file for read, given by its name.                        *
00097 *   Returns GifFileType pointer dynamically allocated which serves as the gif *
00098 * info record. _GifError is cleared if succesfull.                          *
00099 ******************************************************************************/
00100 GifFileType *DGifOpenFileName(const char *FileName)
00101 {
00102     int FileHandle;
00103 
00104     if ((FileHandle = open(FileName, O_RDONLY
00105 #ifdef __MSDOS__
00106                                 | O_BINARY
00107 #endif /* __MSDOS__ */
00108                                           )) == -1) {
00109        _GifError = D_GIF_ERR_OPEN_FAILED;
00110        return NULL;
00111     }
00112 
00113     return DGifOpenFileHandle(FileHandle);
00114 }
00115 
00116 /******************************************************************************
00117 *   Update a new gif file, given its file handle.                           *
00118 *   Returns GifFileType pointer dynamically allocated which serves as the gif *
00119 * info record. _GifError is cleared if succesfull.                          *
00120 ******************************************************************************/
00121 GifFileType *DGifOpenFileHandle(int FileHandle)
00122 {
00123     char Buf[GIF_STAMP_LEN+1];
00124     GifFileType *GifFile;
00125     GifFilePrivateType *Private;
00126     FILE *f;
00127 
00128 #ifdef __MSDOS__
00129     setmode(FileHandle, O_BINARY);   /* Make sure it is in binary mode. */
00130     f = fdopen(FileHandle, "rb");            /* Make it into a stream: */
00131     setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/
00132 #else
00133     f = fdopen(FileHandle, "r");             /* Make it into a stream: */
00134 #endif /* __MSDOS__ */
00135 
00136     if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) {
00137        _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
00138        return NULL;
00139     }
00140 
00141     memset(GifFile, '\0', sizeof(GifFileType));
00142 
00143     if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType)))
00144        == NULL) {
00145        _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
00146        free((char *) GifFile);
00147        return NULL;
00148     }
00149     GifFile->Private = (VoidPtr) Private;
00150     Private->FileHandle = FileHandle;
00151     Private->File = f;
00152     Private->FileState = 0;   /* Make sure bit 0 = 0 (File open for read). */
00153 
00154     /* Lets see if this is a GIF file: */
00155     if (fread(Buf, 1, GIF_STAMP_LEN, Private->File) != GIF_STAMP_LEN) {
00156        _GifError = D_GIF_ERR_READ_FAILED;
00157        free((char *) Private);
00158        free((char *) GifFile);
00159        return NULL;
00160     }
00161 
00162     /* The GIF Version number is ignored at this time. Maybe we should do    */
00163     /* something more useful with it.                                      */
00164     Buf[GIF_STAMP_LEN] = 0;
00165     if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
00166        _GifError = D_GIF_ERR_NOT_GIF_FILE;
00167        free((char *) Private);
00168        free((char *) GifFile);
00169        return NULL;
00170     }
00171 
00172     if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
00173        free((char *) Private);
00174        free((char *) GifFile);
00175        return NULL;
00176     }
00177 
00178     _GifError = 0;
00179 
00180     return GifFile;
00181 }
00182 
00183 /******************************************************************************
00184 *   This routine should be called before any other DGif calls. Note that      *
00185 * this routine is called automatically from DGif file open routines.        *
00186 ******************************************************************************/
00187 int DGifGetScreenDesc(GifFileType *GifFile)
00188 {
00189     int i, BitsPerPixel;
00190     GifByteType Buf[3];
00191     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00192 
00193     if (!IS_READABLE(Private)) {
00194        /* This file was NOT open for reading: */
00195        _GifError = D_GIF_ERR_NOT_READABLE;
00196        return GIF_ERROR;
00197     }
00198 
00199     /* Put the screen descriptor into the file: */
00200     if (DGifGetWord(Private->File, &GifFile->SWidth) == GIF_ERROR ||
00201        DGifGetWord(Private->File, &GifFile->SHeight) == GIF_ERROR)
00202        return GIF_ERROR;
00203 
00204     if (fread(Buf, 1, 3, Private->File) != 3) {
00205        _GifError = D_GIF_ERR_READ_FAILED;
00206        return GIF_ERROR;
00207     }
00208     GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
00209     BitsPerPixel = (Buf[0] & 0x07) + 1;
00210     GifFile->SBackGroundColor = Buf[1];
00211     if (Buf[0] & 0x80) {                /* Do we have global color map? */
00212 
00213        GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
00214 
00215        /* Get the global color map: */
00216        for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
00217            if (fread(Buf, 1, 3, Private->File) != 3) {
00218               _GifError = D_GIF_ERR_READ_FAILED;
00219               return GIF_ERROR;
00220            }
00221            GifFile->SColorMap->Colors[i].Red = Buf[0];
00222            GifFile->SColorMap->Colors[i].Green = Buf[1];
00223            GifFile->SColorMap->Colors[i].Blue = Buf[2];
00224        }
00225     }
00226 
00227     return GIF_OK;
00228 }
00229 
00230 /******************************************************************************
00231 *   This routine should be called before any attemp to read an image.         *
00232 ******************************************************************************/
00233 int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
00234 {
00235     GifByteType Buf;
00236     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00237 
00238     if (!IS_READABLE(Private)) {
00239        /* This file was NOT open for reading: */
00240        _GifError = D_GIF_ERR_NOT_READABLE;
00241        return GIF_ERROR;
00242     }
00243 
00244     if (fread(&Buf, 1, 1, Private->File) != 1) {
00245        _GifError = D_GIF_ERR_READ_FAILED;
00246        return GIF_ERROR;
00247     }
00248 
00249     switch (Buf) {
00250        case ',':
00251            *Type = IMAGE_DESC_RECORD_TYPE;
00252            break;
00253        case '!':
00254            *Type = EXTENSION_RECORD_TYPE;
00255            break;
00256        case ';':
00257            *Type = TERMINATE_RECORD_TYPE;
00258            break;
00259        default:
00260            *Type = UNDEFINED_RECORD_TYPE;
00261            _GifError = D_GIF_ERR_WRONG_RECORD;
00262            return GIF_ERROR;
00263     }
00264 
00265     return GIF_OK;
00266 }
00267 
00268 /******************************************************************************
00269 *   This routine should be called before any attemp to read an image.         *
00270 *   Note it is assumed the Image desc. header (',') has been read.          *
00271 ******************************************************************************/
00272 int DGifGetImageDesc(GifFileType *GifFile)
00273 {
00274     int i, BitsPerPixel;
00275     GifByteType Buf[3];
00276     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00277 
00278     if (!IS_READABLE(Private)) {
00279        /* This file was NOT open for reading: */
00280        _GifError = D_GIF_ERR_NOT_READABLE;
00281        return GIF_ERROR;
00282     }
00283 
00284     if (DGifGetWord(Private->File, &GifFile->Image.Left) == GIF_ERROR ||
00285        DGifGetWord(Private->File, &GifFile->Image.Top) == GIF_ERROR ||
00286        DGifGetWord(Private->File, &GifFile->Image.Width) == GIF_ERROR ||
00287        DGifGetWord(Private->File, &GifFile->Image.Height) == GIF_ERROR)
00288        return GIF_ERROR;
00289     if (fread(Buf, 1, 1, Private->File) != 1) {
00290        _GifError = D_GIF_ERR_READ_FAILED;
00291        return GIF_ERROR;
00292     }
00293     BitsPerPixel = (Buf[0] & 0x07) + 1;
00294     GifFile->Image.Interlace = (Buf[0] & 0x40);
00295     if (Buf[0] & 0x80) {        /* Does this image have local color map? */
00296 
00297        if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
00298            FreeMapObject(GifFile->Image.ColorMap);
00299 
00300        GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
00301     
00302        /* Get the image local color map: */
00303        for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
00304            if (fread(Buf, 1, 3, Private->File) != 3) {
00305               _GifError = D_GIF_ERR_READ_FAILED;
00306               return GIF_ERROR;
00307            }
00308            GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
00309            GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
00310            GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
00311        }
00312     }
00313 
00314     if (GifFile->SavedImages) {
00315        SavedImage    *sp;
00316 
00317        if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
00318                   sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) {
00319            _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
00320            return GIF_ERROR;
00321        }
00322 
00323        sp = &GifFile->SavedImages[GifFile->ImageCount];
00324        memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
00325        sp->RasterBits = (char *)NULL;
00326        sp->ExtensionBlockCount = 0;
00327        sp->ExtensionBlocks = (ExtensionBlock *)NULL;
00328     }
00329 
00330     GifFile->ImageCount++;
00331 
00332     Private->PixelCount = (long) GifFile->Image.Width *
00333                          (long) GifFile->Image.Height;
00334 
00335     DGifSetupDecompress(GifFile);  /* Reset decompress algorithm parameters. */
00336 
00337     return GIF_OK;
00338 }
00339 
00340 /******************************************************************************
00341 *  Get one full scanned line (Line) of length LineLen from GIF file.        *
00342 ******************************************************************************/
00343 int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
00344 {
00345     GifByteType *Dummy;
00346     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00347 
00348     if (!IS_READABLE(Private)) {
00349        /* This file was NOT open for reading: */
00350        _GifError = D_GIF_ERR_NOT_READABLE;
00351        return GIF_ERROR;
00352     }
00353 
00354     if (!LineLen) LineLen = GifFile->Image.Width;
00355 
00356 #if defined(__MSDOS__) || defined(__GNUC__)
00357     if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
00358 #else
00359     if ((Private->PixelCount -= LineLen) > 0xffff0000) {
00360 #endif /* __MSDOS__ */
00361        _GifError = D_GIF_ERR_DATA_TOO_BIG;
00362        return GIF_ERROR;
00363     }
00364 
00365     if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
00366        if (Private->PixelCount == 0) {
00367            /* We probably would not be called any more, so lets clean             */
00368            /* everything before we return: need to flush out all rest of    */
00369            /* image until empty block (size 0) detected. We use GetCodeNext.*/
00370            do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
00371               return GIF_ERROR;
00372            while (Dummy != NULL);
00373        }
00374        return GIF_OK;
00375     }
00376     else
00377        return GIF_ERROR;
00378 }
00379 
00380 /******************************************************************************
00381 * Put one pixel (Pixel) into GIF file.                                      *
00382 ******************************************************************************/
00383 int DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
00384 {
00385     GifByteType *Dummy;
00386     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00387 
00388     if (!IS_READABLE(Private)) {
00389        /* This file was NOT open for reading: */
00390        _GifError = D_GIF_ERR_NOT_READABLE;
00391        return GIF_ERROR;
00392     }
00393 
00394 #if defined(__MSDOS__) || defined(__GNUC__)
00395     if (--Private->PixelCount > 0xffff0000UL)
00396 #else
00397     if (--Private->PixelCount > 0xffff0000)
00398 #endif /* __MSDOS__ */
00399     {
00400        _GifError = D_GIF_ERR_DATA_TOO_BIG;
00401        return GIF_ERROR;
00402     }
00403 
00404     if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
00405        if (Private->PixelCount == 0) {
00406            /* We probably would not be called any more, so lets clean             */
00407            /* everything before we return: need to flush out all rest of    */
00408            /* image until empty block (size 0) detected. We use GetCodeNext.*/
00409            do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
00410               return GIF_ERROR;
00411            while (Dummy != NULL);
00412        }
00413        return GIF_OK;
00414     }
00415     else
00416        return GIF_ERROR;
00417 }
00418 
00419 /******************************************************************************
00420 *   Get an extension block (see GIF manual) from gif file. This routine only  *
00421 * returns the first data block, and DGifGetExtensionNext shouldbe called      *
00422 * after this one until NULL extension is returned.                          *
00423 *   The Extension should NOT be freed by the user (not dynamically allocated).*
00424 *   Note it is assumed the Extension desc. header ('!') has been read.             *
00425 ******************************************************************************/
00426 int DGifGetExtension(GifFileType *GifFile, int *ExtCode,
00427                                               GifByteType **Extension)
00428 {
00429     GifByteType Buf;
00430     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00431 
00432     if (!IS_READABLE(Private)) {
00433        /* This file was NOT open for reading: */
00434        _GifError = D_GIF_ERR_NOT_READABLE;
00435        return GIF_ERROR;
00436     }
00437 
00438     if (fread(&Buf, 1, 1, Private->File) != 1) {
00439        _GifError = D_GIF_ERR_READ_FAILED;
00440        return GIF_ERROR;
00441     }
00442     *ExtCode = Buf;
00443 
00444     return DGifGetExtensionNext(GifFile, Extension);
00445 }
00446 
00447 /******************************************************************************
00448 *   Get a following extension block (see GIF manual) from gif file. This      *
00449 * routine sould be called until NULL Extension is returned.                 *
00450 *   The Extension should NOT be freed by the user (not dynamically allocated).*
00451 ******************************************************************************/
00452 int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension)
00453 {
00454     GifByteType Buf;
00455     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00456 
00457     if (fread(&Buf, 1, 1, Private->File) != 1) {
00458        _GifError = D_GIF_ERR_READ_FAILED;
00459        return GIF_ERROR;
00460     }
00461     if (Buf > 0) {
00462        *Extension = Private->Buf;           /* Use private unused buffer. */
00463        (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
00464        if (fread(&((*Extension)[1]), 1, Buf, Private->File) != Buf) {
00465            _GifError = D_GIF_ERR_READ_FAILED;
00466            return GIF_ERROR;
00467        }
00468     }
00469     else
00470        *Extension = NULL;
00471 
00472     return GIF_OK;
00473 }
00474 
00475 /******************************************************************************
00476 *   This routine should be called last, to close the GIF file.              *
00477 ******************************************************************************/
00478 int DGifCloseFile(GifFileType *GifFile)
00479 {
00480     GifFilePrivateType *Private;
00481     FILE *File;
00482 
00483     if (GifFile == NULL) return GIF_ERROR;
00484 
00485     Private = (GifFilePrivateType *) GifFile->Private;
00486 
00487     if (!IS_READABLE(Private)) {
00488        /* This file was NOT open for reading: */
00489        _GifError = D_GIF_ERR_NOT_READABLE;
00490        return GIF_ERROR;
00491     }
00492 
00493     File = Private->File;
00494 
00495     if (GifFile->Image.ColorMap)
00496        FreeMapObject(GifFile->Image.ColorMap);
00497     if (GifFile->SColorMap)
00498        FreeMapObject(GifFile->SColorMap);
00499     if (Private)
00500        free((char *) Private);
00501     if (GifFile->SavedImages)
00502        FreeSavedImages(GifFile);
00503     free(GifFile);
00504 
00505     if (fclose(File) != 0) {
00506        _GifError = D_GIF_ERR_CLOSE_FAILED;
00507        return GIF_ERROR;
00508     }
00509     return GIF_OK;
00510 }
00511 
00512 /******************************************************************************
00513 *   Get 2 bytes (word) from the given file:                                 *
00514 ******************************************************************************/
00515 static int DGifGetWord(FILE *File, int *Word)
00516 {
00517     unsigned char c[2];
00518 
00519     if (fread(c, 1, 2, File) != 2) {
00520        _GifError = D_GIF_ERR_READ_FAILED;
00521        return GIF_ERROR;
00522     }
00523 
00524     *Word = (((unsigned int) c[1]) << 8) + c[0];
00525     return GIF_OK;
00526 }
00527 
00528 /******************************************************************************
00529 *   Get the image code in compressed form.  his routine can be called if the  *
00530 * information needed to be piped out as is. Obviously this is much faster     *
00531 * than decoding and encoding again. This routine should be followed by calls  *
00532 * to DGifGetCodeNext, until NULL block is returned.                         *
00533 *   The block should NOT be freed by the user (not dynamically allocated).    *
00534 ******************************************************************************/
00535 int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
00536 {
00537     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00538 
00539     if (!IS_READABLE(Private)) {
00540        /* This file was NOT open for reading: */
00541        _GifError = D_GIF_ERR_NOT_READABLE;
00542        return GIF_ERROR;
00543     }
00544 
00545     *CodeSize = Private->BitsPerPixel;
00546 
00547     return DGifGetCodeNext(GifFile, CodeBlock);
00548 }
00549 
00550 /******************************************************************************
00551 *   Continue to get the image code in compressed form. This routine should be *
00552 * called until NULL block is returned.                                      *
00553 *   The block should NOT be freed by the user (not dynamically allocated).    *
00554 ******************************************************************************/
00555 int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
00556 {
00557     GifByteType Buf;
00558     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00559 
00560     if (fread(&Buf, 1, 1, Private->File) != 1) {
00561        _GifError = D_GIF_ERR_READ_FAILED;
00562        return GIF_ERROR;
00563     }
00564 
00565     if (Buf > 0) {
00566        *CodeBlock = Private->Buf;         /* Use private unused buffer. */
00567        (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
00568        if (fread(&((*CodeBlock)[1]), 1, Buf, Private->File) != Buf) {
00569            _GifError = D_GIF_ERR_READ_FAILED;
00570            return GIF_ERROR;
00571        }
00572     }
00573     else {
00574        *CodeBlock = NULL;
00575        Private->Buf[0] = 0;           /* Make sure the buffer is empty! */
00576        Private->PixelCount = 0;   /* And local info. indicate image read. */
00577     }
00578 
00579     return GIF_OK;
00580 }
00581 
00582 /******************************************************************************
00583 *   Setup the LZ decompression for this image:                              *
00584 ******************************************************************************/
00585 static int DGifSetupDecompress(GifFileType *GifFile)
00586 {
00587     int i, BitsPerPixel;
00588     GifByteType CodeSize;
00589     unsigned int *Prefix;
00590     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00591 
00592     fread(&CodeSize, 1, 1, Private->File);    /* Read Code size from file. */
00593     BitsPerPixel = CodeSize;
00594 
00595     Private->Buf[0] = 0;                        /* Input Buffer empty. */
00596     Private->BitsPerPixel = BitsPerPixel;
00597     Private->ClearCode = (1 << BitsPerPixel);
00598     Private->EOFCode = Private->ClearCode + 1;
00599     Private->RunningCode = Private->EOFCode + 1;
00600     Private->RunningBits = BitsPerPixel + 1;      /* Number of bits per code. */
00601     Private->MaxCode1 = 1 << Private->RunningBits;     /* Max. code + 1. */
00602     Private->StackPtr = 0;             /* No pixels on the pixel stack. */
00603     Private->LastCode = NO_SUCH_CODE;
00604     Private->CrntShiftState = 0;   /* No information in CrntShiftDWord. */
00605     Private->CrntShiftDWord = 0;
00606 
00607     Prefix = Private->Prefix;
00608     for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
00609 
00610     return GIF_OK;
00611 }
00612 
00613 /******************************************************************************
00614 *   The LZ decompression routine:                                    *
00615 *   This version decompress the given gif file into Line of length LineLen.   *
00616 *   This routine can be called few times (one per scan line, for example), in *
00617 * order the complete the whole image.                                       *
00618 ******************************************************************************/
00619 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
00620                                                         int LineLen)
00621 {
00622     int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
00623     GifByteType *Stack, *Suffix;
00624     unsigned int *Prefix;
00625     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00626 
00627     StackPtr = Private->StackPtr;
00628     Prefix = Private->Prefix;
00629     Suffix = Private->Suffix;
00630     Stack = Private->Stack;
00631     EOFCode = Private->EOFCode;
00632     ClearCode = Private->ClearCode;
00633     LastCode = Private->LastCode;
00634 
00635     if (StackPtr != 0) {
00636        /* Let pop the stack off before continueing to read the gif file: */
00637        while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
00638     }
00639 
00640     while (i < LineLen) {                     /* Decode LineLen items. */
00641        if (DGifDecompressInput(Private, &CrntCode) == GIF_ERROR)
00642            return GIF_ERROR;
00643 
00644        if (CrntCode == EOFCode) {
00645            /* Note however that usually we will not be here as we will stop */
00646            /* decoding as soon as we got all the pixel, or EOF code will    */
00647            /* not be read at all, and DGifGetLine/Pixel clean everything.   */
00648            if (i != LineLen - 1 || Private->PixelCount != 0) {
00649               _GifError = D_GIF_ERR_EOF_TOO_SOON;
00650               return GIF_ERROR;
00651            }
00652            i++;
00653        }
00654        else if (CrntCode == ClearCode) {
00655            /* We need to start over again: */
00656            for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
00657            Private->RunningCode = Private->EOFCode + 1;
00658            Private->RunningBits = Private->BitsPerPixel + 1;
00659            Private->MaxCode1 = 1 << Private->RunningBits;
00660            LastCode = Private->LastCode = NO_SUCH_CODE;
00661        }
00662        else {
00663            /* Its regular code - if in pixel range simply add it to output  */
00664            /* stream, otherwise trace to codes linked list until the prefix */
00665            /* is in pixel range:                                    */
00666            if (CrntCode < ClearCode) {
00667               /* This is simple - its pixel scalar, so add it to output:   */
00668               Line[i++] = CrntCode;
00669            }
00670            else {
00671               /* Its a code to needed to be traced: trace the linked list  */
00672               /* until the prefix is a pixel, while pushing the suffix     */
00673               /* pixels on our stack. If we done, pop the stack in reverse */
00674               /* (thats what stack is good for!) order to output.          */
00675               if (Prefix[CrntCode] == NO_SUCH_CODE) {
00676                   /* Only allowed if CrntCode is exactly the running code: */
00677                   /* In that case CrntCode = XXXCode, CrntCode or the      */
00678                   /* prefix code is last code and the suffix char is       */
00679                   /* exactly the prefix of last code!                      */
00680                   if (CrntCode == Private->RunningCode - 2) {
00681                      CrntPrefix = LastCode;
00682                      Suffix[Private->RunningCode - 2] =
00683                      Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
00684                                                  LastCode, ClearCode);
00685                   }
00686                   else {
00687                      _GifError = D_GIF_ERR_IMAGE_DEFECT;
00688                      return GIF_ERROR;
00689                   }
00690               }
00691               else
00692                   CrntPrefix = CrntCode;
00693 
00694               /* Now (if image is O.K.) we should not get an NO_SUCH_CODE  */
00695               /* During the trace. As we might loop forever, in case of    */
00696               /* defective image, we count the number of loops we trace    */
00697               /* and stop if we got LZ_MAX_CODE. obviously we can not      */
00698               /* loop more than that.                                      */
00699               j = 0;
00700               while (j++ <= LZ_MAX_CODE &&
00701                      CrntPrefix > ClearCode &&
00702                      CrntPrefix <= LZ_MAX_CODE) {
00703                   Stack[StackPtr++] = Suffix[CrntPrefix];
00704                   CrntPrefix = Prefix[CrntPrefix];
00705               }
00706               if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
00707                   _GifError = D_GIF_ERR_IMAGE_DEFECT;
00708                   return GIF_ERROR;
00709               }
00710               /* Push the last character on stack: */
00711               Stack[StackPtr++] = CrntPrefix;
00712 
00713               /* Now lets pop all the stack into output: */
00714               while (StackPtr != 0 && i < LineLen)
00715                   Line[i++] = Stack[--StackPtr];
00716            }
00717            if (LastCode != NO_SUCH_CODE) {
00718               Prefix[Private->RunningCode - 2] = LastCode;
00719 
00720               if (CrntCode == Private->RunningCode - 2) {
00721                   /* Only allowed if CrntCode is exactly the running code: */
00722                   /* In that case CrntCode = XXXCode, CrntCode or the      */
00723                   /* prefix code is last code and the suffix char is       */
00724                   /* exactly the prefix of last code!                      */
00725                   Suffix[Private->RunningCode - 2] =
00726                      DGifGetPrefixChar(Prefix, LastCode, ClearCode);
00727               }
00728               else {
00729                   Suffix[Private->RunningCode - 2] =
00730                      DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
00731               }
00732            }
00733            LastCode = CrntCode;
00734        }
00735     }
00736 
00737     Private->LastCode = LastCode;
00738     Private->StackPtr = StackPtr;
00739 
00740     return GIF_OK;
00741 }
00742 
00743 /******************************************************************************
00744 * Routine to trace the Prefixes linked list until we get a prefix which is    *
00745 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
00746 * If image is defective, we might loop here forever, so we limit the loops to *
00747 * the maximum possible if image O.k. - LZ_MAX_CODE times.                   *
00748 ******************************************************************************/
00749 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
00750 {
00751     int i = 0;
00752 
00753     while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
00754     return Code;
00755 }
00756 
00757 /******************************************************************************
00758 *   Interface for accessing the LZ codes directly. Set Code to the real code  *
00759 * (12bits), or to -1 if EOF code is returned.                               *
00760 ******************************************************************************/
00761 int DGifGetLZCodes(GifFileType *GifFile, int *Code)
00762 {
00763     GifByteType *CodeBlock;
00764     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00765 
00766     if (!IS_READABLE(Private)) {
00767        /* This file was NOT open for reading: */
00768        _GifError = D_GIF_ERR_NOT_READABLE;
00769        return GIF_ERROR;
00770     }
00771 
00772     if (DGifDecompressInput(Private, Code) == GIF_ERROR)
00773        return GIF_ERROR;
00774 
00775     if (*Code == Private->EOFCode) {
00776        /* Skip rest of codes (hopefully only NULL terminating block): */
00777        do if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
00778            return GIF_ERROR;
00779        while (CodeBlock != NULL);
00780 
00781        *Code = -1;
00782     }
00783     else if (*Code == Private->ClearCode) {
00784        /* We need to start over again: */
00785        Private->RunningCode = Private->EOFCode + 1;
00786        Private->RunningBits = Private->BitsPerPixel + 1;
00787        Private->MaxCode1 = 1 << Private->RunningBits;
00788     }
00789 
00790     return GIF_OK;
00791 }
00792 
00793 /******************************************************************************
00794 *   The LZ decompression input routine:                                     *
00795 *   This routine is responsable for the decompression of the bit stream from  *
00796 * 8 bits (bytes) packets, into the real codes.                              *
00797 *   Returns GIF_OK if read succesfully.                                     *
00798 ******************************************************************************/
00799 static int DGifDecompressInput(GifFilePrivateType *Private, int *Code)
00800 {
00801     GifByteType NextByte;
00802     static unsigned int CodeMasks[] = {
00803        0x0000, 0x0001, 0x0003, 0x0007,
00804        0x000f, 0x001f, 0x003f, 0x007f,
00805        0x00ff, 0x01ff, 0x03ff, 0x07ff,
00806        0x0fff
00807     };
00808 
00809     while (Private->CrntShiftState < Private->RunningBits) {
00810        /* Needs to get more bytes from input stream for next code: */
00811        if (DGifBufferedInput(Private->File, Private->Buf, &NextByte)
00812            == GIF_ERROR) {
00813            return GIF_ERROR;
00814        }
00815        Private->CrntShiftDWord |=
00816               ((unsigned long) NextByte) << Private->CrntShiftState;
00817        Private->CrntShiftState += 8;
00818     }
00819     *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
00820 
00821     Private->CrntShiftDWord >>= Private->RunningBits;
00822     Private->CrntShiftState -= Private->RunningBits;
00823 
00824     /* If code cannt fit into RunningBits bits, must raise its size. Note */
00825     /* however that codes above 4095 are used for special signaling.      */
00826     if (++Private->RunningCode > Private->MaxCode1 &&
00827        Private->RunningBits < LZ_BITS) {
00828        Private->MaxCode1 <<= 1;
00829        Private->RunningBits++;
00830     }
00831     return GIF_OK;
00832 }
00833 
00834 /******************************************************************************
00835 *   This routines read one gif data block at a time and buffers it internally *
00836 * so that the decompression routine could access it.                        *
00837 *   The routine returns the next byte from its internal buffer (or read next  *
00838 * block in if buffer empty) and returns GIF_OK if succesful.                *
00839 ******************************************************************************/
00840 static int DGifBufferedInput(FILE *File, GifByteType *Buf,
00841                                                 GifByteType *NextByte)
00842 {
00843     if (Buf[0] == 0) {
00844        /* Needs to read the next buffer - this one is empty: */
00845        if (fread(Buf, 1, 1, File) != 1)
00846        {
00847            _GifError = D_GIF_ERR_READ_FAILED;
00848            return GIF_ERROR;
00849        }
00850        if (fread(&Buf[1], 1, Buf[0], File) != Buf[0])
00851        {
00852            _GifError = D_GIF_ERR_READ_FAILED;
00853            return GIF_ERROR;
00854        }
00855        *NextByte = Buf[1];
00856        Buf[1] = 2;      /* We use now the second place as last char read! */
00857        Buf[0]--;
00858     }
00859     else {
00860        *NextByte = Buf[Buf[1]++];
00861        Buf[0]--;
00862     }
00863 
00864     return GIF_OK;
00865 }
00866 
00867 /******************************************************************************
00868 * This routine reads an entire GIF into core, hanging all its state info off  *
00869 * the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()   *
00870 * first to initialize I/O.  Its inverse is EGifSpew().                      *
00871 ******************************************************************************/
00872 int DGifSlurp(GifFileType *GifFile)
00873 {
00874     int i, j, Error, ImageSize;
00875     GifRecordType RecordType;
00876     SavedImage *sp;
00877     ExtensionBlock *ep;
00878     GifByteType *ExtData;
00879 
00880     /* Some versions of malloc dislike 0-length requests */
00881     GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
00882 
00883     do {
00884        if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
00885            return(GIF_ERROR);
00886 
00887        switch (RecordType) {
00888            case IMAGE_DESC_RECORD_TYPE:
00889               if (DGifGetImageDesc(GifFile) == GIF_ERROR)
00890                   return(GIF_ERROR);
00891 
00892               sp = &GifFile->SavedImages[GifFile->ImageCount-1];
00893               ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
00894 
00895               sp->RasterBits
00896                   = (GifPixelType*) malloc(ImageSize * sizeof(GifPixelType));
00897 
00898               if (DGifGetLine(GifFile, sp->RasterBits, ImageSize)
00899                   == GIF_ERROR)
00900                   return(GIF_ERROR);
00901 
00902               break;
00903 
00904            case EXTENSION_RECORD_TYPE:
00905 
00906               if (DGifGetExtension(GifFile,&sp->Function,&ExtData)==GIF_ERROR)
00907                   return(GIF_ERROR);
00908               else
00909               {
00910                   ep = &sp->ExtensionBlocks[sp->ExtensionBlockCount++];
00911 
00912                   ep->ByteCount = ExtData[0];
00913                   ep->Bytes = (GifByteType *)malloc(ep->ByteCount * sizeof(GifByteType));
00914                   memcpy(ep->Bytes, ExtData, ep->ByteCount * sizeof(char));
00915               }
00916 
00917               while (ExtData != NULL) {
00918                   if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
00919                      return(GIF_ERROR);
00920                   else
00921                   {
00922                      ep = &sp->ExtensionBlocks[sp->ExtensionBlockCount++];
00923 
00924                      ep->ByteCount = ExtData[0];
00925                      ep->Bytes = (GifByteType *)malloc(ep->ByteCount * sizeof(GifByteType));
00926                      memcpy(ep->Bytes,ExtData,ep->ByteCount * sizeof(char));
00927                   }
00928               }
00929               break;
00930 
00931            case TERMINATE_RECORD_TYPE:
00932               break;
00933 
00934            default:  /* Should be trapped by DGifGetRecordType */
00935               break;
00936        }
00937     }
00938     while
00939        (RecordType != TERMINATE_RECORD_TYPE);
00940 
00941     return(GIF_OK);
00942 }
00943