Files
Client/rylCoder_16.02.2008_src/addons/DevIL/src-IL/src/il_pal.c
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

1097 lines
27 KiB
C

//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 03/15/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_pal.c
//
// Description: Loads palettes from different file formats
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#include "il_pal.h"
#include <string.h>
#include <ctype.h>
#include <limits.h>
//! Loads a palette from FileName into the current image's palette.
ILboolean ILAPIENTRY ilLoadPal(ILconst_string FileName)
{
FILE *f;
ILboolean IsPsp;
char Head[8];
if (FileName == NULL) {
ilSetError(IL_INVALID_PARAM);
return IL_FALSE;
}
if (iCheckExtension(FileName, IL_TEXT("col"))) {
return ilLoadColPal(FileName);
}
if (iCheckExtension(FileName, IL_TEXT("act"))) {
return ilLoadActPal(FileName);
}
if (iCheckExtension(FileName, IL_TEXT("plt"))) {
return ilLoadPltPal(FileName);
}
#ifndef _UNICODE
f = fopen(FileName, "rt");
#else
f = _wfopen(FileName, L"rt");
#endif//_UNICODE
if (f == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return IL_FALSE;
}
fread(Head, 1, 8, f);
if (!strncmp(Head, "JASC-PAL", 8))
IsPsp = IL_TRUE;
else
IsPsp = IL_FALSE;
fclose(f);
if (IsPsp)
return ilLoadJascPal(FileName);
return ilLoadHaloPal(FileName);
}
//! Loads a Paint Shop Pro formatted palette (.pal) file.
ILboolean ilLoadJascPal(ILconst_string FileName)
{
FILE *PalFile;
ILuint NumColours, i, c;
ILubyte Buff[BUFFLEN];
ILboolean Error = IL_FALSE;
ILpal *Pal = &iCurImage->Pal;
if (!iCheckExtension(FileName, IL_TEXT("pal"))) {
ilSetError(IL_INVALID_EXTENSION);
return IL_FALSE;
}
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
#ifndef _UNICODE
PalFile = fopen(FileName, "rt");
#else
PalFile = _wfopen(FileName, L"rt");
#endif//_UNICODE
if (PalFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return IL_FALSE;
}
if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) {
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.Palette = NULL;
}
iFgetw(Buff, BUFFLEN, PalFile);
if (stricmp((const char*)Buff, "JASC-PAL")) {
Error = IL_TRUE;
}
iFgetw(Buff, BUFFLEN, PalFile);
if (stricmp((const char*)Buff, "0100")) {
Error = IL_TRUE;
}
iFgetw(Buff, BUFFLEN, PalFile);
NumColours = atoi((const char*)Buff);
if (NumColours == 0 || Error) {
ilSetError(IL_INVALID_FILE_HEADER);
fclose(PalFile);
return IL_FALSE;
}
Pal->PalSize = NumColours * PALBPP;
Pal->PalType = IL_PAL_RGB24;
Pal->Palette = (ILubyte*)ialloc(NumColours * PALBPP);
if (Pal->Palette == NULL) {
fclose(PalFile);
return IL_FALSE;
}
for (i = 0; i < NumColours; i++) {
for (c = 0; c < PALBPP; c++) {
iFgetw(Buff, BUFFLEN, PalFile);
Pal->Palette[i * PALBPP + c] = atoi((const char*)Buff);
}
}
fclose(PalFile);
return IL_TRUE;
}
// File Get Word
// MaxLen must be greater than 1, because the trailing NULL is always stored.
char *iFgetw(ILubyte *Buff, ILint MaxLen, FILE *File)
{
ILint Temp;
ILint i;
if (Buff == NULL || File == NULL || MaxLen < 2) {
ilSetError(IL_INVALID_PARAM);
return NULL;
}
for (i = 0; i < MaxLen - 1; i++) {
Temp = fgetc(File);
if (Temp == '\n' || Temp == '\0' || Temp == IL_EOF || feof(File)) {
break;
}
if (Temp == ' ') {
while (Temp == ' ') { // Just to get rid of any extra spaces
Temp = fgetc(File);
}
fseek(File, -1, IL_SEEK_CUR); // Go back one
break;
}
if (!isprint(Temp)) { // Skips any non-printing characters
while (!isprint(Temp)) {
Temp = fgetc(File);
}
fseek(File, -1, IL_SEEK_CUR);
break;
}
Buff[i] = Temp;
}
Buff[i] = '\0';
return (char *)Buff;
}
ILboolean ILAPIENTRY ilSavePal(ILconst_string FileName)
{
ILstring Ext = iGetExtension(FileName);
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
#ifndef _UNICODE
if (FileName == NULL || strlen(FileName) < 1 || Ext == NULL) {
#else
if (FileName == NULL || wcslen(FileName) < 1 || Ext == NULL) {
#endif//_UNICODE
ilSetError(IL_INVALID_PARAM);
return IL_FALSE;
}
if (!iCurImage->Pal.Palette || !iCurImage->Pal.PalSize || iCurImage->Pal.PalType == IL_PAL_NONE) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!iStrCmp(Ext, IL_TEXT("pal"))) {
return ilSaveJascPal(FileName);
}
ilSetError(IL_INVALID_EXTENSION);
return IL_FALSE;
}
//! Saves a Paint Shop Pro formatted palette (.pal) file.
ILboolean ilSaveJascPal(ILconst_string FileName)
{
FILE *PalFile;
ILuint i, PalBpp, NumCols = ilGetInteger(IL_PALETTE_NUM_COLS);
ILubyte *CurPal;
if (iCurImage == NULL || NumCols == 0 || NumCols > 256) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
#ifndef _UNICODE
if (FileName == NULL || strlen(FileName) < 5) {
#else
if (FileName == NULL || wcslen(FileName) < 5) {
#endif//_UNICODE
ilSetError(IL_INVALID_VALUE);
return IL_FALSE;
}
if (!iCheckExtension(FileName, IL_TEXT("pal"))) {
ilSetError(IL_INVALID_EXTENSION);
return IL_FALSE;
}
if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
if (iFileExists(FileName)) {
ilSetError(IL_FILE_ALREADY_EXISTS);
return IL_FALSE;
}
}
// Create a copy of the current palette and convert it to RGB24 format.
CurPal = iCurImage->Pal.Palette;
iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
if (!iCurImage->Pal.Palette) {
iCurImage->Pal.Palette = CurPal;
return IL_FALSE;
}
memcpy(iCurImage->Pal.Palette, CurPal, iCurImage->Pal.PalSize);
if (!ilConvertPal(IL_PAL_RGB24)) {
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.Palette = CurPal;
return IL_FALSE;
}
#ifndef _UNICODE
PalFile = fopen(FileName, "wt");
#else
PalFile = _wfopen(FileName, L"wt");
#endif//_UNICODE
if (!PalFile) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return IL_FALSE;
}
// Header needed on all .pal files
fputs("JASC-PAL\n0100\n256\n", PalFile);
PalBpp = ilGetBppPal(iCurImage->Pal.PalType);
for (i = 0; i < iCurImage->Pal.PalSize; i += PalBpp) {
fprintf(PalFile, "%d %d %d\n",
iCurImage->Pal.Palette[i], iCurImage->Pal.Palette[i+1], iCurImage->Pal.Palette[i+2]);
}
NumCols = 256 - NumCols;
for (i = 0; i < NumCols; i++) {
fprintf(PalFile, "0 0 0\n");
}
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.Palette = CurPal;
fclose(PalFile);
return IL_TRUE;
}
//! Loads a Halo formatted palette (.pal) file.
ILboolean ilLoadHaloPal(ILconst_string FileName)
{
ILHANDLE HaloFile;
HALOHEAD HaloHead;
ILushort *TempPal;
ILuint i, Size;
if (!iCheckExtension(FileName, IL_TEXT("pal"))) {
ilSetError(IL_INVALID_EXTENSION);
return IL_FALSE;
}
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
HaloFile = iopenr(FileName);
if (HaloFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return IL_FALSE;
}
if (iread(&HaloHead, sizeof(HALOHEAD), 1) != 1)
return IL_FALSE;
if (HaloHead.Id != 'A' + ('H' << 8) || HaloHead.Version != 0xe3) {
icloser(HaloFile);
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
Size = (HaloHead.MaxIndex + 1) * 3;
TempPal = (ILushort*)ialloc(Size * sizeof(ILushort));
if (TempPal == NULL) {
icloser(HaloFile);
return IL_FALSE;
}
if (iread(TempPal, sizeof(ILushort), Size) != Size) {
icloser(HaloFile);
ifree(TempPal);
return IL_FALSE;
}
if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) {
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.Palette = NULL;
}
iCurImage->Pal.PalType = IL_PAL_RGB24;
iCurImage->Pal.PalSize = Size;
iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
if (iCurImage->Pal.Palette == NULL) {
icloser(HaloFile);
return IL_FALSE;
}
for (i = 0; i < iCurImage->Pal.PalSize; i++, TempPal++) {
iCurImage->Pal.Palette[i] = (ILubyte)*TempPal;
}
TempPal -= iCurImage->Pal.PalSize;
ifree(TempPal);
icloser(HaloFile);
return IL_TRUE;
}
// Hasn't been tested
// @TODO: Test the thing!
//! Loads a .col palette file
ILboolean ilLoadColPal(ILconst_string FileName)
{
ILuint RealFileSize, FileSize;
ILushort Version;
ILHANDLE ColFile;
if (!iCheckExtension(FileName, IL_TEXT("col"))) {
ilSetError(IL_INVALID_EXTENSION);
return IL_FALSE;
}
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
ColFile = iopenr(FileName);
if (ColFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return IL_FALSE;
}
if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) {
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.Palette = NULL;
}
iseek(0, IL_SEEK_END);
RealFileSize = ftell((FILE*)ColFile);
iseek(0, IL_SEEK_SET);
if (RealFileSize > 768) { // has a header
fread(&FileSize, 4, 1, (FILE*)ColFile);
if ((FileSize - 8) % 3 != 0) { // check to make sure an even multiple of 3!
icloser(ColFile);
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
if (iread(&Version, 2, 1) != 1) {
icloser(ColFile);
return IL_FALSE;
}
if (Version != 0xB123) {
icloser(ColFile);
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
if (iread(&Version, 2, 1) != 1) {
icloser(ColFile);
return IL_FALSE;
}
if (Version != 0) {
icloser(ColFile);
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
}
iCurImage->Pal.Palette = (ILubyte*)ialloc(768);
if (iCurImage->Pal.Palette == NULL) {
icloser(ColFile);
return IL_FALSE;
}
if (iread(iCurImage->Pal.Palette, 1, 768) != 768) {
icloser(ColFile);
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.Palette = NULL;
return IL_FALSE;
}
iCurImage->Pal.PalSize = 768;
iCurImage->Pal.PalType = IL_PAL_RGB24;
icloser(ColFile);
return IL_TRUE;
}
//! Loads an .act palette file.
ILboolean ilLoadActPal(ILconst_string FileName)
{
ILHANDLE ActFile;
if (!iCheckExtension(FileName, IL_TEXT("act"))) {
ilSetError(IL_INVALID_EXTENSION);
return IL_FALSE;
}
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
ActFile = iopenr(FileName);
if (ActFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return IL_FALSE;
}
if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) {
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.Palette = NULL;
}
iCurImage->Pal.PalType = IL_PAL_RGB24;
iCurImage->Pal.PalSize = 768;
iCurImage->Pal.Palette = (ILubyte*)ialloc(768);
if (!iCurImage->Pal.Palette) {
icloser(ActFile);
return IL_FALSE;
}
if (iread(iCurImage->Pal.Palette, 1, 768) != 768) {
icloser(ActFile);
return IL_FALSE;
}
icloser(ActFile);
return IL_TRUE;
}
//! Loads an .plt palette file.
ILboolean ilLoadPltPal(ILconst_string FileName)
{
ILHANDLE PltFile;
if (!iCheckExtension(FileName, IL_TEXT("plt"))) {
ilSetError(IL_INVALID_EXTENSION);
return IL_FALSE;
}
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
PltFile = iopenr(FileName);
if (PltFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return IL_FALSE;
}
if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) {
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.Palette = NULL;
}
iCurImage->Pal.PalSize = GetLittleUInt();
if (iCurImage->Pal.PalSize == 0) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
iCurImage->Pal.PalType = IL_PAL_RGB24;
iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
if (!iCurImage->Pal.Palette) {
icloser(PltFile);
return IL_FALSE;
}
if (iread(iCurImage->Pal.Palette, iCurImage->Pal.PalSize, 1) != 1) {
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.Palette = NULL;
icloser(PltFile);
return IL_FALSE;
}
icloser(PltFile);
return IL_TRUE;
}
ILAPI ILpal* ILAPIENTRY iCopyPal()
{
ILpal *Pal;
if (iCurImage == NULL || iCurImage->Pal.Palette == NULL ||
iCurImage->Pal.PalSize == 0 || iCurImage->Pal.PalType == IL_PAL_NONE) {
ilSetError(IL_ILLEGAL_OPERATION);
return NULL;
}
Pal = (ILpal*)ialloc(sizeof(ILpal));
if (Pal == NULL) {
return NULL;
}
Pal->Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
if (Pal->Palette == NULL) {
ifree(Pal);
return NULL;
}
memcpy(Pal->Palette, iCurImage->Pal.Palette, iCurImage->Pal.PalSize);
Pal->PalSize = iCurImage->Pal.PalSize;
Pal->PalType = iCurImage->Pal.PalType;
return Pal;
}
// Converts the palette to the DestFormat format.
ILAPI ILpal* ILAPIENTRY iConvertPal(ILpal *Pal, ILenum DestFormat)
{
ILpal *NewPal = NULL;
ILuint i, j, NewPalSize;
// Checks to see if the current image is valid and has a palette
if (Pal == NULL || Pal->PalSize == 0 || Pal->Palette == NULL || Pal->PalType == IL_PAL_NONE) {
ilSetError(IL_ILLEGAL_OPERATION);
return NULL;
}
/*if (Pal->PalType == DestFormat) {
return NULL;
}*/
NewPal = (ILpal*)ialloc(sizeof(ILpal));
if (NewPal == NULL) {
return NULL;
}
NewPal->PalSize = Pal->PalSize;
NewPal->PalType = Pal->PalType;
switch (DestFormat)
{
case IL_PAL_RGB24:
case IL_PAL_BGR24:
switch (Pal->PalType)
{
case IL_PAL_RGB24:
NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize);
if (NewPal->Palette == NULL)
goto alloc_error;
if (DestFormat == IL_PAL_BGR24) {
j = ilGetBppPal(Pal->PalType);
for (i = 0; i < Pal->PalSize; i += j) {
NewPal->Palette[i] = Pal->Palette[i+2];
NewPal->Palette[i+1] = Pal->Palette[i+1];
NewPal->Palette[i+2] = Pal->Palette[i];
}
}
else {
memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize);
}
NewPal->PalType = DestFormat;
break;
case IL_PAL_BGR24:
NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize);
if (NewPal->Palette == NULL)
goto alloc_error;
if (DestFormat == IL_PAL_RGB24) {
j = ilGetBppPal(Pal->PalType);
for (i = 0; i < Pal->PalSize; i += j) {
NewPal->Palette[i] = Pal->Palette[i+2];
NewPal->Palette[i+1] = Pal->Palette[i+1];
NewPal->Palette[i+2] = Pal->Palette[i];
}
}
else {
memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize);
}
NewPal->PalType = DestFormat;
break;
case IL_PAL_BGR32:
case IL_PAL_BGRA32:
NewPalSize = (ILuint)((ILfloat)Pal->PalSize * 3.0f / 4.0f);
NewPal->Palette = (ILubyte*)ialloc(NewPalSize);
if (NewPal->Palette == NULL)
goto alloc_error;
if (DestFormat == IL_PAL_RGB24) {
for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) {
NewPal->Palette[j] = Pal->Palette[i+2];
NewPal->Palette[j+1] = Pal->Palette[i+1];
NewPal->Palette[j+2] = Pal->Palette[i];
}
}
else {
for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) {
NewPal->Palette[j] = Pal->Palette[i];
NewPal->Palette[j+1] = Pal->Palette[i+1];
NewPal->Palette[j+2] = Pal->Palette[i+2];
}
}
NewPal->PalSize = NewPalSize;
NewPal->PalType = DestFormat;
break;
case IL_PAL_RGB32:
case IL_PAL_RGBA32:
NewPalSize = (ILuint)((ILfloat)Pal->PalSize * 3.0f / 4.0f);
NewPal->Palette = (ILubyte*)ialloc(NewPalSize);
if (NewPal->Palette == NULL)
goto alloc_error;
if (DestFormat == IL_PAL_RGB24) {
for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) {
NewPal->Palette[j] = Pal->Palette[i];
NewPal->Palette[j+1] = Pal->Palette[i+1];
NewPal->Palette[j+2] = Pal->Palette[i+2];
}
}
else {
for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) {
NewPal->Palette[j] = Pal->Palette[i+2];
NewPal->Palette[j+1] = Pal->Palette[i+1];
NewPal->Palette[j+2] = Pal->Palette[i];
}
}
NewPal->PalSize = NewPalSize;
NewPal->PalType = DestFormat;
break;
default:
ilSetError(IL_INVALID_PARAM);
return NULL;
}
break;
case IL_PAL_RGB32:
case IL_PAL_RGBA32:
case IL_PAL_BGR32:
case IL_PAL_BGRA32:
switch (Pal->PalType)
{
case IL_PAL_RGB24:
case IL_PAL_BGR24:
NewPalSize = Pal->PalSize * 4 / 3;
NewPal->Palette = (ILubyte*)ialloc(NewPalSize);
if (NewPal->Palette == NULL)
goto alloc_error;
if ((Pal->PalType == IL_PAL_BGR24 && (DestFormat == IL_PAL_RGB32 || DestFormat == IL_PAL_RGBA32)) ||
(Pal->PalType == IL_PAL_RGB24 && (DestFormat == IL_PAL_BGR32 || DestFormat == IL_PAL_BGRA32))) {
for (i = 0, j = 0; i < Pal->PalSize; i += 3, j += 4) {
NewPal->Palette[j] = Pal->Palette[i+2];
NewPal->Palette[j+1] = Pal->Palette[i+1];
NewPal->Palette[j+2] = Pal->Palette[i];
NewPal->Palette[j+3] = 255;
}
}
else {
for (i = 0, j = 0; i < Pal->PalSize; i += 3, j += 4) {
NewPal->Palette[j] = Pal->Palette[i];
NewPal->Palette[j+1] = Pal->Palette[i+1];
NewPal->Palette[j+2] = Pal->Palette[i+2];
NewPal->Palette[j+3] = 255;
}
}
NewPal->PalSize = NewPalSize;
NewPal->PalType = DestFormat;
break;
case IL_PAL_RGB32:
NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize);
if (NewPal->Palette == NULL)
goto alloc_error;
if (DestFormat == IL_PAL_BGR32 || DestFormat == IL_PAL_BGRA32) {
for (i = 0; i < Pal->PalSize; i += 4) {
NewPal->Palette[i] = Pal->Palette[i+2];
NewPal->Palette[i+1] = Pal->Palette[i+1];
NewPal->Palette[i+2] = Pal->Palette[i];
NewPal->Palette[i+3] = 255;
}
}
else {
for (i = 0; i < Pal->PalSize; i += 4) {
NewPal->Palette[i] = Pal->Palette[i];
NewPal->Palette[i+1] = Pal->Palette[i+1];
NewPal->Palette[i+2] = Pal->Palette[i+2];
NewPal->Palette[i+3] = 255;
}
}
NewPal->PalType = DestFormat;
break;
case IL_PAL_RGBA32:
NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize);
if (NewPal->Palette == NULL)
goto alloc_error;
if (DestFormat == IL_PAL_BGR32 || DestFormat == IL_PAL_BGRA32) {
for (i = 0; i < Pal->PalSize; i += 4) {
NewPal->Palette[i] = Pal->Palette[i+2];
NewPal->Palette[i+1] = Pal->Palette[i+1];
NewPal->Palette[i+2] = Pal->Palette[i];
NewPal->Palette[i+3] = Pal->Palette[i+3];
}
}
else {
memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize);
}
NewPal->PalType = DestFormat;
break;
case IL_PAL_BGR32:
NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize);
if (NewPal->Palette == NULL)
goto alloc_error;
if (DestFormat == IL_PAL_RGB32 || DestFormat == IL_PAL_RGBA32) {
for (i = 0; i < Pal->PalSize; i += 4) {
NewPal->Palette[i] = Pal->Palette[i+2];
NewPal->Palette[i+1] = Pal->Palette[i+1];
NewPal->Palette[i+2] = Pal->Palette[i];
NewPal->Palette[i+3] = 255;
}
}
else {
for (i = 0; i < Pal->PalSize; i += 4) {
NewPal->Palette[i] = Pal->Palette[i];
NewPal->Palette[i+1] = Pal->Palette[i+1];
NewPal->Palette[i+2] = Pal->Palette[i+2];
NewPal->Palette[i+3] = 255;
}
}
NewPal->PalType = DestFormat;
break;
case IL_PAL_BGRA32:
NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize);
if (NewPal->Palette == NULL)
goto alloc_error;
if (DestFormat == IL_PAL_RGB32 || DestFormat == IL_PAL_RGBA32) {
for (i = 0; i < Pal->PalSize; i += 4) {
NewPal->Palette[i] = Pal->Palette[i+2];
NewPal->Palette[i+1] = Pal->Palette[i+1];
NewPal->Palette[i+2] = Pal->Palette[i];
NewPal->Palette[i+3] = Pal->Palette[i+3];
}
}
else {
memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize);
}
NewPal->PalType = DestFormat;
break;
default:
ilSetError(IL_INVALID_PARAM);
return NULL;
}
break;
default:
ilSetError(IL_INVALID_PARAM);
return NULL;
}
NewPal->PalType = DestFormat;
return NewPal;
alloc_error:
ifree(NewPal);
return NULL;
}
//! Converts the current image to the DestFormat format.
ILboolean ILAPIENTRY ilConvertPal(ILenum DestFormat)
{
ILpal *Pal;
if (iCurImage == NULL || iCurImage->Pal.Palette == NULL ||
iCurImage->Pal.PalSize == 0 || iCurImage->Pal.PalType == IL_PAL_NONE) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
Pal = iConvertPal(&iCurImage->Pal, DestFormat);
if (Pal == NULL)
return IL_FALSE;
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.PalSize = Pal->PalSize;
iCurImage->Pal.PalType = Pal->PalType;
iCurImage->Pal.Palette = (ILubyte*)ialloc(Pal->PalSize);
if (iCurImage->Pal.Palette == NULL) {
return IL_FALSE;
}
memcpy(iCurImage->Pal.Palette, Pal->Palette, Pal->PalSize);
ifree(Pal->Palette);
ifree(Pal);
return IL_TRUE;
}
// Sets the current palette.
ILAPI ILvoid ILAPIENTRY ilSetPal(ILpal *Pal)
{
if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE) {
ifree(iCurImage->Pal.Palette);
}
if (Pal->Palette && Pal->PalSize && Pal->PalType != IL_PAL_NONE) {
iCurImage->Pal.Palette = (ILubyte*)ialloc(Pal->PalSize);
if (iCurImage->Pal.Palette == NULL)
return;
memcpy(iCurImage->Pal.Palette, Pal->Palette, Pal->PalSize);
iCurImage->Pal.PalSize = Pal->PalSize;
iCurImage->Pal.PalType = Pal->PalType;
}
else {
iCurImage->Pal.Palette = NULL;
iCurImage->Pal.PalSize = 0;
iCurImage->Pal.PalType = IL_PAL_NONE;
}
return;
}
ILuint CurSort = 0;
typedef struct COL_CUBE
{
ILubyte Min[3];
ILubyte Val[3];
ILubyte Max[3];
} COL_CUBE;
int sort_func(void *e1, void *e2)
{
return ((COL_CUBE*)e1)->Val[CurSort] - ((COL_CUBE*)e2)->Val[CurSort];
}
ILboolean ILAPIENTRY ilApplyPal(ILconst_string FileName)
{
ILimage Image, *CurImage = iCurImage;
ILubyte *NewData;
ILuint *PalInfo, NumColours, NumPix, MaxDist, DistEntry=0, i, j;
ILint Dist1, Dist2, Dist3;
ILboolean Same;
ILenum Origin;
// COL_CUBE *Cubes;
if( iCurImage == NULL || (iCurImage->Format != IL_BYTE || iCurImage->Format != IL_UNSIGNED_BYTE) ) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
NewData = (ILubyte*)ialloc(iCurImage->Width * iCurImage->Height * iCurImage->Depth);
if (NewData == NULL) {
return IL_FALSE;
}
iCurImage = &Image;
imemclear(&Image, sizeof(ILimage));
// IL_PAL_RGB24, because we don't want to make parts transparent that shouldn't be.
if (!ilLoadPal(FileName) || !ilConvertPal(IL_PAL_RGB24)) {
ifree(NewData);
iCurImage = CurImage;
return IL_FALSE;
}
NumColours = Image.Pal.PalSize / 3; // RGB24 is 3 bytes per entry.
PalInfo = (ILuint*)ialloc(NumColours * sizeof(ILuint));
if (PalInfo == NULL) {
ifree(NewData);
iCurImage = CurImage;
return IL_FALSE;
}
NumPix = CurImage->SizeOfData / ilGetBppFormat(CurImage->Format);
switch (CurImage->Format)
{
case IL_COLOUR_INDEX:
iCurImage = CurImage;
if (!ilConvertPal(IL_PAL_RGB24)) {
ifree(NewData);
ifree(PalInfo);
return IL_FALSE;
}
NumPix = iCurImage->Pal.PalSize / ilGetBppPal(iCurImage->Pal.PalType);
for (i = 0; i < NumPix; i++) {
for (j = 0; j < Image.Pal.PalSize; j += 3) {
// No need to perform a sqrt.
Dist1 = (ILint)iCurImage->Pal.Palette[i] - (ILint)Image.Pal.Palette[j];
Dist2 = (ILint)iCurImage->Pal.Palette[i+1] - (ILint)Image.Pal.Palette[j+1];
Dist3 = (ILint)iCurImage->Pal.Palette[i+2] - (ILint)Image.Pal.Palette[j+2];
PalInfo[j / 3] = Dist1 * Dist1 + Dist2 * Dist2 + Dist3 * Dist3;
}
MaxDist = UINT_MAX;
DistEntry = 0;
for (j = 0; j < NumColours; j++) {
if (PalInfo[j] < MaxDist) {
DistEntry = j;
MaxDist = PalInfo[j];
}
}
iCurImage->Pal.Palette[i] = DistEntry;
}
for (i = 0; i < iCurImage->SizeOfData; i++) {
NewData[i] = iCurImage->Pal.Palette[iCurImage->Data[i]];
}
break;
case IL_RGB:
case IL_RGBA:
/*Cube = (COL_CUBE*)ialloc(NumColours * sizeof(COL_CUBE));
// @TODO: Check if ialloc failed here!
for (i = 0; i < NumColours; i++)
memcpy(&Cubes[i].Val, Image.Pal.Palette[i * 3], 3);
for (j = 0; j < 3; j++) {
qsort(Cubes, NumColours, sizeof(COL_CUBE), sort_func);
Cubes[0].Min = 0;
Cubes[NumColours-1] = UCHAR_MAX;
NumColours--;
for (i = 1; i < NumColours; i++) {
Cubes[i].Min[CurSort] = Cubes[i-1].Val[CurSort] + 1;
Cubes[i-1].Max[CurSort] = Cubes[i].Val[CurSort] - 1;
}
CurSort++;
NumColours++;
}*/
for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp) {
Same = IL_TRUE;
if (i != 0) {
for (j = 0; j < CurImage->Bpp; j++) {
if (CurImage->Data[i-CurImage->Bpp+j] != CurImage->Data[i+j]) {
Same = IL_FALSE;
break;
}
}
}
if (Same) {
NewData[i / CurImage->Bpp] = DistEntry;
continue;
}
for (j = 0; j < Image.Pal.PalSize; j += 3) {
// No need to perform a sqrt.
Dist1 = (ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j];
Dist2 = (ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j+1];
Dist3 = (ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j+2];
PalInfo[j / 3] = Dist1 * Dist1 + Dist2 * Dist2 + Dist3 * Dist3;
}
MaxDist = UINT_MAX;
DistEntry = 0;
for (j = 0; j < NumColours; j++) {
if (PalInfo[j] < MaxDist) {
DistEntry = j;
MaxDist = PalInfo[j];
}
}
NewData[i / CurImage->Bpp] = DistEntry;
}
break;
case IL_BGR:
case IL_BGRA:
for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp) {
for (j = 0; j < NumColours; j++) {
// No need to perform a sqrt.
PalInfo[j] = ((ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j * 3]) *
((ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j * 3]) +
((ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j * 3 + 1]) *
((ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j * 3 + 1]) +
((ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j * 3 + 2]) *
((ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j * 3 + 2]);
}
MaxDist = UINT_MAX;
DistEntry = 0;
for (j = 0; j < NumColours; j++) {
if (PalInfo[j] < MaxDist) {
DistEntry = j;
MaxDist = PalInfo[j];
}
}
NewData[i / CurImage->Bpp] = DistEntry;
}
break;
case IL_LUMINANCE:
case IL_LUMINANCE_ALPHA:
for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp ) {
for (j = 0; j < NumColours; j++) {
// No need to perform a sqrt.
PalInfo[j] = ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3]) *
((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3]) +
((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 1]) *
((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 1]) +
((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 2]) *
((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 2]);
}
MaxDist = UINT_MAX;
DistEntry = 0;
for (j = 0; j < NumColours; j++) {
if (PalInfo[j] < MaxDist) {
DistEntry = j;
MaxDist = PalInfo[j];
}
}
NewData[i] = DistEntry;
}
break;
default: // Should be no other!
break;
}
iCurImage = CurImage;
Origin = iCurImage->Origin;
if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, 1,
IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NewData)) {
ifree(Image.Pal.Palette);
ifree(PalInfo);
ifree(NewData);
return IL_FALSE;
}
iCurImage->Origin = Origin;
iCurImage->Pal.Palette = Image.Pal.Palette;
iCurImage->Pal.PalSize = Image.Pal.PalSize;
iCurImage->Pal.PalType = Image.Pal.PalType;
ifree(PalInfo);
ifree(NewData);
return IL_TRUE;
}