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 /* 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
1.7.6.1
|