mirror of
https://github.com/love2d/megasource.git
synced 2026-08-19 20:20:11 +02:00
Add DevIL 1.7.8.
This commit is contained in:
@@ -0,0 +1,755 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// ImageLib Sources
|
||||
// Copyright (C) 2000-2008 by Denton Woods
|
||||
// Last modified: 03/07/2009
|
||||
//
|
||||
// Filename: src-IL/src/il_gif.c
|
||||
//
|
||||
// Description: Reads from a Graphics Interchange Format (.gif) file.
|
||||
//
|
||||
// The LZW decompression code is based on code released to the public domain
|
||||
// by Javier Arevalo and can be found at
|
||||
// http://www.programmersheaven.com/zone10/cat452
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "il_internal.h"
|
||||
#ifndef IL_NO_GIF
|
||||
|
||||
#include "il_gif.h"
|
||||
|
||||
|
||||
ILenum GifType;
|
||||
|
||||
//! Checks if the file specified in FileName is a valid Gif file.
|
||||
ILboolean ilIsValidGif(ILconst_string FileName)
|
||||
{
|
||||
ILHANDLE GifFile;
|
||||
ILboolean bGif = IL_FALSE;
|
||||
|
||||
if (!iCheckExtension(FileName, IL_TEXT("gif"))) {
|
||||
ilSetError(IL_INVALID_EXTENSION);
|
||||
return bGif;
|
||||
}
|
||||
|
||||
GifFile = iopenr(FileName);
|
||||
if (GifFile == NULL) {
|
||||
ilSetError(IL_COULD_NOT_OPEN_FILE);
|
||||
return bGif;
|
||||
}
|
||||
|
||||
bGif = ilIsValidGifF(GifFile);
|
||||
icloser(GifFile);
|
||||
|
||||
return bGif;
|
||||
}
|
||||
|
||||
|
||||
//! Checks if the ILHANDLE contains a valid Gif file at the current position.
|
||||
ILboolean ilIsValidGifF(ILHANDLE File)
|
||||
{
|
||||
ILuint FirstPos;
|
||||
ILboolean bRet;
|
||||
|
||||
iSetInputFile(File);
|
||||
FirstPos = itell();
|
||||
bRet = iIsValidGif();
|
||||
iseek(FirstPos, IL_SEEK_SET);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
//! Checks if Lump is a valid Gif lump.
|
||||
ILboolean ilIsValidGifL(const void *Lump, ILuint Size)
|
||||
{
|
||||
iSetInputLump(Lump, Size);
|
||||
return iIsValidGif();
|
||||
}
|
||||
|
||||
|
||||
// Internal function to get the header and check it.
|
||||
ILboolean iIsValidGif()
|
||||
{
|
||||
char Header[6];
|
||||
|
||||
if (iread(Header, 1, 6) != 6)
|
||||
return IL_FALSE;
|
||||
iseek(-6, IL_SEEK_CUR);
|
||||
|
||||
if (!strnicmp(Header, "GIF87A", 6))
|
||||
return IL_TRUE;
|
||||
if (!strnicmp(Header, "GIF89A", 6))
|
||||
return IL_TRUE;
|
||||
|
||||
return IL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//! Reads a Gif file
|
||||
ILboolean ilLoadGif(ILconst_string FileName)
|
||||
{
|
||||
ILHANDLE GifFile;
|
||||
ILboolean bGif = IL_FALSE;
|
||||
|
||||
GifFile = iopenr(FileName);
|
||||
if (GifFile == NULL) {
|
||||
ilSetError(IL_COULD_NOT_OPEN_FILE);
|
||||
return bGif;
|
||||
}
|
||||
|
||||
bGif = ilLoadGifF(GifFile);
|
||||
icloser(GifFile);
|
||||
|
||||
return bGif;
|
||||
}
|
||||
|
||||
|
||||
//! Reads an already-opened Gif file
|
||||
ILboolean ilLoadGifF(ILHANDLE File)
|
||||
{
|
||||
ILuint FirstPos;
|
||||
ILboolean bRet;
|
||||
|
||||
iSetInputFile(File);
|
||||
FirstPos = itell();
|
||||
bRet = iLoadGifInternal();
|
||||
iseek(FirstPos, IL_SEEK_SET);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
//! Reads from a memory "lump" that contains a Gif
|
||||
ILboolean ilLoadGifL(const void *Lump, ILuint Size)
|
||||
{
|
||||
iSetInputLump(Lump, Size);
|
||||
return iLoadGifInternal();
|
||||
}
|
||||
|
||||
|
||||
// Internal function used to load the Gif.
|
||||
ILboolean iLoadGifInternal()
|
||||
{
|
||||
GIFHEAD Header;
|
||||
ILpal GlobalPal;
|
||||
|
||||
if (iCurImage == NULL) {
|
||||
ilSetError(IL_ILLEGAL_OPERATION);
|
||||
return IL_FALSE;
|
||||
}
|
||||
|
||||
GlobalPal.Palette = NULL;
|
||||
GlobalPal.PalSize = 0;
|
||||
|
||||
//read header
|
||||
iread(&Header.Sig, 1, 6);
|
||||
Header.Width = GetLittleUShort();
|
||||
Header.Height = GetLittleUShort();
|
||||
Header.ColourInfo = igetc();
|
||||
Header.Background = igetc();
|
||||
Header.Aspect = igetc();
|
||||
|
||||
if (!strnicmp(Header.Sig, "GIF87A", 6)) {
|
||||
GifType = GIF87A;
|
||||
}
|
||||
else if (!strnicmp(Header.Sig, "GIF89A", 6)) {
|
||||
GifType = GIF89A;
|
||||
}
|
||||
else {
|
||||
ilSetError(IL_INVALID_FILE_HEADER);
|
||||
return IL_FALSE;
|
||||
}
|
||||
|
||||
if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL))
|
||||
return IL_FALSE;
|
||||
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
|
||||
|
||||
// Check for a global colour map.
|
||||
if (Header.ColourInfo & (1 << 7)) {
|
||||
if (!iGetPalette(Header.ColourInfo, &GlobalPal, IL_FALSE, NULL)) {
|
||||
return IL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetImages(&GlobalPal, &Header))
|
||||
return IL_FALSE;
|
||||
|
||||
if (GlobalPal.Palette && GlobalPal.PalSize)
|
||||
ifree(GlobalPal.Palette);
|
||||
GlobalPal.Palette = NULL;
|
||||
GlobalPal.PalSize = 0;
|
||||
|
||||
return ilFixImage();
|
||||
}
|
||||
|
||||
|
||||
ILboolean iGetPalette(ILubyte Info, ILpal *Pal, ILboolean UsePrevPal, ILimage *PrevImage)
|
||||
{
|
||||
ILuint PalSize, PalOffset = 0;
|
||||
|
||||
// If we have a local palette and have to use the previous frame as well,
|
||||
// we have to copy the palette from the previous frame, in addition
|
||||
// to the data, which we copy in GetImages.
|
||||
|
||||
// The ld(palettes bpp - 1) is stored in the lower
|
||||
// 3 bits of Info (weird gif format ... :) )
|
||||
PalSize = (1 << ((Info & 0x7) + 1)) * 3;
|
||||
if (UsePrevPal) {
|
||||
if (PrevImage == NULL) { // Cannot use the previous palette if it does not exist.
|
||||
ilSetError(IL_ILLEGAL_FILE_VALUE);
|
||||
return IL_FALSE;
|
||||
}
|
||||
PalSize = PalSize + PrevImage->Pal.PalSize;
|
||||
PalOffset = PrevImage->Pal.PalSize;
|
||||
}
|
||||
if (PalSize > 256 * 3) {
|
||||
ilSetError(IL_ILLEGAL_FILE_VALUE);
|
||||
return IL_FALSE;
|
||||
}
|
||||
Pal->PalSize = PalSize;
|
||||
|
||||
Pal->PalType = IL_PAL_RGB24;
|
||||
//Pal->Palette = (ILubyte*)ialloc(Pal->PalSize);
|
||||
Pal->Palette = (ILubyte*)ialloc(256 * 3);
|
||||
if (Pal->Palette == NULL)
|
||||
return IL_FALSE;
|
||||
if (UsePrevPal)
|
||||
memcpy(Pal->Palette, PrevImage->Pal.Palette, PrevImage->Pal.PalSize); // Copy the old palette over.
|
||||
if (iread(Pal->Palette + PalOffset, 1, Pal->PalSize) != Pal->PalSize) { // Read the new palette.
|
||||
ifree(Pal->Palette);
|
||||
Pal->Palette = NULL;
|
||||
return IL_FALSE;
|
||||
}
|
||||
|
||||
return IL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
ILboolean GetImages(ILpal *GlobalPal, GIFHEAD *GifHead)
|
||||
{
|
||||
IMAGEDESC ImageDesc, OldImageDesc;
|
||||
GFXCONTROL Gfx;
|
||||
ILboolean BaseImage = IL_TRUE;
|
||||
ILimage *Image = iCurImage, *TempImage = NULL, *PrevImage = NULL;
|
||||
ILuint NumImages = 0, i;
|
||||
ILint input;
|
||||
ILuint PalOffset;
|
||||
|
||||
OldImageDesc.ImageInfo = 0; // to initialize the data with an harmless value
|
||||
Gfx.Used = IL_TRUE;
|
||||
|
||||
while (!ieof()) {
|
||||
ILubyte DisposalMethod = 1;
|
||||
|
||||
i = itell();
|
||||
if (!SkipExtensions(&Gfx))
|
||||
goto error_clean;
|
||||
i = itell();
|
||||
|
||||
if (!Gfx.Used)
|
||||
DisposalMethod = (Gfx.Packed & 0x1C) >> 2;
|
||||
|
||||
//read image descriptor
|
||||
ImageDesc.Separator = igetc();
|
||||
if (ImageDesc.Separator != 0x2C) //end of image
|
||||
break;
|
||||
ImageDesc.OffX = GetLittleUShort();
|
||||
ImageDesc.OffY = GetLittleUShort();
|
||||
ImageDesc.Width = GetLittleUShort();
|
||||
ImageDesc.Height = GetLittleUShort();
|
||||
ImageDesc.ImageInfo = igetc();
|
||||
|
||||
if (ieof()) {
|
||||
ilGetError(); // Gets rid of the IL_FILE_READ_ERROR that inevitably results.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!BaseImage) {
|
||||
NumImages++;
|
||||
Image->Next = ilNewImage(iCurImage->Width, iCurImage->Height, 1, 1, 1);
|
||||
if (Image->Next == NULL)
|
||||
goto error_clean;
|
||||
//20040612: DisposalMethod controls how the new images data is to be combined
|
||||
//with the old image. 0 means that it doesn't matter how they are combined,
|
||||
//1 means keep the old image, 2 means set to background color, 3 is
|
||||
//load the image that was in place before the current (this is not implemented
|
||||
//here! (TODO?))
|
||||
if (DisposalMethod == 2 || DisposalMethod == 3)
|
||||
//Note that this is actually wrong, too: If the image has a local
|
||||
//color table, we should really search for the best fit of the
|
||||
//background color table and use that index (?). Furthermore,
|
||||
//we should only memset the part of the image that is not read
|
||||
//later (if we are sure that no parts of the read image are transparent).
|
||||
if (!Gfx.Used && Gfx.Packed & 0x1)
|
||||
memset(Image->Next->Data, Gfx.Transparent, Image->SizeOfData);
|
||||
else
|
||||
memset(Image->Next->Data, GifHead->Background, Image->SizeOfData);
|
||||
else if (DisposalMethod == 1 || DisposalMethod == 0)
|
||||
memcpy(Image->Next->Data, Image->Data, Image->SizeOfData);
|
||||
//Interlacing has to be removed after the image was copied (line above)
|
||||
if (OldImageDesc.ImageInfo & (1 << 6)) { // Image is interlaced.
|
||||
if (!RemoveInterlace(Image))
|
||||
goto error_clean;
|
||||
}
|
||||
|
||||
PrevImage = Image;
|
||||
Image = Image->Next;
|
||||
Image->Format = IL_COLOUR_INDEX;
|
||||
Image->Origin = IL_ORIGIN_UPPER_LEFT;
|
||||
} else {
|
||||
BaseImage = IL_FALSE;
|
||||
if (!Gfx.Used && Gfx.Packed & 0x1)
|
||||
memset(Image->Data, Gfx.Transparent, Image->SizeOfData);
|
||||
else
|
||||
memset(Image->Data, GifHead->Background, Image->SizeOfData);
|
||||
}
|
||||
|
||||
Image->OffX = ImageDesc.OffX;
|
||||
Image->OffY = ImageDesc.OffY;
|
||||
PalOffset = 0;
|
||||
|
||||
// Check to see if the image has its own palette.
|
||||
if (ImageDesc.ImageInfo & (1 << 7)) {
|
||||
ILboolean UsePrevPal = IL_FALSE;
|
||||
if (DisposalMethod == 1 && NumImages != 0) { // Cannot be the first image for this.
|
||||
PalOffset = PrevImage->Pal.PalSize;
|
||||
UsePrevPal = IL_TRUE;
|
||||
}
|
||||
if (!iGetPalette(ImageDesc.ImageInfo, &Image->Pal, UsePrevPal, PrevImage)) {
|
||||
goto error_clean;
|
||||
}
|
||||
} else {
|
||||
if (!iCopyPalette(&Image->Pal, GlobalPal)) {
|
||||
goto error_clean;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GifGetData(Image, Image->Data + ImageDesc.OffX + ImageDesc.OffY*Image->Width, Image->SizeOfData,
|
||||
ImageDesc.Width, ImageDesc.Height, Image->Width, PalOffset, &Gfx)) {
|
||||
memset(Image->Data, 0, Image->SizeOfData); //@TODO: Remove this. For debugging purposes right now.
|
||||
ilSetError(IL_ILLEGAL_FILE_VALUE);
|
||||
goto error_clean;
|
||||
}
|
||||
|
||||
// See if there was a valid graphics control extension.
|
||||
if (!Gfx.Used) {
|
||||
Gfx.Used = IL_TRUE;
|
||||
Image->Duration = Gfx.Delay * 10; // We want it in milliseconds.
|
||||
|
||||
// See if a transparent colour is defined.
|
||||
if (Gfx.Packed & 1) {
|
||||
if (!ConvertTransparent(Image, Gfx.Transparent)) {
|
||||
goto error_clean;
|
||||
}
|
||||
}
|
||||
}
|
||||
i = itell();
|
||||
// Terminates each block.
|
||||
if((input = igetc()) == IL_EOF)
|
||||
goto error_clean;
|
||||
|
||||
if (input != 0x00)
|
||||
iseek(-1, IL_SEEK_CUR);
|
||||
// break;
|
||||
|
||||
OldImageDesc = ImageDesc;
|
||||
}
|
||||
|
||||
//Deinterlace last image
|
||||
if (OldImageDesc.ImageInfo & (1 << 6)) { // Image is interlaced.
|
||||
if (!RemoveInterlace(Image))
|
||||
goto error_clean;
|
||||
}
|
||||
|
||||
if (BaseImage) // Was not able to load any images in...
|
||||
return IL_FALSE;
|
||||
|
||||
return IL_TRUE;
|
||||
|
||||
error_clean:
|
||||
Image = iCurImage->Next;
|
||||
/* while (Image) {
|
||||
TempImage = Image;
|
||||
Image = Image->Next;
|
||||
ilCloseImage(TempImage);
|
||||
}*/
|
||||
return IL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
ILboolean SkipExtensions(GFXCONTROL *Gfx)
|
||||
{
|
||||
ILint Code;
|
||||
ILint Label;
|
||||
ILint Size;
|
||||
|
||||
// DW (06-03-2002): Apparently there can be...
|
||||
//if (GifType == GIF87A)
|
||||
// return IL_TRUE; // No extensions in the GIF87a format.
|
||||
|
||||
do {
|
||||
if((Code = igetc()) == IL_EOF)
|
||||
return IL_FALSE;
|
||||
|
||||
if (Code != 0x21) {
|
||||
iseek(-1, IL_SEEK_CUR);
|
||||
return IL_TRUE;
|
||||
}
|
||||
|
||||
if((Label = igetc()) == IL_EOF)
|
||||
return IL_FALSE;
|
||||
|
||||
switch (Label)
|
||||
{
|
||||
case 0xF9:
|
||||
Gfx->Size = igetc();
|
||||
Gfx->Packed = igetc();
|
||||
Gfx->Delay = GetLittleUShort();
|
||||
Gfx->Transparent = igetc();
|
||||
Gfx->Terminator = igetc();
|
||||
if (ieof())
|
||||
return IL_FALSE;
|
||||
Gfx->Used = IL_FALSE;
|
||||
break;
|
||||
/*case 0xFE:
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
break;*/
|
||||
default:
|
||||
do {
|
||||
if((Size = igetc()) == IL_EOF)
|
||||
return IL_FALSE;
|
||||
iseek(Size, IL_SEEK_CUR);
|
||||
} while (!ieof() && Size != 0);
|
||||
}
|
||||
|
||||
// @TODO: Handle this better.
|
||||
if (ieof()) {
|
||||
ilSetError(IL_FILE_READ_ERROR);
|
||||
return IL_FALSE;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
return IL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
#define MAX_CODES 4096
|
||||
|
||||
ILint curr_size, clear, ending, newcodes, top_slot, slot, navail_bytes = 0, nbits_left = 0;
|
||||
ILubyte b1;
|
||||
ILubyte byte_buff[257];
|
||||
ILubyte *pbytes;
|
||||
ILubyte *stack;
|
||||
ILubyte *suffix;
|
||||
ILshort *prefix;
|
||||
|
||||
ILboolean success;
|
||||
|
||||
ILuint code_mask[13] =
|
||||
{
|
||||
0L,
|
||||
0x0001L, 0x0003L,
|
||||
0x0007L, 0x000FL,
|
||||
0x001FL, 0x003FL,
|
||||
0x007FL, 0x00FFL,
|
||||
0x01FFL, 0x03FFL,
|
||||
0x07FFL, 0x0FFFL
|
||||
};
|
||||
|
||||
|
||||
ILint get_next_code(void) {
|
||||
ILint i, t;
|
||||
ILuint ret;
|
||||
|
||||
//20050102: Tests for IL_EOF were added because this function
|
||||
//crashed sometimes if igetc() returned IL_EOF
|
||||
//(for example "table-add-column-before-active.gif" included in the
|
||||
//mozilla source package)
|
||||
|
||||
if (!nbits_left) {
|
||||
if (navail_bytes <= 0) {
|
||||
pbytes = byte_buff;
|
||||
navail_bytes = igetc();
|
||||
|
||||
if(navail_bytes == IL_EOF) {
|
||||
success = IL_FALSE;
|
||||
return ending;
|
||||
}
|
||||
|
||||
if (navail_bytes) {
|
||||
for (i = 0; i < navail_bytes; i++) {
|
||||
if((t = igetc()) == IL_EOF) {
|
||||
success = IL_FALSE;
|
||||
return ending;
|
||||
}
|
||||
byte_buff[i] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
b1 = *pbytes++;
|
||||
nbits_left = 8;
|
||||
navail_bytes--;
|
||||
}
|
||||
|
||||
ret = b1 >> (8 - nbits_left);
|
||||
while (curr_size > nbits_left) {
|
||||
if (navail_bytes <= 0) {
|
||||
pbytes = byte_buff;
|
||||
navail_bytes = igetc();
|
||||
|
||||
if(navail_bytes == IL_EOF) {
|
||||
success = IL_FALSE;
|
||||
return ending;
|
||||
}
|
||||
|
||||
if (navail_bytes) {
|
||||
for (i = 0; i < navail_bytes; i++) {
|
||||
if((t = igetc()) == IL_EOF) {
|
||||
success = IL_FALSE;
|
||||
return ending;
|
||||
}
|
||||
byte_buff[i] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
b1 = *pbytes++;
|
||||
ret |= b1 << nbits_left;
|
||||
nbits_left += 8;
|
||||
navail_bytes--;
|
||||
}
|
||||
nbits_left -= curr_size;
|
||||
|
||||
return (ret & code_mask[curr_size]);
|
||||
}
|
||||
|
||||
static void cleanUpGifLoadState()
|
||||
{
|
||||
ifree(stack);
|
||||
ifree(suffix);
|
||||
ifree(prefix);
|
||||
|
||||
}
|
||||
|
||||
ILboolean GifGetData(ILimage *Image, ILubyte *Data, ILuint ImageSize, ILuint Width, ILuint Height, ILuint Stride, ILuint PalOffset, GFXCONTROL *Gfx)
|
||||
{
|
||||
ILubyte *sp;
|
||||
ILint code, fc, oc;
|
||||
ILubyte DisposalMethod = 0;
|
||||
ILint c, size;
|
||||
ILuint i = 0, Read = 0, j = 0;
|
||||
ILubyte *DataPtr = Data;
|
||||
|
||||
if (!Gfx->Used)
|
||||
DisposalMethod = (Gfx->Packed & 0x1C) >> 2;
|
||||
if((size = igetc()) == IL_EOF)
|
||||
return IL_FALSE;
|
||||
|
||||
if (size < 2 || 9 < size) {
|
||||
return IL_FALSE;
|
||||
}
|
||||
|
||||
stack = (ILubyte*)ialloc(MAX_CODES + 1);
|
||||
suffix = (ILubyte*)ialloc(MAX_CODES + 1);
|
||||
prefix = (ILshort*)ialloc(sizeof(*prefix) * (MAX_CODES + 1));
|
||||
if (!stack || !suffix || !prefix)
|
||||
{
|
||||
cleanUpGifLoadState();
|
||||
return IL_FALSE;
|
||||
}
|
||||
|
||||
curr_size = size + 1;
|
||||
top_slot = 1 << curr_size;
|
||||
clear = 1 << size;
|
||||
ending = clear + 1;
|
||||
slot = newcodes = ending + 1;
|
||||
navail_bytes = nbits_left = 0;
|
||||
oc = fc = 0;
|
||||
sp = stack;
|
||||
|
||||
while ((c = get_next_code()) != ending && Read < Height) {
|
||||
if (c == clear)
|
||||
{
|
||||
curr_size = size + 1;
|
||||
slot = newcodes;
|
||||
top_slot = 1 << curr_size;
|
||||
while ((c = get_next_code()) == clear);
|
||||
if (c == ending)
|
||||
break;
|
||||
if (c >= slot)
|
||||
c = 0;
|
||||
oc = fc = c;
|
||||
|
||||
if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == c && (Gfx->Packed & 0x1) != 0)
|
||||
i++;
|
||||
else if (i < Width)
|
||||
DataPtr[i++] = c + PalOffset;
|
||||
|
||||
if (i == Width)
|
||||
{
|
||||
DataPtr += Stride;
|
||||
i = 0;
|
||||
Read += 1;
|
||||
++j;
|
||||
if (j >= Height) {
|
||||
cleanUpGifLoadState();
|
||||
return IL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
code = c;
|
||||
//BG-2007-01-10: several fixes for incomplete GIFs
|
||||
if (code >= slot)
|
||||
{
|
||||
code = oc;
|
||||
if (sp >= stack + MAX_CODES) {
|
||||
cleanUpGifLoadState();
|
||||
return IL_FALSE;
|
||||
}
|
||||
*sp++ = fc;
|
||||
}
|
||||
|
||||
if (code >= MAX_CODES)
|
||||
return IL_FALSE;
|
||||
while (code >= newcodes)
|
||||
{
|
||||
if (sp >= stack + MAX_CODES)
|
||||
{
|
||||
cleanUpGifLoadState();
|
||||
return IL_FALSE;
|
||||
}
|
||||
*sp++ = suffix[code];
|
||||
code = prefix[code];
|
||||
}
|
||||
|
||||
if (sp >= stack + MAX_CODES) {
|
||||
cleanUpGifLoadState();
|
||||
return IL_FALSE;
|
||||
}
|
||||
|
||||
*sp++ = (ILbyte)code;
|
||||
if (slot < top_slot)
|
||||
{
|
||||
fc = code;
|
||||
suffix[slot] = fc;
|
||||
prefix[slot++] = oc;
|
||||
oc = c;
|
||||
}
|
||||
if (slot >= top_slot && curr_size < 12)
|
||||
{
|
||||
top_slot <<= 1;
|
||||
curr_size++;
|
||||
}
|
||||
while (sp > stack)
|
||||
{
|
||||
sp--;
|
||||
if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == *sp && (Gfx->Packed & 0x1) != 0)
|
||||
i++;
|
||||
else if (i < Width)
|
||||
DataPtr[i++] = *sp + PalOffset;
|
||||
|
||||
if (i == Width)
|
||||
{
|
||||
i = 0;
|
||||
Read += 1;
|
||||
j = (j+1) % Height;
|
||||
// Needs to start from Data, not Image->Data.
|
||||
DataPtr = Data + j * Stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanUpGifLoadState();
|
||||
return IL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*From the GIF spec:
|
||||
|
||||
The rows of an Interlaced images are arranged in the following order:
|
||||
|
||||
Group 1 : Every 8th. row, starting with row 0. (Pass 1)
|
||||
Group 2 : Every 8th. row, starting with row 4. (Pass 2)
|
||||
Group 3 : Every 4th. row, starting with row 2. (Pass 3)
|
||||
Group 4 : Every 2nd. row, starting with row 1. (Pass 4)
|
||||
*/
|
||||
|
||||
ILboolean RemoveInterlace(ILimage *image)
|
||||
{
|
||||
ILubyte *NewData;
|
||||
ILuint i, j = 0;
|
||||
|
||||
NewData = (ILubyte*)ialloc(image->SizeOfData);
|
||||
if (NewData == NULL)
|
||||
return IL_FALSE;
|
||||
|
||||
//changed 20041230: images with offsety != 0 were not
|
||||
//deinterlaced correctly before...
|
||||
for (i = 0; i < image->OffY; i++, j++) {
|
||||
memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps);
|
||||
}
|
||||
|
||||
for (i = 0 + image->OffY; i < image->Height; i += 8, j++) {
|
||||
memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps);
|
||||
}
|
||||
|
||||
for (i = 4 + image->OffY; i < image->Height; i += 8, j++) {
|
||||
memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps);
|
||||
}
|
||||
|
||||
for (i = 2 + image->OffY; i < image->Height; i += 4, j++) {
|
||||
memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps);
|
||||
}
|
||||
|
||||
for (i = 1 + image->OffY; i < image->Height; i += 2, j++) {
|
||||
memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps);
|
||||
}
|
||||
|
||||
ifree(image->Data);
|
||||
image->Data = NewData;
|
||||
|
||||
return IL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Uses the transparent colour index to make an alpha channel.
|
||||
ILboolean ConvertTransparent(ILimage *Image, ILubyte TransColour)
|
||||
{
|
||||
ILubyte *Palette;
|
||||
ILuint i, j;
|
||||
|
||||
if (!Image->Pal.Palette || !Image->Pal.PalSize) {
|
||||
ilSetError(IL_INTERNAL_ERROR);
|
||||
return IL_FALSE;
|
||||
}
|
||||
|
||||
Palette = (ILubyte*)ialloc(Image->Pal.PalSize / 3 * 4);
|
||||
if (Palette == NULL)
|
||||
return IL_FALSE;
|
||||
|
||||
for (i = 0, j = 0; i < Image->Pal.PalSize; i += 3, j += 4) {
|
||||
Palette[j ] = Image->Pal.Palette[i ];
|
||||
Palette[j+1] = Image->Pal.Palette[i+1];
|
||||
Palette[j+2] = Image->Pal.Palette[i+2];
|
||||
if (j/4 == TransColour)
|
||||
Palette[j+3] = 0x00;
|
||||
else
|
||||
Palette[j+3] = 0xFF;
|
||||
}
|
||||
|
||||
ifree(Image->Pal.Palette);
|
||||
Image->Pal.Palette = Palette;
|
||||
Image->Pal.PalSize = Image->Pal.PalSize / 3 * 4;
|
||||
Image->Pal.PalType = IL_PAL_RGBA32;
|
||||
|
||||
return IL_TRUE;
|
||||
}
|
||||
|
||||
#endif //IL_NO_GIF
|
||||
Reference in New Issue
Block a user