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         return GIF_ERROR;
00324     }
00325 
00326     switch (Buf) {
00327       case ',':
00328           *Type = IMAGE_DESC_RECORD_TYPE;
00329           break;
00330       case '!':
00331           *Type = EXTENSION_RECORD_TYPE;
00332           break;
00333       case ';':
00334           *Type = TERMINATE_RECORD_TYPE;
00335           break;
00336       default:
00337           *Type = UNDEFINED_RECORD_TYPE;
00338           return GIF_ERROR;
00339     }
00340 
00341     return GIF_OK;
00342 }
00343 
00344 /******************************************************************************
00345  * This routine should be called before any attempt to read an image.
00346  * Note it is assumed the Image desc. header (',') has been read.
00347  *****************************************************************************/
00348 static int
00349 DGifGetImageDesc(GifFileType * GifFile) {
00350 
00351     int i, BitsPerPixel;
00352     GifByteType Buf[3];
00353     GifFilePrivateType *Private = GifFile->Private;
00354     SavedImage *sp;
00355 
00356     if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
00357         DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
00358         DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
00359         DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
00360         return GIF_ERROR;
00361     if (READ(GifFile, Buf, 1) != 1) {
00362         return GIF_ERROR;
00363     }
00364     BitsPerPixel = (Buf[0] & 0x07) + 1;
00365     GifFile->Image.Interlace = (Buf[0] & 0x40);
00366     if (Buf[0] & 0x80) {    /* Does this image have local color map? */
00367 
00368         /*** FIXME: Why do we check both of these in order to do this?
00369          * Why do we have both Image and SavedImages? */
00370         if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
00371             FreeMapObject(GifFile->Image.ColorMap);
00372 
00373         GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
00374         if (GifFile->Image.ColorMap == NULL) {
00375             return GIF_ERROR;
00376         }
00377 
00378         /* Get the image local color map: */
00379         for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
00380             if (READ(GifFile, Buf, 3) != 3) {
00381                 FreeMapObject(GifFile->Image.ColorMap);
00382                 GifFile->Image.ColorMap = NULL;
00383                 return GIF_ERROR;
00384             }
00385             GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
00386             GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
00387             GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
00388         }
00389     } else if (GifFile->Image.ColorMap) {
00390         FreeMapObject(GifFile->Image.ColorMap);
00391         GifFile->Image.ColorMap = NULL;
00392     }
00393 
00394     if (GifFile->SavedImages) {
00395         if ((GifFile->SavedImages = ungif_realloc(GifFile->SavedImages,
00396                                       sizeof(SavedImage) *
00397                                       (GifFile->ImageCount + 1))) == NULL) {
00398             return GIF_ERROR;
00399         }
00400     } else {
00401         if ((GifFile->SavedImages = ungif_alloc(sizeof(SavedImage))) == NULL) {
00402             return GIF_ERROR;
00403         }
00404     }
00405 
00406     sp = &GifFile->SavedImages[GifFile->ImageCount];
00407     sp->ImageDesc = GifFile->Image;
00408     if (GifFile->Image.ColorMap != NULL) {
00409         sp->ImageDesc.ColorMap = MakeMapObject(
00410                                  GifFile->Image.ColorMap->ColorCount,
00411                                  GifFile->Image.ColorMap->Colors);
00412         if (sp->ImageDesc.ColorMap == NULL) {
00413             return GIF_ERROR;
00414         }
00415     }
00416     sp->RasterBits = NULL;
00417     sp->ExtensionBlockCount = 0;
00418     sp->ExtensionBlocks = NULL;
00419 
00420     GifFile->ImageCount++;
00421 
00422     Private->PixelCount = (long)GifFile->Image.Width *
00423        (long)GifFile->Image.Height;
00424 
00425     DGifSetupDecompress(GifFile);  /* Reset decompress algorithm parameters. */
00426 
00427     return GIF_OK;
00428 }
00429 
00430 /******************************************************************************
00431  * Get one full scanned line (Line) of length LineLen from GIF file.
00432  *****************************************************************************/
00433 static int
00434 DGifGetLine(GifFileType * GifFile,
00435             GifPixelType * Line,
00436             int LineLen) {
00437 
00438     GifByteType *Dummy;
00439     GifFilePrivateType *Private = GifFile->Private;
00440 
00441     if (!LineLen)
00442         LineLen = GifFile->Image.Width;
00443 
00444     if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
00445         return GIF_ERROR;
00446     }
00447 
00448     if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
00449         if (Private->PixelCount == 0) {
00450             /* We probably would not be called any more, so lets clean
00451              * everything before we return: need to flush out all rest of
00452              * image until empty block (size 0) detected. We use GetCodeNext. */
00453             do
00454                 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
00455                     return GIF_ERROR;
00456             while (Dummy != NULL) ;
00457         }
00458         return GIF_OK;
00459     } else
00460         return GIF_ERROR;
00461 }
00462 
00463 /******************************************************************************
00464  * Get an extension block (see GIF manual) from gif file. This routine only
00465  * returns the first data block, and DGifGetExtensionNext should be called
00466  * after this one until NULL extension is returned.
00467  * The Extension should NOT be freed by the user (not dynamically allocated).
00468  * Note it is assumed the Extension desc. header ('!') has been read.
00469  *****************************************************************************/
00470 static int
00471 DGifGetExtension(GifFileType * GifFile,
00472                  int *ExtCode,
00473                  GifByteType ** Extension) {
00474 
00475     GifByteType Buf;
00476 
00477     if (READ(GifFile, &Buf, 1) != 1) {
00478         return GIF_ERROR;
00479     }
00480     *ExtCode = Buf;
00481 
00482     return DGifGetExtensionNext(GifFile, Extension);
00483 }
00484 
00485 /******************************************************************************
00486  * Get a following extension block (see GIF manual) from gif file. This
00487  * routine should be called until NULL Extension is returned.
00488  * The Extension should NOT be freed by the user (not dynamically allocated).
00489  *****************************************************************************/
00490 static int
00491 DGifGetExtensionNext(GifFileType * GifFile,
00492                      GifByteType ** Extension) {
00493 
00494     GifByteType Buf;
00495     GifFilePrivateType *Private = GifFile->Private;
00496 
00497     if (READ(GifFile, &Buf, 1) != 1) {
00498         return GIF_ERROR;
00499     }
00500     if (Buf > 0) {
00501         *Extension = Private->Buf;    /* Use private unused buffer. */
00502         (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
00503         if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
00504             return GIF_ERROR;
00505         }
00506     } else
00507         *Extension = NULL;
00508 
00509     return GIF_OK;
00510 }
00511 
00512 /******************************************************************************
00513  * Get 2 bytes (word) from the given file:
00514  *****************************************************************************/
00515 static int
00516 DGifGetWord(GifFileType * GifFile,
00517             GifWord *Word) {
00518 
00519     unsigned char c[2];
00520 
00521     if (READ(GifFile, c, 2) != 2) {
00522         return GIF_ERROR;
00523     }
00524 
00525     *Word = (((unsigned int)c[1]) << 8) + c[0];
00526     return GIF_OK;
00527 }
00528 
00529 /******************************************************************************
00530  * Continue to get the image code in compressed form. This routine should be
00531  * called until NULL block is returned.
00532  * The block should NOT be freed by the user (not dynamically allocated).
00533  *****************************************************************************/
00534 static int
00535 DGifGetCodeNext(GifFileType * GifFile,
00536                 GifByteType ** CodeBlock) {
00537 
00538     GifByteType Buf;
00539     GifFilePrivateType *Private = GifFile->Private;
00540 
00541     if (READ(GifFile, &Buf, 1) != 1) {
00542         return GIF_ERROR;
00543     }
00544 
00545     if (Buf > 0) {
00546         *CodeBlock = Private->Buf;    /* Use private unused buffer. */
00547         (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
00548         if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
00549             return GIF_ERROR;
00550         }
00551     } else {
00552         *CodeBlock = NULL;
00553         Private->Buf[0] = 0;    /* Make sure the buffer is empty! */
00554         Private->PixelCount = 0;    /* And local info. indicate image read. */
00555     }
00556 
00557     return GIF_OK;
00558 }
00559 
00560 /******************************************************************************
00561  * Setup the LZ decompression for this image:
00562  *****************************************************************************/
00563 static int
00564 DGifSetupDecompress(GifFileType * GifFile) {
00565 
00566     int i, BitsPerPixel;
00567     GifByteType CodeSize;
00568     GifPrefixType *Prefix;
00569     GifFilePrivateType *Private = GifFile->Private;
00570 
00571     READ(GifFile, &CodeSize, 1);    /* Read Code size from file. */
00572     BitsPerPixel = CodeSize;
00573 
00574     Private->Buf[0] = 0;    /* Input Buffer empty. */
00575     Private->BitsPerPixel = BitsPerPixel;
00576     Private->ClearCode = (1 << BitsPerPixel);
00577     Private->EOFCode = Private->ClearCode + 1;
00578     Private->RunningCode = Private->EOFCode + 1;
00579     Private->RunningBits = BitsPerPixel + 1;    /* Number of bits per code. */
00580     Private->MaxCode1 = 1 << Private->RunningBits;    /* Max. code + 1. */
00581     Private->StackPtr = 0;    /* No pixels on the pixel stack. */
00582     Private->LastCode = NO_SUCH_CODE;
00583     Private->CrntShiftState = 0;    /* No information in CrntShiftDWord. */
00584     Private->CrntShiftDWord = 0;
00585 
00586     Prefix = Private->Prefix;
00587     for (i = 0; i <= LZ_MAX_CODE; i++)
00588         Prefix[i] = NO_SUCH_CODE;
00589 
00590     return GIF_OK;
00591 }
00592 
00593 /******************************************************************************
00594  * The LZ decompression routine:
00595  * This version decompress the given gif file into Line of length LineLen.
00596  * This routine can be called few times (one per scan line, for example), in
00597  * order the complete the whole image.
00598  *****************************************************************************/
00599 static int
00600 DGifDecompressLine(GifFileType * GifFile,
00601                    GifPixelType * Line,
00602                    int LineLen) {
00603 
00604     int i = 0;
00605     int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
00606     GifByteType *Stack, *Suffix;
00607     GifPrefixType *Prefix;
00608     GifFilePrivateType *Private = GifFile->Private;
00609 
00610     StackPtr = Private->StackPtr;
00611     Prefix = Private->Prefix;
00612     Suffix = Private->Suffix;
00613     Stack = Private->Stack;
00614     EOFCode = Private->EOFCode;
00615     ClearCode = Private->ClearCode;
00616     LastCode = Private->LastCode;
00617 
00618     if (StackPtr != 0) {
00619         /* Let pop the stack off before continuing to read the gif file: */
00620         while (StackPtr != 0 && i < LineLen)
00621             Line[i++] = Stack[--StackPtr];
00622     }
00623 
00624     while (i < LineLen) {    /* Decode LineLen items. */
00625         if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
00626             return GIF_ERROR;
00627 
00628         if (CrntCode == EOFCode) {
00629             /* Note, however, that usually we will not be here as we will stop
00630              * decoding as soon as we got all the pixel, or EOF code will
00631              * not be read at all, and DGifGetLine/Pixel clean everything.  */
00632             if (i != LineLen - 1 || Private->PixelCount != 0) {
00633                 return GIF_ERROR;
00634             }
00635             i++;
00636         } else if (CrntCode == ClearCode) {
00637             /* We need to start over again: */
00638             for (j = 0; j <= LZ_MAX_CODE; j++)
00639                 Prefix[j] = NO_SUCH_CODE;
00640             Private->RunningCode = Private->EOFCode + 1;
00641             Private->RunningBits = Private->BitsPerPixel + 1;
00642             Private->MaxCode1 = 1 << Private->RunningBits;
00643             LastCode = Private->LastCode = NO_SUCH_CODE;
00644         } else {
00645             /* It's a regular code - if in pixel range simply add it to output
00646              * stream, otherwise trace to codes linked list until the prefix
00647              * is in pixel range: */
00648             if (CrntCode < ClearCode) {
00649                 /* This is simple - its pixel scalar, so add it to output: */
00650                 Line[i++] = CrntCode;
00651             } else {
00652                 /* It's a code to be traced: trace the linked list
00653                  * until the prefix is a pixel, while pushing the suffix
00654                  * pixels on our stack. If we done, pop the stack in reverse
00655                  * order (that's what stack is good for!) for output.  */
00656                 if (Prefix[CrntCode] == NO_SUCH_CODE) {
00657                     /* Only allowed if CrntCode is exactly the running code:
00658                      * In that case CrntCode = XXXCode, CrntCode or the
00659                      * prefix code is last code and the suffix char is
00660                      * exactly the prefix of last code! */
00661                     if (CrntCode == Private->RunningCode - 2) {
00662                         CrntPrefix = LastCode;
00663                         Suffix[Private->RunningCode - 2] =
00664                            Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
00665                                                                  LastCode,
00666                                                                  ClearCode);
00667                     } else {
00668                         return GIF_ERROR;
00669                     }
00670                 } else
00671                     CrntPrefix = CrntCode;
00672 
00673                 /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
00674                  * during the trace. As we might loop forever, in case of
00675                  * defective image, we count the number of loops we trace
00676                  * and stop if we got LZ_MAX_CODE. Obviously we cannot
00677                  * loop more than that.  */
00678                 j = 0;
00679                 while (j++ <= LZ_MAX_CODE &&
00680                        CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
00681                     Stack[StackPtr++] = Suffix[CrntPrefix];
00682                     CrntPrefix = Prefix[CrntPrefix];
00683                 }
00684                 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
00685                     return GIF_ERROR;
00686                 }
00687                 /* Push the last character on stack: */
00688                 Stack[StackPtr++] = CrntPrefix;
00689 
00690                 /* Now lets pop all the stack into output: */
00691                 while (StackPtr != 0 && i < LineLen)
00692                     Line[i++] = Stack[--StackPtr];
00693             }
00694             if (LastCode != NO_SUCH_CODE) {
00695                 Prefix[Private->RunningCode - 2] = LastCode;
00696 
00697                 if (CrntCode == Private->RunningCode - 2) {
00698                     /* Only allowed if CrntCode is exactly the running code:
00699                      * In that case CrntCode = XXXCode, CrntCode or the
00700                      * prefix code is last code and the suffix char is
00701                      * exactly the prefix of last code! */
00702                     Suffix[Private->RunningCode - 2] =
00703                        DGifGetPrefixChar(Prefix, LastCode, ClearCode);
00704                 } else {
00705                     Suffix[Private->RunningCode - 2] =
00706                        DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
00707                 }
00708             }
00709             LastCode = CrntCode;
00710         }
00711     }
00712 
00713     Private->LastCode = LastCode;
00714     Private->StackPtr = StackPtr;
00715 
00716     return GIF_OK;
00717 }
00718 
00719 /******************************************************************************
00720  * Routine to trace the Prefixes linked list until we get a prefix which is
00721  * not code, but a pixel value (less than ClearCode). Returns that pixel value.
00722  * If image is defective, we might loop here forever, so we limit the loops to
00723  * the maximum possible if image O.k. - LZ_MAX_CODE times.
00724  *****************************************************************************/
00725 static int
00726 DGifGetPrefixChar(const GifPrefixType *Prefix,
00727                   int Code,
00728                   int ClearCode) {
00729 
00730     int i = 0;
00731 
00732     while (Code > ClearCode && i++ <= LZ_MAX_CODE)
00733         Code = Prefix[Code];
00734     return Code;
00735 }
00736 
00737 /******************************************************************************
00738  * The LZ decompression input routine:
00739  * This routine is responsible for the decompression of the bit stream from
00740  * 8 bits (bytes) packets, into the real codes.
00741  * Returns GIF_OK if read successfully.
00742  *****************************************************************************/
00743 static int
00744 DGifDecompressInput(GifFileType * GifFile,
00745                     int *Code) {
00746 
00747     GifFilePrivateType *Private = GifFile->Private;
00748 
00749     GifByteType NextByte;
00750     static const unsigned short CodeMasks[] = {
00751         0x0000, 0x0001, 0x0003, 0x0007,
00752         0x000f, 0x001f, 0x003f, 0x007f,
00753         0x00ff, 0x01ff, 0x03ff, 0x07ff,
00754         0x0fff
00755     };
00756     /* The image can't contain more than LZ_BITS per code. */
00757     if (Private->RunningBits > LZ_BITS) {
00758         return GIF_ERROR;
00759     }
00760 
00761     while (Private->CrntShiftState < Private->RunningBits) {
00762         /* Needs to get more bytes from input stream for next code: */
00763         if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
00764             return GIF_ERROR;
00765         }
00766         Private->CrntShiftDWord |=
00767            ((unsigned long)NextByte) << Private->CrntShiftState;
00768         Private->CrntShiftState += 8;
00769     }
00770     *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
00771 
00772     Private->CrntShiftDWord >>= Private->RunningBits;
00773     Private->CrntShiftState -= Private->RunningBits;
00774 
00775     /* If code cannot fit into RunningBits bits, must raise its size. Note
00776      * however that codes above 4095 are used for special signaling.
00777      * If we're using LZ_BITS bits already and we're at the max code, just
00778      * keep using the table as it is, don't increment Private->RunningCode.
00779      */
00780     if (Private->RunningCode < LZ_MAX_CODE + 2 &&
00781             ++Private->RunningCode > Private->MaxCode1 &&
00782             Private->RunningBits < LZ_BITS) {
00783         Private->MaxCode1 <<= 1;
00784         Private->RunningBits++;
00785     }
00786     return GIF_OK;
00787 }
00788 
00789 /******************************************************************************
00790  * This routines read one gif data block at a time and buffers it internally
00791  * so that the decompression routine could access it.
00792  * The routine returns the next byte from its internal buffer (or read next
00793  * block in if buffer empty) and returns GIF_OK if successful.
00794  *****************************************************************************/
00795 static int
00796 DGifBufferedInput(GifFileType * GifFile,
00797                   GifByteType * Buf,
00798                   GifByteType * NextByte) {
00799 
00800     if (Buf[0] == 0) {
00801         /* Needs to read the next buffer - this one is empty: */
00802         if (READ(GifFile, Buf, 1) != 1) {
00803             return GIF_ERROR;
00804         }
00805         /* There shouldn't be any empty data blocks here as the LZW spec
00806          * says the LZW termination code should come first.  Therefore we
00807          * shouldn't be inside this routine at that point.
00808          */
00809         if (Buf[0] == 0) {
00810             return GIF_ERROR;
00811         }
00812         if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
00813             return GIF_ERROR;
00814         }
00815         *NextByte = Buf[1];
00816         Buf[1] = 2;    /* We use now the second place as last char read! */
00817         Buf[0]--;
00818     } else {
00819         *NextByte = Buf[Buf[1]++];
00820         Buf[0]--;
00821     }
00822 
00823     return GIF_OK;
00824 }
00825 
00826 /******************************************************************************
00827  * This routine reads an entire GIF into core, hanging all its state info off
00828  * the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()
00829  * first to initialize I/O.  Its inverse is EGifSpew().
00830  ******************************************************************************/
00831 int
00832 DGifSlurp(GifFileType * GifFile) {
00833 
00834     int ImageSize;
00835     GifRecordType RecordType;
00836     SavedImage *sp;
00837     GifByteType *ExtData;
00838     SavedImage temp_save;
00839 
00840     temp_save.ExtensionBlocks = NULL;
00841     temp_save.ExtensionBlockCount = 0;
00842 
00843     do {
00844         if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
00845             return (GIF_ERROR);
00846 
00847         switch (RecordType) {
00848           case IMAGE_DESC_RECORD_TYPE:
00849               if (DGifGetImageDesc(GifFile) == GIF_ERROR)
00850                   return (GIF_ERROR);
00851 
00852               sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
00853               ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
00854 
00855               sp->RasterBits = ungif_alloc(ImageSize * sizeof(GifPixelType));
00856               if (sp->RasterBits == NULL) {
00857                   return GIF_ERROR;
00858               }
00859               if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) ==
00860                   GIF_ERROR)
00861                   return (GIF_ERROR);
00862               if (temp_save.ExtensionBlocks) {
00863                   sp->ExtensionBlocks = temp_save.ExtensionBlocks;
00864                   sp->ExtensionBlockCount = temp_save.ExtensionBlockCount;
00865 
00866                   temp_save.ExtensionBlocks = NULL;
00867                   temp_save.ExtensionBlockCount = 0;
00868 
00869                   /* FIXME: The following is wrong.  It is left in only for
00870                    * backwards compatibility.  Someday it should go away. Use
00871                    * the sp->ExtensionBlocks->Function variable instead. */
00872                   sp->Function = sp->ExtensionBlocks[0].Function;
00873               }
00874               break;
00875 
00876           case EXTENSION_RECORD_TYPE:
00877               if (DGifGetExtension(GifFile, &temp_save.Function, &ExtData) ==
00878                   GIF_ERROR)
00879                   return (GIF_ERROR);
00880               while (ExtData != NULL) {
00881 
00882                   /* Create an extension block with our data */
00883                   if (AddExtensionBlock(&temp_save, ExtData[0], &ExtData[1])
00884                       == GIF_ERROR)
00885                       return (GIF_ERROR);
00886 
00887                   if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
00888                       return (GIF_ERROR);
00889                   temp_save.Function = 0;
00890               }
00891               break;
00892 
00893           case TERMINATE_RECORD_TYPE:
00894               break;
00895 
00896           default:    /* Should be trapped by DGifGetRecordType */
00897               break;
00898         }
00899     } while (RecordType != TERMINATE_RECORD_TYPE);
00900 
00901     /* Just in case the Gif has an extension block without an associated
00902      * image... (Should we save this into a savefile structure with no image
00903      * instead? Have to check if the present writing code can handle that as
00904      * well.... */
00905     if (temp_save.ExtensionBlocks)
00906         FreeExtension(&temp_save);
00907 
00908     return (GIF_OK);
00909 }
00910 
00911 /******************************************************************************
00912  * GifFileType constructor with user supplied input function (TVT)
00913  *****************************************************************************/
00914 GifFileType *
00915 DGifOpen(void *userData,
00916          InputFunc readFunc) {
00917 
00918     unsigned char Buf[GIF_STAMP_LEN + 1];
00919     GifFileType *GifFile;
00920     GifFilePrivateType *Private;
00921 
00922     GifFile = ungif_alloc(sizeof(GifFileType));
00923     if (GifFile == NULL) {
00924         return NULL;
00925     }
00926 
00927     memset(GifFile, '\0', sizeof(GifFileType));
00928 
00929     Private = ungif_alloc(sizeof(GifFilePrivateType));
00930     if (!Private) {
00931         ungif_free(GifFile);
00932         return NULL;
00933     }
00934 
00935     GifFile->Private = (void*)Private;
00936 
00937     Private->Read = readFunc;    /* TVT */
00938     GifFile->UserData = userData;    /* TVT */
00939 
00940     /* Lets see if this is a GIF file: */
00941     if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
00942         ungif_free(Private);
00943         ungif_free(GifFile);
00944         return NULL;
00945     }
00946 
00947     /* The GIF Version number is ignored at this time. Maybe we should do
00948      * something more useful with it. */
00949     Buf[GIF_STAMP_LEN] = 0;
00950     if (memcmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
00951         ungif_free(Private);
00952         ungif_free(GifFile);
00953         return NULL;
00954     }
00955 
00956     if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
00957         ungif_free(Private);
00958         ungif_free(GifFile);
00959         return NULL;
00960     }
00961 
00962     return GifFile;
00963 }
00964 
00965 /******************************************************************************
00966  * This routine should be called last, to close the GIF file.
00967  *****************************************************************************/
00968 int
00969 DGifCloseFile(GifFileType * GifFile) {
00970 
00971     GifFilePrivateType *Private;
00972 
00973     if (GifFile == NULL)
00974         return GIF_ERROR;
00975 
00976     Private = GifFile->Private;
00977 
00978     if (GifFile->Image.ColorMap) {
00979         FreeMapObject(GifFile->Image.ColorMap);
00980         GifFile->Image.ColorMap = NULL;
00981     }
00982 
00983     if (GifFile->SColorMap) {
00984         FreeMapObject(GifFile->SColorMap);
00985         GifFile->SColorMap = NULL;
00986     }
00987 
00988     ungif_free(Private);
00989     Private = NULL;
00990 
00991     if (GifFile->SavedImages) {
00992         FreeSavedImages(GifFile);
00993         GifFile->SavedImages = NULL;
00994     }
00995 
00996     ungif_free(GifFile);
00997 
00998     return GIF_OK;
00999 }

Generated on Sat May 26 2012 04:24:22 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.