mirror of
https://github.com/love2d/megasource.git
synced 2026-08-17 11:11:35 +02:00
713 lines
14 KiB
C
713 lines
14 KiB
C
//-----------------------------------------------------------------------------
|
|
//
|
|
// ImageLib Sources
|
|
// Copyright (C) 2000-2009 by Denton Woods
|
|
// Last modified: 03/07/2009
|
|
//
|
|
// Filename: src-IL/src/il_psp.c
|
|
//
|
|
// Description: Reads a Paint Shop Pro file.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
#include "il_internal.h"
|
|
#include "il_psp.h"
|
|
#ifndef IL_NO_PSP
|
|
|
|
|
|
ILubyte PSPSignature[32] = {
|
|
0x50, 0x61, 0x69, 0x6E, 0x74, 0x20, 0x53, 0x68, 0x6F, 0x70, 0x20, 0x50, 0x72, 0x6F, 0x20, 0x49,
|
|
0x6D, 0x61, 0x67, 0x65, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x0A, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
ILubyte GenAttHead[4] = {
|
|
0x7E, 0x42, 0x4B, 0x00
|
|
};
|
|
|
|
|
|
// Make these global, since they contain most of the image information.
|
|
GENATT_CHUNK AttChunk;
|
|
PSPHEAD Header;
|
|
ILuint NumChannels;
|
|
ILubyte **Channels = NULL;
|
|
ILubyte *Alpha = NULL;
|
|
ILpal Pal;
|
|
|
|
|
|
|
|
//! Checks if the file specified in FileName is a valid Psp file.
|
|
ILboolean ilIsValidPsp(ILconst_string FileName)
|
|
{
|
|
ILHANDLE PspFile;
|
|
ILboolean bPsp = IL_FALSE;
|
|
|
|
if (!iCheckExtension(FileName, IL_TEXT("psp"))) {
|
|
ilSetError(IL_INVALID_EXTENSION);
|
|
return bPsp;
|
|
}
|
|
|
|
PspFile = iopenr(FileName);
|
|
if (PspFile == NULL) {
|
|
ilSetError(IL_COULD_NOT_OPEN_FILE);
|
|
return bPsp;
|
|
}
|
|
|
|
bPsp = ilIsValidPspF(PspFile);
|
|
icloser(PspFile);
|
|
|
|
return bPsp;
|
|
}
|
|
|
|
|
|
//! Checks if the ILHANDLE contains a valid Psp file at the current position.
|
|
ILboolean ilIsValidPspF(ILHANDLE File)
|
|
{
|
|
ILuint FirstPos;
|
|
ILboolean bRet;
|
|
|
|
iSetInputFile(File);
|
|
FirstPos = itell();
|
|
bRet = iIsValidPsp();
|
|
iseek(FirstPos, IL_SEEK_SET);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
//! Checks if Lump is a valid Psp lump.
|
|
ILboolean ilIsValidPspL(const void *Lump, ILuint Size)
|
|
{
|
|
iSetInputLump(Lump, Size);
|
|
return iIsValidPsp();
|
|
}
|
|
|
|
|
|
// Internal function used to get the Psp header from the current file.
|
|
ILboolean iGetPspHead()
|
|
{
|
|
if (iread(Header.FileSig, 1, 32) != 32)
|
|
return IL_FALSE;
|
|
Header.MajorVersion = GetLittleUShort();
|
|
Header.MinorVersion = GetLittleUShort();
|
|
|
|
return IL_TRUE;
|
|
}
|
|
|
|
|
|
// Internal function to get the header and check it.
|
|
ILboolean iIsValidPsp()
|
|
{
|
|
if (!iGetPspHead())
|
|
return IL_FALSE;
|
|
iseek(-(ILint)sizeof(PSPHEAD), IL_SEEK_CUR);
|
|
|
|
return iCheckPsp();
|
|
}
|
|
|
|
|
|
// Internal function used to check if the HEADER is a valid Psp header.
|
|
ILboolean iCheckPsp()
|
|
{
|
|
if (stricmp(Header.FileSig, "Paint Shop Pro Image File\n\x1a"))
|
|
return IL_FALSE;
|
|
if (Header.MajorVersion < 3 || Header.MajorVersion > 5)
|
|
return IL_FALSE;
|
|
if (Header.MinorVersion != 0)
|
|
return IL_FALSE;
|
|
|
|
|
|
return IL_TRUE;
|
|
}
|
|
|
|
|
|
//! Reads a PSP file
|
|
ILboolean ilLoadPsp(ILconst_string FileName)
|
|
{
|
|
ILHANDLE PSPFile;
|
|
ILboolean bPsp = IL_FALSE;
|
|
|
|
PSPFile = iopenr(FileName);
|
|
if (PSPFile == NULL) {
|
|
ilSetError(IL_COULD_NOT_OPEN_FILE);
|
|
return bPsp;
|
|
}
|
|
|
|
bPsp = ilLoadPspF(PSPFile);
|
|
icloser(PSPFile);
|
|
|
|
return bPsp;
|
|
}
|
|
|
|
|
|
//! Reads an already-opened PSP file
|
|
ILboolean ilLoadPspF(ILHANDLE File)
|
|
{
|
|
ILuint FirstPos;
|
|
ILboolean bRet;
|
|
|
|
iSetInputFile(File);
|
|
FirstPos = itell();
|
|
bRet = iLoadPspInternal();
|
|
iseek(FirstPos, IL_SEEK_SET);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
//! Reads from a memory "lump" that contains a PSP
|
|
ILboolean ilLoadPspL(const void *Lump, ILuint Size)
|
|
{
|
|
iSetInputLump(Lump, Size);
|
|
return iLoadPspInternal();
|
|
}
|
|
|
|
|
|
// Internal function used to load the PSP.
|
|
ILboolean iLoadPspInternal()
|
|
{
|
|
if (iCurImage == NULL) {
|
|
ilSetError(IL_ILLEGAL_OPERATION);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
Channels = NULL;
|
|
Alpha = NULL;
|
|
Pal.Palette = NULL;
|
|
|
|
if (!iGetPspHead())
|
|
return IL_FALSE;
|
|
if (!iCheckPsp()) {
|
|
ilSetError(IL_INVALID_FILE_HEADER);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
if (!ReadGenAttributes())
|
|
return IL_FALSE;
|
|
if (!ParseChunks())
|
|
return IL_FALSE;
|
|
if (!AssembleImage())
|
|
return IL_FALSE;
|
|
|
|
Cleanup();
|
|
return ilFixImage();
|
|
}
|
|
|
|
|
|
ILboolean ReadGenAttributes()
|
|
{
|
|
BLOCKHEAD AttHead;
|
|
ILint Padding;
|
|
ILuint ChunkLen;
|
|
|
|
if (iread(&AttHead, sizeof(AttHead), 1) != 1)
|
|
return IL_FALSE;
|
|
UShort(&AttHead.BlockID);
|
|
UInt(&AttHead.BlockLen);
|
|
|
|
if (AttHead.HeadID[0] != 0x7E || AttHead.HeadID[1] != 0x42 ||
|
|
AttHead.HeadID[2] != 0x4B || AttHead.HeadID[3] != 0x00) {
|
|
ilSetError(IL_INVALID_FILE_HEADER);
|
|
return IL_FALSE;
|
|
}
|
|
if (AttHead.BlockID != PSP_IMAGE_BLOCK) {
|
|
ilSetError(IL_INVALID_FILE_HEADER);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
ChunkLen = GetLittleUInt();
|
|
if (Header.MajorVersion != 3)
|
|
ChunkLen -= 4;
|
|
if (iread(&AttChunk, IL_MIN(sizeof(AttChunk), ChunkLen), 1) != 1)
|
|
return IL_FALSE;
|
|
|
|
// Can have new entries in newer versions of the spec (4.0).
|
|
Padding = (ChunkLen) - sizeof(AttChunk);
|
|
if (Padding > 0)
|
|
iseek(Padding, IL_SEEK_CUR);
|
|
|
|
// @TODO: Anything but 24 not supported yet...
|
|
if (AttChunk.BitDepth != 24 && AttChunk.BitDepth != 8) {
|
|
ilSetError(IL_INVALID_FILE_HEADER);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
// @TODO; Add support for compression...
|
|
if (AttChunk.Compression != PSP_COMP_NONE && AttChunk.Compression != PSP_COMP_RLE) {
|
|
ilSetError(IL_INVALID_FILE_HEADER);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
// @TODO: Check more things in the general attributes chunk here.
|
|
|
|
return IL_TRUE;
|
|
}
|
|
|
|
|
|
ILboolean ParseChunks()
|
|
{
|
|
BLOCKHEAD Block;
|
|
ILuint Pos;
|
|
|
|
do {
|
|
if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) {
|
|
ilGetError(); // Get rid of the erroneous IL_FILE_READ_ERROR.
|
|
return IL_TRUE;
|
|
}
|
|
if (Header.MajorVersion == 3)
|
|
Block.BlockLen = GetLittleUInt();
|
|
else
|
|
UInt(&Block.BlockLen);
|
|
|
|
if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 ||
|
|
Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) {
|
|
return IL_TRUE;
|
|
}
|
|
UShort(&Block.BlockID);
|
|
UInt(&Block.BlockLen);
|
|
|
|
Pos = itell();
|
|
|
|
switch (Block.BlockID)
|
|
{
|
|
case PSP_LAYER_START_BLOCK:
|
|
if (!ReadLayerBlock(Block.BlockLen))
|
|
return IL_FALSE;
|
|
break;
|
|
|
|
case PSP_ALPHA_BANK_BLOCK:
|
|
if (!ReadAlphaBlock(Block.BlockLen))
|
|
return IL_FALSE;
|
|
break;
|
|
|
|
case PSP_COLOR_BLOCK:
|
|
if (!ReadPalette(Block.BlockLen))
|
|
return IL_FALSE;
|
|
break;
|
|
|
|
// Gets done in the next iseek, so this is now commented out.
|
|
//default:
|
|
//iseek(Block.BlockLen, IL_SEEK_CUR);
|
|
}
|
|
|
|
// Skip to next block just in case we didn't read the entire block.
|
|
iseek(Pos + Block.BlockLen, IL_SEEK_SET);
|
|
|
|
// @TODO: Do stuff here.
|
|
|
|
} while (1);
|
|
|
|
return IL_TRUE;
|
|
}
|
|
|
|
|
|
ILboolean ReadLayerBlock(ILuint BlockLen)
|
|
{
|
|
BLOCKHEAD Block;
|
|
LAYERINFO_CHUNK LayerInfo;
|
|
LAYERBITMAP_CHUNK Bitmap;
|
|
ILuint ChunkSize, Padding, i, j;
|
|
ILushort NumChars;
|
|
|
|
BlockLen;
|
|
|
|
// Layer sub-block header
|
|
if (iread(&Block, 1, sizeof(Block)) != sizeof(Block))
|
|
return IL_FALSE;
|
|
if (Header.MajorVersion == 3)
|
|
Block.BlockLen = GetLittleUInt();
|
|
else
|
|
UInt(&Block.BlockLen);
|
|
|
|
if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 ||
|
|
Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) {
|
|
return IL_FALSE;
|
|
}
|
|
if (Block.BlockID != PSP_LAYER_BLOCK)
|
|
return IL_FALSE;
|
|
|
|
|
|
if (Header.MajorVersion == 3) {
|
|
iseek(256, IL_SEEK_CUR); // We don't care about the name of the layer.
|
|
iread(&LayerInfo, sizeof(LayerInfo), 1);
|
|
if (iread(&Bitmap, sizeof(Bitmap), 1) != 1)
|
|
return IL_FALSE;
|
|
}
|
|
else { // Header.MajorVersion >= 4
|
|
ChunkSize = GetLittleUInt();
|
|
NumChars = GetLittleUShort();
|
|
iseek(NumChars, IL_SEEK_CUR); // We don't care about the layer's name.
|
|
|
|
ChunkSize -= (2 + 4 + NumChars);
|
|
|
|
if (iread(&LayerInfo, IL_MIN(sizeof(LayerInfo), ChunkSize), 1) != 1)
|
|
return IL_FALSE;
|
|
|
|
// Can have new entries in newer versions of the spec (5.0).
|
|
Padding = (ChunkSize) - sizeof(LayerInfo);
|
|
if (Padding > 0)
|
|
iseek(Padding, IL_SEEK_CUR);
|
|
|
|
ChunkSize = GetLittleUInt();
|
|
if (iread(&Bitmap, sizeof(Bitmap), 1) != 1)
|
|
return IL_FALSE;
|
|
Padding = (ChunkSize - 4) - sizeof(Bitmap);
|
|
if (Padding > 0)
|
|
iseek(Padding, IL_SEEK_CUR);
|
|
}
|
|
|
|
|
|
Channels = (ILubyte**)ialloc(sizeof(ILubyte*) * Bitmap.NumChannels);
|
|
if (Channels == NULL) {
|
|
return IL_FALSE;
|
|
}
|
|
|
|
NumChannels = Bitmap.NumChannels;
|
|
|
|
for (i = 0; i < NumChannels; i++) {
|
|
Channels[i] = GetChannel();
|
|
if (Channels[i] == NULL) {
|
|
for (j = 0; j < i; j++)
|
|
ifree(Channels[j]);
|
|
return IL_FALSE;
|
|
}
|
|
}
|
|
|
|
return IL_TRUE;
|
|
}
|
|
|
|
|
|
ILboolean ReadAlphaBlock(ILuint BlockLen)
|
|
{
|
|
BLOCKHEAD Block;
|
|
ALPHAINFO_CHUNK AlphaInfo;
|
|
ALPHA_CHUNK AlphaChunk;
|
|
ILushort NumAlpha, StringSize;
|
|
ILuint ChunkSize, Padding;
|
|
|
|
if (Header.MajorVersion == 3) {
|
|
NumAlpha = GetLittleUShort();
|
|
}
|
|
else {
|
|
ChunkSize = GetLittleUInt();
|
|
NumAlpha = GetLittleUShort();
|
|
Padding = (ChunkSize - 4 - 2);
|
|
if (Padding > 0)
|
|
iseek(Padding, IL_SEEK_CUR);
|
|
}
|
|
|
|
// Alpha channel header
|
|
if (iread(&Block, 1, sizeof(Block)) != sizeof(Block))
|
|
return IL_FALSE;
|
|
if (Header.MajorVersion == 3)
|
|
Block.BlockLen = GetLittleUInt();
|
|
else
|
|
UInt(&Block.BlockLen);
|
|
|
|
if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 ||
|
|
Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) {
|
|
return IL_FALSE;
|
|
}
|
|
if (Block.BlockID != PSP_ALPHA_CHANNEL_BLOCK)
|
|
return IL_FALSE;
|
|
|
|
|
|
if (Header.MajorVersion >= 4) {
|
|
ChunkSize = GetLittleUInt();
|
|
StringSize = GetLittleUShort();
|
|
iseek(StringSize, IL_SEEK_CUR);
|
|
if (iread(&AlphaInfo, sizeof(AlphaInfo), 1) != 1)
|
|
return IL_FALSE;
|
|
Padding = (ChunkSize - 4 - 2 - StringSize - sizeof(AlphaInfo));
|
|
if (Padding > 0)
|
|
iseek(Padding, IL_SEEK_CUR);
|
|
|
|
ChunkSize = GetLittleUInt();
|
|
if (iread(&AlphaChunk, sizeof(AlphaChunk), 1) != 1)
|
|
return IL_FALSE;
|
|
Padding = (ChunkSize - 4 - sizeof(AlphaChunk));
|
|
if (Padding > 0)
|
|
iseek(Padding, IL_SEEK_CUR);
|
|
}
|
|
else {
|
|
iseek(256, IL_SEEK_CUR);
|
|
iread(&AlphaInfo, sizeof(AlphaInfo), 1);
|
|
if (iread(&AlphaChunk, sizeof(AlphaChunk), 1) != 1)
|
|
return IL_FALSE;
|
|
}
|
|
|
|
|
|
/*Alpha = (ILubyte*)ialloc(AlphaInfo.AlphaRect.x2 * AlphaInfo.AlphaRect.y2);
|
|
if (Alpha == NULL) {
|
|
return IL_FALSE;
|
|
}*/
|
|
|
|
|
|
Alpha = GetChannel();
|
|
if (Alpha == NULL)
|
|
return IL_FALSE;
|
|
|
|
return IL_TRUE;
|
|
}
|
|
|
|
|
|
ILubyte *GetChannel()
|
|
{
|
|
BLOCKHEAD Block;
|
|
CHANNEL_CHUNK Channel;
|
|
ILubyte *CompData, *Data;
|
|
ILuint ChunkSize, Padding;
|
|
|
|
if (iread(&Block, 1, sizeof(Block)) != sizeof(Block))
|
|
return NULL;
|
|
if (Header.MajorVersion == 3)
|
|
Block.BlockLen = GetLittleUInt();
|
|
else
|
|
UInt(&Block.BlockLen);
|
|
|
|
if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 ||
|
|
Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) {
|
|
ilSetError(IL_ILLEGAL_FILE_VALUE);
|
|
return NULL;
|
|
}
|
|
if (Block.BlockID != PSP_CHANNEL_BLOCK) {
|
|
ilSetError(IL_ILLEGAL_FILE_VALUE);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
if (Header.MajorVersion >= 4) {
|
|
ChunkSize = GetLittleUInt();
|
|
if (iread(&Channel, sizeof(Channel), 1) != 1)
|
|
return NULL;
|
|
|
|
Padding = (ChunkSize - 4) - sizeof(Channel);
|
|
if (Padding > 0)
|
|
iseek(Padding, IL_SEEK_CUR);
|
|
}
|
|
else {
|
|
if (iread(&Channel, sizeof(Channel), 1) != 1)
|
|
return NULL;
|
|
}
|
|
|
|
|
|
CompData = (ILubyte*)ialloc(Channel.CompLen);
|
|
Data = (ILubyte*)ialloc(AttChunk.Width * AttChunk.Height);
|
|
if (CompData == NULL || Data == NULL) {
|
|
ifree(Data);
|
|
ifree(CompData);
|
|
return NULL;
|
|
}
|
|
|
|
if (iread(CompData, 1, Channel.CompLen) != Channel.CompLen) {
|
|
ifree(CompData);
|
|
ifree(Data);
|
|
return NULL;
|
|
}
|
|
|
|
switch (AttChunk.Compression)
|
|
{
|
|
case PSP_COMP_NONE:
|
|
ifree(Data);
|
|
return CompData;
|
|
break;
|
|
|
|
case PSP_COMP_RLE:
|
|
if (!UncompRLE(CompData, Data, Channel.CompLen)) {
|
|
ifree(CompData);
|
|
ifree(Data);
|
|
return IL_FALSE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ifree(CompData);
|
|
ifree(Data);
|
|
ilSetError(IL_INVALID_FILE_HEADER);
|
|
return NULL;
|
|
}
|
|
|
|
ifree(CompData);
|
|
|
|
return Data;
|
|
}
|
|
|
|
|
|
ILboolean UncompRLE(ILubyte *CompData, ILubyte *Data, ILuint CompLen)
|
|
{
|
|
ILubyte Run, Colour;
|
|
ILint i, /*x, y,*/ Count/*, Total = 0*/;
|
|
|
|
/*for (y = 0; y < AttChunk.Height; y++) {
|
|
for (x = 0, Count = 0; x < AttChunk.Width; ) {
|
|
Run = *CompData++;
|
|
if (Run > 128) {
|
|
Run -= 128;
|
|
Colour = *CompData++;
|
|
memset(Data, Colour, Run);
|
|
Data += Run;
|
|
Count += 2;
|
|
}
|
|
else {
|
|
memcpy(Data, CompData, Run);
|
|
CompData += Run;
|
|
Data += Run;
|
|
Count += Run;
|
|
}
|
|
x += Run;
|
|
}
|
|
|
|
Total += Count;
|
|
|
|
if (Count % 4) { // Has to be on a 4-byte boundary.
|
|
CompData += (4 - (Count % 4)) % 4;
|
|
Total += (4 - (Count % 4)) % 4;
|
|
}
|
|
|
|
if (Total >= CompLen)
|
|
return IL_FALSE;
|
|
}*/
|
|
|
|
for (i = 0, Count = 0; i < (ILint)CompLen; ) {
|
|
Run = *CompData++;
|
|
i++;
|
|
if (Run > 128) {
|
|
Run -= 128;
|
|
Colour = *CompData++;
|
|
i++;
|
|
memset(Data, Colour, Run);
|
|
}
|
|
else {
|
|
memcpy(Data, CompData, Run);
|
|
CompData += Run;
|
|
i += Run;
|
|
}
|
|
Data += Run;
|
|
Count += Run;
|
|
}
|
|
|
|
return IL_TRUE;
|
|
}
|
|
|
|
|
|
ILboolean ReadPalette(ILuint BlockLen)
|
|
{
|
|
ILuint ChunkSize, PalCount, Padding;
|
|
|
|
if (Header.MajorVersion >= 4) {
|
|
ChunkSize = GetLittleUInt();
|
|
PalCount = GetLittleUInt();
|
|
Padding = (ChunkSize - 4 - 4);
|
|
if (Padding > 0)
|
|
iseek(Padding, IL_SEEK_CUR);
|
|
}
|
|
else {
|
|
PalCount = GetLittleUInt();
|
|
}
|
|
|
|
Pal.PalSize = PalCount * 4;
|
|
Pal.PalType = IL_PAL_BGRA32;
|
|
Pal.Palette = (ILubyte*)ialloc(Pal.PalSize);
|
|
if (Pal.Palette == NULL)
|
|
return IL_FALSE;
|
|
|
|
if (iread(Pal.Palette, Pal.PalSize, 1) != 1) {
|
|
ifree(Pal.Palette);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
return IL_TRUE;
|
|
}
|
|
|
|
|
|
ILboolean AssembleImage()
|
|
{
|
|
ILuint Size, i, j;
|
|
|
|
Size = AttChunk.Width * AttChunk.Height;
|
|
|
|
if (NumChannels == 1) {
|
|
ilTexImage(AttChunk.Width, AttChunk.Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL);
|
|
for (i = 0; i < Size; i++) {
|
|
iCurImage->Data[i] = Channels[0][i];
|
|
}
|
|
|
|
if (Pal.Palette) {
|
|
iCurImage->Format = IL_COLOUR_INDEX;
|
|
iCurImage->Pal.PalSize = Pal.PalSize;
|
|
iCurImage->Pal.PalType = Pal.PalType;
|
|
iCurImage->Pal.Palette = Pal.Palette;
|
|
}
|
|
}
|
|
else {
|
|
if (Alpha) {
|
|
ilTexImage(AttChunk.Width, AttChunk.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL);
|
|
for (i = 0, j = 0; i < Size; i++, j += 4) {
|
|
iCurImage->Data[j ] = Channels[0][i];
|
|
iCurImage->Data[j+1] = Channels[1][i];
|
|
iCurImage->Data[j+2] = Channels[2][i];
|
|
iCurImage->Data[j+3] = Alpha[i];
|
|
}
|
|
}
|
|
|
|
else if (NumChannels == 4) {
|
|
|
|
ilTexImage(AttChunk.Width, AttChunk.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL);
|
|
|
|
for (i = 0, j = 0; i < Size; i++, j += 4) {
|
|
|
|
iCurImage->Data[j ] = Channels[0][i];
|
|
|
|
iCurImage->Data[j+1] = Channels[1][i];
|
|
|
|
iCurImage->Data[j+2] = Channels[2][i];
|
|
|
|
iCurImage->Data[j+3] = Channels[3][i];
|
|
|
|
}
|
|
|
|
}
|
|
else if (NumChannels == 3) {
|
|
ilTexImage(AttChunk.Width, AttChunk.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL);
|
|
for (i = 0, j = 0; i < Size; i++, j += 3) {
|
|
iCurImage->Data[j ] = Channels[0][i];
|
|
iCurImage->Data[j+1] = Channels[1][i];
|
|
iCurImage->Data[j+2] = Channels[2][i];
|
|
}
|
|
}
|
|
else
|
|
return IL_FALSE;
|
|
}
|
|
|
|
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
|
|
|
|
return IL_TRUE;
|
|
}
|
|
|
|
|
|
ILboolean Cleanup()
|
|
{
|
|
ILuint i;
|
|
|
|
if (Channels) {
|
|
for (i = 0; i < NumChannels; i++) {
|
|
ifree(Channels[i]);
|
|
}
|
|
ifree(Channels);
|
|
}
|
|
|
|
if (Alpha) {
|
|
ifree(Alpha);
|
|
}
|
|
|
|
Channels = NULL;
|
|
Alpha = NULL;
|
|
Pal.Palette = NULL;
|
|
|
|
return IL_TRUE;
|
|
}
|
|
|
|
|
|
|
|
#endif//IL_NO_PSP
|