Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenungif.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
1.7.6.1
|