ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ungif.c
Go to the documentation of this file.
00001 /*
00002  * Gif extracting routines - derived from libungif
00003  *
00004  * Portions Copyright 2006 Mike McCormack
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 /*
00022  * Original copyright notice:
00023  *
00024  * The GIFLIB distribution is Copyright (c) 1997  Eric S. Raymond
00025  *
00026  * Permission is hereby granted, free of charge, to any person obtaining a copy
00027  * of this software and associated documentation files (the "Software"), to deal
00028  * in the Software without restriction, including without limitation the rights
00029  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00030  * copies of the Software, and to permit persons to whom the Software is
00031  * furnished to do so, subject to the following conditions:
00032  *
00033  * The above copyright notice and this permission notice shall be included in
00034  * all copies or substantial portions of the Software.
00035  */
00036 
00037 
00038 /******************************************************************************
00039  *   "Gif-Lib" - Yet another gif library.
00040  *
00041  * Written by:  Gershon Elber            IBM PC Ver 1.1,    Aug. 1990
00042  ******************************************************************************
00043  * The kernel of the GIF Decoding process can be found here.
00044  ******************************************************************************
00045  * History:
00046  * 16 Jun 89 - Version 1.0 by Gershon Elber.
00047  *  3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names).
00048  *****************************************************************************/
00049 
00050 #include <stdlib.h>
00051 #include <string.h>
00052 #include "ungif.h"
00053 
00054 #include <stdarg.h>
00055 #include "windef.h"
00056 #include "winbase.h"
00057 
00058 static void *ungif_alloc( size_t sz )
00059 {
00060     return HeapAlloc( GetProcessHeap(), 0, sz );
00061 }
00062 
00063 static void *ungif_calloc( size_t num, size_t sz )
00064 {
00065     return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, num*sz );
00066 }
00067 
00068 static void *ungif_realloc( void *ptr, size_t sz )
00069 {
00070     return HeapReAlloc( GetProcessHeap(), 0, ptr, sz );
00071 }
00072 
00073 static void ungif_free( void *ptr )
00074 {
00075     HeapFree( GetProcessHeap(), 0, ptr );
00076 }
00077 
00078 #define LZ_MAX_CODE         4095    /* Biggest code possible in 12 bits. */
00079 #define LZ_BITS             12
00080 
00081 #define NO_SUCH_CODE        4098    /* Impossible code, to signal empty. */
00082 
00083 typedef struct GifFilePrivateType {
00084     GifWord BitsPerPixel,     /* Bits per pixel (Codes uses at least this + 1). */
00085       ClearCode,   /* The CLEAR LZ code. */
00086       EOFCode,     /* The EOF LZ code. */
00087       RunningCode, /* The next code algorithm can generate. */
00088       RunningBits, /* The number of bits required to represent RunningCode. */
00089       MaxCode1,    /* 1 bigger than max. possible code, in RunningBits bits. */
00090       LastCode,    /* The code before the current code. */
00091       CrntCode,    /* Current algorithm code. */
00092       StackPtr,    /* For character stack (see below). */
00093       CrntShiftState;    /* Number of bits in CrntShiftDWord. */
00094     unsigned long CrntShiftDWord;   /* For bytes decomposition into codes. */
00095     unsigned long PixelCount;   /* Number of pixels in image. */
00096     InputFunc Read;     /* function to read gif input (TVT) */
00097     GifByteType Buf[256];   /* Compressed input is buffered here. */
00098     GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */
00099     GifByteType Suffix[LZ_MAX_CODE + 1];    /* So we can trace the codes. */
00100     GifPrefixType Prefix[LZ_MAX_CODE + 1];
00101 } GifFilePrivateType;
00102 
00103 /* avoid extra function call in case we use fread (TVT) */
00104 #define READ(_gif,_buf,_len) \
00105     ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len)
00106 
00107 static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
00108 static int DGifSetupDecompress(GifFileType *GifFile);
00109 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen);
00110 static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code, int ClearCode);
00111 static int DGifDecompressInput(GifFileType *GifFile, int *Code);
00112 static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
00113                              GifByteType *NextByte);
00114 
00115 static int DGifGetExtensionNext(GifFileType * GifFile, GifByteType ** GifExtension);
00116 static int DGifGetCodeNext(GifFileType * GifFile, GifByteType ** GifCodeBlock);
00117 
00118 /******************************************************************************
00119  * Miscellaneous utility functions
00120  *****************************************************************************/
00121 
00122 /* return smallest bitfield size n will fit in */
00123 static int
00124 BitSize(int n) {
00125 
00126     register int i;
00127 
00128     for (i = 1; i <= 8; i++)
00129         if ((1 << i) >= n)
00130             break;
00131     return (i);
00132 }
00133 
00134 /******************************************************************************
00135  * Color map object functions
00136  *****************************************************************************/
00137 
00138 /*
00139  * Allocate a color map of given size; initialize with contents of
00140  * ColorMap if that pointer is non-NULL.
00141  */
00142 static ColorMapObject *
00143 MakeMapObject(int ColorCount,
00144               const GifColorType * ColorMap) {
00145 
00146     ColorMapObject *Object;
00147 
00148     /*** FIXME: Our ColorCount has to be a power of two.  Is it necessary to
00149      * make the user know that or should we automatically round up instead? */
00150     if (ColorCount != (1 << BitSize(ColorCount))) {
00151         return NULL;
00152     }
00153 
00154     Object = ungif_alloc(sizeof(ColorMapObject));
00155     if (Object == NULL) {
00156         return NULL;
00157     }
00158 
00159     Object->Colors = ungif_calloc(ColorCount, sizeof(GifColorType));
00160     if (Object->Colors == NULL) {
00161         return NULL;
00162     }
00163 
00164     Object->ColorCount = ColorCount;
00165     Object->BitsPerPixel = BitSize(ColorCount);
00166 
00167     if (ColorMap) {
00168         memcpy(Object->Colors, ColorMap, ColorCount * sizeof(GifColorType));
00169     }
00170 
00171     return (Object);
00172 }
00173 
00174 /*
00175  * Free a color map object
00176  */
00177 static void
00178 FreeMapObject(ColorMapObject * Object) {
00179 
00180     if (Object != NULL) {
00181         ungif_free(Object->Colors);
00182         ungif_free(Object);
00183         /*** FIXME:
00184          * When we are willing to break API we need to make this function
00185          * FreeMapObject(ColorMapObject **Object)
00186          * and do this assignment to NULL here:
00187          * *Object = NULL;
00188          */
00189     }
00190 }
00191 
00192 static int
00193 AddExtensionBlock(SavedImage * New,
00194                   int Len,
00195                   const unsigned char ExtData[]) {
00196 
00197     ExtensionBlock *ep;
00198 
00199     if (New->ExtensionBlocks == NULL)
00200         New->ExtensionBlocks = ungif_alloc(sizeof(ExtensionBlock));
00201     else
00202         New->ExtensionBlocks = ungif_realloc(New->ExtensionBlocks,
00203                                       sizeof(ExtensionBlock) *
00204                                       (New->ExtensionBlockCount + 1));
00205 
00206     if (New->ExtensionBlocks == NULL)
00207         return (GIF_ERROR);
00208 
00209     ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
00210 
00211     ep->ByteCount=Len;
00212     ep->Bytes = ungif_alloc(ep->ByteCount);
00213     if (ep->Bytes == NULL)
00214         return (GIF_ERROR);
00215 
00216     if (ExtData) {
00217         memcpy(ep->Bytes, ExtData, Len);
00218         ep->Function = New->Function;
00219     }
00220 
00221     return (GIF_OK);
00222 }
00223 
00224 static void
00225 FreeExtension(SavedImage * Image)
00226 {
00227     ExtensionBlock *ep;
00228 
00229     if ((Image == NULL) || (Image->ExtensionBlocks == NULL)) {
00230         return;
00231     }
00232     for (ep = Image->ExtensionBlocks;
00233          ep < (Image->ExtensionBlocks + Image->ExtensionBlockCount); ep++)
00234         ungif_free(ep->Bytes);
00235     ungif_free(Image->ExtensionBlocks);
00236     Image->ExtensionBlocks = NULL;
00237 }
00238 
00239 /******************************************************************************
00240  * Image block allocation functions
00241 ******************************************************************************/
00242 
00243 static void
00244 FreeSavedImages(GifFileType * GifFile) {
00245 
00246     SavedImage *sp;
00247 
00248     if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
00249         return;
00250     }
00251     for (sp = GifFile->SavedImages;
00252          sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {
00253         if (sp->ImageDesc.ColorMap) {
00254             FreeMapObject(sp->ImageDesc.ColorMap);
00255             sp->ImageDesc.ColorMap = NULL;
00256         }
00257 
00258         ungif_free(sp->RasterBits);
00259 
00260         if (sp->ExtensionBlocks)
00261             FreeExtension(sp);
00262     }
00263     ungif_free(GifFile->SavedImages);
00264     GifFile->SavedImages=NULL;
00265 }
00266 
00267 /******************************************************************************
00268  * This routine should be called before any other DGif calls. Note that
00269  * this routine is called automatically from DGif file open routines.
00270  *****************************************************************************/
00271 static int
00272 DGifGetScreenDesc(GifFileType * GifFile) {
00273 
00274     int i, BitsPerPixel;
00275     GifByteType Buf[3];
00276 
00277     /* Put the screen descriptor into the file: */
00278     if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
00279         DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
00280         return GIF_ERROR;
00281 
00282     if (READ(GifFile, Buf, 3) != 3) {
00283         return GIF_ERROR;
00284     }
00285     GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
00286     BitsPerPixel = (Buf[0] & 0x07) + 1;
00287     GifFile->SBackGroundColor = Buf[1];
00288     if (Buf[0] & 0x80) {    /* Do we have global color map? */
00289 
00290         GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
00291         if (GifFile->SColorMap == NULL) {
00292             return GIF_ERROR;
00293         }
00294 
00295         /* Get the global color map: */
00296         for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
00297             if (READ(GifFile, Buf, 3) != 3) {
00298                 FreeMapObject(GifFile->SColorMap);
00299                 GifFile->SColorMap = NULL;
00300                 return GIF_ERROR;
00301             }
00302             GifFile->SColorMap->Colors[i].Red = Buf[0];
00303             GifFile->SColorMap->Colors[i].Green = Buf[1];
00304             GifFile->SColorMap->Colors[i].Blue = Buf[2];
00305         }
00306     } else {
00307         GifFile->SColorMap = NULL;
00308     }
00309 
00310     return GIF_OK;
00311 }
00312 
00313 /******************************************************************************
00314  * This routine should be called before any attempt to read an image.
00315  *****************************************************************************/
00316 static int
00317 DGifGetRecordType(GifFileType * GifFile,
00318                   GifRecordType * Type) {
00319 
00320     GifByteType Buf;
00321 
00322     if (READ(GifFile, &Buf, 1) != 1) {
00323         /* Wine-specific behavior: Native accepts broken GIF files that have no
00324          * terminator, so we match this by treating EOF as a terminator. */
00325         *Type = TERMINATE_RECORD_TYPE;
00326         return GIF_OK;
00327     }
00328 
00329     switch (Buf) {
00330       case ',':
00331           *Type = IMAGE_DESC_RECORD_TYPE;
00332           break;
00333       case '!':
00334           *Type = EXTENSION_RECORD_TYPE;
00335           break;
00336       case ';':
00337           *Type = TERMINATE_RECORD_TYPE;
00338           break;
00339       default:
00340           *Type = UNDEFINED_RECORD_TYPE;
00341           return GIF_ERROR;
00342     }
00343 
00344     return GIF_OK;
00345 }
00346 
00347 /******************************************************************************
00348  * This routine should be called before any attempt to read an image.
00349  * Note it is assumed the Image desc. header (',') has been read.
00350  *****************************************************************************/
00351 static int
00352 DGifGetImageDesc(GifFileType * GifFile) {
00353 
00354     int i, BitsPerPixel;
00355     GifByteType Buf[3];
00356     GifFilePrivateType *Private = GifFile->Private;
00357     SavedImage *sp;
00358 
00359     if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
00360         DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
00361         DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
00362         DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
00363         return GIF_ERROR;
00364     if (READ(GifFile, Buf, 1) != 1) {
00365         return GIF_ERROR;
00366     }
00367     BitsPerPixel = (Buf[0] & 0x07) + 1;
00368     GifFile->Image.Interlace = (Buf[0] & 0x40);
00369     if (Buf[0] & 0x80) {    /* Does this image have local color map? */
00370 
00371         /*** FIXME: Why do we check both of these in order to do this?
00372          * Why do we have both Image and SavedImages? */
00373         if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
00374             FreeMapObject(GifFile->Image.ColorMap);
00375 
00376         GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
00377         if (GifFile->Image.ColorMap == NULL) {
00378             return GIF_ERROR;
00379         }
00380 
00381         /* Get the image local color map: */
00382         for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
00383             if (READ(GifFile, Buf, 3) != 3) {
00384                 FreeMapObject(GifFile->Image.ColorMap);
00385                 GifFile->Image.ColorMap = NULL;
00386                 return GIF_ERROR;
00387             }
00388             GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
00389             GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
00390             GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
00391         }
00392     } else if (GifFile->Image.ColorMap) {
00393         FreeMapObject(GifFile->Image.ColorMap);
00394         GifFile->Image.ColorMap = NULL;
00395     }
00396 
00397     if (GifFile->SavedImages) {
00398         if ((GifFile->SavedImages = ungif_realloc(GifFile->SavedImages,
00399                                       sizeof(SavedImage) *
00400                                       (GifFile->ImageCount + 1))) == NULL) {
00401             return GIF_ERROR;
00402         }
00403     } else {
00404         if ((GifFile->SavedImages = ungif_alloc(sizeof(SavedImage))) == NULL) {
00405             return GIF_ERROR;
00406         }
00407     }
00408 
00409     sp = &GifFile->SavedImages[GifFile->ImageCount];
00410     sp->ImageDesc = GifFile->Image;
00411     if (GifFile->Image.ColorMap != NULL) {
00412         sp->ImageDesc.ColorMap = MakeMapObject(
00413                                  GifFile->Image.ColorMap->ColorCount,
00414                                  GifFile->Image.ColorMap->Colors);
00415         if (sp->ImageDesc.ColorMap == NULL) {
00416             return GIF_ERROR;
00417         }
00418     }
00419     sp->RasterBits = NULL;
00420     sp->ExtensionBlockCount = 0;
00421     sp->ExtensionBlocks = NULL;
00422 
00423     GifFile->ImageCount++;
00424 
00425     Private->PixelCount = (long)GifFile->Image.Width *
00426        (long)GifFile->Image.Height;
00427 
00428     DGifSetupDecompress(GifFile);  /* Reset decompress algorithm parameters. */
00429 
00430     return GIF_OK;
00431 }
00432 
00433 /******************************************************************************
00434  * Get one full scanned line (Line) of length LineLen from GIF file.
00435  *****************************************************************************/
00436 static int
00437 DGifGetLine(GifFileType * GifFile,
00438             GifPixelType * Line,
00439             int LineLen) {
00440 
00441     GifByteType *Dummy;
00442     GifFilePrivateType *Private = GifFile->Private;
00443 
00444     if (!LineLen)
00445         LineLen = GifFile->Image.Width;
00446 
00447     if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
00448         return GIF_ERROR;
00449     }
00450 
00451     if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
00452         if (Private->PixelCount == 0) {
00453             /* We probably would not be called any more, so lets clean
00454              * everything before we return: need to flush out all rest of
00455              * image until empty block (size 0) detected. We use GetCodeNext. */
00456             do
00457                 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
00458                     return GIF_ERROR;
00459             while (Dummy != NULL) ;
00460         }
00461         return GIF_OK;
00462     } else
00463         return GIF_ERROR;
00464 }
00465 
00466 /******************************************************************************
00467  * Get an extension block (see GIF manual) from gif file. This routine only
00468  * returns the first data block, and DGifGetExtensionNext should be called
00469  * after this one until NULL extension is returned.
00470  * The Extension should NOT be freed by the user (not dynamically allocated).
00471  * Note it is assumed the Extension desc. header ('!') has been read.
00472  *****************************************************************************/
00473 static int
00474 DGifGetExtension(GifFileType * GifFile,
00475                  int *ExtCode,
00476                  GifByteType ** Extension) {
00477 
00478     GifByteType Buf;
00479 
00480     if (READ(GifFile, &Buf, 1) != 1) {
00481         return GIF_ERROR;
00482     }
00483     *ExtCode = Buf;
00484 
00485     return DGifGetExtensionNext(GifFile, Extension);
00486 }
00487 
00488 /******************************************************************************
00489  * Get a following extension block (see GIF manual) from gif file. This
00490  * routine should be called until NULL Extension is returned.
00491  * The Extension should NOT be freed by the user (not dynamically allocated).
00492  *****************************************************************************/
00493 static int
00494 DGifGetExtensionNext(GifFileType * GifFile,
00495                      GifByteType ** Extension) {
00496 
00497     GifByteType Buf;
00498     GifFilePrivateType *Private = GifFile->Private;
00499 
00500     if (READ(GifFile, &Buf, 1) != 1) {
00501         return GIF_ERROR;
00502     }
00503     if (Buf > 0) {
00504         *Extension = Private->Buf;    /* Use private unused buffer. */
00505         (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
00506         if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
00507             return GIF_ERROR;
00508         }
00509     } else
00510         *Extension = NULL;
00511 
00512     return GIF_OK;
00513 }
00514 
00515 /******************************************************************************
00516  * Get 2 bytes (word) from the given file:
00517  *****************************************************************************/
00518 static int
00519 DGifGetWord(GifFileType * GifFile,
00520             GifWord *Word) {
00521 
00522     unsigned char c[2];
00523 
00524     if (READ(GifFile, c, 2) != 2) {
00525         return GIF_ERROR;
00526     }
00527 
00528     *Word = (((unsigned int)c[1]) << 8) + c[0];
00529     return GIF_OK;
00530 }
00531 
00532 /******************************************************************************
00533  * Continue to get the image code in compressed form. This routine should be
00534  * called until NULL block is returned.
00535  * The block should NOT be freed by the user (not dynamically allocated).
00536  *****************************************************************************/
00537 static int
00538 DGifGetCodeNext(GifFileType * GifFile,
00539                 GifByteType ** CodeBlock) {
00540 
00541     GifByteType Buf;
00542     GifFilePrivateType *Private = GifFile->Private;
00543 
00544     if (READ(GifFile, &Buf, 1) != 1) {
00545         return GIF_ERROR;
00546     }
00547 
00548     if (Buf > 0) {
00549         *CodeBlock = Private->Buf;    /* Use private unused buffer. */
00550         (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
00551         if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
00552             return GIF_ERROR;
00553         }
00554     } else {
00555         *CodeBlock = NULL;
00556         Private->Buf[0] = 0;    /* Make sure the buffer is empty! */
00557         Private->PixelCount = 0;    /* And local info. indicate image read. */
00558     }
00559 
00560     return GIF_OK;
00561 }
00562 
00563 /******************************************************************************
00564  * Setup the LZ decompression for this image:
00565  *****************************************************************************/
00566 static int
00567 DGifSetupDecompress(GifFileType * GifFile) {
00568 
00569     int i, BitsPerPixel;
00570     GifByteType CodeSize;
00571     GifPrefixType *Prefix;
00572     GifFilePrivateType *Private = GifFile->Private;
00573 
00574     READ(GifFile, &CodeSize, 1);    /* Read Code size from file. */
00575     BitsPerPixel = CodeSize;
00576 
00577     Private->Buf[0] = 0;    /* Input Buffer empty. */
00578     Private->BitsPerPixel = BitsPerPixel;
00579     Private->ClearCode = (1 << BitsPerPixel);
00580     Private->EOFCode = Private->ClearCode + 1;
00581     Private->RunningCode = Private->EOFCode + 1;
00582     Private->RunningBits = BitsPerPixel + 1;    /* Number of bits per code. */
00583     Private->MaxCode1 = 1 << Private->RunningBits;    /* Max. code + 1. */
00584     Private->StackPtr = 0;    /* No pixels on the pixel stack. */
00585     Private->LastCode = NO_SUCH_CODE;
00586     Private->CrntShiftState = 0;    /* No information in CrntShiftDWord. */
00587     Private->CrntShiftDWord = 0;
00588 
00589     Prefix = Private->Prefix;
00590     for (i = 0; i <= LZ_MAX_CODE; i++)
00591         Prefix[i] = NO_SUCH_CODE;
00592 
00593     return GIF_OK;
00594 }
00595 
00596 /******************************************************************************
00597  * The LZ decompression routine:
00598  * This version decompress the given gif file into Line of length LineLen.
00599  * This routine can be called few times (one per scan line, for example), in
00600  * order the complete the whole image.
00601  *****************************************************************************/
00602 static int
00603 DGifDecompressLine(GifFileType * GifFile,
00604                    GifPixelType * Line,
00605                    int LineLen) {
00606 
00607     int i = 0;
00608     int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
00609     GifByteType *Stack, *Suffix;
00610     GifPrefixType *Prefix;
00611     GifFilePrivateType *Private = GifFile->Private;
00612 
00613     StackPtr = Private->StackPtr;
00614     Prefix = Private->Prefix;
00615     Suffix = Private->Suffix;
00616     Stack = Private->Stack;
00617     EOFCode = Private->EOFCode;
00618     ClearCode = Private->ClearCode;
00619     LastCode = Private->LastCode;
00620 
00621     if (StackPtr != 0) {
00622         /* Let pop the stack off before continuing to read the gif file: */
00623         while (StackPtr != 0 && i < LineLen)
00624             Line[i++] = Stack[--StackPtr];
00625     }
00626 
00627     while (i < LineLen) {    /* Decode LineLen items. */
00628         if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
00629             return GIF_ERROR;
00630 
00631         if (CrntCode == EOFCode) {
00632             /* Note, however, that usually we will not be here as we will stop
00633              * decoding as soon as we got all the pixel, or EOF code will
00634              * not be read at all, and DGifGetLine/Pixel clean everything.  */
00635             if (i != LineLen - 1 || Private->PixelCount != 0) {
00636                 return GIF_ERROR;
00637             }
00638             i++;
00639         } else if (CrntCode == ClearCode) {
00640             /* We need to start over again: */
00641             for (j = 0; j <= LZ_MAX_CODE; j++)
00642                 Prefix[j] = NO_SUCH_CODE;
00643             Private->RunningCode = Private->EOFCode + 1;
00644             Private->RunningBits = Private->BitsPerPixel + 1;
00645             Private->MaxCode1 = 1 << Private->RunningBits;
00646             LastCode = Private->LastCode = NO_SUCH_CODE;
00647         } else {
00648             /* It's a regular code - if in pixel range simply add it to output
00649              * stream, otherwise trace to codes linked list until the prefix
00650              * is in pixel range: */
00651             if (CrntCode < ClearCode) {
00652                 /* This is simple - its pixel scalar, so add it to output: */
00653                 Line[i++] = CrntCode;
00654             } else {
00655                 /* It's a code to be traced: trace the linked list
00656                  * until the prefix is a pixel, while pushing the suffix
00657                  * pixels on our stack. If we done, pop the stack in reverse
00658                  * order (that's what stack is good for!) for output.  */
00659                 if (Prefix[CrntCode] == NO_SUCH_CODE) {
00660                     /* Only allowed if CrntCode is exactly the running code:
00661                      * In that case CrntCode = XXXCode, CrntCode or the
00662                      * prefix code is last code and the suffix char is
00663                      * exactly the prefix of last code! */
00664                     if (CrntCode == Private->RunningCode - 2) {
00665                         CrntPrefix = LastCode;
00666                         Suffix[Private->RunningCode - 2] =
00667                            Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
00668                                                                  LastCode,
00669                                                                  ClearCode);
00670                     } else {
00671                         return GIF_ERROR;
00672                     }
00673                 } else
00674                     CrntPrefix = CrntCode;
00675 
00676                 /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
00677                  * during the trace. As we might loop forever, in case of
00678                  * defective image, we count the number of loops we trace
00679                  * and stop if we got LZ_MAX_CODE. Obviously we cannot
00680                  * loop more than that.  */
00681                 j = 0;
00682                 while (j++ <= LZ_MAX_CODE &&
00683                        CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
00684                     Stack[StackPtr++] = Suffix[CrntPrefix];
00685                     CrntPrefix = Prefix[CrntPrefix];
00686                 }
00687                 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
00688                     return GIF_ERROR;
00689                 }
00690                 /* Push the last character on stack: */
00691                 Stack[StackPtr++] = CrntPrefix;
00692 
00693                 /* Now lets pop all the stack into output: */
00694                 while (StackPtr != 0 && i < LineLen)
00695                     Line[i++] = Stack[--StackPtr];
00696             }
00697             if (LastCode != NO_SUCH_CODE) {
00698                 Prefix[Private->RunningCode - 2] = LastCode;
00699 
00700                 if (CrntCode == Private->RunningCode - 2) {
00701                     /* Only allowed if CrntCode is exactly the running code:
00702                      * In that case CrntCode = XXXCode, CrntCode or the
00703                      * prefix code is last code and the suffix char is
00704                      * exactly the prefix of last code! */
00705                     Suffix[Private->RunningCode - 2] =
00706                        DGifGetPrefixChar(Prefix, LastCode, ClearCode);
00707                 } else {
00708                     Suffix[Private->RunningCode - 2] =
00709                        DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
00710                 }
00711             }
00712             LastCode = CrntCode;
00713         }
00714     }
00715 
00716     Private->LastCode = LastCode;
00717     Private->StackPtr = StackPtr;
00718 
00719     return GIF_OK;
00720 }
00721 
00722 /******************************************************************************
00723  * Routine to trace the Prefixes linked list until we get a prefix which is
00724  * not code, but a pixel value (less than ClearCode). Returns that pixel value.
00725  * If image is defective, we might loop here forever, so we limit the loops to
00726  * the maximum possible if image O.k. - LZ_MAX_CODE times.
00727  *****************************************************************************/
00728 static int
00729 DGifGetPrefixChar(const GifPrefixType *Prefix,
00730                   int Code,
00731                   int ClearCode) {
00732 
00733     int i = 0;
00734 
00735     while (Code > ClearCode && i++ <= LZ_MAX_CODE)
00736         Code = Prefix[Code];
00737     return Code;
00738 }
00739 
00740 /******************************************************************************
00741  * The LZ decompression input routine:
00742  * This routine is responsible for the decompression of the bit stream from
00743  * 8 bits (bytes) packets, into the real codes.
00744  * Returns GIF_OK if read successfully.
00745  *****************************************************************************/
00746 static int
00747 DGifDecompressInput(GifFileType * GifFile,
00748                     int *Code) {
00749 
00750     GifFilePrivateType *Private = GifFile->Private;
00751 
00752     GifByteType NextByte;
00753     static const unsigned short CodeMasks[] = {
00754         0x0000, 0x0001, 0x0003, 0x0007,
00755         0x000f, 0x001f, 0x003f, 0x007f,
00756         0x00ff, 0x01ff, 0x03ff, 0x07ff,
00757         0x0fff
00758     };
00759     /* The image can't contain more than LZ_BITS per code. */
00760     if (Private->RunningBits > LZ_BITS) {
00761         return GIF_ERROR;
00762     }
00763 
00764     while (Private->CrntShiftState < Private->RunningBits) {
00765         /* Needs to get more bytes from input stream for next code: */
00766         if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
00767             return GIF_ERROR;
00768         }
00769         Private->CrntShiftDWord |=
00770            ((unsigned long)NextByte) << Private->CrntShiftState;
00771         Private->CrntShiftState += 8;
00772     }
00773     *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
00774 
00775     Private->CrntShiftDWord >>= Private->RunningBits;
00776     Private->CrntShiftState -= Private->RunningBits;
00777 
00778     /* If code cannot fit into RunningBits bits, must raise its size. Note
00779      * however that codes above 4095 are used for special signaling.
00780      * If we're using LZ_BITS bits already and we're at the max code, just
00781      * keep using the table as it is, don't increment Private->RunningCode.
00782      */
00783     if (Private->RunningCode < LZ_MAX_CODE + 2 &&
00784             ++Private->RunningCode > Private->MaxCode1 &&
00785             Private->RunningBits < LZ_BITS) {
00786         Private->MaxCode1 <<= 1;
00787         Private->RunningBits++;
00788     }
00789     return GIF_OK;
00790 }
00791 
00792 /******************************************************************************
00793  * This routines read one gif data block at a time and buffers it internally
00794  * so that the decompression routine could access it.
00795  * The routine returns the next byte from its internal buffer (or read next
00796  * block in if buffer empty) and returns GIF_OK if successful.
00797  *****************************************************************************/
00798 static int
00799 DGifBufferedInput(GifFileType * GifFile,
00800                   GifByteType * Buf,
00801                   GifByteType * NextByte) {
00802 
00803     if (Buf[0] == 0) {
00804         /* Needs to read the next buffer - this one is empty: */
00805         if (READ(GifFile, Buf, 1) != 1) {
00806             return GIF_ERROR;
00807         }
00808         /* There shouldn't be any empty data blocks here as the LZW spec
00809          * says the LZW termination code should come first.  Therefore we
00810          * shouldn't be inside this routine at that point.
00811          */
00812         if (Buf[0] == 0) {
00813             return GIF_ERROR;
00814         }
00815         if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
00816             return GIF_ERROR;
00817         }
00818         *NextByte = Buf[1];
00819         Buf[1] = 2;    /* We use now the second place as last char read! */
00820         Buf[0]--;
00821     } else {
00822         *NextByte = Buf[Buf[1]++];
00823         Buf[0]--;
00824     }
00825 
00826     return GIF_OK;
00827 }
00828 
00829 /******************************************************************************
00830  * This routine reads an entire GIF into core, hanging all its state info off
00831  * the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()
00832  * first to initialize I/O.  Its inverse is EGifSpew().
00833  ******************************************************************************/
00834 int
00835 DGifSlurp(GifFileType * GifFile) {
00836 
00837     int ImageSize;
00838     GifRecordType RecordType;
00839     SavedImage *sp;
00840     GifByteType *ExtData;
00841     SavedImage temp_save;
00842 
00843     temp_save.ExtensionBlocks = NULL;
00844     temp_save.ExtensionBlockCount = 0;
00845 
00846     do {
00847         if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
00848             return (GIF_ERROR);
00849 
00850         switch (RecordType) {
00851           case IMAGE_DESC_RECORD_TYPE:
00852               if (DGifGetImageDesc(GifFile) == GIF_ERROR)
00853                   return (GIF_ERROR);
00854 
00855               sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
00856               ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
00857 
00858               sp->RasterBits = ungif_alloc(ImageSize * sizeof(GifPixelType));
00859               if (sp->RasterBits == NULL) {
00860                   return GIF_ERROR;
00861               }
00862               if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) ==
00863                   GIF_ERROR)
00864                   return (GIF_ERROR);
00865               if (temp_save.ExtensionBlocks) {
00866                   sp->ExtensionBlocks = temp_save.ExtensionBlocks;
00867                   sp->ExtensionBlockCount = temp_save.ExtensionBlockCount;
00868 
00869                   temp_save.ExtensionBlocks = NULL;
00870                   temp_save.ExtensionBlockCount = 0;
00871 
00872                   /* FIXME: The following is wrong.  It is left in only for
00873                    * backwards compatibility.  Someday it should go away. Use
00874                    * the sp->ExtensionBlocks->Function variable instead. */
00875                   sp->Function = sp->ExtensionBlocks[0].Function;
00876               }
00877               break;
00878 
00879           case EXTENSION_RECORD_TYPE:
00880               if (DGifGetExtension(GifFile, &temp_save.Function, &ExtData) ==
00881                   GIF_ERROR)
00882                   return (GIF_ERROR);
00883               while (ExtData != NULL) {
00884 
00885                   /* Create an extension block with our data */
00886                   if (AddExtensionBlock(&temp_save, ExtData[0], &ExtData[1])
00887                       == GIF_ERROR)
00888                       return (GIF_ERROR);
00889 
00890                   if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
00891                       return (GIF_ERROR);
00892                   temp_save.Function = 0;
00893               }
00894               break;
00895 
00896           case TERMINATE_RECORD_TYPE:
00897               break;
00898 
00899           default:    /* Should be trapped by DGifGetRecordType */
00900               break;
00901         }
00902     } while (RecordType != TERMINATE_RECORD_TYPE);
00903 
00904     /* Just in case the Gif has an extension block without an associated
00905      * image... (Should we save this into a savefile structure with no image
00906      * instead? Have to check if the present writing code can handle that as
00907      * well.... */
00908     if (temp_save.ExtensionBlocks)
00909         FreeExtension(&temp_save);
00910 
00911     return (GIF_OK);
00912 }
00913 
00914 /******************************************************************************
00915  * GifFileType constructor with user supplied input function (TVT)
00916  *****************************************************************************/
00917 GifFileType *
00918 DGifOpen(void *userData,
00919          InputFunc readFunc) {
00920 
00921     unsigned char Buf[GIF_STAMP_LEN + 1];
00922     GifFileType *GifFile;
00923     GifFilePrivateType *Private;
00924 
00925     GifFile = ungif_alloc(sizeof(GifFileType));
00926     if (GifFile == NULL) {
00927         return NULL;
00928     }
00929 
00930     memset(GifFile, '\0', sizeof(GifFileType));
00931 
00932     Private = ungif_alloc(sizeof(GifFilePrivateType));
00933     if (!Private) {
00934         ungif_free(GifFile);
00935         return NULL;
00936     }
00937 
00938     GifFile->Private = (void*)Private;
00939 
00940     Private->Read = readFunc;    /* TVT */
00941     GifFile->UserData = userData;    /* TVT */
00942 
00943     /* Lets see if this is a GIF file: */
00944     if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
00945         ungif_free(Private);
00946         ungif_free(GifFile);
00947         return NULL;
00948     }
00949 
00950     /* The GIF Version number is ignored at this time. Maybe we should do
00951      * something more useful with it. */
00952     Buf[GIF_STAMP_LEN] = 0;
00953     if (memcmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
00954         ungif_free(Private);
00955         ungif_free(GifFile);
00956         return NULL;
00957     }
00958 
00959     if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
00960         ungif_free(Private);
00961         ungif_free(GifFile);
00962         return NULL;
00963     }
00964 
00965     return GifFile;
00966 }
00967 
00968 /******************************************************************************
00969  * This routine should be called last, to close the GIF file.
00970  *****************************************************************************/
00971 int
00972 DGifCloseFile(GifFileType * GifFile) {
00973 
00974     GifFilePrivateType *Private;
00975 
00976     if (GifFile == NULL)
00977         return GIF_ERROR;
00978 
00979     Private = GifFile->Private;
00980 
00981     if (GifFile->Image.ColorMap) {
00982         FreeMapObject(GifFile->Image.ColorMap);
00983         GifFile->Image.ColorMap = NULL;
00984     }
00985 
00986     if (GifFile->SColorMap) {
00987         FreeMapObject(GifFile->SColorMap);
00988         GifFile->SColorMap = NULL;
00989     }
00990 
00991     ungif_free(Private);
00992     Private = NULL;
00993 
00994     if (GifFile->SavedImages) {
00995         FreeSavedImages(GifFile);
00996         GifFile->SavedImages = NULL;
00997     }
00998 
00999     ungif_free(GifFile);
01000 
01001     return GIF_OK;
01002 }

Generated on Sun May 27 2012 04:25:47 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.