- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-IL/src/il_gif.c

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2000-2008 by Denton Woods
    00005 // Last modified: 08/17/2008
    00006 //
    00007 // Filename: src-IL/src/il_gif.c
    00008 //
    00009 // Description: Reads from a Graphics Interchange Format (.gif) file.
    00010 //
    00011 //  The LZW decompression code is based on code released to the public domain
    00012 //    by Javier Arevalo and can be found at
    00013 //    http://www.programmersheaven.com/zone10/cat452
    00014 //
    00015 //-----------------------------------------------------------------------------
    00016
    00017
    00018 #include "il_internal.h"
    00019 #ifndef IL_NO_GIF
    00020
    00021 #include "il_gif.h"
    00022
    00023
    00024 ILenum  GifType;
    00025
    00027 ILboolean ilIsValidGif(ILconst_string FileName)
    00028 {
    00029         ILHANDLE        GifFile;
    00030         ILboolean       bGif = IL_FALSE;
    00031
    00032         if (!iCheckExtension(FileName, IL_TEXT("gif"))) {
    00033                 ilSetError(IL_INVALID_EXTENSION);
    00034                 return bGif;
    00035         }
    00036
    00037         GifFile = iopenr(FileName);
    00038         if (GifFile == NULL) {
    00039                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00040                 return bGif;
    00041         }
    00042
    00043         bGif = ilIsValidGifF(GifFile);
    00044         icloser(GifFile);
    00045
    00046         return bGif;
    00047 }
    00048
    00049
    00051 ILboolean ilIsValidGifF(ILHANDLE File)
    00052 {
    00053         ILuint          FirstPos;
    00054         ILboolean       bRet;
    00055
    00056         iSetInputFile(File);
    00057         FirstPos = itell();
    00058         bRet = iIsValidGif();
    00059         iseek(FirstPos, IL_SEEK_SET);
    00060
    00061         return bRet;
    00062 }
    00063
    00064
    00066 ILboolean ilIsValidGifL(const void *Lump, ILuint Size)
    00067 {
    00068         iSetInputLump(Lump, Size);
    00069         return iIsValidGif();
    00070 }
    00071
    00072
    00073 // Internal function to get the header and check it.
    00074 ILboolean iIsValidGif()
    00075 {
    00076         char Header[6];
    00077
    00078         if (iread(Header, 1, 6) != 6)
    00079                 return IL_FALSE;
    00080         iseek(-6, IL_SEEK_CUR);
    00081
    00082         if (!strnicmp(Header, "GIF87A", 6))
    00083                 return IL_TRUE;
    00084         if (!strnicmp(Header, "GIF89A", 6))
    00085                 return IL_TRUE;
    00086
    00087         return IL_FALSE;
    00088 }
    00089
    00090
    00092 ILboolean ilLoadGif(ILconst_string FileName)
    00093 {
    00094         ILHANDLE        GifFile;
    00095         ILboolean       bGif = IL_FALSE;
    00096
    00097         GifFile = iopenr(FileName);
    00098         if (GifFile == NULL) {
    00099                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00100                 return bGif;
    00101         }
    00102
    00103         bGif = ilLoadGifF(GifFile);
    00104         icloser(GifFile);
    00105
    00106         return bGif;
    00107 }
    00108
    00109
    00111 ILboolean ilLoadGifF(ILHANDLE File)
    00112 {
    00113         ILuint          FirstPos;
    00114         ILboolean       bRet;
    00115
    00116         iSetInputFile(File);
    00117         FirstPos = itell();
    00118         bRet = iLoadGifInternal();
    00119         iseek(FirstPos, IL_SEEK_SET);
    00120
    00121         return bRet;
    00122 }
    00123
    00124
    00126 ILboolean ilLoadGifL(const void *Lump, ILuint Size)
    00127 {
    00128         iSetInputLump(Lump, Size);
    00129         return iLoadGifInternal();
    00130 }
    00131
    00132
    00133 // Internal function used to load the Gif.
    00134 ILboolean iLoadGifInternal()
    00135 {
    00136         GIFHEAD Header;
    00137         ILpal   GlobalPal;
    00138
    00139         if (iCurImage == NULL) {
    00140                 ilSetError(IL_ILLEGAL_OPERATION);
    00141                 return IL_FALSE;
    00142         }
    00143
    00144         GlobalPal.Palette = NULL;
    00145         GlobalPal.PalSize = 0;
    00146
    00147         //read header
    00148         iread(&Header.Sig, 1, 6);
    00149         Header.Width = GetLittleUShort();
    00150     Header.Height = GetLittleUShort();
    00151         Header.ColourInfo = igetc();
    00152         Header.Background = igetc();
    00153         Header.Aspect = igetc();
    00154
    00155         if (!strnicmp(Header.Sig, "GIF87A", 6)) {
    00156                 GifType = GIF87A;
    00157         }
    00158         else if (!strnicmp(Header.Sig, "GIF89A", 6)) {
    00159                 GifType = GIF89A;
    00160         }
    00161         else {
    00162                 ilSetError(IL_INVALID_FILE_HEADER);
    00163                 return IL_FALSE;
    00164         }
    00165
    00166         if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL))
    00167                 return IL_FALSE;
    00168         iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
    00169
    00170         // Check for a global colour map.
    00171         if (Header.ColourInfo & (1 << 7)) {
    00172                 if (!iGetPalette(Header.ColourInfo, &GlobalPal, IL_FALSE, NULL)) {
    00173                         return IL_FALSE;
    00174                 }
    00175         }
    00176
    00177         if (!GetImages(&GlobalPal, &Header))
    00178                 return IL_FALSE;
    00179
    00180         if (GlobalPal.Palette && GlobalPal.PalSize)
    00181                 ifree(GlobalPal.Palette);
    00182         GlobalPal.Palette = NULL;
    00183         GlobalPal.PalSize = 0;
    00184
    00185         ilFixImage();
    00186
    00187         return IL_TRUE;
    00188 }
    00189
    00190
    00191 ILboolean iGetPalette(ILubyte Info, ILpal *Pal, ILboolean UsePrevPal, ILimage *PrevImage)
    00192 {
    00193         ILuint PalSize, PalOffset = 0;
    00194
    00195         // If we have a local palette and have to use the previous frame as well,
    00196         //  we have to copy the palette from the previous frame, in addition
    00197         //  to the data, which we copy in GetImages.
    00198
    00199         // The ld(palettes bpp - 1) is stored in the lower
    00200         // 3 bits of Info (weird gif format ... :) )
    00201         PalSize = (1 << ((Info & 0x7) + 1)) * 3;
    00202         if (UsePrevPal) {
    00203                 if (PrevImage == NULL) {  // Cannot use the previous palette if it does not exist.
    00204                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00205                         return IL_FALSE;
    00206                 }
    00207                 PalSize = PalSize + PrevImage->Pal.PalSize;
    00208                 PalOffset = PrevImage->Pal.PalSize;
    00209         }
    00210         if (PalSize > 256 * 3) {
    00211                 ilSetError(IL_ILLEGAL_FILE_VALUE);
    00212                 return IL_FALSE;
    00213         }
    00214         Pal->PalSize = PalSize;
    00215
    00216         Pal->PalType = IL_PAL_RGB24;
    00217         //Pal->Palette = (ILubyte*)ialloc(Pal->PalSize);
    00218         Pal->Palette = (ILubyte*)ialloc(256 * 3);
    00219         if (Pal->Palette == NULL)
    00220                 return IL_FALSE;
    00221         if (UsePrevPal)
    00222                 memcpy(Pal->Palette, PrevImage->Pal.Palette, PrevImage->Pal.PalSize);  // Copy the old palette over.
    00223         if (iread(Pal->Palette + PalOffset, 1, Pal->PalSize) != Pal->PalSize) {  // Read the new palette.
    00224                 ifree(Pal->Palette);
    00225                 Pal->Palette = NULL;
    00226                 return IL_FALSE;
    00227         }
    00228
    00229         return IL_TRUE;
    00230 }
    00231
    00232
    00233 ILboolean GetImages(ILpal *GlobalPal, GIFHEAD *GifHead)
    00234 {
    00235         IMAGEDESC       ImageDesc, OldImageDesc;
    00236         GFXCONTROL      Gfx;
    00237         ILboolean       BaseImage = IL_TRUE;
    00238         ILimage         *Image = iCurImage, *TempImage = NULL, *PrevImage = NULL;
    00239         ILuint          NumImages = 0, i;
    00240         ILint           input;
    00241         ILuint          PalOffset;
    00242
    00243         OldImageDesc.ImageInfo = 0; // to initialize the data with an harmless value
    00244         Gfx.Used = IL_TRUE;
    00245
    00246         while (!ieof()) {
    00247                 ILubyte DisposalMethod = 1;
    00248
    00249                 i = itell();
    00250                 if (!SkipExtensions(&Gfx))
    00251                         goto error_clean;
    00252                 i = itell();
    00253
    00254                 if (!Gfx.Used)
    00255                         DisposalMethod = (Gfx.Packed & 0x1C) >> 2;
    00256
    00257                 //read image descriptor
    00258                 ImageDesc.Separator = igetc();
    00259                 if (ImageDesc.Separator != 0x2C) //end of image
    00260                         break;
    00261                 ImageDesc.OffX = GetLittleUShort();
    00262                 ImageDesc.OffY = GetLittleUShort();
    00263                 ImageDesc.Width = GetLittleUShort();
    00264                 ImageDesc.Height = GetLittleUShort();
    00265                 ImageDesc.ImageInfo = igetc();
    00266
    00267                 if (ieof()) {
    00268                         ilGetError();  // Gets rid of the IL_FILE_READ_ERROR that inevitably results.
    00269                         break;
    00270                 }
    00271
    00272
    00273                 if (!BaseImage) {
    00274                         NumImages++;
    00275                         Image->Next = ilNewImage(iCurImage->Width, iCurImage->Height, 1, 1, 1);
    00276                         if (Image->Next == NULL)
    00277                                 goto error_clean;
    00278                         //20040612: DisposalMethod controls how the new images data is to be combined
    00279                         //with the old image. 0 means that it doesn't matter how they are combined,
    00280                         //1 means keep the old image, 2 means set to background color, 3 is
    00281                         //load the image that was in place before the current (this is not implemented
    00282                         //here! (TODO?))
    00283                         if (DisposalMethod == 2 || DisposalMethod == 3)
    00284                                 //Note that this is actually wrong, too: If the image has a local
    00285                                 //color table, we should really search for the best fit of the
    00286                                 //background color table and use that index (?). Furthermore,
    00287                                 //we should only memset the part of the image that is not read
    00288                                 //later (if we are sure that no parts of the read image are transparent).
    00289                                 if (!Gfx.Used && Gfx.Packed & 0x1)
    00290                                         memset(Image->Next->Data, Gfx.Transparent, Image->SizeOfData);
    00291                                 else
    00292                                         memset(Image->Next->Data, GifHead->Background, Image->SizeOfData);
    00293                         else if (DisposalMethod == 1 || DisposalMethod == 0)
    00294                                 memcpy(Image->Next->Data, Image->Data, Image->SizeOfData);
    00295                         //Interlacing has to be removed after the image was copied (line above)
    00296                         if (OldImageDesc.ImageInfo & (1 << 6)) {  // Image is interlaced.
    00297                                 if (!RemoveInterlace(Image))
    00298                                         goto error_clean;
    00299                         }
    00300
    00301                         PrevImage = Image;
    00302                         Image = Image->Next;
    00303                         Image->Format = IL_COLOUR_INDEX;
    00304                         Image->Origin = IL_ORIGIN_UPPER_LEFT;
    00305                 } else {
    00306                         BaseImage = IL_FALSE;
    00307                         if (!Gfx.Used && Gfx.Packed & 0x1)
    00308                                 memset(Image->Data, Gfx.Transparent, Image->SizeOfData);
    00309                         else
    00310                             memset(Image->Data, GifHead->Background, Image->SizeOfData);
    00311                 }
    00312
    00313                 Image->OffX = ImageDesc.OffX;
    00314                 Image->OffY = ImageDesc.OffY;
    00315                 PalOffset = 0;
    00316
    00317                 // Check to see if the image has its own palette.
    00318                 if (ImageDesc.ImageInfo & (1 << 7)) {
    00319                         ILboolean UsePrevPal = IL_FALSE;
    00320                         if (DisposalMethod == 1 && NumImages != 0) {  // Cannot be the first image for this.
    00321                                 PalOffset = PrevImage->Pal.PalSize;
    00322                                 UsePrevPal = IL_TRUE;
    00323                         }
    00324                         if (!iGetPalette(ImageDesc.ImageInfo, &Image->Pal, UsePrevPal, PrevImage)) {
    00325                                 goto error_clean;
    00326                         }
    00327                 } else {
    00328                         if (!iCopyPalette(&Image->Pal, GlobalPal)) {
    00329                                 goto error_clean;
    00330                         }
    00331                 }
    00332
    00333                 if (!GifGetData(Image, Image->Data + ImageDesc.OffX + ImageDesc.OffY*Image->Width, Image->SizeOfData,
    00334                                 ImageDesc.Width, ImageDesc.Height, Image->Width, PalOffset, &Gfx)) {
    00335                         memset(Image->Data, 0, Image->SizeOfData);  //@TODO: Remove this.  For debugging purposes right now.
    00336                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00337                         goto error_clean;
    00338                 }
    00339
    00340                 // See if there was a valid graphics control extension.
    00341                 if (!Gfx.Used) {
    00342                         Gfx.Used = IL_TRUE;
    00343                         Image->Duration = Gfx.Delay * 10;  // We want it in milliseconds.
    00344
    00345                         // See if a transparent colour is defined.
    00346                         if (Gfx.Packed & 1) {
    00347                                 if (!ConvertTransparent(Image, Gfx.Transparent)) {
    00348                                         goto error_clean;
    00349                                 }
    00350                 }
    00351                 }
    00352                 i = itell();
    00353                 // Terminates each block.
    00354                 if((input = igetc()) == IL_EOF)
    00355                         goto error_clean;
    00356
    00357                 if (input != 0x00)
    00358                     iseek(-1, IL_SEEK_CUR);
    00359                 //      break;
    00360
    00361                 OldImageDesc = ImageDesc;
    00362         }
    00363
    00364         //Deinterlace last image
    00365         if (OldImageDesc.ImageInfo & (1 << 6)) {  // Image is interlaced.
    00366                 if (!RemoveInterlace(Image))
    00367                         goto error_clean;
    00368         }
    00369
    00370         if (BaseImage)  // Was not able to load any images in...
    00371                 return IL_FALSE;
    00372
    00373         return IL_TRUE;
    00374
    00375 error_clean:
    00376         Image = iCurImage->Next;
    00377     /*  while (Image) {
    00378                 TempImage = Image;
    00379                 Image = Image->Next;
    00380                 ilCloseImage(TempImage);
    00381         }*/
    00382         return IL_FALSE;
    00383 }
    00384
    00385
    00386 ILboolean SkipExtensions(GFXCONTROL *Gfx)
    00387 {
    00388         ILint   Code;
    00389         ILint   Label;
    00390         ILint   Size;
    00391
    00392         // DW (06-03-2002):  Apparently there can be...
    00393         //if (GifType == GIF87A)
    00394         //      return IL_TRUE;  // No extensions in the GIF87a format.
    00395
    00396         do {
    00397                 if((Code = igetc()) == IL_EOF)
    00398                         return IL_FALSE;
    00399
    00400                 if (Code != 0x21) {
    00401                         iseek(-1, IL_SEEK_CUR);
    00402                         return IL_TRUE;
    00403                 }
    00404
    00405                 if((Label = igetc()) == IL_EOF)
    00406                         return IL_FALSE;
    00407
    00408                 switch (Label)
    00409                 {
    00410                         case 0xF9:
    00411                                 Gfx->Size = igetc();
    00412                                 Gfx->Packed = igetc();
    00413                                 Gfx->Delay = GetLittleUShort();
    00414                                 Gfx->Transparent = igetc();
    00415                                 Gfx->Terminator = igetc();
    00416                                 if (ieof())
    00417                                         return IL_FALSE;
    00418                                 Gfx->Used = IL_FALSE;
    00419                                 break;
    00420                         /*case 0xFE:
    00421                                 break;
    00422
    00423                         case 0x01:
    00424                                 break;*/
    00425                         default:
    00426                                 do {
    00427                                         if((Size = igetc()) == IL_EOF)
    00428                                                 return IL_FALSE;
    00429                                         iseek(Size, IL_SEEK_CUR);
    00430                                 } while (!ieof() && Size != 0);
    00431                 }
    00432
    00433                 // @TODO:  Handle this better.
    00434                 if (ieof()) {
    00435                         ilSetError(IL_FILE_READ_ERROR);
    00436                         return IL_FALSE;
    00437                 }
    00438         } while (1);
    00439
    00440         return IL_TRUE;
    00441 }
    00442
    00443
    00444 #define MAX_CODES 4096
    00445
    00446 ILint   curr_size, clear, ending, newcodes, top_slot, slot, navail_bytes = 0, nbits_left = 0;
    00447 ILubyte b1;
    00448 ILubyte byte_buff[257];
    00449 ILubyte *pbytes;
    00450 ILubyte *stack;
    00451 ILubyte *suffix;
    00452 ILshort *prefix;
    00453
    00454 ILboolean success;
    00455
    00456 ILuint code_mask[13] =
    00457 {
    00458    0L,
    00459    0x0001L, 0x0003L,
    00460    0x0007L, 0x000FL,
    00461    0x001FL, 0x003FL,
    00462    0x007FL, 0x00FFL,
    00463    0x01FFL, 0x03FFL,
    00464    0x07FFL, 0x0FFFL
    00465 };
    00466
    00467
    00468 ILint get_next_code(void) {
    00469         ILint   i, t;
    00470         ILuint  ret;
    00471
    00472         //20050102: Tests for IL_EOF were added because this function
    00473         //crashed sometimes if igetc() returned IL_EOF
    00474         //(for example "table-add-column-before-active.gif" included in the
    00475         //mozilla source package)
    00476
    00477         if (!nbits_left) {
    00478                 if (navail_bytes <= 0) {
    00479                         pbytes = byte_buff;
    00480                         navail_bytes = igetc();
    00481
    00482                         if(navail_bytes == IL_EOF) {
    00483                                 success = IL_FALSE;
    00484                                 return ending;
    00485                         }
    00486
    00487                         if (navail_bytes) {
    00488                                 for (i = 0; i < navail_bytes; i++) {
    00489                                         if((t = igetc()) == IL_EOF) {
    00490                                                 success = IL_FALSE;
    00491                                                 return ending;
    00492                                         }
    00493                                         byte_buff[i] = t;
    00494                                 }
    00495                         }
    00496                 }
    00497                 b1 = *pbytes++;
    00498                 nbits_left = 8;
    00499                 navail_bytes--;
    00500         }
    00501
    00502         ret = b1 >> (8 - nbits_left);
    00503         while (curr_size > nbits_left) {
    00504                 if (navail_bytes <= 0) {
    00505                         pbytes = byte_buff;
    00506                         navail_bytes = igetc();
    00507
    00508                         if(navail_bytes == IL_EOF) {
    00509                                 success = IL_FALSE;
    00510                                 return ending;
    00511                         }
    00512
    00513                         if (navail_bytes) {
    00514                                 for (i = 0; i < navail_bytes; i++) {
    00515                                         if((t = igetc()) == IL_EOF) {
    00516                                                 success = IL_FALSE;
    00517                                                 return ending;
    00518                                         }
    00519                                         byte_buff[i] = t;
    00520                                 }
    00521                         }
    00522                 }
    00523                 b1 = *pbytes++;
    00524                 ret |= b1 << nbits_left;
    00525                 nbits_left += 8;
    00526                 navail_bytes--;
    00527         }
    00528         nbits_left -= curr_size;
    00529
    00530         return (ret & code_mask[curr_size]);
    00531 }
    00532
    00533 static void cleanUpGifLoadState()
    00534 {
    00535         ifree(stack);
    00536         ifree(suffix);
    00537         ifree(prefix);
    00538
    00539 }
    00540
    00541 ILboolean GifGetData(ILimage *Image, ILubyte *Data, ILuint ImageSize, ILuint Width, ILuint Height, ILuint Stride, ILuint PalOffset, GFXCONTROL *Gfx)
    00542 {
    00543         ILubyte *sp;
    00544         ILint   code, fc, oc;
    00545         ILubyte DisposalMethod = 0;
    00546         ILint   c, size;
    00547         ILuint  i = 0, Read = 0, j = 0;
    00548         ILubyte *DataPtr = Data;
    00549
    00550         if (!Gfx->Used)
    00551                 DisposalMethod = (Gfx->Packed & 0x1C) >> 2;
    00552         if((size = igetc()) == IL_EOF)
    00553                 return IL_FALSE;
    00554
    00555         if (size < 2 || 9 < size) {
    00556                 return IL_FALSE;
    00557         }
    00558
    00559         stack  = (ILubyte*)ialloc(MAX_CODES + 1);
    00560         suffix = (ILubyte*)ialloc(MAX_CODES + 1);
    00561         prefix = (ILshort*)ialloc(sizeof(*prefix) * (MAX_CODES + 1));
    00562         if (!stack || !suffix || !prefix)
    00563         {
    00564                 cleanUpGifLoadState();
    00565                 return IL_FALSE;
    00566         }
    00567
    00568         curr_size = size + 1;
    00569         top_slot = 1 << curr_size;
    00570         clear = 1 << size;
    00571         ending = clear + 1;
    00572         slot = newcodes = ending + 1;
    00573         navail_bytes = nbits_left = 0;
    00574         oc = fc = 0;
    00575         sp = stack;
    00576
    00577         while ((c = get_next_code()) != ending && Read < Height) {
    00578                 if (c == clear)
    00579                 {
    00580                         curr_size = size + 1;
    00581                         slot = newcodes;
    00582                         top_slot = 1 << curr_size;
    00583                         while ((c = get_next_code()) == clear);
    00584                         if (c == ending)
    00585                                 break;
    00586                         if (c >= slot)
    00587                                 c = 0;
    00588                         oc = fc = c;
    00589
    00590                         if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == c && (Gfx->Packed & 0x1) != 0)
    00591                                 i++;
    00592                         else if (i < Width)
    00593                                 DataPtr[i++] = c + PalOffset;
    00594
    00595                         if (i == Width)
    00596                         {
    00597                                 DataPtr += Stride;
    00598                                 i = 0;
    00599                                 Read += 1;
    00600                 ++j;
    00601                 if (j >= Height) {
    00602                    cleanUpGifLoadState();
    00603                    return IL_FALSE;
    00604                 }
    00605                         }
    00606                 }
    00607                 else
    00608                 {
    00609                         code = c;
    00610             //BG-2007-01-10: several fixes for incomplete GIFs
    00611                         if (code >= slot)
    00612                         {
    00613                                 code = oc;
    00614                 if (sp >= stack + MAX_CODES) {
    00615                    cleanUpGifLoadState();
    00616                    return IL_FALSE;
    00617                 }
    00618                 *sp++ = fc;
    00619                         }
    00620
    00621             if (code >= MAX_CODES)
    00622                 return IL_FALSE;
    00623                 while (code >= newcodes)
    00624                                 {
    00625                     if (sp >= stack + MAX_CODES)
    00626                                         {
    00627                         cleanUpGifLoadState();
    00628                         return IL_FALSE;
    00629                     }
    00630                     *sp++ = suffix[code];
    00631                     code = prefix[code];
    00632                 }
    00633
    00634                 if (sp >= stack + MAX_CODES) {
    00635                 cleanUpGifLoadState();
    00636                 return IL_FALSE;
    00637             }
    00638
    00639             *sp++ = (ILbyte)code;
    00640                         if (slot < top_slot)
    00641                         {
    00642                                 fc = code;
    00643                                 suffix[slot]   = fc;
    00644                                 prefix[slot++] = oc;
    00645                                 oc = c;
    00646                         }
    00647                         if (slot >= top_slot && curr_size < 12)
    00648                         {
    00649                                 top_slot <<= 1;
    00650                                 curr_size++;
    00651                         }
    00652                         while (sp > stack)
    00653                         {
    00654                                 sp--;
    00655                                 if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == *sp && (Gfx->Packed & 0x1) != 0)
    00656                                         i++;
    00657                                 else if (i < Width)
    00658                                         DataPtr[i++] = *sp + PalOffset;
    00659
    00660                                 if (i == Width)
    00661                                 {
    00662                                         i = 0;
    00663                                         Read += 1;
    00664                     j = (j+1) % Height;
    00665                                         // Needs to start from Data, not Image->Data.
    00666                                         DataPtr = Data + j * Stride;
    00667                                 }
    00668                         }
    00669                 }
    00670         }
    00671         cleanUpGifLoadState();
    00672         return IL_TRUE;
    00673 }
    00674
    00675
    00676 /*From the GIF spec:
    00677
    00678   The rows of an Interlaced images are arranged in the following order:
    00679
    00680       Group 1 : Every 8th. row, starting with row 0.              (Pass 1)
    00681       Group 2 : Every 8th. row, starting with row 4.              (Pass 2)
    00682       Group 3 : Every 4th. row, starting with row 2.              (Pass 3)
    00683       Group 4 : Every 2nd. row, starting with row 1.              (Pass 4)
    00684 */
    00685
    00686 ILboolean RemoveInterlace(ILimage *image)
    00687 {
    00688         ILubyte *NewData;
    00689         ILuint  i, j = 0;
    00690
    00691         NewData = (ILubyte*)ialloc(image->SizeOfData);
    00692         if (NewData == NULL)
    00693                 return IL_FALSE;
    00694
    00695         //changed 20041230: images with offsety != 0 were not
    00696         //deinterlaced correctly before...
    00697         for (i = 0; i < image->OffY; i++, j++) {
    00698                 memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps);
    00699         }
    00700
    00701         for (i = 0 + image->OffY; i < image->Height; i += 8, j++) {
    00702                 memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps);
    00703         }
    00704
    00705         for (i = 4 + image->OffY; i < image->Height; i += 8, j++) {
    00706                 memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps);
    00707         }
    00708
    00709         for (i = 2 + image->OffY; i < image->Height; i += 4, j++) {
    00710                 memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps);
    00711         }
    00712
    00713         for (i = 1 + image->OffY; i < image->Height; i += 2, j++) {
    00714                 memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps);
    00715         }
    00716
    00717         ifree(image->Data);
    00718         image->Data = NewData;
    00719
    00720         return IL_TRUE;
    00721 }
    00722
    00723
    00724 // Assumes that Dest has nothing in it.
    00725 ILboolean iCopyPalette(ILpal *Dest, ILpal *Src)
    00726 {
    00727         if (Src->Palette == NULL || Src->PalSize == 0)
    00728                 return IL_FALSE;
    00729
    00730         Dest->Palette = (ILubyte*)ialloc(Src->PalSize);
    00731         if (Dest->Palette == NULL)
    00732                 return IL_FALSE;
    00733
    00734         memcpy(Dest->Palette, Src->Palette, Src->PalSize);
    00735
    00736         Dest->PalSize = Src->PalSize;
    00737         Dest->PalType = Src->PalType;
    00738
    00739         return IL_TRUE;
    00740 }
    00741
    00742
    00743 // Uses the transparent colour index to make an alpha channel.
    00744 ILboolean ConvertTransparent(ILimage *Image, ILubyte TransColour)
    00745 {
    00746         ILubyte *Palette;
    00747         ILuint  i, j;
    00748
    00749         if (!Image->Pal.Palette || !Image->Pal.PalSize) {
    00750                 ilSetError(IL_INTERNAL_ERROR);
    00751                 return IL_FALSE;
    00752         }
    00753
    00754         Palette = (ILubyte*)ialloc(Image->Pal.PalSize / 3 * 4);
    00755         if (Palette == NULL)
    00756                 return IL_FALSE;
    00757
    00758         for (i = 0, j = 0; i < Image->Pal.PalSize; i += 3, j += 4) {
    00759                 Palette[j  ] = Image->Pal.Palette[i  ];
    00760                 Palette[j+1] = Image->Pal.Palette[i+1];
    00761                 Palette[j+2] = Image->Pal.Palette[i+2];
    00762                 if (j/4 == TransColour)
    00763                         Palette[j+3] = 0x00;
    00764                 else
    00765                         Palette[j+3] = 0xFF;
    00766         }
    00767
    00768         ifree(Image->Pal.Palette);
    00769         Image->Pal.Palette = Palette;
    00770         Image->Pal.PalSize = Image->Pal.PalSize / 3 * 4;
    00771         Image->Pal.PalType = IL_PAL_RGBA32;
    00772
    00773         return IL_TRUE;
    00774 }
    00775
    00776 #endif //IL_NO_GIF