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 #ifdef _WIN32
00014 #include "../win32/config.h"
00015 #else
00016 #include "../config.h"
00017 #endif
00018 
00019 #if defined (__MSDOS__) && !defined(__DJGPP__) && !defined(__GNUC__)
00020 #include <alloc.h>
00021 #include <sys\stat.h>
00022 #else
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #endif /* __MSDOS__ */
00026 
00027 #ifdef HAVE_UNISTD_H
00028 #include <unistd.h>
00029 #endif
00030 #ifdef HAVE_STDLIB_H
00031 #include <stdlib.h>
00032 #endif
00033 #include <fcntl.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include "gif_lib.h"
00037 #include "gif_lib_private.h"
00038 
00039 #define COMMENT_EXT_FUNC_CODE   0xfe /* Extension function code for comment. */
00040 
00041 /* avoid extra function call in case we use fread (TVT) */
00042 #define READ(_gif,_buf,_len)                                     \
00043   (((GifFilePrivateType*)_gif->Private)->Read ?                   \
00044     ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \
00045     fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File))
00046 
00047 static int DGifGetWord(GifFileType *GifFile, int *Word);
00048 static int DGifSetupDecompress(GifFileType *GifFile);
00049 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
00050                                                                 int LineLen);
00051 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
00052 static int DGifDecompressInput(GifFileType *GifFile, int *Code);
00053 static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
00054                                                      GifByteType *NextByte);
00055 
00056 /******************************************************************************
00057 * GifFileType constructor with user supplied input function (TVT)             *
00058 *                                                                             *
00059 ******************************************************************************/
00060 GifFileType *DGifOpen( void* userData, InputFunc readFunc )
00061 {
00062     unsigned char Buf[GIF_STAMP_LEN+1];
00063     GifFileType *GifFile;
00064     GifFilePrivateType *Private;
00065 
00066 
00067     if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) {
00068           _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
00069           return NULL;
00070     }
00071 
00072     memset(GifFile, '\0', sizeof(GifFileType));
00073 
00074     if (!(Private = (GifFilePrivateType*) malloc(sizeof(GifFilePrivateType)))){
00075           _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
00076           free((char *) GifFile);
00077           return NULL;
00078     }
00079 
00080     GifFile->Private = (VoidPtr) Private;
00081     Private->FileHandle = 0;
00082     Private->File = 0;
00083     Private->FileState = FILE_STATE_READ;
00084 
00085         Private->Read     = readFunc;  /* TVT */
00086         GifFile->UserData = userData;    /* TVT */
00087 
00088     /* Lets see if this is a GIF file: */
00089     if ( READ( GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
00090           _GifError = D_GIF_ERR_READ_FAILED;
00091           free((char *) Private);
00092           free((char *) GifFile);
00093           return NULL;
00094     }
00095 
00096     /* The GIF Version number is ignored at this time. Maybe we should do    */
00097     /* something more useful with it.                                        */
00098     Buf[GIF_STAMP_LEN] = 0;
00099     if (strncmp(GIF_STAMP, (char*)Buf, GIF_VERSION_POS) != 0) {
00100           _GifError = D_GIF_ERR_NOT_GIF_FILE;
00101           free((char *) Private);
00102           free((char *) GifFile);
00103           return NULL;
00104     }
00105 
00106     if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
00107           free((char *) Private);
00108           free((char *) GifFile);
00109           return NULL;
00110     }
00111 
00112     _GifError = 0;
00113 
00114     return GifFile;
00115 }
00116 
00117 /******************************************************************************
00118 *   This routine should be called before any other DGif calls. Note that      *
00119 * this routine is called automatically from DGif file open routines.          *
00120 ******************************************************************************/
00121 int DGifGetScreenDesc(GifFileType *GifFile)
00122 {
00123     int i, BitsPerPixel;
00124     GifByteType Buf[3];
00125     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00126 
00127     if (!IS_READABLE(Private)) {
00128         /* This file was NOT open for reading: */
00129         _GifError = D_GIF_ERR_NOT_READABLE;
00130         return GIF_ERROR;
00131     }
00132 
00133     /* Put the screen descriptor into the file: */
00134     if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
00135         DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
00136         return GIF_ERROR;
00137 
00138     if (READ( GifFile, Buf, 3) != 3) {
00139         _GifError = D_GIF_ERR_READ_FAILED;
00140         return GIF_ERROR;
00141     }
00142     GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
00143     BitsPerPixel = (Buf[0] & 0x07) + 1;
00144     GifFile->SBackGroundColor = Buf[1];
00145     if (Buf[0] & 0x80) {                     /* Do we have global color map? */
00146 
00147         GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
00148 
00149         /* Get the global color map: */
00150         for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
00151             if (READ(GifFile, Buf, 3) != 3) {
00152                 _GifError = D_GIF_ERR_READ_FAILED;
00153                 return GIF_ERROR;
00154             }
00155             GifFile->SColorMap->Colors[i].Red = Buf[0];
00156             GifFile->SColorMap->Colors[i].Green = Buf[1];
00157             GifFile->SColorMap->Colors[i].Blue = Buf[2];
00158         }
00159     }
00160 
00161     return GIF_OK;
00162 }
00163 
00164 /******************************************************************************
00165 *   This routine should be called before any attemp to read an image.         *
00166 ******************************************************************************/
00167 int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
00168 {
00169     GifByteType Buf;
00170     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00171 
00172     if (!IS_READABLE(Private)) {
00173         /* This file was NOT open for reading: */
00174         _GifError = D_GIF_ERR_NOT_READABLE;
00175         return GIF_ERROR;
00176     }
00177 
00178     if (READ( GifFile, &Buf, 1) != 1) {
00179         _GifError = D_GIF_ERR_READ_FAILED;
00180         return GIF_ERROR;
00181     }
00182 
00183     switch (Buf) {
00184         case ',':
00185             *Type = IMAGE_DESC_RECORD_TYPE;
00186             break;
00187         case '!':
00188             *Type = EXTENSION_RECORD_TYPE;
00189             break;
00190         case ';':
00191             *Type = TERMINATE_RECORD_TYPE;
00192             break;
00193         default:
00194             *Type = UNDEFINED_RECORD_TYPE;
00195             _GifError = D_GIF_ERR_WRONG_RECORD;
00196             return GIF_ERROR;
00197     }
00198 
00199     return GIF_OK;
00200 }
00201 
00202 /******************************************************************************
00203 *   This routine should be called before any attemp to read an image.         *
00204 *   Note it is assumed the Image desc. header (',') has been read.            *
00205 ******************************************************************************/
00206 int DGifGetImageDesc(GifFileType *GifFile)
00207 {
00208     int i, BitsPerPixel;
00209     GifByteType Buf[3];
00210     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00211         SavedImage      *sp;
00212 
00213     if (!IS_READABLE(Private)) {
00214         /* This file was NOT open for reading: */
00215         _GifError = D_GIF_ERR_NOT_READABLE;
00216         return GIF_ERROR;
00217     }
00218     if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
00219         DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
00220         DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
00221         DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
00222         return GIF_ERROR;
00223     if (READ(GifFile,Buf, 1) != 1) {
00224         _GifError = D_GIF_ERR_READ_FAILED;
00225         return GIF_ERROR;
00226     }
00227     BitsPerPixel = (Buf[0] & 0x07) + 1;
00228     GifFile->Image.Interlace = (Buf[0] & 0x40);
00229     if (Buf[0] & 0x80) {            /* Does this image have local color map? */
00230 
00231         if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
00232             FreeMapObject(GifFile->Image.ColorMap);
00233 
00234         GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
00235         /* Get the image local color map: */
00236         for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
00237             if (READ(GifFile,Buf, 3) != 3) {
00238                 _GifError = D_GIF_ERR_READ_FAILED;
00239                 return GIF_ERROR;
00240             }
00241             GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
00242             GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
00243             GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
00244         }
00245     }
00246     if (GifFile->SavedImages) {
00247             if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
00248                      sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) {
00249                 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
00250                 return GIF_ERROR;
00251             }
00252     } else {
00253         if ((GifFile->SavedImages =
00254              (SavedImage *)malloc(sizeof(SavedImage))) == NULL) {
00255             _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
00256             return GIF_ERROR;
00257         }
00258     }
00259 
00260         sp = &GifFile->SavedImages[GifFile->ImageCount];
00261         memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
00262     if (GifFile->Image.ColorMap != NULL) {
00263         sp->ImageDesc.ColorMap = MakeMapObject(
00264                 GifFile->Image.ColorMap->ColorCount,
00265                 GifFile->Image.ColorMap->Colors);
00266     }
00267         sp->RasterBits = (char *)NULL;
00268         sp->ExtensionBlockCount = 0;
00269         sp->ExtensionBlocks = (ExtensionBlock *)NULL;
00270 
00271     GifFile->ImageCount++;
00272 
00273     Private->PixelCount = (long) GifFile->Image.Width *
00274                             (long) GifFile->Image.Height;
00275 
00276     DGifSetupDecompress(GifFile);  /* Reset decompress algorithm parameters. */
00277 
00278     return GIF_OK;
00279 }
00280 
00281 /******************************************************************************
00282 *  Get one full scanned line (Line) of length LineLen from GIF file.          *
00283 ******************************************************************************/
00284 int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
00285 {
00286     GifByteType *Dummy;
00287     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00288 
00289     if (!IS_READABLE(Private)) {
00290         /* This file was NOT open for reading: */
00291         _GifError = D_GIF_ERR_NOT_READABLE;
00292         return GIF_ERROR;
00293     }
00294 
00295     if (!LineLen) LineLen = GifFile->Image.Width;
00296 
00297 #if defined(__MSDOS__) || defined(__GNUC__)
00298     if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
00299 #else
00300     if ((Private->PixelCount -= LineLen) > 0xffff0000) {
00301 #endif /* __MSDOS__ */
00302         _GifError = D_GIF_ERR_DATA_TOO_BIG;
00303         return GIF_ERROR;
00304     }
00305 
00306     if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
00307         if (Private->PixelCount == 0) {
00308             /* We probably would not be called any more, so lets clean       */
00309             /* everything before we return: need to flush out all rest of    */
00310             /* image until empty block (size 0) detected. We use GetCodeNext.*/
00311             do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
00312                 return GIF_ERROR;
00313             while (Dummy != NULL);
00314         }
00315         return GIF_OK;
00316     }
00317     else
00318         return GIF_ERROR;
00319 }
00320 
00321 /******************************************************************************
00322 *   Get an extension block (see GIF manual) from gif file. This routine only  *
00323 * returns the first data block, and DGifGetExtensionNext shouldbe called      *
00324 * after this one until NULL extension is returned.                            *
00325 *   The Extension should NOT be freed by the user (not dynamically allocated).*
00326 *   Note it is assumed the Extension desc. header ('!') has been read.        *
00327 ******************************************************************************/
00328 int DGifGetExtension(GifFileType *GifFile, int *ExtCode,
00329                                                     GifByteType **Extension)
00330 {
00331     GifByteType Buf;
00332     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00333 
00334     if (!IS_READABLE(Private)) {
00335         /* This file was NOT open for reading: */
00336         _GifError = D_GIF_ERR_NOT_READABLE;
00337         return GIF_ERROR;
00338     }
00339 
00340     if (READ(GifFile,&Buf, 1) != 1) {
00341         _GifError = D_GIF_ERR_READ_FAILED;
00342         return GIF_ERROR;
00343     }
00344     *ExtCode = Buf;
00345 
00346     return DGifGetExtensionNext(GifFile, Extension);
00347 }
00348 
00349 /******************************************************************************
00350 *   Get a following extension block (see GIF manual) from gif file. This      *
00351 * routine should be called until NULL Extension is returned.                  *
00352 *   The Extension should NOT be freed by the user (not dynamically allocated).*
00353 ******************************************************************************/
00354 int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension)
00355 {
00356     GifByteType Buf;
00357     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00358 
00359     if (READ(GifFile,&Buf, 1) != 1) {
00360         _GifError = D_GIF_ERR_READ_FAILED;
00361         return GIF_ERROR;
00362     }
00363     if (Buf > 0) {
00364         *Extension = Private->Buf;           /* Use private unused buffer. */
00365         (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
00366         if (READ(GifFile,&((*Extension)[1]), Buf) != Buf) {
00367             _GifError = D_GIF_ERR_READ_FAILED;
00368             return GIF_ERROR;
00369         }
00370     }
00371     else
00372         *Extension = NULL;
00373 
00374     return GIF_OK;
00375 }
00376 
00377 /******************************************************************************
00378 *   This routine should be called last, to close the GIF file.                *
00379 ******************************************************************************/
00380 int DGifCloseFile(GifFileType *GifFile)
00381 {
00382     GifFilePrivateType *Private;
00383     FILE *File;
00384         int ret = GIF_OK;
00385 
00386     if (GifFile == NULL) return GIF_ERROR;
00387 
00388     Private = (GifFilePrivateType *) GifFile->Private;
00389 
00390     if (!IS_READABLE(Private)) {
00391                 /* This file was NOT open for reading: */
00392                 _GifError = D_GIF_ERR_NOT_READABLE;
00393                 ret = GIF_ERROR; /* we have to free everything regardless */
00394     }
00395 
00396     File = Private->File;
00397 
00398     if (GifFile->Image.ColorMap)
00399     {
00400                 FreeMapObject(GifFile->Image.ColorMap);
00401         GifFile->Image.ColorMap = NULL;
00402     }
00403 
00404     if (GifFile->SColorMap)
00405     {
00406                 FreeMapObject(GifFile->SColorMap);
00407                 GifFile->SColorMap = NULL;
00408     }
00409 
00410     if (Private)
00411     {
00412                 free((char *) Private);
00413                 GifFile->Private = NULL;
00414     }
00415 
00416     if (GifFile->SavedImages)
00417     {
00418                 FreeSavedImages(GifFile);
00419                 GifFile->SavedImages = NULL;
00420     }
00421 
00422     free(GifFile);
00423 
00424     if ( File && (fclose(File) != 0)) 
00425         {
00426                 _GifError = D_GIF_ERR_CLOSE_FAILED;
00427                 ret = GIF_ERROR;
00428     }
00429     return ret;
00430 }
00431 
00432 /******************************************************************************
00433 *   Get 2 bytes (word) from the given file:                                   *
00434 ******************************************************************************/
00435 static int DGifGetWord(GifFileType *GifFile, int *Word)
00436 {
00437     unsigned char c[2];
00438 
00439     if (READ(GifFile,c, 2) != 2) {
00440         _GifError = D_GIF_ERR_READ_FAILED;
00441         return GIF_ERROR;
00442     }
00443 
00444     *Word = (((unsigned int) c[1]) << 8) + c[0];
00445     return GIF_OK;
00446 }
00447 
00448 /******************************************************************************
00449 *   Get the image code in compressed form.  his routine can be called if the  *
00450 * information needed to be piped out as is. Obviously this is much faster     *
00451 * than decoding and encoding again. This routine should be followed by calls  *
00452 * to DGifGetCodeNext, until NULL block is returned.                           *
00453 *   The block should NOT be freed by the user (not dynamically allocated).    *
00454 ******************************************************************************/
00455 int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
00456 {
00457     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00458 
00459     if (!IS_READABLE(Private)) {
00460         /* This file was NOT open for reading: */
00461         _GifError = D_GIF_ERR_NOT_READABLE;
00462         return GIF_ERROR;
00463     }
00464 
00465     *CodeSize = Private->BitsPerPixel;
00466 
00467     return DGifGetCodeNext(GifFile, CodeBlock);
00468 }
00469 
00470 /******************************************************************************
00471 *   Continue to get the image code in compressed form. This routine should be *
00472 * called until NULL block is returned.                                        *
00473 *   The block should NOT be freed by the user (not dynamically allocated).    *
00474 ******************************************************************************/
00475 int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
00476 {
00477     GifByteType Buf;
00478     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00479     if (READ(GifFile,&Buf, 1) != 1) {
00480         _GifError = D_GIF_ERR_READ_FAILED;
00481         return GIF_ERROR;
00482     }
00483     if (Buf > 0) {
00484                 int ret ; 
00485         *CodeBlock = Private->Buf;             /* Use private unused buffer. */
00486         (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
00487         ret = READ(GifFile,&((*CodeBlock)[1]), Buf);
00488         if ( ret != Buf) 
00489         {
00490                 if( Buf == 59 ) 
00491                 {
00492                         fseek( GifFile->UserData, -1, SEEK_END );       
00493                         *CodeBlock = NULL ; 
00494                         return GIF_OK;
00495                 }        
00496             _GifError = D_GIF_ERR_READ_FAILED;
00497             return GIF_ERROR;
00498         }
00499     }
00500     else {
00501         *CodeBlock = NULL;
00502         Private->Buf[0] = 0;               /* Make sure the buffer is empty! */
00503         Private->PixelCount = 0;   /* And local info. indicate image read. */
00504     }
00505 
00506     return GIF_OK;
00507 }
00508 
00509 /******************************************************************************
00510 *   Setup the LZ decompression for this image:                                *
00511 ******************************************************************************/
00512 static int DGifSetupDecompress(GifFileType *GifFile)
00513 {
00514     int i, BitsPerPixel;
00515     GifByteType CodeSize;
00516     unsigned int *Prefix;
00517     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00518 
00519     READ(GifFile,&CodeSize, 1);    /* Read Code size from file. */
00520     BitsPerPixel = CodeSize;
00521 
00522     Private->Buf[0] = 0;                              /* Input Buffer empty. */
00523     Private->BitsPerPixel = BitsPerPixel;
00524     Private->ClearCode = (1 << BitsPerPixel);
00525     Private->EOFCode = Private->ClearCode + 1;
00526     Private->RunningCode = Private->EOFCode + 1;
00527     Private->RunningBits = BitsPerPixel + 1;     /* Number of bits per code. */
00528     Private->MaxCode1 = 1 << Private->RunningBits;     /* Max. code + 1. */
00529     Private->StackPtr = 0;                  /* No pixels on the pixel stack. */
00530     Private->LastCode = NO_SUCH_CODE;
00531     Private->CrntShiftState = 0;        /* No information in CrntShiftDWord. */
00532     Private->CrntShiftDWord = 0;
00533 
00534     Prefix = Private->Prefix;
00535     for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
00536 
00537     return GIF_OK;
00538 }
00539 
00540 /******************************************************************************
00541 *   The LZ decompression routine:                                             *
00542 *   This version decompress the given gif file into Line of length LineLen.   *
00543 *   This routine can be called few times (one per scan line, for example), in *
00544 * order the complete the whole image.                                         *
00545 ******************************************************************************/
00546 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
00547                                                                 int LineLen)
00548 {
00549     int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
00550     GifByteType *Stack, *Suffix;
00551     unsigned int *Prefix;
00552     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
00553 
00554     StackPtr = Private->StackPtr;
00555     Prefix = Private->Prefix;
00556     Suffix = Private->Suffix;
00557     Stack = Private->Stack;
00558     EOFCode = Private->EOFCode;
00559     ClearCode = Private->ClearCode;
00560     LastCode = Private->LastCode;
00561 
00562     if (StackPtr != 0) {
00563         /* Let pop the stack off before continueing to read the gif file: */
00564         while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
00565     }
00566 
00567     while (i < LineLen) {                           /* Decode LineLen items. */
00568         if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
00569             return GIF_ERROR;
00570 
00571         if (CrntCode == EOFCode) {
00572             /* Note however that usually we will not be here as we will stop */
00573             /* decoding as soon as we got all the pixel, or EOF code will    */
00574             /* not be read at all, and DGifGetLine/Pixel clean everything.   */
00575             if (i != LineLen - 1 || Private->PixelCount != 0) {
00576                 _GifError = D_GIF_ERR_EOF_TOO_SOON;
00577                 return GIF_ERROR;
00578             }
00579             i++;
00580         }
00581         else if (CrntCode == ClearCode) {
00582             /* We need to start over again: */
00583             for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
00584             Private->RunningCode = Private->EOFCode + 1;
00585             Private->RunningBits = Private->BitsPerPixel + 1;
00586             Private->MaxCode1 = 1 << Private->RunningBits;
00587             LastCode = Private->LastCode = NO_SUCH_CODE;
00588         }
00589         else {
00590             /* Its regular code - if in pixel range simply add it to output  */
00591             /* stream, otherwise trace to codes linked list until the prefix */
00592             /* is in pixel range:                                            */
00593             if (CrntCode < ClearCode) {
00594                 /* This is simple - its pixel scalar, so add it to output:   */
00595                 Line[i++] = CrntCode;
00596             }
00597             else {
00598                 /* Its a code to needed to be traced: trace the linked list  */
00599                 /* until the prefix is a pixel, while pushing the suffix     */
00600                 /* pixels on our stack. If we done, pop the stack in reverse */
00601                 /* (thats what stack is good for!) order to output.          */
00602                 if (Prefix[CrntCode] == NO_SUCH_CODE) {
00603                     /* Only allowed if CrntCode is exactly the running code: */
00604                     /* In that case CrntCode = XXXCode, CrntCode or the      */
00605                     /* prefix code is last code and the suffix char is       */
00606                     /* exactly the prefix of last code!                      */
00607                     if (CrntCode == Private->RunningCode - 2) {
00608                         CrntPrefix = LastCode;
00609                         Suffix[Private->RunningCode - 2] =
00610                         Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
00611                                                         LastCode, ClearCode);
00612                     }
00613                     else {
00614                         /*fprintf( stderr, "error at line %d, CrntCode = %d,  Private->RunningCode - 2 = %d\n", __LINE__, CrntCode, Private->RunningCode - 2 ); */
00615                         _GifError = D_GIF_ERR_IMAGE_DEFECT;
00616                         return GIF_ERROR;
00617                     }
00618                 }
00619                 else
00620                     CrntPrefix = CrntCode;
00621 
00622                 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE  */
00623                 /* During the trace. As we might loop forever, in case of    */
00624                 /* defective image, we count the number of loops we trace    */
00625                 /* and stop if we got LZ_MAX_CODE. obviously we can not      */
00626                 /* loop more than that.                                      */
00627                 j = 0;
00628                 while (j++ <= LZ_MAX_CODE &&
00629                        CrntPrefix > ClearCode &&
00630                        CrntPrefix <= LZ_MAX_CODE) {
00631                     Stack[StackPtr++] = Suffix[CrntPrefix];
00632                     CrntPrefix = Prefix[CrntPrefix];
00633                 }
00634                 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
00635                         /* fprintf( stderr,  "error at line %d, j = %d, CrntPrefix = %d\n", __LINE__, j, CrntPrefix ); */
00636                     _GifError = D_GIF_ERR_IMAGE_DEFECT;
00637                     return GIF_ERROR;
00638                 }
00639                 /* Push the last character on stack: */
00640                 Stack[StackPtr++] = CrntPrefix;
00641 
00642                 /* Now lets pop all the stack into output: */
00643                 while (StackPtr != 0 && i < LineLen)
00644                     Line[i++] = Stack[--StackPtr];
00645             }
00646             if (LastCode != NO_SUCH_CODE) {
00647                 Prefix[Private->RunningCode - 2] = LastCode;
00648 
00649                 if (CrntCode == Private->RunningCode - 2) {
00650                     /* Only allowed if CrntCode is exactly the running code: */
00651                     /* In that case CrntCode = XXXCode, CrntCode or the      */
00652                     /* prefix code is last code and the suffix char is       */
00653                     /* exactly the prefix of last code!                      */
00654                     Suffix[Private->RunningCode - 2] =
00655                         DGifGetPrefixChar(Prefix, LastCode, ClearCode);
00656                 }
00657                 else {
00658                     Suffix[Private->RunningCode - 2] =
00659                         DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
00660                 }
00661             }
00662             LastCode = CrntCode;
00663         }
00664     }
00665 
00666     Private->LastCode = LastCode;
00667     Private->StackPtr = StackPtr;
00668 
00669     return GIF_OK;
00670 }
00671 
00672 /******************************************************************************
00673 * Routine to trace the Prefixes linked list until we get a prefix which is    *
00674 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
00675 * If image is defective, we might loop here forever, so we limit the loops to *
00676 * the maximum possible if image O.k. - LZ_MAX_CODE times.                     *
00677 ******************************************************************************/
00678 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
00679 {
00680     int i = 0;
00681 
00682     while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
00683     return Code;
00684 }
00685 
00686 /******************************************************************************
00687 *   The LZ decompression input routine:                                       *
00688 *   This routine is responsable for the decompression of the bit stream from  *
00689 * 8 bits (bytes) packets, into the real codes.                                *
00690 *   Returns GIF_OK if read succesfully.                                       *
00691 ******************************************************************************/
00692 static int DGifDecompressInput(GifFileType *GifFile, int *Code)
00693 {
00694     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
00695 
00696     GifByteType NextByte;
00697     static unsigned int CodeMasks[] = {
00698         0x0000, 0x0001, 0x0003, 0x0007,
00699         0x000f, 0x001f, 0x003f, 0x007f,
00700         0x00ff, 0x01ff, 0x03ff, 0x07ff,
00701         0x0fff
00702     };
00703 
00704     while (Private->CrntShiftState < Private->RunningBits) {
00705         /* Needs to get more bytes from input stream for next code: */
00706         if (DGifBufferedInput(GifFile, Private->Buf, &NextByte)
00707             == GIF_ERROR) {
00708             return GIF_ERROR;
00709         }
00710         Private->CrntShiftDWord |=
00711                 ((unsigned long) NextByte) << Private->CrntShiftState;
00712         Private->CrntShiftState += 8;
00713     }
00714     *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
00715 
00716     Private->CrntShiftDWord >>= Private->RunningBits;
00717     Private->CrntShiftState -= Private->RunningBits;
00718 
00719     /* If code cannt fit into RunningBits bits, must raise its size. Note */
00720     /* however that codes above 4095 are used for special signaling.      */
00721     if (++Private->RunningCode > Private->MaxCode1 &&
00722         Private->RunningBits < LZ_BITS) {
00723         Private->MaxCode1 <<= 1;
00724         Private->RunningBits++;
00725     }
00726     return GIF_OK;
00727 }
00728 
00729 /******************************************************************************
00730 *   This routines read one gif data block at a time and buffers it internally *
00731 * so that the decompression routine could access it.                          *
00732 *   The routine returns the next byte from its internal buffer (or read next  *
00733 * block in if buffer empty) and returns GIF_OK if succesful.                  *
00734 ******************************************************************************/
00735 static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
00736                                                       GifByteType *NextByte)
00737 {
00738     if (Buf[0] == 0) {
00739         /* Needs to read the next buffer - this one is empty: */
00740         if (READ(GifFile, Buf, 1) != 1)
00741         {
00742             _GifError = D_GIF_ERR_READ_FAILED;
00743             return GIF_ERROR;
00744         }
00745         if (READ(GifFile,&Buf[1], Buf[0]) != Buf[0])
00746         {
00747             _GifError = D_GIF_ERR_READ_FAILED;
00748             return GIF_ERROR;
00749         }
00750         *NextByte = Buf[1];
00751         Buf[1] = 2;        /* We use now the second place as last char read! */
00752         Buf[0]--;
00753     }
00754     else {
00755         *NextByte = Buf[Buf[1]++];
00756         Buf[0]--;
00757     }
00758 
00759     return GIF_OK;
00760 }
00761 
00762 

Generated on Tue Jul 5 14:13:32 2011 for ROOT_528-00b_version by  doxygen 1.5.1