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>
This commit is contained in:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Last modified: 17/04/2005
// by Meloni Dario
//
// Description: Common altivec function.
//
//-----------------------------------------------------------------------------
#include "config.h"
#ifdef ALTIVEC_GCC
#include "altivec_common.h"
// from http://developer.apple.com/hardware/ve/alignment.html
/*vector unsigned char load_unaligned( unsigned char *buffer ) {
vector unsigned char MSQ, LSQ;
vector unsigned char mask;
MSQ = vec_ld(0, buffer); // most significant quadword
LSQ = vec_ld(15, buffer); // least significant quadword
mask = vec_lvsl(0, buffer); // create the permute mask
return vec_perm(MSQ, LSQ, mask);// align the data
}*/
vector float fill_vector_f( float value ) {
vector_t vec;
vec.sf[0] = value;
vector float temp = vec_ld(0,vec.sf);
return vec_splat(temp,0);
}
inline unsigned int round16( unsigned int v ) {
return ((int)((v/16)*10)%10) > 0 ? (v/16) : (v/16)+1;
}
#endif

View File

@@ -0,0 +1,228 @@
#include "config.h"
#ifdef ALTIVEC_GCC
#include "altivec_typeconversion.h"
static inline void abc2cba_internal( register const vector unsigned char p[4], unsigned char *data, register unsigned int length, unsigned char *newdata ) {
register vector unsigned char d0,d1,d2,t0,t1,t2;
length = eround16(length);
if( length >= 3 ) {
length -= 3;
d2 = vec_ld(32,data);
d1 = vec_ld(16,data);
d0 = vec_ld(0,data);
while( length >= 3 ) {
t0 = vec_perm(d0,d1,p[0]);
t1 = vec_perm(d1,d0,p[1]);
t2 = vec_perm(d2,d1,p[2]);
t1 = vec_perm(t1,d2,p[3]);
vec_st(t0,0,newdata);
vec_st(t1,16,newdata);
vec_st(t2,32,newdata);
length -= 3;
data += 16*3;
newdata += 16*3;
d2 = vec_ld(32,data);
d1 = vec_ld(16,data);
d0 = vec_ld(0,data);
}
t0 = vec_perm(d0,d1,p[0]);
t1 = vec_perm(d1,d0,p[1]);
t2 = vec_perm(d2,d1,p[2]);
t1 = vec_perm(t1,d2,p[3]);
vec_st(t0,0,newdata);
vec_st(t1,16,newdata);
vec_st(t2,32,newdata);
}
if( length == 2 ) {
d0 = vec_ld(0,data);
d1 = vec_ld(16,data);
t0 = vec_perm(d0,d1,p[0]);
t1 = vec_perm(d1,d0,p[1]);
vec_st(t0,0,newdata);
vec_st(t1,16,newdata);
} else if( length == 1 ) {
d0 = vec_ld(0,data);
t0 = vec_perm(d0,d0,p[0]);
vec_st(t0,0,newdata);
}
}
static inline void abcd2cbad_internal( register const vector unsigned char p, unsigned char *data, unsigned int length, unsigned char *newdata ) {
register vector unsigned char d0,d1,d2,z;
z = vec_splat_u8(0);
length = eround16(length);
if( length >= 3 ) {
length -= 3;
d2 = vec_ld(32,data);
d1 = vec_ld(16,data);
d0 = vec_ld(0,data);
while( length >= 3 ) {
d0 = vec_perm(d0,z,p);
d1 = vec_perm(d1,z,p);
d2 = vec_perm(d2,z,p);
vec_st(d0,0,newdata);
vec_st(d1,16,newdata);
vec_st(d2,32,newdata);
length -= 3;
data += 16*3;
newdata += 16*3;
d2 = vec_ld(32,data);
d1 = vec_ld(16,data);
d0 = vec_ld(0,data);
}
d0 = vec_perm(d0,z,p);
d1 = vec_perm(d1,z,p);
d2 = vec_perm(d2,z,p);
vec_st(d0,0,newdata);
vec_st(d1,16,newdata);
vec_st(d2,32,newdata);
}
if( length == 2 ) {
d0 = vec_ld(0,data);
d1 = vec_ld(16,data);
d0 = vec_perm(d0,z,p);
d1 = vec_perm(d1,z,p);
vec_st(d0,0,newdata);
vec_st(d1,16,newdata);
} else if( length == 1 ) {
d0 = vec_ld(0,data);
d0 = vec_perm(d0,d0,z);
vec_st(d0,0,newdata);
}
}
// Format conversion function
void abc2cba_byte( ILubyte *data, ILuint length, ILubyte *newdata ) {
const vector unsigned char p[4] =
{ (vector unsigned char)(0x02,0x01,0x00,0x05,0x04,0x03,0x08,0x07,0x06,0x0B,0x0A,0x09,0x0E,0x0D,0x0C,0x11),
(vector unsigned char)(0x00,0x10,0x04,0x03,0x02,0x07,0x06,0x05,0x0A,0x09,0x08,0x0D,0x0C,0x0B,0x0E,0x0F),
(vector unsigned char)(0x1E,0x03,0x02,0x01,0x06,0x05,0x04,0x09,0x08,0x07,0x0C,0x0B,0x0A,0x0F,0x0E,0x0D),
(vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x10,0x0F)};
abc2cba_internal(p,data,length,newdata);
}
void abc2cba_short( ILushort *data, ILuint length, ILushort *newdata ) {
const vector unsigned char p[4] =
{ (vector unsigned char)(0x04,0x05,0x02,0x03,0x00,0x01,0x0A,0x0B,0x08,0x09,0x06,0x07,0x10,0x11,0x0E,0x0F),
(vector unsigned char)(0x1C,0x1D,0x06,0x07,0x04,0x05,0x02,0x03,0x0C,0x0D,0x0A,0x0B,0x08,0x09,0x0E,0x0F),
(vector unsigned char)(0x00,0x01,0x1E,0x1F,0x08,0x09,0x06,0x07,0x04,0x05,0x0E,0x0F,0x0C,0x0D,0x0A,0x0B),
(vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x12,0x13)};
abc2cba_internal(p,(ILubyte*)data,length,(ILubyte*)newdata);
}
void abc2cba_int( ILuint *data, ILuint length, ILuint *newdata ) {
const vector unsigned char p[4] =
{ (vector unsigned char)(0x08,0x09,0x0A,0x0B,0x04,0x05,0x06,0x07,0x00,0x01,0x02,0x03,0x14,0x15,0x16,0x17),
(vector unsigned char)(0x00,0x01,0x02,0x03,0x1C,0x1D,0x1E,0x1F,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F),
(vector unsigned char)(0x18,0x19,0x1A,0x1B,0x0C,0x0D,0x0E,0x0F,0x08,0x09,0x0A,0x0B,0x04,0x05,0x06,0x07),
(vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x0C,0x0D,0x0E,0x0F)};
abc2cba_internal(p,(ILubyte*)data,length,(ILubyte*)newdata);
}
void abc2cba_double( ILdouble *data, ILuint length, ILdouble *newdata ) {
const vector unsigned char p[4] =
{ (vector unsigned char)(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F),
(vector unsigned char)(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F),
(vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F),
(vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F)};
abc2cba_internal(p,(ILubyte*)data,length,(ILubyte*)newdata);
}
void abcd2cbad_byte( ILubyte *data, ILuint length, ILubyte *newdata ) {
const vector unsigned char p = (vector unsigned char)(0x02,0x01,0x00,0x03,0x06,0x05,0x04,0x07,0x0A,0x09,0x08,0x0B, 0x0E,0x0D,0x0C,0x0F);
abcd2cbad_internal(p,data,length,newdata);
}
void abcd2cbad_short( ILushort *data, ILuint length, ILushort *newdata ) {
const vector unsigned char p = (vector unsigned char)(0x04,0x05,0x02,0x03,0x00,0x01,0x06,0x07,0x0C,0x0D,0x0A,0x0B,0x08,0x09,0x0E,0x0F);
abcd2cbad_internal(p,(ILubyte*)data,length,(ILubyte*)newdata);
}
void abcd2cbad_int( ILuint *data, ILuint length, ILuint *newdata ) {
const vector unsigned char p = (vector unsigned char)(0x08,0x09,0x0A,0x0B,0x04,0x05,0x06,0x07,0x00,0x01,0x02,0x03,0x0C,0x0D,0x0E,0x0F);
abcd2cbad_internal(p,(ILubyte*)data,length,(ILubyte*)newdata);
}
void abcd2cbad_double( ILdouble *tdata, ILuint length, ILdouble *tnewdata ) {
register ILubyte *data = (ILubyte*)tdata;
register ILubyte *newdata = (ILubyte*)tnewdata;
const vector unsigned char p = (vector unsigned char)(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F);
register vector unsigned char d0,d1,d2,d3,t0,t1,t2,t3;
length = eround16(length);
if( length >= 4 ) {
length -= 4;
d3 = vec_ld(48,data);
d2 = vec_ld(32,data);
d1 = vec_ld(16,data);
d0 = vec_ld(0,data);
while( length >= 4 ) {
t0 = vec_perm(d0,d1,p);
t1 = vec_perm(d1,d0,p);
t2 = vec_perm(d2,d3,p);
t3 = vec_perm(d3,d2,p);
vec_st(t0,0,newdata);
vec_st(t1,16,newdata);
vec_st(t2,32,newdata);
vec_st(t3,48,newdata);
length -= 4;
data += 16*4;
newdata += 16*4;
d3 = vec_ld(48,data);
d2 = vec_ld(32,data);
d1 = vec_ld(16,data);
d0 = vec_ld(0,data);
}
t0 = vec_perm(d0,d1,p);
t1 = vec_perm(d1,d0,p);
t2 = vec_perm(d2,d3,p);
t3 = vec_perm(d3,d2,p);
vec_st(d0,0,newdata);
vec_st(d1,16,newdata);
vec_st(d2,32,newdata);
vec_st(d3,48,newdata);
}
if( length == 2 ) {
d0 = vec_ld(0,data);
d1 = vec_ld(16,data);
t0 = vec_perm(d0,d1,p);
t1 = vec_perm(d1,d0,p);
vec_st(t0,0,newdata);
vec_st(t1,16,newdata);
}
}
#endif

View File

@@ -0,0 +1,252 @@
#define __ALLOC_C
#include "il_internal.h"
#include <stdlib.h>
#include <math.h>
#ifdef MM_MALLOC
#include <mm_malloc.h>
#endif
static ILvoid ILAPIENTRY DefaultFreeFunc(const ILvoid * CONST_RESTRICT Ptr);
static ILvoid* ILAPIENTRY DefaultAllocFunc(const ILuint Size);
static mAlloc ialloc_ptr = DefaultAllocFunc;
static mFree ifree_ptr = DefaultFreeFunc;
/*** Vector Allocation/Deallocation Function ***/
#ifdef VECTORMEM
ILvoid *vec_malloc( const ILuint size ) {
const ILuint _size = size % 16 > 0 ? size + 16 - (size % 16) : size; // align size value
#ifdef MM_MALLOC
return _mm_malloc(_size,16);
#else
#ifdef VALLOC
return valloc( _size );
#else
#ifdef POSIX_MEMALIGN
char *buffer;
return posix_memalign(&buffer, 16, _size) == 0 ? buffer : NULL;
#else
#ifdef MEMALIGN
return memalign( 16, _size );
#else
// Memalign hack from ffmpeg for MinGW
void *ptr;
int diff;
ptr = malloc(_size+16+1);
diff= ((-(int)ptr - 1)&15) + 1;
ptr += diff;
((char*)ptr)[-1]= diff;
return ptr;
#endif //MEMALIGN
#endif //POSIX_MEMALIGN
#endif //VALLOC
#endif //MM_MALLOC
}
ILvoid *ivec_align_buffer( ILvoid *buffer, const ILuint size ) {
if( (size_t)buffer % 16 != 0 ) {
void *aligned_buffer = vec_malloc( size );
memcpy( aligned_buffer, buffer, size );
ifree( buffer );
return aligned_buffer;
}
return buffer;
}
#endif
/*** Allocation/Deallocation Function ***/
ILvoid* ILAPIENTRY ialloc(const ILuint Size) {
ILvoid *Ptr = ialloc_ptr(Size);
if (Ptr == NULL)
ilSetError(IL_OUT_OF_MEMORY);
return Ptr;
}
ILvoid ILAPIENTRY ifree(const ILvoid * CONST_RESTRICT Ptr) {
ifree_ptr(Ptr);
return;
}
ILvoid* ILAPIENTRY icalloc(const ILuint Size, const ILuint Num) {
ILvoid *Ptr = ialloc(Size * Num);
if (Ptr == NULL)
return Ptr;
imemclear(Ptr, Size * Num);
return Ptr;
}
/*** Default Allocation/Deallocation Function ***/
static ILvoid* ILAPIENTRY DefaultAllocFunc(const ILuint Size) {
#ifdef VECTORMEM
return (ILvoid*)vec_malloc(Size);
#else
return malloc(Size);
#endif //VECTORMEM
}
static ILvoid ILAPIENTRY DefaultFreeFunc(const ILvoid * CONST_RESTRICT ptr) {
if( ptr ) {
#ifdef MM_MALLOC
_mm_free((ILvoid*)ptr);
#else
#if defined(VECTORMEM) & !defined(POSIX_MEMALIGN) & !defined(VALLOC) & !defined(MEMALIGN) & !defined(MM_MALLOC)
free(ptr - ((char*)ptr)[-1]);
#else
free(ptr);
#endif //OTHERS...
#endif //MM_MALLOC
}
}
/*** Manipulate Allocation/Deallocation Function ***/
ILvoid ILAPIENTRY ilResetMemory() { // Deprecated
ialloc_ptr = DefaultAllocFunc;
ifree_ptr = DefaultFreeFunc;
}
ILvoid ILAPIENTRY ilSetMemory(mAlloc AllocFunc, mFree FreeFunc) {
ialloc_ptr = AllocFunc == NULL ? DefaultAllocFunc : AllocFunc;
ifree_ptr = FreeFunc == NULL ? DefaultFreeFunc : FreeFunc;
}
/*#if defined(_WIN32) && defined(_MEM_DEBUG)
#include <windows.h>
int bAtexit = 0;
typedef struct ALLOC_INFO
{
unsigned long address;
unsigned long size;
char file[64];
unsigned long line;
struct ALLOC_INFO *Next;
} ALLOC_INFO;
ALLOC_INFO *AllocList;
void AddTrack(unsigned long addr, unsigned long size, const char *file, unsigned long line)
{
ALLOC_INFO *Temp;
if (AllocList == NULL) {
AllocList = (ALLOC_INFO*)malloc(sizeof(ALLOC_INFO)); // Just assume it succeeds.
AllocList->address = addr;
AllocList->size = size;
AllocList->line = line;
strncpy(AllocList->file, file, 63);
AllocList->Next = NULL;
}
else {
Temp = AllocList;
AllocList = (ALLOC_INFO*)malloc(sizeof(ALLOC_INFO)); // Just assume it succeeds.
AllocList->address = addr;
AllocList->size = size;
AllocList->line = line;
strncpy(AllocList->file, file, 63);
AllocList->Next = Temp;
}
return;
}
void RemoveTrack(unsigned long addr)
{
ALLOC_INFO *Temp, *Prev;
Temp = AllocList;
Prev = NULL;
if (Temp == NULL)
return;
while (Temp != NULL) {
if (Temp->address == addr) {
if (Prev == NULL) {
AllocList = Temp->Next;
free(Temp);
}
else {
Prev->Next = Temp->Next;
free(Temp);
}
break;
}
Prev = Temp;
Temp = Temp->Next;
}
return;
}
void DumpUnfreed(void)
{
unsigned long TotalSize = 0;
char buf[1024];
ALLOC_INFO *i = AllocList;
OutputDebugString("DevIL Unfreed Information:\n");
while (i != NULL) {
sprintf(buf, "%s(%d) : %d bytes unfreed at %d\n", i->file, i->line, i->size, i->address);
OutputDebugString(buf);
TotalSize += i->size;
AllocList = i->Next;
free(i);
i = AllocList;
}
sprintf(buf, "-----------------------------------------------------------\n");
OutputDebugString(buf);
sprintf(buf, "Total Unfreed: %d bytes\n\n\n", TotalSize);
OutputDebugString(buf);
}
void AddToAtexit()
{
if (bAtexit)
return;
atexit(DumpUnfreed);
bAtexit = 1;
}
void *c_alloc(unsigned long size, unsigned long num, const char *file, unsigned long line)
{
void *ptr;
ptr = calloc(size, num);
if (!ptr)
return NULL;
AddToAtexit();
AddTrack((unsigned long)ptr, size * num, file, line);
return ptr;
}
void *m_alloc(unsigned long size, const char *file, unsigned long line)
{
void *ptr;
ptr = malloc(size);
if (!ptr)
return NULL;
AddToAtexit();
AddTrack((unsigned long)ptr, size, file, line);
return ptr;
}
void f_ree(void *ptr)
{
RemoveTrack((unsigned long)ptr);
free(ptr);
return;
}
#endif//defined(_WIN32) && defined(_MEM_DEBUG)*/

View File

@@ -0,0 +1,152 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_bits.c
//
// Description: Implements a file class that reads/writes bits directly.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#include "il_bits.h"
// Opens a BITFILE just like fopen opens a FILE.
/*BITFILE *bopen(const char *FileName, const char *Mode)
{
BITFILE *ToReturn = NULL;
if (FileName != NULL) {
ToReturn = (BITFILE*)ialloc(sizeof(BITFILE));
if (ToReturn != NULL) {
iopenr((char*)FileName);
ToReturn->File = iGetFile();
ToReturn->BitPos = 0;
ToReturn->ByteBitOff = 8;
ToReturn->Buff = 0;
}
}
return ToReturn;
}*/
// Converts a FILE to a BITFILE.
BITFILE *bfile(ILHANDLE File)
{
BITFILE *ToReturn = NULL;
if (File != NULL) {
ToReturn = (BITFILE*)ialloc(sizeof(BITFILE));
if (ToReturn != NULL) {
ToReturn->File = File;
ToReturn->BitPos = itell() << 3;
ToReturn->ByteBitOff = 8;
ToReturn->Buff = 0;
}
}
return ToReturn;
}
// Closes an open BITFILE and frees memory for it.
ILint bclose(BITFILE *BitFile)
{
if (BitFile == NULL || BitFile->File == NULL)
return IL_EOF;
icloser(BitFile->File);
ifree(BitFile);
return 0;
}
// Returns the current bit position of a BITFILE.
ILint btell(BITFILE *BitFile)
{
return BitFile->BitPos;
}
// Seeks in a BITFILE just like fseek for FILE.
ILint bseek(BITFILE *BitFile, ILuint Offset, ILuint Mode)
{
ILint KeepPos, Len;
if (BitFile == NULL || BitFile->File == NULL)
return 1;
switch (Mode)
{
case IL_SEEK_SET:
if (iseek(Offset >> 3, Mode)) {
BitFile->BitPos = Offset;
BitFile->ByteBitOff = BitFile->BitPos % 8;
}
break;
case IL_SEEK_CUR:
if (iseek(Offset >> 3, Mode)) {
BitFile->BitPos += Offset;
BitFile->ByteBitOff = BitFile->BitPos % 8;
}
break;
case IL_SEEK_END:
KeepPos = itell();
iseek(0, IL_SEEK_END);
Len = itell();
iseek(0, IL_SEEK_SET);
if (iseek(Offset >> 3, Mode)) {
BitFile->BitPos = (Len << 3) + Offset;
BitFile->ByteBitOff = BitFile->BitPos % 8;
}
break;
default:
return 1;
}
return 0;
}
// hehe, "bread". It reads data into Buffer from the BITFILE, just like fread for FILE.
ILint bread(ILvoid *Buffer, ILuint Size, ILuint Number, BITFILE *BitFile)
{
//Note that this function is somewhat useless: In binary image
//formats, there are some pad bits after each scanline. This
//function does not take that into account, so...
ILuint BuffPos = 0, Count = Size * Number;
while (BuffPos < Count) {
if (BitFile->ByteBitOff < 0 || BitFile->ByteBitOff > 7) {
BitFile->ByteBitOff = 7;
if (iread(&BitFile->Buff, 1, 1) != 1) // Reached eof or error...
return BuffPos;
}
*((ILubyte*)(Buffer) + BuffPos) = (ILubyte)!!(BitFile->Buff & (1 << BitFile->ByteBitOff));
BuffPos++;
BitFile->ByteBitOff--;
}
return BuffPos;
}
// Not implemented yet.
/*ILint bwrite(ILvoid *Buffer, ILuint Size, ILuint Number, BITFILE *BitFile)
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,150 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 03/02/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_cut.c
//
// Description: Reads a Dr. Halo .cut file
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_CUT
#include "il_manip.h"
#include "il_pal.h"
#include "il_bits.h"
// Wrap it just in case...
#ifdef _MSC_VER
#pragma pack(push, packed_struct, 1)
#endif
typedef struct CUT_HEAD
{
ILushort Width;
ILushort Height;
ILint Dummy;
} IL_PACKSTRUCT CUT_HEAD;
#ifdef _MSC_VER
#pragma pack(pop, packed_struct)
#endif
ILboolean iLoadCutInternal();
//! Reads a .cut file
ILboolean ilLoadCut(ILconst_string FileName)
{
ILHANDLE CutFile;
ILboolean bCut = IL_FALSE;
CutFile = iopenr(FileName);
if (CutFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bCut;
}
bCut = ilLoadCutF(CutFile);
icloser(CutFile);
return bCut;
}
//! Reads an already-opened .cut file
ILboolean ilLoadCutF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadCutInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a .cut
ILboolean ilLoadCutL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadCutInternal();
}
// Note: .Cut support has not been tested yet!
// A .cut can only have 1 bpp.
// We need to add support for the .pal's PSP outputs with these...
ILboolean iLoadCutInternal()
{
CUT_HEAD Header;
ILuint Size, i = 0, j;
ILubyte Count, Run;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
Header.Width = GetLittleShort();
Header.Height = GetLittleShort();
Header.Dummy = GetLittleInt();
if (Header.Width == 0 || Header.Height == 0) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { // always 1 bpp
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
Size = Header.Width * Header.Height;
while (i < Size) {
Count = igetc();
if (Count == 0) { // end of row
igetc(); // Not supposed to be here, but
igetc(); // PSP is putting these two bytes here...WHY?!
continue;
}
if (Count & BIT_7) { // rle-compressed
ClearBits(Count, BIT_7);
Run = igetc();
for (j = 0; j < Count; j++) {
iCurImage->Data[i++] = Run;
}
}
else { // run of pixels
for (j = 0; j < Count; j++) {
iCurImage->Data[i++] = igetc();
}
}
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; // Not sure
/*iCurImage->Pal.Palette = SharedPal.Palette;
iCurImage->Pal.PalSize = SharedPal.PalSize;
iCurImage->Pal.PalType = SharedPal.PalType;*/
ilFixImage();
return IL_TRUE;
}
/* ?????????
ILvoid ilPopToast() {
ILstring flipCode = IL_TEXT("#flipCode and www.flipCode.com rule you all.");
flipCode[0] = flipCode[0];
}
*/
#endif//IL_NO_CUT

View File

@@ -0,0 +1,493 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/20/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_dcx.c
//
// Description: Reads from a .dcx file.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_DCX
#include "il_dcx.h"
#include "il_manip.h"
//! Checks if the file specified in FileName is a valid .dcx file.
ILboolean ilIsValidDcx(ILconst_string FileName) {
ILHANDLE DcxFile;
ILboolean bDcx = IL_FALSE;
if (!iCheckExtension(FileName, IL_TEXT("dcx"))) {
ilSetError(IL_INVALID_EXTENSION);
return bDcx;
}
DcxFile = iopenr(FileName);
if (DcxFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bDcx;
}
bDcx = ilIsValidDcxF(DcxFile);
icloser(DcxFile);
return bDcx;
}
//! Checks if the ILHANDLE contains a valid .dcx file at the current position.
ILboolean ilIsValidDcxF(ILHANDLE File) {
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iIsValidDcx();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Checks if Lump is a valid .dcx lump.
ILboolean ilIsValidDcxL(const ILvoid *Lump, ILuint Size) {
iSetInputLump(Lump, Size);
return iIsValidDcx();
}
// Internal function obtain the .dcx header from the current file.
ILboolean iGetDcxHead(DCXHEAD *Head) {
Head->Xmin = GetLittleUShort();
Head->Ymin = GetLittleUShort();
Head->Xmax = GetLittleUShort();
Head->Ymax = GetLittleUShort();
Head->HDpi = GetLittleUShort();
Head->VDpi = GetLittleUShort();
Head->Bps = GetLittleUShort();
Head->PaletteInfo = GetLittleUShort();
Head->HScreenSize = GetLittleUShort();
Head->VScreenSize = GetLittleUShort();
return IL_TRUE;
}
// Internal function to get the header and check it.
ILboolean iIsValidDcx()
{
ILuint Signature;
if (iread(&Signature, 1, 4) != 4)
return IL_FALSE;
iseek(-4, IL_SEEK_CUR);
return (Signature == 987654321);
}
// Internal function used to check if the HEADER is a valid .dcx header.
// Should we also do a check on Header->Bpp?
ILboolean iCheckDcx(DCXHEAD *Header)
{
ILuint Test, i;
// There are other versions, but I am not supporting them as of yet.
// Got rid of the Reserved check, because I've seen some .dcx files with invalid values in it.
if (Header->Manufacturer != 10 || Header->Version != 5 || Header->Encoding != 1/* || Header->Reserved != 0*/)
return IL_FALSE;
// See if the padding size is correct
Test = Header->Xmax - Header->Xmin + 1;
/*if (Header->Bpp >= 8) {
if (Test & 1) {
if (Header->Bps != Test + 1)
return IL_FALSE;
}
else {
if (Header->Bps != Test) // No padding
return IL_FALSE;
}
}*/
for (i = 0; i < 54; i++) {
if (Header->Filler[i] != 0)
return IL_FALSE;
}
return IL_TRUE;
}
//! Reads a .dcx file
ILboolean ilLoadDcx(ILconst_string FileName)
{
ILHANDLE DcxFile;
ILboolean bDcx = IL_FALSE;
DcxFile = iopenr(FileName);
if (DcxFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bDcx;
}
bDcx = ilLoadDcxF(DcxFile);
icloser(DcxFile);
return bDcx;
}
//! Reads an already-opened .dcx file
ILboolean ilLoadDcxF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadDcxInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a .dcx
ILboolean ilLoadDcxL(const ILvoid *Lump, ILuint Size) {
iSetInputLump(Lump, Size);
return iLoadDcxInternal();
}
// Internal function used to load the .dcx.
ILboolean iLoadDcxInternal()
{
DCXHEAD Header;
ILuint Signature, i, Entries[1024], Num = 0;
ILimage *Image, *Base;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!iIsValidDcx())
return IL_FALSE;
iread(&Signature, 1, 4);
do {
if (iread(&Entries[Num], 1, 4) != 4)
return IL_FALSE;
Num++;
} while (Entries[Num-1] != 0);
for (i = 0; i < Num; i++) {
iseek(Entries[i], IL_SEEK_SET);
iGetDcxHead(&Header);
/*if (!iCheckDcx(&Header)) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}*/
Image = iUncompressDcx(&Header);
if (Image == NULL)
return IL_FALSE;
if (i == 0) {
ilTexImage(Image->Width, Image->Height, 1, Image->Bpp, Image->Format, Image->Type, Image->Data);
Base = iCurImage;
Base->Origin = IL_ORIGIN_UPPER_LEFT;
ilCloseImage(Image);
}
else {
iCurImage->Next = Image;
iCurImage = iCurImage->Next;
}
}
ilFixImage();
return IL_TRUE;
}
// Internal function to uncompress the .dcx (all .dcx files are rle compressed)
ILimage *iUncompressDcx(DCXHEAD *Header)
{
ILubyte ByteHead, Colour, *ScanLine = NULL /* Only one plane */;
ILuint c, i, x, y;//, Read = 0;
ILimage *Image = NULL;
if (Header->Bpp < 8) {
/*ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;*/
return iUncompressDcxSmall(Header);
}
Image = ilNewImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 1);
if (Image == NULL)
return NULL;
/*if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}*/
Image->Origin = IL_ORIGIN_UPPER_LEFT;
ScanLine = (ILubyte*)ialloc(Header->Bps);
if (ScanLine == NULL)
goto dcx_error;
switch (Image->Bpp)
{
case 1:
Image->Format = IL_COLOUR_INDEX;
Image->Pal.PalType = IL_PAL_RGB24;
Image->Pal.PalSize = 256 * 3; // Need to find out for sure...
Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize);
if (Image->Pal.Palette == NULL)
goto dcx_error;
break;
//case 2: // No 16-bit images in the dcx format!
case 3:
Image->Format = IL_RGB;
Image->Pal.Palette = NULL;
Image->Pal.PalSize = 0;
Image->Pal.PalType = IL_PAL_NONE;
break;
case 4:
Image->Format = IL_RGBA;
Image->Pal.Palette = NULL;
Image->Pal.PalSize = 0;
Image->Pal.PalType = IL_PAL_NONE;
break;
default:
ilSetError(IL_ILLEGAL_FILE_VALUE);
goto dcx_error;
}
/*StartPos = itell();
Compressed = (ILubyte*)ialloc(Image->SizeOfData * 4 / 3);
iread(Compressed, 1, Image->SizeOfData * 4 / 3);
for (y = 0; y < Image->Height; y++) {
for (c = 0; c < Image->Bpp; c++) {
x = 0;
while (x < Header->Bps) {
ByteHead = Compressed[Read++];
if ((ByteHead & 0xC0) == 0xC0) {
ByteHead &= 0x3F;
Colour = Compressed[Read++];
for (i = 0; i < ByteHead; i++) {
ScanLine[x++] = Colour;
}
}
else {
ScanLine[x++] = ByteHead;
}
}
for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes ;)
Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x];
}
}
}
ifree(Compressed);
iseek(StartPos + Read, IL_SEEK_SET);*/
//changed 2003-09-01
if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
iPreCache(iCurImage->SizeOfData);
//TODO: because the .pcx-code was broken this
//code is probably broken, too
for (y = 0; y < Image->Height; y++) {
for (c = 0; c < Image->Bpp; c++) {
x = 0;
while (x < Header->Bps) {
if (iread(&ByteHead, 1, 1) != 1) {
iUnCache();
goto dcx_error;
}
if ((ByteHead & 0xC0) == 0xC0) {
ByteHead &= 0x3F;
if (iread(&Colour, 1, 1) != 1) {
iUnCache();
goto dcx_error;
}
for (i = 0; i < ByteHead; i++) {
ScanLine[x++] = Colour;
}
}
else {
ScanLine[x++] = ByteHead;
}
}
for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes ;)
Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x];
}
}
}
iUnCache();
ifree(ScanLine);
// Read in the palette
if (Image->Bpp == 1) {
ByteHead = igetc(); // the value 12, because it signals there's a palette for some reason...
// We should do a check to make certain it's 12...
if (ByteHead != 12)
iseek(-1, IL_SEEK_CUR);
if (iread(Image->Pal.Palette, 1, Image->Pal.PalSize) != Image->Pal.PalSize) {
ilCloseImage(Image);
return NULL;
}
}
return Image;
dcx_error:
ifree(ScanLine);
ilCloseImage(Image);
return NULL;
}
ILimage *iUncompressDcxSmall(DCXHEAD *Header)
{
ILuint i = 0, j, k, c, d, x, y, Bps;
ILubyte HeadByte, Colour, Data = 0, *ScanLine = NULL;
ILimage *Image;
Image = ilNewImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 1);
if (Image == NULL)
return NULL;
/*if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}*/
Image->Origin = IL_ORIGIN_UPPER_LEFT;
switch (Header->NumPlanes)
{
case 1:
Image->Format = IL_LUMINANCE;
break;
case 4:
Image->Format = IL_COLOUR_INDEX;
break;
default:
ilSetError(IL_ILLEGAL_FILE_VALUE);
ilCloseImage(Image);
return NULL;
}
if (Header->NumPlanes == 1) {
for (j = 0; j < Image->Height; j++) {
i = 0;
while (i < Image->Width) {
if (iread(&HeadByte, 1, 1) != 1)
goto file_read_error;
if (HeadByte >= 192) {
HeadByte -= 192;
if (iread(&Data, 1, 1) != 1)
goto file_read_error;
for (c = 0; c < HeadByte; c++) {
k = 128;
for (d = 0; d < 8 && i < Image->Width; d++) {
Image->Data[j * Image->Width + i++] = (!!(Data & k) == 1 ? 255 : 0);
k >>= 1;
}
}
}
else {
k = 128;
for (c = 0; c < 8 && i < Image->Width; c++) {
Image->Data[j * Image->Width + i++] = (!!(HeadByte & k) == 1 ? 255 : 0);
k >>= 1;
}
}
}
if (Data != 0)
igetc(); // Skip pad byte if last byte not a 0
}
}
else { // 4-bit images
Bps = Header->Bps * Header->NumPlanes * 2;
Image->Pal.Palette = (ILubyte*)ialloc(16 * 3); // Size of palette always (48 bytes).
Image->Pal.PalSize = 16 * 3;
Image->Pal.PalType = IL_PAL_RGB24;
ScanLine = (ILubyte*)ialloc(Bps);
if (Image->Pal.Palette == NULL || ScanLine == NULL) {
ifree(ScanLine);
ilCloseImage(Image);
return NULL;
}
memcpy(Image->Pal.Palette, Header->ColMap, 16 * 3);
imemclear(Image->Data, Image->SizeOfData); // Since we do a += later.
for (y = 0; y < Image->Height; y++) {
for (c = 0; c < Header->NumPlanes; c++) {
x = 0;
while (x < Bps) {
if (iread(&HeadByte, 1, 1) != 1)
goto file_read_error;
if ((HeadByte & 0xC0) == 0xC0) {
HeadByte &= 0x3F;
if (iread(&Colour, 1, 1) != 1)
goto file_read_error;
for (i = 0; i < HeadByte; i++) {
k = 128;
for (j = 0; j < 8; j++) {
ScanLine[x++] = !!(Colour & k);
k >>= 1;
}
}
}
else {
k = 128;
for (j = 0; j < 8; j++) {
ScanLine[x++] = !!(HeadByte & k);
k >>= 1;
}
}
}
for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes. ;)
Image->Data[y * Image->Width + x] += ScanLine[x] << c;
}
}
}
ifree(ScanLine);
}
return Image;
file_read_error:
ifree(ScanLine);
ilCloseImage(Image);
return NULL;
}
#endif//IL_NO_DCX

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,276 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_doom.c
//
// Description: Reads Doom textures and flats
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_DOOM
#include "il_manip.h"
#include "il_pal.h"
#include "il_doompal.h"
ILboolean iLoadDoomInternal(ILvoid);
ILboolean iLoadDoomFlatInternal(ILvoid);
//
// READ A DOOM IMAGE
//
//! Reads a Doom file
ILboolean ilLoadDoom(ILconst_string FileName)
{
ILHANDLE DoomFile;
ILboolean bDoom = IL_FALSE;
// Not sure of any kind of specified extension...maybe .lmp?
/*if (!iCheckExtension(FileName, "")) {
ilSetError(IL_INVALID_EXTENSION);
return NULL;
}*/
DoomFile = iopenr(FileName);
if (DoomFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bDoom;
}
bDoom = ilLoadDoomF(DoomFile);
icloser(DoomFile);
return bDoom;
}
//! Reads an already-opened Doom file
ILboolean ilLoadDoomF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadDoomInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a Doom texture
ILboolean ilLoadDoomL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadDoomInternal();
}
// From the DTE sources (mostly by Denton Woods with corrections by Randy Heit)
ILboolean iLoadDoomInternal()
{
ILshort width, height, graphic_header[2], column_loop, row_loop;
ILint column_offset, pointer_position, first_pos;
ILubyte post, topdelta, length;
ILubyte *NewData;
ILuint i;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
first_pos = itell(); // Needed to go back to the offset table
width = GetLittleShort();
height = GetLittleShort();
graphic_header[0] = GetLittleShort(); // Not even used
graphic_header[1] = GetLittleShort(); // Not even used
if (!ilTexImage(width, height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
iCurImage->Pal.Palette = (ILubyte*)ialloc(IL_DOOMPAL_SIZE);
if (iCurImage->Pal.Palette == NULL) {
return IL_FALSE;
}
iCurImage->Pal.PalSize = IL_DOOMPAL_SIZE;
iCurImage->Pal.PalType = IL_PAL_RGB24;
memcpy(iCurImage->Pal.Palette, ilDefaultDoomPal, IL_DOOMPAL_SIZE);
// 247 is always the transparent colour (usually cyan)
memset(iCurImage->Data, 247, iCurImage->SizeOfData);
for (column_loop = 0; column_loop < width; column_loop++) {
column_offset = GetLittleInt();
pointer_position = itell();
iseek(first_pos + column_offset, IL_SEEK_SET);
while (1) {
if (iread(&topdelta, 1, 1) != 1)
return IL_FALSE;
if (topdelta == 255)
break;
if (iread(&length, 1, 1) != 1)
return IL_FALSE;
if (iread(&post, 1, 1) != 1)
return IL_FALSE; // Skip extra byte for scaling
for (row_loop = 0; row_loop < length; row_loop++) {
if (iread(&post, 1, 1) != 1)
return IL_FALSE;
if (row_loop + topdelta < height)
iCurImage->Data[(row_loop+topdelta) * width + column_loop] = post;
}
iread(&post, 1, 1); // Skip extra scaling byte
}
iseek(pointer_position, IL_SEEK_SET);
}
// Converts palette entry 247 (cyan) to transparent.
if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) {
NewData = (ILubyte*)ialloc(iCurImage->SizeOfData * 4);
if (NewData == NULL) {
return IL_FALSE;
}
for (i = 0; i < iCurImage->SizeOfData; i++) {
NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]];
NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]];
NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]];
NewData[i * 4 + 3] = iCurImage->Data[i] != 247 ? 255 : 0;
}
if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth,
4, IL_RGBA, iCurImage->Type, NewData)) {
ifree(NewData);
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
ifree(NewData);
}
ilFixImage();
return IL_TRUE;
}
//
// READ A DOOM FLAT
//
//! Reads a Doom flat file
ILboolean ilLoadDoomFlat(ILconst_string FileName)
{
ILHANDLE FlatFile;
ILboolean bFlat = IL_FALSE;
// Not sure of any kind of specified extension...maybe .lmp?
/*if (!iCheckExtension(FileName, "")) {
ilSetError(IL_INVALID_EXTENSION);
return NULL;
}*/
FlatFile = iopenr(FileName);
if (FlatFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bFlat;
}
bFlat = ilLoadDoomF(FlatFile);
icloser(FlatFile);
return bFlat;
}
//! Reads an already-opened Doom flat file
ILboolean ilLoadDoomFlatF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadDoomFlatInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a Doom flat
ILboolean ilLoadDoomFlatL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadDoomFlatInternal();
}
// Basically just ireads 4096 bytes and copies the palette
ILboolean iLoadDoomFlatInternal()
{
ILubyte *NewData;
ILuint i;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!ilTexImage(64, 64, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
iCurImage->Pal.Palette = (ILubyte*)ialloc(IL_DOOMPAL_SIZE);
if (iCurImage->Pal.Palette == NULL) {
return IL_FALSE;
}
iCurImage->Pal.PalSize = IL_DOOMPAL_SIZE;
iCurImage->Pal.PalType = IL_PAL_RGB24;
memcpy(iCurImage->Pal.Palette, ilDefaultDoomPal, IL_DOOMPAL_SIZE);
if (iread(iCurImage->Data, 1, 4096) != 4096)
return IL_FALSE;
if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) {
NewData = (ILubyte*)ialloc(iCurImage->SizeOfData * 4);
if (NewData == NULL) {
return IL_FALSE;
}
for (i = 0; i < iCurImage->SizeOfData; i++) {
NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]];
NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]];
NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]];
NewData[i * 4 + 3] = iCurImage->Data[i] != 247 ? 255 : 0;
}
if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth,
4, IL_RGBA, iCurImage->Type, NewData)) {
ifree(NewData);
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
ifree(NewData);
}
ilFixImage();
return IL_TRUE;
}
#endif

View File

@@ -0,0 +1,266 @@
#define IL_ENDIAN_C
#include "il_endian.h"
ILvoid EndianSwapData(void *_Image) {
ILuint i;
ILubyte *temp, *s, *d;
ILushort *ShortS, *ShortD;
ILuint *IntS, *IntD;
ILfloat *FltS, *FltD;
ILdouble *DblS, *DblD;
ILimage *Image = (ILimage*)_Image;
switch (Image->Type) {
case IL_BYTE:
case IL_UNSIGNED_BYTE:
switch (Image->Bpp) {
case 3:
temp = (ILubyte*)ialloc(Image->SizeOfData);
if (temp == NULL)
return;
s = Image->Data;
d = temp;
for( i = Image->Width * Image->Height; i > 0; i-- ) {
*d++ = *(s+2);
*d++ = *(s+1);
*d++ = *s;
s += 3;
}
ifree(Image->Data);
Image->Data = temp;
break;
case 4:
temp = (ILubyte*)ialloc(Image->SizeOfData);
if (temp == NULL)
return;
s = Image->Data;
d = temp;
for (i = Image->Width * Image->Height; i > 0; i--) {
*d++ = *(s+3);
*d++ = *(s+2);
*d++ = *(s+1);
*d++ = *s;
s += 4;
}
ifree(Image->Data);
Image->Data = temp;
break;
}
break;
case IL_SHORT:
case IL_UNSIGNED_SHORT:
switch (Image->Bpp) {
case 3:
temp = (ILubyte*)ialloc(Image->SizeOfData);
if (temp == NULL)
return;
ShortS = (ILushort*)Image->Data;
ShortD = (ILushort*)temp;
for (i = Image->Width * Image->Height; i > 0; i--) {
*ShortD = *ShortS++; iSwapUShort(ShortD++);
*ShortD = *ShortS++; iSwapUShort(ShortD++);
*ShortD = *ShortS++; iSwapUShort(ShortD++);
}
ifree(Image->Data);
Image->Data = temp;
break;
case 4:
temp = (ILubyte*)ialloc(Image->SizeOfData);
if (temp == NULL)
return;
ShortS = (ILushort*)Image->Data;
ShortD = (ILushort*)temp;
for (i = Image->Width * Image->Height; i > 0; i--) {
*ShortD = *ShortS++; iSwapUShort(ShortD++);
*ShortD = *ShortS++; iSwapUShort(ShortD++);
*ShortD = *ShortS++; iSwapUShort(ShortD++);
*ShortD = *ShortS++; iSwapUShort(ShortD++);
}
ifree(Image->Data);
Image->Data = temp;
break;
}
break;
case IL_INT:
case IL_UNSIGNED_INT:
switch (Image->Bpp)
{
case 3:
temp = (ILubyte*)ialloc(Image->SizeOfData);
if (temp == NULL)
return;
IntS = (ILuint*)Image->Data;
IntD = (ILuint*)temp;
for (i = Image->Width * Image->Height; i > 0; i--) {
*IntD = *IntS++; iSwapUInt(IntD++);
*IntD = *IntS++; iSwapUInt(IntD++);
*IntD = *IntS++; iSwapUInt(IntD++);
}
ifree(Image->Data);
Image->Data = temp;
break;
case 4:
temp = (ILubyte*)ialloc(Image->SizeOfData);
if (temp == NULL)
return;
IntS = (ILuint*)Image->Data;
IntD = (ILuint*)temp;
for (i = Image->Width * Image->Height; i > 0; i--) {
*IntD = *IntS++; iSwapUInt(IntD++);
*IntD = *IntS++; iSwapUInt(IntD++);
*IntD = *IntS++; iSwapUInt(IntD++);
*IntD = *IntS++; iSwapUInt(IntD++);
}
ifree(Image->Data);
Image->Data = temp;
break;
}
break;
case IL_FLOAT:
switch (Image->Bpp)
{
case 3:
temp = (ILubyte*)ialloc(Image->SizeOfData);
if (temp == NULL)
return;
FltS = (ILfloat*)Image->Data;
FltD = (ILfloat*)temp;
for (i = Image->Width * Image->Height; i > 0; i--) {
*FltD = *FltS++; iSwapFloat(FltD++);
*FltD = *FltS++; iSwapFloat(FltD++);
*FltD = *FltS++; iSwapFloat(FltD++);
}
ifree(Image->Data);
Image->Data = temp;
break;
case 4:
temp = (ILubyte*)ialloc(Image->SizeOfData);
if (temp == NULL)
return;
FltS = (ILfloat*)Image->Data;
FltD = (ILfloat*)temp;
for (i = Image->Width * Image->Height; i > 0; i--) {
*FltD = *FltS++; iSwapFloat(FltD++);
*FltD = *FltS++; iSwapFloat(FltD++);
*FltD = *FltS++; iSwapFloat(FltD++);
*FltD = *FltS++; iSwapFloat(FltD++);
}
ifree(Image->Data);
Image->Data = temp;
break;
}
break;
case IL_DOUBLE:
switch (Image->Bpp)
{
case 3:
temp = (ILubyte*)ialloc(Image->SizeOfData);
if (temp == NULL)
return;
DblS = (ILdouble*)Image->Data;
DblD = (ILdouble*)temp;
for (i = Image->Width * Image->Height; i > 0; i--) {
*DblD = *DblS++; iSwapDouble(DblD++);
*DblD = *DblS++; iSwapDouble(DblD++);
*DblD = *DblS++; iSwapDouble(DblD++);
}
ifree(Image->Data);
Image->Data = temp;
break;
case 4:
temp = (ILubyte*)ialloc(Image->SizeOfData);
if (temp == NULL)
return;
DblS = (ILdouble*)Image->Data;
DblD = (ILdouble*)temp;
for (i = Image->Width * Image->Height; i > 0; i--) {
*DblD = *DblS++; iSwapDouble(DblD++);
*DblD = *DblS++; iSwapDouble(DblD++);
*DblD = *DblS++; iSwapDouble(DblD++);
*DblD = *DblS++; iSwapDouble(DblD++);
}
ifree(Image->Data);
Image->Data = temp;
break;
}
break;
}
if( iCurImage->Format == IL_COLOUR_INDEX ) {
switch (iCurImage->Pal.PalType) {
case IL_PAL_RGB24:
case IL_PAL_BGR24:
temp = (ILubyte*)ialloc(Image->Pal.PalSize);
if (temp == NULL)
return;
s = Image->Pal.Palette;
d = temp;
for (i = Image->Pal.PalSize / 3; i > 0; i--) {
*d++ = *(s+2);
*d++ = *(s+1);
*d++ = *s;
s += 3;
}
ifree(Image->Pal.Palette);
Image->Pal.Palette = temp;
break;
case IL_PAL_RGBA32:
case IL_PAL_RGB32:
case IL_PAL_BGRA32:
case IL_PAL_BGR32:
temp = (ILubyte*)ialloc(Image->Pal.PalSize);
if (temp == NULL)
return;
s = Image->Pal.Palette;
d = temp;
for (i = Image->Pal.PalSize / 4; i > 0; i--) {
*d++ = *(s+3);
*d++ = *(s+2);
*d++ = *(s+1);
*d++ = *s;
s += 4;
}
ifree(Image->Pal.Palette);
Image->Pal.Palette = temp;
break;
}
}
return;
}

View File

@@ -0,0 +1,56 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_error.c
//
// Description: The error functions
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#define IL_ERROR_STACK_SIZE 32 // Needed elsewhere?
ILenum ilErrorNum[IL_ERROR_STACK_SIZE];
ILint ilErrorPlace = (-1);
// Sets the current error
// If you go past the stack size for this, it cycles the errors, almost like a LRU algo.
ILAPI ILvoid ILAPIENTRY ilSetError(ILenum Error)
{
ILuint i;
ilErrorPlace++;
if (ilErrorPlace >= IL_ERROR_STACK_SIZE) {
for (i = 0; i < IL_ERROR_STACK_SIZE - 2; i++) {
ilErrorNum[i] = ilErrorNum[i+1];
}
ilErrorPlace = IL_ERROR_STACK_SIZE - 1;
}
ilErrorNum[ilErrorPlace] = Error;
return;
}
//! Gets the last error on the error stack
ILenum ILAPIENTRY ilGetError(ILvoid)
{
ILenum ilReturn;
if (ilErrorPlace >= 0) {
ilReturn = ilErrorNum[ilErrorPlace];
ilErrorPlace--;
}
else
ilReturn = IL_NO_ERROR;
return ilReturn;
}

View File

@@ -0,0 +1,290 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 06/13/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_fastconv.c
//
// Description: Converts between several image formats
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifdef ALTIVEC_GCC
#include "altivec_typeconversion.h"
#endif
ILboolean iFastConvert(ILenum DestFormat)
{
ILubyte *BytePtr = iCurImage->Data;
ILushort *ShortPtr = (ILushort*)iCurImage->Data;
ILuint *IntPtr = (ILuint*)iCurImage->Data;
ILfloat *FloatPtr = (ILfloat*)iCurImage->Data;
ILdouble *DblPtr = (ILdouble*)iCurImage->Data;
#ifndef ALTIVEC_GCC
ILuint SizeOfData, i=0;
ILubyte TempByte = 0;
ILushort TempShort = 0;
ILuint TempInt = 0;
ILfloat TempFloat = 0;
ILdouble TempDbl = 0;
#endif
switch (DestFormat)
{
case IL_RGB:
case IL_BGR:
if (iCurImage->Format != IL_RGB && iCurImage->Format != IL_BGR)
return IL_FALSE;
switch (iCurImage->Type)
{
case IL_BYTE:
case IL_UNSIGNED_BYTE:
#ifdef ALTIVEC_GCC
abc2cba_byte(BytePtr,iCurImage->SizeOfData,BytePtr);
#else
SizeOfData = iCurImage->SizeOfData / 3;
#ifdef USE_WIN32_ASM
__asm
{
mov ebx, BytePtr
mov ecx, SizeOfData
L1:
mov al,[ebx+0]
xchg al,[ebx+2]
mov [ebx+0],al
add ebx,3
loop L1
}
#else
for (i = 0; i < SizeOfData; i++) {
TempByte = BytePtr[0];
BytePtr[0] = BytePtr[2];
BytePtr[2] = TempByte;
BytePtr += 3;
}
#endif//USE_WIN32_ASM
#endif
return IL_TRUE;
case IL_SHORT:
case IL_UNSIGNED_SHORT:
#ifdef ALTIVEC_GCC
abc2cba_short(ShortPtr,iCurImage->SizeOfData,ShortPtr);
#else
SizeOfData = iCurImage->SizeOfData / 6; // 3*2
#ifdef USE_WIN32_ASM
__asm
{
mov ebx, ShortPtr
mov ecx, SizeOfData
L2:
mov ax,[ebx+0]
xchg ax,[ebx+4]
mov [ebx+0],ax
add ebx,6
loop L2
}
#else
for (i = 0; i < SizeOfData; i++) {
TempShort = ShortPtr[0];
ShortPtr[0] = ShortPtr[2];
ShortPtr[2] = TempShort;
ShortPtr += 3;
}
#endif//USE_WIN32_ASM
#endif
return IL_TRUE;
case IL_INT:
case IL_UNSIGNED_INT:
#ifdef ALTIVEC_GCC
abc2cba_int(IntPtr,iCurImage->SizeOfData,IntPtr);
#else
SizeOfData = iCurImage->SizeOfData / 12; // 3*4
#ifdef USE_WIN32_ASM
__asm
{
mov ebx, IntPtr
mov ecx, SizeOfData
L3:
mov eax,[ebx+0]
xchg eax,[ebx+8]
mov [ebx+0],ax
add ebx,12
loop L3
}
#else
for (i = 0; i < SizeOfData; i++) {
TempInt = IntPtr[0];
IntPtr[0] = IntPtr[2];
IntPtr[2] = TempInt;
IntPtr += 3;
}
#endif//USE_WIN32_ASM
#endif
return IL_TRUE;
case IL_FLOAT:
#ifdef ALTIVEC_GCC
abc2cba_float(FloatPtr,iCurImage->SizeOfData,FloatPtr);
#else
SizeOfData = iCurImage->SizeOfData / 12; // 3*4
for (i = 0; i < SizeOfData; i++) {
TempFloat = FloatPtr[0];
FloatPtr[0] = FloatPtr[2];
FloatPtr[2] = TempFloat;
FloatPtr += 3;
}
#endif
return IL_TRUE;
case IL_DOUBLE:
#ifdef ALTIVEC_GCC
abc2cba_double(DblPtr,iCurImage->SizeOfData,DblPtr);
#else
SizeOfData = iCurImage->SizeOfData / 24; // 3*8
for (i = 0; i < SizeOfData; i++) {
TempDbl = DblPtr[0];
DblPtr[0] = DblPtr[2];
DblPtr[2] = TempDbl;
DblPtr += 3;
}
#endif
return IL_TRUE;
}
break;
case IL_RGBA:
case IL_BGRA:
if (iCurImage->Format != IL_RGBA && iCurImage->Format != IL_BGRA)
return IL_FALSE;
switch (iCurImage->Type)
{
case IL_BYTE:
case IL_UNSIGNED_BYTE:
#ifdef ALTIVEC_GCC
abcd2cbad_byte(BytePtr,iCurImage->SizeOfData,BytePtr);
#else
SizeOfData = iCurImage->SizeOfData / 4;
#ifdef USE_WIN32_ASM
__asm
{
mov ebx, BytePtr
mov ecx, SizeOfData
L4:
mov eax,[ebx]
bswap eax
ror eax,8
mov [ebx], eax
add ebx,4
loop L4
}
#else
for (i = 0; i < SizeOfData; i++) {
TempByte = BytePtr[0];
BytePtr[0] = BytePtr[2];
BytePtr[2] = TempByte;
BytePtr += 4;
}
#endif//USE_WIN32_ASM
#endif
return IL_TRUE;
case IL_SHORT:
case IL_UNSIGNED_SHORT:
#ifdef ALTIVEC_GCC
abcd2cbad_short(ShortPtr,iCurImage->SizeOfData,ShortPtr);
#else
SizeOfData = iCurImage->SizeOfData / 8; // 4*2
#ifdef USE_WIN32_ASM
__asm
{
mov ebx, ShortPtr
mov ecx, SizeOfData
L5:
mov ax,[ebx+0]
xchg ax,[ebx+4]
mov [ebx+0],ax
add ebx,8
loop L5
}
#else
for (i = 0; i < SizeOfData; i++) {
TempShort = ShortPtr[0];
ShortPtr[0] = ShortPtr[2];
ShortPtr[2] = TempShort;
ShortPtr += 4;
}
#endif//USE_WIN32_ASM
#endif
return IL_TRUE;
case IL_INT:
case IL_UNSIGNED_INT:
#ifdef ALTIVEC_GCC
abcd2cbad_int(IntPtr,iCurImage->SizeOfData,IntPtr);
#else
SizeOfData = iCurImage->SizeOfData / 16; // 4*4
#ifdef USE_WIN32_ASM
__asm
{
mov ebx, IntPtr
mov ecx, SizeOfData
L6:
mov eax,[ebx+0]
xchg eax,[ebx+8]
mov [ebx+0],ax
add ebx,16
loop L6
}
#else
for (i = 0; i < SizeOfData; i++) {
TempInt = IntPtr[0];
IntPtr[0] = IntPtr[2];
IntPtr[2] = TempInt;
IntPtr += 4;
}
#endif//USE_WIN32_ASM
#endif
return IL_TRUE;
case IL_FLOAT:
#ifdef ALTIVEC_GCC
abcd2cbad_float(FloatPtr,iCurImage->SizeOfData,FloatPtr);
#else
SizeOfData = iCurImage->SizeOfData / 16; // 4*4
for (i = 0; i < SizeOfData; i++) {
TempFloat = FloatPtr[0];
FloatPtr[0] = FloatPtr[2];
FloatPtr[2] = TempFloat;
FloatPtr += 4;
}
#endif
return IL_TRUE;
case IL_DOUBLE:
#ifdef ALTIVEC_GCC
abcd2cbad_double(DblPtr,iCurImage->SizeOfData,DblPtr);
#else
SizeOfData = iCurImage->SizeOfData / 32; // 4*8
for (i = 0; i < SizeOfData; i++) {
TempDbl = DblPtr[0];
DblPtr[0] = DblPtr[2];
DblPtr[2] = TempDbl;
DblPtr += 4;
}
#endif
return IL_TRUE;
}
}
return IL_FALSE;
}

View File

@@ -0,0 +1,695 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 09/01/2003 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_files.c
//
// Description: File handling for DevIL
//
//-----------------------------------------------------------------------------
#define __FILES_C
#include "il_internal.h"
#include <stdarg.h>
// All specific to the next set of functions
ILboolean ILAPIENTRY iEofFile(ILvoid);
ILboolean ILAPIENTRY iEofLump(ILvoid);
ILint ILAPIENTRY iGetcFile(ILvoid);
ILint ILAPIENTRY iGetcLump(ILvoid);
ILuint ILAPIENTRY iReadFile(ILvoid *Buffer, ILuint Size, ILuint Number);
ILuint ILAPIENTRY iReadLump(ILvoid *Buffer, const ILuint Size, const ILuint Number);
ILuint ILAPIENTRY iSeekRFile(ILint Offset, ILuint Mode);
ILuint ILAPIENTRY iSeekRLump(ILint Offset, ILuint Mode);
ILuint ILAPIENTRY iSeekWFile(ILint Offset, ILuint Mode);
ILuint ILAPIENTRY iSeekWLump(ILint Offset, ILuint Mode);
ILuint ILAPIENTRY iTellRFile(ILvoid);
ILuint ILAPIENTRY iTellRLump(ILvoid);
ILuint ILAPIENTRY iTellWFile(ILvoid);
ILuint ILAPIENTRY iTellWLump(ILvoid);
ILint ILAPIENTRY iPutcFile(ILubyte Char);
ILint ILAPIENTRY iPutcLump(ILubyte Char);
ILint ILAPIENTRY iWriteFile(const ILvoid *Buffer, ILuint Size, ILuint Number);
ILint ILAPIENTRY iWriteLump(const ILvoid *Buffer, ILuint Size, ILuint Number);
ILHANDLE FileRead = NULL, FileWrite = NULL;
const ILvoid *ReadLump = NULL;
ILvoid *WriteLump = NULL;
ILuint ReadLumpPos = 0, ReadLumpSize = 0, ReadFileStart = 0, WriteFileStart = 0;
ILuint WriteLumpPos = 0, WriteLumpSize = 0;
fGetcProc GetcProcCopy;
fReadProc ReadProcCopy;
fSeekRProc SeekProcCopy;
fTellRProc TellProcCopy;
ILHANDLE (ILAPIENTRY *iopenCopy)(ILstring);
ILvoid (ILAPIENTRY *icloseCopy)(ILHANDLE);
ILboolean UseCache = IL_FALSE;
ILubyte *Cache = NULL;
ILuint CacheSize, CachePos, CacheStartPos, CacheBytesRead;
/*// Just preserves the current read functions and replaces
// the current read functions with the default read funcs.
ILvoid ILAPIENTRY iPreserveReadFuncs()
{
// Create backups
GetcProcCopy = GetcProc;
ReadProcCopy = ReadProc;
SeekProcCopy = SeekRProc;
TellProcCopy = TellRProc;
iopenCopy = iopenr;
icloseCopy = icloser;
// Set the standard procs to read
ilResetRead();
return;
}
// Restores the read functions - must be used after iPreserveReadFuncs().
ILvoid ILAPIENTRY iRestoreReadFuncs()
{
GetcProc = GetcProcCopy;
ReadProc = ReadProcCopy;
SeekRProc = SeekProcCopy;
TellRProc = TellProcCopy;
iopenr = iopenCopy;
icloser = icloseCopy;
return;
}*/
// Next 7 functions are the default read functions
ILHANDLE ILAPIENTRY iDefaultOpenR(ILconst_string FileName)
{
#ifndef _UNICODE
return (ILHANDLE)fopen(FileName, "rb");
#else
return (ILHANDLE)_wfopen(FileName, L"rb");
#endif//UNICODE
}
ILvoid ILAPIENTRY iDefaultCloseR(ILHANDLE Handle)
{
fclose((FILE*)Handle);
return;
}
ILboolean ILAPIENTRY iDefaultEof(ILHANDLE Handle)
{
ILuint OrigPos, FileSize;
// Find out the filesize for checking for the end of file
OrigPos = itell();
iseek(0, IL_SEEK_END);
FileSize = itell();
iseek(OrigPos, IL_SEEK_SET);
if (itell() >= FileSize)
return IL_TRUE;
return IL_FALSE;
}
ILint ILAPIENTRY iDefaultGetc(ILHANDLE Handle)
{
ILint Val;
if (!UseCache) {
Val = fgetc((FILE*)Handle);
if (Val == IL_EOF)
ilSetError(IL_FILE_READ_ERROR);
}
else {
Val = 0;
if (iread(&Val, 1, 1) != 1)
return IL_EOF;
}
return Val;
}
ILint ILAPIENTRY iDefaultRead(ILvoid *Buffer, ILuint Size, ILuint Number, ILHANDLE Handle)
{
return fread(Buffer, Size, Number, (FILE*)Handle);
}
ILint ILAPIENTRY iDefaultRSeek(ILHANDLE Handle, ILint Offset, ILint Mode)
{
return fseek((FILE*)Handle, Offset, Mode);
}
ILint ILAPIENTRY iDefaultWSeek(ILHANDLE Handle, ILint Offset, ILint Mode)
{
return fseek((FILE*)Handle, Offset, Mode);
}
ILint ILAPIENTRY iDefaultRTell(ILHANDLE Handle)
{
return ftell((FILE*)Handle);
}
ILint ILAPIENTRY iDefaultWTell(ILHANDLE Handle)
{
return ftell((FILE*)Handle);
}
ILHANDLE ILAPIENTRY iDefaultOpenW(ILconst_string FileName)
{
#ifndef _UNICODE
return (ILHANDLE)fopen(FileName, "wb");
#else
return (ILHANDLE)_wfopen(FileName, L"wb");
#endif//_UNICODE
}
ILvoid ILAPIENTRY iDefaultCloseW(ILHANDLE Handle)
{
fclose((FILE*)Handle);
return;
}
ILint ILAPIENTRY iDefaultPutc(ILubyte Char, ILHANDLE Handle)
{
return fputc(Char, (FILE*)Handle);
}
ILint ILAPIENTRY iDefaultWrite(const ILvoid *Buffer, ILuint Size, ILuint Number, ILHANDLE Handle)
{
return fwrite(Buffer, Size, Number, (FILE*)Handle);
}
ILvoid ILAPIENTRY ilResetRead()
{
ilSetRead(iDefaultOpenR, iDefaultCloseR, iDefaultEof, iDefaultGetc,
iDefaultRead, iDefaultRSeek, iDefaultRTell);
return;
}
ILvoid ILAPIENTRY ilResetWrite()
{
ilSetWrite(iDefaultOpenW, iDefaultCloseW, iDefaultPutc,
iDefaultWSeek, iDefaultWTell, iDefaultWrite);
return;
}
//! Allows you to override the default file-reading functions.
ILvoid ILAPIENTRY ilSetRead(fOpenRProc Open, fCloseRProc Close, fEofProc Eof, fGetcProc Getc, fReadProc Read, fSeekRProc Seek, fTellRProc Tell)
{
iopenr = Open;
icloser = Close;
EofProc = Eof;
GetcProc = Getc;
ReadProc = Read;
SeekRProc = Seek;
TellRProc = Tell;
return;
}
//! Allows you to override the default file-writing functions.
ILvoid ILAPIENTRY ilSetWrite(fOpenRProc Open, fCloseRProc Close, fPutcProc Putc, fSeekWProc Seek, fTellWProc Tell, fWriteProc Write)
{
iopenw = Open;
iclosew = Close;
PutcProc = Putc;
WriteProc = Write;
SeekWProc = Seek;
TellWProc = Tell;
return;
}
// Tells DevIL that we're reading from a file, not a lump
ILvoid iSetInputFile(ILHANDLE File)
{
ieof = iEofFile;
igetc = iGetcFile;
iread = iReadFile;
iseek = iSeekRFile;
itell = iTellRFile;
FileRead = File;
ReadFileStart = itell();
}
// Tells DevIL that we're reading from a lump, not a file
ILvoid iSetInputLump(const ILvoid *Lump, ILuint Size)
{
ieof = iEofLump;
igetc = iGetcLump;
iread = iReadLump;
iseek = iSeekRLump;
itell = iTellRLump;
ReadLump = Lump;
ReadLumpPos = 0;
ReadLumpSize = Size;
}
// Tells DevIL that we're writing to a file, not a lump
ILvoid iSetOutputFile(ILHANDLE File)
{
// Helps with ilGetLumpPos().
WriteLump = NULL;
WriteLumpPos = 0;
WriteLumpSize = 0;
iputc = iPutcFile;
iseekw = iSeekWFile;
itellw = iTellWFile;
iwrite = iWriteFile;
FileWrite = File;
}
// Tells DevIL that we're writing to a lump, not a file
ILvoid iSetOutputLump(ILvoid *Lump, ILuint Size)
{
iputc = iPutcLump;
iseekw = iSeekWLump;
itellw = iTellWLump;
iwrite = iWriteLump;
WriteLump = Lump;
WriteLumpPos = 0;
WriteLumpSize = Size;
}
ILuint ILAPIENTRY ilGetLumpPos()
{
if (WriteLump)
return WriteLumpPos;
return 0;
}
ILuint ILAPIENTRY ilprintf(const char *Line, ...)
{
char Buffer[2048]; // Hope this is large enough
va_list VaLine;
ILuint i;
va_start(VaLine, Line);
vsprintf(Buffer, Line, VaLine);
va_end(VaLine);
i = strlen(Buffer);
iwrite(Buffer, 1, i);
return i;
}
// To pad zeros where needed...
ILvoid ipad(ILuint NumZeros)
{
ILuint i = 0;
for (; i < NumZeros; i++)
iputc(0);
return;
}
//
// The rest of the functions following in this file are quite
// self-explanatory, except where commented.
//
// Next 12 functions are the default write functions
ILboolean ILAPIENTRY iEofFile(ILvoid)
{
return EofProc((FILE*)FileRead);
}
ILboolean ILAPIENTRY iEofLump(ILvoid)
{
if (ReadLumpSize)
return (ReadLumpPos >= ReadLumpSize);
return IL_FALSE;
}
ILint ILAPIENTRY iGetcFile(ILvoid)
{
if (!UseCache) {
return GetcProc(FileRead);
}
if (CachePos >= CacheSize) {
iPreCache(CacheSize);
}
CacheBytesRead++;
return Cache[CachePos++];
}
ILint ILAPIENTRY iGetcLump(ILvoid)
{
// If ReadLumpSize is 0, don't even check to see if we've gone past the bounds.
if (ReadLumpSize > 0) {
if (ReadLumpPos + 1 > ReadLumpSize) {
ReadLumpPos--;
ilSetError(IL_FILE_READ_ERROR);
return IL_EOF;
}
}
return *((ILubyte*)ReadLump + ReadLumpPos++);
}
ILuint ILAPIENTRY iReadFile(ILvoid *Buffer, ILuint Size, ILuint Number)
{
ILuint TotalBytes = 0, BytesCopied;
ILuint BuffSize = Size * Number;
ILuint NumRead;
if (!UseCache) {
NumRead = ReadProc(Buffer, Size, Number, FileRead);
if (NumRead != Number)
ilSetError(IL_FILE_READ_ERROR);
return NumRead;
}
/*if (Cache == NULL || CacheSize == 0) { // Shouldn't happen, but we check anyway.
return ReadProc(Buffer, Size, Number, FileRead);
}*/
if (BuffSize < CacheSize - CachePos) {
memcpy(Buffer, Cache + CachePos, BuffSize);
CachePos += BuffSize;
CacheBytesRead += BuffSize;
if (Size != 0)
BuffSize /= Size;
return BuffSize;
}
else {
while (TotalBytes < BuffSize) {
// If loop through more than once, after first, CachePos is 0.
if (TotalBytes + CacheSize - CachePos > BuffSize)
BytesCopied = BuffSize - TotalBytes;
else
BytesCopied = CacheSize - CachePos;
memcpy((ILubyte*)Buffer + TotalBytes, Cache + CachePos, BytesCopied);
TotalBytes += BytesCopied;
CachePos += BytesCopied;
if (TotalBytes < BuffSize) {
iPreCache(CacheSize);
}
}
}
CacheBytesRead += TotalBytes;
if (Size != 0)
TotalBytes /= Size;
if (TotalBytes != Number)
ilSetError(IL_FILE_READ_ERROR);
return TotalBytes;
}
ILuint ILAPIENTRY iReadLump(ILvoid *Buffer, const ILuint Size, const ILuint Number)
{
ILuint i, ByteSize = Size * Number;
for (i = 0; i < ByteSize; i++) {
*((ILubyte*)Buffer + i) = *((ILubyte*)ReadLump + ReadLumpPos + i);
if (ReadLumpSize > 0) { // ReadLumpSize is too large to care about apparently
if (ReadLumpPos + i > ReadLumpSize) {
ReadLumpPos += i;
if (i != Number)
ilSetError(IL_FILE_READ_ERROR);
return i;
}
}
}
ReadLumpPos += i;
if (Size != 0)
i /= Size;
if (i != Number)
ilSetError(IL_FILE_READ_ERROR);
return i;
}
ILboolean iPreCache(ILuint Size)
{
// Reading from a memory lump, so don't cache.
if (iread == iReadLump) {
//iUnCache(); // DW: Removed 06-10-2002.
return IL_TRUE;
}
if (Cache) {
ifree(Cache);
}
if (Size == 0) {
Size = 1;
}
Cache = (ILubyte*)ialloc(Size);
if (Cache == NULL) {
return IL_FALSE;
}
UseCache = IL_FALSE;
CacheStartPos = itell();
CacheSize = iread(Cache, 1, Size);
if (CacheSize != Size)
ilGetError(); // Get rid of the IL_FILE_READ_ERROR.
//2003-09-09: uncommented the following line to prevent
//an infinite loop in ilPreCache()
CacheSize = Size;
CachePos = 0;
UseCache = IL_TRUE;
CacheBytesRead = 0;
return IL_TRUE;
}
ILvoid iUnCache()
{
//changed 2003-09-01:
//make iUnCache smart enough to return if
//no cache is used
if(!UseCache)
return;
if (iread == iReadLump)
return;
CacheSize = 0;
CachePos = 0;
if (Cache) {
ifree(Cache);
Cache = NULL;
}
UseCache = IL_FALSE;
iseek(CacheStartPos + CacheBytesRead, IL_SEEK_SET);
return;
}
ILuint ILAPIENTRY iSeekRFile(ILint Offset, ILuint Mode)
{
if (Mode == IL_SEEK_SET)
Offset += ReadFileStart; // This allows us to use IL_SEEK_SET in the middle of a file.
return SeekRProc(FileRead, Offset, Mode);
}
// Returns 1 on error, 0 on success
ILuint ILAPIENTRY iSeekRLump(ILint Offset, ILuint Mode)
{
switch (Mode)
{
case IL_SEEK_SET:
if (Offset > (ILint)ReadLumpSize)
return 1;
ReadLumpPos = Offset;
break;
case IL_SEEK_CUR:
if (ReadLumpPos + Offset > ReadLumpSize)
return 1;
ReadLumpPos += Offset;
break;
case IL_SEEK_END:
if (Offset > 0)
return 1;
// Should we use >= instead?
if (abs(Offset) > (ILint)ReadLumpSize) // If ReadLumpSize == 0, too bad
return 1;
ReadLumpPos = ReadLumpSize + Offset;
break;
default:
return 1;
}
return 0;
}
ILuint ILAPIENTRY iTellRFile(ILvoid)
{
return TellRProc(FileRead);
}
ILuint ILAPIENTRY iTellRLump(ILvoid)
{
return ReadLumpPos;
}
ILHANDLE ILAPIENTRY iGetFile(ILvoid)
{
return FileRead;
}
const ILubyte* ILAPIENTRY iGetLump(ILvoid) {
return (ILubyte *)ReadLump;
}
// Next 4 functions are the default write functions
ILint ILAPIENTRY iPutcFile(ILubyte Char)
{
return PutcProc(Char, FileWrite);
}
ILint ILAPIENTRY iPutcLump(ILubyte Char)
{
if (WriteLumpPos >= WriteLumpSize)
return IL_EOF; // IL_EOF
*((ILubyte*)(WriteLump) + WriteLumpPos++) = Char;
return Char;
}
ILint ILAPIENTRY iWriteFile(const ILvoid *Buffer, ILuint Size, ILuint Number)
{
ILuint NumWritten;
NumWritten = WriteProc(Buffer, Size, Number, FileWrite);
if (NumWritten != Number) {
ilSetError(IL_FILE_WRITE_ERROR);
return 0;
}
return NumWritten;
}
ILint ILAPIENTRY iWriteLump(const ILvoid *Buffer, ILuint Size, ILuint Number)
{
ILuint SizeBytes = Size * Number;
ILuint i = 0;
for (; i < SizeBytes; i++) {
if (WriteLumpSize > 0) {
if (WriteLumpPos + i >= WriteLumpSize) { // Should we use > instead?
ilSetError(IL_FILE_WRITE_ERROR);
WriteLumpPos += i;
return i;
}
}
*((ILubyte*)WriteLump + WriteLumpPos + i) = *((ILubyte*)Buffer + i);
}
WriteLumpPos += SizeBytes;
return SizeBytes;
}
ILuint ILAPIENTRY iSeekWFile(ILint Offset, ILuint Mode)
{
if (Mode == IL_SEEK_SET)
Offset += WriteFileStart; // This allows us to use IL_SEEK_SET in the middle of a file.
return SeekWProc(FileWrite, Offset, Mode);
}
// Returns 1 on error, 0 on success
ILuint ILAPIENTRY iSeekWLump(ILint Offset, ILuint Mode)
{
switch (Mode)
{
case IL_SEEK_SET:
if (Offset > (ILint)WriteLumpSize)
return 1;
WriteLumpPos = Offset;
break;
case IL_SEEK_CUR:
if (WriteLumpPos + Offset > WriteLumpSize)
return 1;
WriteLumpPos += Offset;
break;
case IL_SEEK_END:
if (Offset > 0)
return 1;
// Should we use >= instead?
if (abs(Offset) > (ILint)WriteLumpSize) // If WriteLumpSize == 0, too bad
return 1;
WriteLumpPos = WriteLumpSize + Offset;
break;
default:
return 1;
}
return 0;
}
ILuint ILAPIENTRY iTellWFile(ILvoid)
{
return TellWProc(FileWrite);
}
ILuint ILAPIENTRY iTellWLump(ILvoid)
{
return WriteLumpPos;
}

View File

@@ -0,0 +1,766 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 06/13/2002 <--Y2K Compliant! =]
//
// 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 ILvoid *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 ILvoid *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)) {
return IL_FALSE;
}
}
if (!GetImages(&GlobalPal, &Header))
return IL_FALSE;
if (GlobalPal.Palette && GlobalPal.PalSize)
ifree(GlobalPal.Palette);
GlobalPal.Palette = NULL;
GlobalPal.PalSize = 0;
ilFixImage();
return IL_TRUE;
}
ILboolean iGetPalette(ILubyte Info, ILpal *Pal)
{
// The ld(palettes bpp - 1) is stored in the lower
// 3 bits of Info (weird gif format ... :) )
Pal->PalSize = (1 << ((Info & 0x7) + 1)) * 3;
Pal->PalType = IL_PAL_RGB24;
Pal->Palette = (ILubyte*)ialloc(Pal->PalSize);
if (Pal->Palette == NULL)
return IL_FALSE;
if (iread(Pal->Palette, 1, Pal->PalSize) != Pal->PalSize) {
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;
ILuint NumImages = 0, i;
ILint input;
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;
}
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);
//memset(Image->Data, GifHead->Background, Image->SizeOfData);
}
Image->OffX = ImageDesc.OffX;
Image->OffY = ImageDesc.OffY;
// Check to see if the image has its own palette.
if (ImageDesc.ImageInfo & (1 << 7)) {
if (!iGetPalette(ImageDesc.ImageInfo, &Image->Pal)) {
goto error_clean;
}
}
else {
if (!iCopyPalette(&Image->Pal, GlobalPal)) {
goto error_clean;
}
}
if (!GifGetData(Image->Data + ImageDesc.OffX + ImageDesc.OffY*Image->Width, Image->SizeOfData,
ImageDesc.Width, ImageDesc.Height, Image->Width, &Gfx)) {
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(ILubyte *Data, ILuint ImageSize, ILuint Width, ILuint Height, ILuint Stride, GFXCONTROL *Gfx) {
ILubyte *sp;
ILint code, fc, oc;
ILubyte DisposalMethod = 0;
ILint c, size;
ILuint i = 0, Read = 0, j = 0;
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) {
Data[i++] = c;
}
}
if (i == Width) {
Data += Stride;
i = 0;
Read += 1;
++j;
if (j >= Height) {
cleanUpGifLoadState();
return IL_FALSE;
}
}
} else {
code = c;
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) {
Data[i++] = *sp;
}
}
if (i == Width) {
Data += Stride;
i = 0;
Read += 1;
++j;
if (j >= Height) {
cleanUpGifLoadState();
return IL_FALSE;
}
}
}
}
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;
}
// Assumes that Dest has nothing in it.
ILboolean iCopyPalette(ILpal *Dest, ILpal *Src)
{
if (Src->Palette == NULL || Src->PalSize == 0)
return IL_FALSE;
Dest->Palette = (ILubyte*)ialloc(Src->PalSize);
if (Dest->Palette == NULL)
return IL_FALSE;
memcpy(Dest->Palette, Src->Palette, Src->PalSize);
Dest->PalSize = Src->PalSize;
Dest->PalType = Src->PalType;
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

View File

@@ -0,0 +1,349 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2004 by Denton Woods (this file by thakis)
// Last modified: 09/06/2004
//
// Filename: src-IL/src/il_bmp.c
//
// Description: Reads a RADIANCE High Dynamic Range Image
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_HDR
#include "il_hdr.h"
#include "il_endian.h"
//! Checks if the file specified in FileName is a valid .hdr file.
ILboolean ilIsValidHdr(ILconst_string FileName)
{
ILHANDLE HdrFile;
ILboolean bHdr = IL_FALSE;
if (!iCheckExtension(FileName, IL_TEXT("hdr"))) {
ilSetError(IL_INVALID_EXTENSION);
return bHdr;
}
HdrFile = iopenr(FileName);
if (HdrFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bHdr;
}
bHdr = ilIsValidHdrF(HdrFile);
icloser(HdrFile);
return bHdr;
}
//! Checks if the ILHANDLE contains a valid .hdr file at the current position.
ILboolean ilIsValidHdrF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iIsValidHdr();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Checks if Lump is a valid .hdr lump.
ILboolean ilIsValidHdrL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iIsValidHdr();
}
// Internal function used to get the .hdr header from the current file.
ILboolean iGetHdrHead(HDRHEADER *Header)
{
ILboolean done = IL_FALSE;
char a, b;
char x[3], y[3]; //changed 20050217: added space for the '\0' char
char buff[80];
ILuint count = 0;
iread(Header->Signature, 1, 10);
//skip lines until an empty line is found.
//this marks the end of header information,
//the next line contains the image's dimension.
//TODO: read header contents into variables
//(EXPOSURE, orientation, xyz correction, ...)
if (iread(&a, 1, 1) != 1)
return IL_FALSE;
while(!done) {
if (iread(&b, 1, 1) != 1)
return IL_FALSE;
if (b == '\n' && a == '\n')
done = IL_TRUE;
else
a = b;
}
//read dimensions (note that this assumes a somewhat valid image)
if (iread(&a, 1, 1) != 1)
return IL_FALSE;
while (a != '\n') {
buff[count] = a;
if (iread(&a, 1, 1) != 1)
return IL_FALSE;
++count;
}
buff[count] = '\0';
//note that this is not the 100% correct way to load hdr images:
//in a perfect world we would check if there's a +/- X/Y in front
//of width and heigth and mirror + rotate the image after decoding
//according to that. But HDRShop doesn't do that either (and that's
//my reference program :) ) and it's just a rotate and a mirror,
//nothing that really changes the appearance of the loaded image...
//(The code as it is now assumes that y contains "-Y" and x contains
//"+X" after the following line)
//Furthermore, this crashes if the read strings are longer than 2 chars o_O
sscanf(buff, "%s %d %s %d", y, &Header->Height, x, &Header->Width);
return IL_TRUE;
}
// Internal function to get the header and check it.
ILboolean iIsValidHdr()
{
char Head[10];
ILint Read;
Read = iread(Head, 1, 10);
iseek(-Read, IL_SEEK_CUR); // Go ahead and restore to previous state
if (Read != 10)
return IL_FALSE;
return
strnicmp(Head, "#?RADIANCE", 10) == 0
|| strnicmp(Head, "#?RGBE", 6) == 0;
}
// Internal function used to check if the HEADER is a valid .hdr header.
ILboolean iCheckHdr(HDRHEADER *Header)
{
return
strnicmp(Header->Signature, "#?RADIANCE", 10) == 0
|| strnicmp(Header->Signature, "#?RGBE", 6) == 0;
}
//! Reads a .hdr file
ILboolean ilLoadHdr(ILconst_string FileName)
{
ILHANDLE HdrFile;
ILboolean bHdr = IL_FALSE;
HdrFile = iopenr(FileName);
if (HdrFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bHdr;
}
bHdr = ilLoadHdrF(HdrFile);
icloser(HdrFile);
return bHdr;
}
//! Reads an already-opened .hdr file
ILboolean ilLoadHdrF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadHdrInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a .hdr
ILboolean ilLoadHdrL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadHdrInternal();
}
// Internal function used to load the .hdr.
ILboolean iLoadHdrInternal()
{
HDRHEADER Header;
ILfloat *data;
ILubyte *scanline;
ILuint i, j, e, r, g, b;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!iGetHdrHead(&Header)) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
if (!iCheckHdr(&Header)) {
//iseek(-(ILint)sizeof(BMPHEAD), IL_SEEK_CUR);
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
// Update the current image with the new dimensions
if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_FLOAT, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
//read image data
if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
iPreCache(iCurImage->Width / 8 * iCurImage->Height);
data = (ILfloat*)iCurImage->Data;
scanline = (ILubyte*)ialloc(Header.Width*4);
for (i = 0; i < Header.Height; ++i) {
ReadScanline(scanline, Header.Width);
//convert hdrs internal format to floats
for (j = 0; j < 4*Header.Width; j += 4) {
ILuint *ee;
ILfloat t, *ff;
e = scanline[j + 3];
r = scanline[j + 0];
g = scanline[j + 1];
b = scanline[j + 2];
//t = (float)pow(2.f, ((ILint)e) - 128);
if (e != 0)
e = (e - 1) << 23;
// All this just to avoid stric-aliasing warnings...
// was: t = *(ILfloat*)&e
ee = &e;
ff = (ILfloat*)ee;
t = *ff;
data[0] = (r/255.0f)*t;
data[1] = (g/255.0f)*t;
data[2] = (b/255.0f)*t;
data += 3;
}
}
iUnCache();
ifree(scanline);
return ilFixImage();
}
ILvoid ReadScanline(ILubyte *scanline, ILuint w) {
ILubyte *runner;
ILuint r, g, b, e, read, shift;
r = igetc();
g = igetc();
b = igetc();
e = igetc();
//check if the scanline is in the new format
//if so, e, r, g, g are stored separated and are
//rle-compressed independently.
if (r == 2 && g == 2) {
ILuint length = (b << 8) | e;
ILuint j, t, k;
if (length > w)
length = w; //fix broken files
for (k = 0; k < 4; ++k) {
runner = scanline + k;
j = 0;
while (j < length) {
t = igetc();
if (t > 128) { //Run?
ILubyte val = igetc();
t &= 127;
//copy current byte
while (t > 0 && j < length) {
*runner = val;
runner += 4;
--t;
++j;
}
}
else { //No Run.
//read new bytes
while (t > 0 && j < length) {
*runner = igetc();
runner += 4;
--t;
++j;
}
}
}
}
return; //done decoding a scanline in separated format
}
//if we come here, we are dealing with old-style scanlines
shift = 0;
read = 0;
runner = scanline;
while (read < w) {
if (read != 0) {
r = igetc();
g = igetc();
b = igetc();
e = igetc();
}
//if all three mantissas are 1, then this is a rle
//count dword
if (r == 1 && g == 1 && b == 1) {
ILuint length = e;
ILuint j;
for (j = length << shift; j > 0 && read < w; --j) {
memcpy(runner, runner - 4, 4);
runner += 4;
++read;
}
//if more than one rle count dword is read
//consecutively, they are higher order bytes
//of the first read value. shift keeps track of
//that.
shift += 8;
}
else {
runner[0] = r;
runner[1] = g;
runner[2] = b;
runner[3] = e;
shift = 0;
runner += 4;
++read;
}
}
}
#endif//IL_NO_HDR

View File

@@ -0,0 +1,135 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 02/19/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_header.c
//
// Description: Generates a C-style header file for the current image.
//
//-----------------------------------------------------------------------------
#ifndef IL_NO_CHEAD
#include "il_internal.h"
// Just a guess...let's see what's purty!
#define MAX_LINE_WIDTH 14
//! Generates a C-style header file for the current image.
ILboolean ilSaveCHeader(ILconst_string FileName, const char *InternalName)
{
FILE *HeadFile;
ILuint i = 0, j;
ILimage *TempImage;
const char *Name;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
Name = iGetString(IL_CHEAD_HEADER_STRING);
if (Name == NULL)
Name = InternalName;
if (FileName == NULL || Name == NULL ||
#ifndef _UNICODE
strlen(FileName) < 1 || strlen(Name) < 1) {
#else
wcslen(FileName) < 1 || wcslen(FileName) < 1) {
#endif//_UNICODE
ilSetError(IL_INVALID_VALUE);
return IL_FALSE;
}
if (!iCheckExtension(FileName, IL_TEXT("h"))) {
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;
}
}
if (iCurImage->Bpc > 1) {
TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE);
if (TempImage == NULL)
return IL_FALSE;
} else {
TempImage = iCurImage;
}
#ifndef _WIN32_WCE
HeadFile = fopen(FileName, "wb");
#else
HeadFile = _wfopen(FileName, L"wb");
#endif//_WIN32_WCE
if (HeadFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return IL_FALSE;
}
fprintf(HeadFile, "//#include <il/il.h>\n");
fprintf(HeadFile, "// C Image Header:\n\n\n");
fprintf(HeadFile, "// IMAGE_BPP is in bytes per pixel, *not* bits\n");
fprintf(HeadFile, "#define IMAGE_BPP %d\n",iCurImage->Bpp);
fprintf(HeadFile, "#define IMAGE_WIDTH %d\n", iCurImage->Width);
fprintf(HeadFile, "#define IMAGE_HEIGHT %d\n", iCurImage->Height);
fprintf(HeadFile, "#define IMAGE_DEPTH %d\n\n\n", iCurImage->Depth);
fprintf(HeadFile, "#define IMAGE_TYPE 0x%X\n", iCurImage->Type);
fprintf(HeadFile, "#define IMAGE_FORMAT 0x%X\n\n\n", iCurImage->Format);
fprintf(HeadFile, "ILubyte %s[] = {\n", Name);
for (; i < TempImage->SizeOfData; i += MAX_LINE_WIDTH) {
fprintf(HeadFile, "\t");
for (j = 0; j < MAX_LINE_WIDTH; j++) {
if (i + j >= TempImage->SizeOfData - 1) {
fprintf(HeadFile, "%4d", TempImage->Data[i+j]);
break;
}
else
fprintf(HeadFile, "%4d,", TempImage->Data[i+j]);
}
fprintf(HeadFile, "\n");
}
if (TempImage != iCurImage)
ilCloseImage(TempImage);
fprintf(HeadFile, "};\n");
if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE) {
fprintf(HeadFile, "\n\n");
fprintf(HeadFile, "#define IMAGE_PALSIZE %u\n\n", iCurImage->Pal.PalSize);
fprintf(HeadFile, "#define IMAGE_PALTYPE 0x%X\n\n", iCurImage->Pal.PalType);
fprintf(HeadFile, "ILubyte %sPal[] = {\n", Name);
for (i = 0; i < iCurImage->Pal.PalSize; i += MAX_LINE_WIDTH) {
fprintf(HeadFile, "\t");
for (j = 0; j < MAX_LINE_WIDTH; j++) {
if (i + j >= iCurImage->Pal.PalSize - 1) {
fprintf(HeadFile, " %4d", iCurImage->Pal.Palette[i+j]);
break;
}
else
fprintf(HeadFile, " %4d,", iCurImage->Pal.Palette[i+j]);
}
fprintf(HeadFile, "\n");
}
fprintf(HeadFile, "};\n");
}
fclose(HeadFile);
return IL_TRUE;
}
#endif//IL_NO_CHEAD

View File

@@ -0,0 +1,394 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2001-2002 by Denton Woods
// Last modified: 06/13/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_icon.c
//
// Description: Reads from a Windows icon (.ico) file.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_ICO
#include "il_icon.h"
//! Reads an icon file.
ILboolean ilLoadIcon(ILconst_string FileName)
{
ILHANDLE IconFile;
ILboolean bIcon = IL_FALSE;
IconFile = iopenr(FileName);
if (IconFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bIcon;
}
bIcon = ilLoadIconF(IconFile);
icloser(IconFile);
return bIcon;
}
//! Reads an already-opened icon file.
ILboolean ilLoadIconF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadIconInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains an icon.
ILboolean ilLoadIconL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadIconInternal();
}
// Internal function used to load the icon.
ILboolean iLoadIconInternal()
{
ICODIR IconDir;
ICODIRENTRY *DirEntries = NULL;
ICOIMAGE *IconImages = NULL;
ILimage *Image = NULL;
ILint i;
ILuint Size, PadSize, ANDPadSize, j, k, l, m, x, w, CurAndByte, AndBytes;
ILboolean BaseCreated = IL_FALSE;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
IconDir.Reserved = GetLittleShort();
IconDir.Type = GetLittleShort();
IconDir.Count = GetLittleShort();
if (ieof())
goto file_read_error;
DirEntries = (ICODIRENTRY*)ialloc(sizeof(ICODIRENTRY) * IconDir.Count);
IconImages = (ICOIMAGE*)ialloc(sizeof(ICOIMAGE) * IconDir.Count);
if (DirEntries == NULL || IconImages == NULL) {
ifree(DirEntries);
ifree(IconImages);
return IL_FALSE;
}
// Make it easier for file_read_error.
for (i = 0; i < IconDir.Count; i++)
imemclear(&IconImages[i], sizeof(ICOIMAGE));
for (i = 0; i < IconDir.Count; ++i) {
DirEntries[i].Width = igetc();
DirEntries[i].Height = igetc();
DirEntries[i].NumColours = igetc();
DirEntries[i].Reserved = igetc();
DirEntries[i].Planes = GetLittleShort();
DirEntries[i].Bpp = GetLittleShort();
DirEntries[i].SizeOfData = GetLittleUInt();
DirEntries[i].Offset = GetLittleUInt();
if(ieof())
goto file_read_error;
}
for (i = 0; i < IconDir.Count; i++) {
iseek(DirEntries[i].Offset, IL_SEEK_SET);
IconImages[i].Head.Size = GetLittleInt();
IconImages[i].Head.Width = GetLittleInt();
IconImages[i].Head.Height = GetLittleInt();
IconImages[i].Head.Planes = GetLittleShort();
IconImages[i].Head.BitCount = GetLittleShort();
IconImages[i].Head.Compression = GetLittleInt();
IconImages[i].Head.SizeImage = GetLittleInt();
IconImages[i].Head.XPixPerMeter = GetLittleInt();
IconImages[i].Head.YPixPerMeter = GetLittleInt();
IconImages[i].Head.ColourUsed = GetLittleInt();
IconImages[i].Head.ColourImportant = GetLittleInt();
if (ieof())
goto file_read_error;
if (IconImages[i].Head.BitCount < 8) {
if (IconImages[i].Head.ColourUsed == 0) {
switch (IconImages[i].Head.BitCount)
{
case 1:
IconImages[i].Head.ColourUsed = 2;
break;
case 4:
IconImages[i].Head.ColourUsed = 16;
break;
}
}
IconImages[i].Pal = (ILubyte*)ialloc(IconImages[i].Head.ColourUsed * 4);
if (IconImages[i].Pal == NULL)
goto file_read_error; // @TODO: Rename the label.
if (iread(IconImages[i].Pal, IconImages[i].Head.ColourUsed * 4, 1) != 1)
goto file_read_error;
}
else if (IconImages[i].Head.BitCount == 8) {
IconImages[i].Pal = (ILubyte*)ialloc(256 * 4);
if (IconImages[i].Pal == NULL)
goto file_read_error;
if (iread(IconImages[i].Pal, 1, 256 * 4) != 256*4)
goto file_read_error;
}
else {
IconImages[i].Pal = NULL;
}
PadSize = (4 - ((IconImages[i].Head.Width*IconImages[i].Head.BitCount + 7) / 8) % 4) % 4; // Has to be DWORD-aligned.
ANDPadSize = (4 - ((IconImages[i].Head.Width + 7) / 8) % 4) % 4; // AND is 1 bit/pixel
Size = ((IconImages[i].Head.Width*IconImages[i].Head.BitCount + 7) / 8 + PadSize)
* (IconImages[i].Head.Height / 2);
IconImages[i].Data = (ILubyte*)ialloc(Size);
if (IconImages[i].Data == NULL)
goto file_read_error;
if (iread(IconImages[i].Data, 1, Size) != Size)
goto file_read_error;
Size = (((IconImages[i].Head.Width + 7) /8) + ANDPadSize) * (IconImages[i].Head.Height / 2);
IconImages[i].AND = (ILubyte*)ialloc(Size);
if (IconImages[i].AND == NULL)
goto file_read_error;
if (iread(IconImages[i].AND, 1, Size) != Size)
goto file_read_error;
}
for (i = 0; i < IconDir.Count; i++) {
if (IconImages[i].Head.BitCount != 1 && IconImages[i].Head.BitCount != 4 &&
IconImages[i].Head.BitCount != 8 && IconImages[i].Head.BitCount != 24 &&
IconImages[i].Head.BitCount != 32)
continue;
if (!BaseCreated) {
ilTexImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL);
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
Image = iCurImage;
BaseCreated = IL_TRUE;
}
else {
Image->Next = ilNewImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, 1);
Image = Image->Next;
Image->Format = IL_BGRA;
}
Image->Type = IL_UNSIGNED_BYTE;
j = 0; k = 0; l = 128; CurAndByte = 0; x = 0;
w = IconImages[i].Head.Width;
PadSize = (4 - ((w*IconImages[i].Head.BitCount + 7) / 8) % 4) % 4; // Has to be DWORD-aligned.
ANDPadSize = (4 - ((w + 7) / 8) % 4) % 4; // AND is 1 bit/pixel
AndBytes = (w + 7) / 8;
if (IconImages[i].Head.BitCount == 1) {
for (; j < Image->SizeOfData; k++) {
for (m = 128; m && x < w; m >>= 1) {
Image->Data[j] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4];
Image->Data[j+1] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4 + 1];
Image->Data[j+2] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4 + 2];
Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
j += 4;
l >>= 1;
++x;
}
if (l == 0 || x == w) {
l = 128;
CurAndByte++;
if (x == w) {
CurAndByte += ANDPadSize;
k += PadSize;
x = 0;
}
}
}
}
else if (IconImages[i].Head.BitCount == 4) {
for (; j < Image->SizeOfData; j += 8, k++) {
Image->Data[j] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4];
Image->Data[j+1] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4 + 1];
Image->Data[j+2] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4 + 2];
Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
l >>= 1;
++x;
if(x < w) {
Image->Data[j+4] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4];
Image->Data[j+5] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4 + 1];
Image->Data[j+6] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4 + 2];
Image->Data[j+7] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
l >>= 1;
++x;
}
else
j -= 4;
if (l == 0 || x == w) {
l = 128;
CurAndByte++;
if (x == w) {
CurAndByte += ANDPadSize;
k += PadSize;
x = 0;
}
}
}
}
else if (IconImages[i].Head.BitCount == 8) {
for (; j < Image->SizeOfData; j += 4, k++) {
Image->Data[j] = IconImages[i].Pal[IconImages[i].Data[k] * 4];
Image->Data[j+1] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 1];
Image->Data[j+2] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 2];
Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
l >>= 1;
++x;
if (l == 0 || x == w) {
l = 128;
CurAndByte++;
if (x == w) {
CurAndByte += ANDPadSize;
k += PadSize;
x = 0;
}
}
}
}
else if (IconImages[i].Head.BitCount == 24) {
for (; j < Image->SizeOfData; j += 4, k += 3) {
Image->Data[j] = IconImages[i].Data[k];
Image->Data[j+1] = IconImages[i].Data[k+1];
Image->Data[j+2] = IconImages[i].Data[k+2];
Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
l >>= 1;
++x;
if (l == 0 || x == w) {
l = 128;
CurAndByte++;
if (x == w) {
CurAndByte += ANDPadSize;
k += PadSize;
x = 0;
}
}
}
}
else if (IconImages[i].Head.BitCount == 32) {
for (; j < Image->SizeOfData; j += 4, k += 4) {
Image->Data[j] = IconImages[i].Data[k];
Image->Data[j+1] = IconImages[i].Data[k+1];
Image->Data[j+2] = IconImages[i].Data[k+2];
//If the icon has 4 channels, use 4th channel for alpha...
//(for winxp style icons with true alpha channel
Image->Data[j+3] = IconImages[i].Data[k+3];
}
}
}
for (i = 0; i < IconDir.Count; i++) {
ifree(IconImages[i].Pal);
ifree(IconImages[i].Data);
ifree(IconImages[i].AND);
}
ifree(IconImages);
ifree(DirEntries);
ilFixImage();
return IL_TRUE;
file_read_error:
if (IconImages) {
for (i = 0; i < IconDir.Count; i++) {
if (IconImages[i].Pal)
ifree(IconImages[i].Pal);
if (IconImages[i].Data)
ifree(IconImages[i].Data);
if (IconImages[i].AND)
ifree(IconImages[i].AND);
}
ifree(IconImages);
}
if (DirEntries)
ifree(DirEntries);
return IL_FALSE;
}
#endif

View File

@@ -0,0 +1,348 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_internal.c
//
// Description: Internal stuff for DevIL
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#include <string.h>
#include <stdlib.h>
ILimage *iCurImage = NULL;
/* Siigron: added this for Linux... a #define should work, but for some reason
it doesn't (anyone who knows why?) */
#if !_WIN32 || (_WIN32 && __GNUC__) // Cygwin
int stricmp(const char *src1, const char *src2)
{
return strcasecmp(src1, src2);
}
int strnicmp(const char *src1, const char *src2, size_t max)
{
return strncasecmp(src1, src2, max);
}
#elif _WIN32_WCE
int stricmp(const char *src1, const char *src2)
{
return _stricmp(src1, src2);
}
int strnicmp(const char *src1, const char *src2, size_t max)
{
return _strnicmp(src1, src2, max);
}
#endif /* _WIN32 */
#if _UNICODE //_WIN32_WCE
int iStrCmp(ILconst_string src1, ILconst_string src2)
{
return wcsicmp(src1, src2);
}
#else
int iStrCmp(ILconst_string src1, ILconst_string src2)
{
return stricmp(src1, src2);
}
#endif
//! Glut's portability.txt says to use this...
char *ilStrDup(const char *Str)
{
char *copy;
copy = (char*)ialloc(strlen(Str) + 1);
if (copy == NULL)
return NULL;
strcpy(copy, Str);
return copy;
}
// Because MSVC++'s version is too stupid to check for NULL...
ILuint ilStrLen(const char *Str)
{
const char *eos = Str;
if (Str == NULL)
return 0;
while (*eos++);
return((int)(eos - Str - 1));
}
// Simple function to test if a filename has a given extension, disregarding case
ILboolean iCheckExtension(ILconst_string Arg, ILconst_string Ext)
{
ILboolean PeriodFound = IL_FALSE;
ILint i;
#ifndef _UNICODE
char *Argu = (char*)Arg; // pointer to arg so we don't destroy arg
if (Arg == NULL || Ext == NULL || !strlen(Arg) || !strlen(Ext)) // if not a good filename/extension, exit early
return IL_FALSE;
Argu += strlen(Arg); // start at the end
for (i = strlen(Arg); i >= 0; i--) {
if (*Argu == '.') { // try to find a period
PeriodFound = IL_TRUE;
break;
}
Argu--;
}
if (!PeriodFound) // if no period, no extension
return IL_FALSE;
if (!stricmp(Argu+1, Ext)) // extension and ext match?
return IL_TRUE;
#else
wchar_t *Argu = (wchar_t*)Arg;
if (Arg == NULL || Ext == NULL || !wcslen(Arg) || !wcslen(Ext)) // if not a good filename/extension, exit early
return IL_FALSE;
Argu += wcslen(Arg); // start at the end
for (i = wcslen(Arg); i >= 0; i--) {
if (*Argu == '.') { // try to find a period
PeriodFound = IL_TRUE;
break;
}
Argu--;
}
if (!PeriodFound) // if no period, no extension
return IL_FALSE;
if (!wcsicmp(Argu+1, Ext)) // extension and ext match?
return IL_TRUE;
#endif//_WIN32_WCE
return IL_FALSE; // if all else fails, return IL_FALSE
}
ILstring iGetExtension(ILconst_string FileName) {
ILboolean PeriodFound = IL_FALSE;
#ifndef _UNICODE
char *Ext = (char*)FileName;
ILint i, Len = strlen(FileName);
#else
wchar_t *Ext = (wchar_t*)FileName;
ILint i, Len = wcslen(FileName);
#endif//_UNICODE
if (FileName == NULL || !Len) // if not a good filename/extension, exit early
return NULL;
Ext += Len; // start at the end
for (i = Len; i >= 0; i--) {
if (*Ext == '.') { // try to find a period
PeriodFound = IL_TRUE;
break;
}
Ext--;
}
if (!PeriodFound) // if no period, no extension
return NULL;
return Ext+1;
}
// Checks if the file exists
ILboolean iFileExists(ILconst_string FileName)
{
#ifndef _UNICODE
FILE *CheckFile = fopen(FileName, "rb");
#else
FILE *CheckFile = _wfopen(FileName, L"rb");
#endif//_UNICODE
if (CheckFile) {
fclose(CheckFile);
return IL_TRUE;
}
return IL_FALSE;
}
// Last time I tried, MSVC++'s fgets() was really really screwy
ILbyte *iFgets(char *buffer, ILuint maxlen)
{
ILuint counter = 0;
ILint temp = '\0';
while ((temp = igetc()) && temp != '\n' && temp != IL_EOF && counter < maxlen) {
buffer[counter] = temp;
counter++;
}
buffer[counter] = '\0';
if (temp == IL_EOF && counter == 0) // Only return NULL if no data was "got".
return NULL;
return (ILbyte*)buffer;
}
// A fast integer squareroot, completely accurate for x < 289.
// Taken from http://atoms.org.uk/sqrt/
// There is also a version that is accurate for all integers
// < 2^31, if we should need it
static int table[] = {
0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57,
59, 61, 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83,
84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 102,
103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118,
119, 120, 121, 122, 123, 124, 125, 126, 128, 128, 129, 130, 131, 132,
133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145,
146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, 156, 157,
158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168,
169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178,
179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188,
189, 189, 190, 191, 192, 192, 193, 193, 194, 195, 195, 196, 197, 197,
198, 199, 199, 200, 201, 201, 202, 203, 203, 204, 204, 205, 206, 206,
207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 214, 214, 215,
215, 216, 217, 217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223,
224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, 230, 231,
231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246,
246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253,
253, 254, 254, 255
};
int iSqrt(int x) {
if (x >= 0x10000) {
if (x >= 0x1000000) {
if (x >= 0x10000000) {
if (x >= 0x40000000) {
return (table[x >> 24] << 8);
} else {
return (table[x >> 22] << 7);
}
} else if (x >= 0x4000000) {
return (table[x >> 20] << 6);
} else {
return (table[x >> 18] << 5);
}
} else if (x >= 0x100000) {
if (x >= 0x400000) {
return (table[x >> 16] << 4);
} else {
return (table[x >> 14] << 3);
}
} else if (x >= 0x40000) {
return (table[x >> 12] << 2);
} else {
return (table[x >> 10] << 1);
}
} else if (x >= 0x100) {
if (x >= 0x1000) {
if (x >= 0x4000) {
return (table[x >> 8]);
} else {
return (table[x >> 6] >> 1);
}
} else if (x >= 0x400) {
return (table[x >> 4] >> 2);
} else {
return (table[x >> 2] >> 3);
}
} else if (x >= 0) {
return table[x] >> 4;
}
//hm, x was negative....
return -1;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,200 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_lif.c
//
// Description: Reads a Homeworld image.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_LIF
#include "il_lif.h"
//! Checks if the file specified in FileName is a valid Lif file.
ILboolean ilIsValidLif(ILconst_string FileName)
{
ILHANDLE LifFile;
ILboolean bLif = IL_FALSE;
if (!iCheckExtension(FileName, IL_TEXT("lif"))) {
ilSetError(IL_INVALID_EXTENSION);
return bLif;
}
LifFile = iopenr(FileName);
if (LifFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bLif;
}
bLif = ilIsValidLifF(LifFile);
icloser(LifFile);
return bLif;
}
//! Checks if the ILHANDLE contains a valid Lif file at the current position.
ILboolean ilIsValidLifF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iIsValidLif();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Checks if Lump is a valid Lif lump.
ILboolean ilIsValidLifL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iIsValidLif();
}
// Internal function used to get the Lif header from the current file.
ILboolean iGetLifHead(LIF_HEAD *Header)
{
iread(Header->Id, 1, 8);
Header->Version = GetLittleUInt();
Header->Flags = GetLittleUInt();
Header->Width = GetLittleUInt();
Header->Height = GetLittleUInt();
Header->PaletteCRC = GetLittleUInt();
Header->ImageCRC = GetLittleUInt();
Header->PalOffset = GetLittleUInt();
Header->TeamEffect0 = GetLittleUInt();
Header->TeamEffect1 = GetLittleUInt();
return IL_TRUE;
}
// Internal function to get the header and check it.
ILboolean iIsValidLif()
{
LIF_HEAD Head;
if (!iGetLifHead(&Head))
return IL_FALSE;
iseek(-(ILint)sizeof(LIF_HEAD), IL_SEEK_CUR);
return iCheckLif(&Head);
}
// Internal function used to check if the HEADER is a valid Lif header.
ILboolean iCheckLif(LIF_HEAD *Header)
{
if (Header->Version != 260 || Header->Flags != 50)
return IL_FALSE;
if (stricmp(Header->Id, "Willy 7"))
return IL_FALSE;
return IL_TRUE;
}
//! Reads a .Lif file
ILboolean ilLoadLif(ILconst_string FileName)
{
ILHANDLE LifFile;
ILboolean bLif = IL_FALSE;
LifFile = iopenr(FileName);
if (LifFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bLif;
}
bLif = ilLoadLifF(LifFile);
icloser(LifFile);
return bLif;
}
//! Reads an already-opened .Lif file
ILboolean ilLoadLifF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadLifInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a .Lif
ILboolean ilLoadLifL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadLifInternal();
}
ILboolean iLoadLifInternal()
{
LIF_HEAD LifHead;
ILuint i;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!iGetLifHead(&LifHead))
return IL_FALSE;
if (!ilTexImage(LifHead.Width, LifHead.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
iCurImage->Pal.Palette = (ILubyte*)ialloc(1024);
if (iCurImage->Pal.Palette == NULL)
return IL_FALSE;
iCurImage->Pal.PalSize = 1024;
iCurImage->Pal.PalType = IL_PAL_RGBA32;
if (iread(iCurImage->Data, LifHead.Width * LifHead.Height, 1) != 1)
return IL_FALSE;
if (iread(iCurImage->Pal.Palette, 1, 1024) != 1024)
return IL_FALSE;
// Each data offset is offset by -1, so we add one.
for (i = 0; i < iCurImage->SizeOfData; i++) {
iCurImage->Data[i]++;
}
ilFixImage();
return IL_TRUE;
}
#endif//IL_NO_LIF

View File

@@ -0,0 +1,30 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 02/16/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_main.c
//
// Description: Startup function
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
/* Only needed for MSVC++ unless extended to actually do something =) */
#if defined(_WIN32) && defined(_MSC_VER)
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
hModule; ul_reason_for_call; lpReserved;
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
//ilInit();
}
return TRUE;
}
#endif

View File

@@ -0,0 +1,882 @@
//-----------------------------------------------------------------------------
// Description: Image manipulation
#include "il_internal.h"
#include <il/il.h>
#include "il_manip.h"
ILAPI ILvoid ILAPIENTRY iFlipBuffer( ILubyte *buff, ILuint depth, ILuint line_size, ILuint line_num ) {
ILubyte *StartPtr, *EndPtr;
ILuint y, d;
const ILuint size = line_num * line_size;
for( d = 0; d < depth; d++ ) {
StartPtr = buff + d * size;
EndPtr = buff + d * size + size;
for( y = 0; y < (line_num/2); y++ ) {
EndPtr -= line_size;
iMemSwap(StartPtr,EndPtr,line_size);
StartPtr += line_size;
}
}
}
// Just created for internal use.
ILubyte* iFlipNewBuffer( ILubyte *buff, ILuint depth, ILuint line_size, ILuint line_num ) {
ILubyte *data;
ILubyte *s1, *s2;
ILuint y, d;
const ILuint size = line_num * line_size;
if( (data = (ILubyte*)ialloc(depth*size)) == NULL)
return IL_FALSE;
for( d = 0; d < depth; d++ ) {
s1 = buff + d * size;
s2 = data + d * size+size;
for( y = 0; y < line_num; y++ ) {
s2 -= line_size;
memcpy(s2,s1,line_size);
s1 += line_size;
}
}
return data;
}
// Flips an image over its x axis
ILboolean ilFlipImage() {
if( iCurImage == NULL ) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
iCurImage->Origin = (iCurImage->Origin == IL_ORIGIN_LOWER_LEFT) ?
IL_ORIGIN_UPPER_LEFT : IL_ORIGIN_LOWER_LEFT;
iFlipBuffer(iCurImage->Data,iCurImage->Depth,iCurImage->Bps,iCurImage->Height);
return IL_TRUE;
}
// Just created for internal use.
ILubyte* ILAPIENTRY iGetFlipped(ILimage *img) {
if( img == NULL ) {
ilSetError(IL_ILLEGAL_OPERATION);
return NULL;
}
return iFlipNewBuffer(img->Data,img->Depth,img->Bps,img->Height);
}
//@JASON New routine created 28/03/2001
//! Mirrors an image over its y axis
ILboolean ILAPIENTRY iMirror() {
ILubyte *Data, *DataPtr, *Temp;
ILuint y, d, PixLine;
ILint x, c;
ILushort *ShortPtr, *TempShort;
ILuint *IntPtr, *TempInt;
ILdouble *DblPtr, *TempDbl;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
Data = (ILubyte*)ialloc(iCurImage->SizeOfData);
if (Data == NULL)
return IL_FALSE;
PixLine = iCurImage->Bps / iCurImage->Bpc;
switch (iCurImage->Bpc)
{
case 1:
Temp = iCurImage->Data;
for (d = 0; d < iCurImage->Depth; d++) {
DataPtr = Data + d * iCurImage->SizeOfPlane;
for (y = 0; y < iCurImage->Height; y++) {
for (x = iCurImage->Width - 1; x >= 0; x--) {
for (c = 0; c < iCurImage->Bpp; c++, Temp++) {
DataPtr[y * PixLine + x * iCurImage->Bpp + c] = *Temp;
}
}
}
}
break;
case 2:
TempShort = (ILushort*)iCurImage->Data;
for (d = 0; d < iCurImage->Depth; d++) {
ShortPtr = (ILushort*)(Data + d * iCurImage->SizeOfPlane);
for (y = 0; y < iCurImage->Height; y++) {
for (x = iCurImage->Width - 1; x >= 0; x--) {
for (c = 0; c < iCurImage->Bpp; c++, TempShort++) {
ShortPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempShort;
}
}
}
}
break;
case 4:
TempInt = (ILuint*)iCurImage->Data;
for (d = 0; d < iCurImage->Depth; d++) {
IntPtr = (ILuint*)(Data + d * iCurImage->SizeOfPlane);
for (y = 0; y < iCurImage->Height; y++) {
for (x = iCurImage->Width - 1; x >= 0; x--) {
for (c = 0; c < iCurImage->Bpp; c++, TempInt++) {
IntPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempInt;
}
}
}
}
break;
case 8:
TempDbl = (ILdouble*)iCurImage->Data;
for (d = 0; d < iCurImage->Depth; d++) {
DblPtr = (ILdouble*)(Data + d * iCurImage->SizeOfPlane);
for (y = 0; y < iCurImage->Height; y++) {
for (x = iCurImage->Width - 1; x >= 0; x--) {
for (c = 0; c < iCurImage->Bpp; c++, TempDbl++) {
DblPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempDbl;
}
}
}
}
break;
}
ifree(iCurImage->Data);
iCurImage->Data = Data;
return IL_TRUE;
}
// Should we add type to the parameter list?
// Copies a 1d block of pixels to the buffer pointed to by Data.
ILboolean ilCopyPixels1D(ILuint XOff, ILuint Width, ILvoid *Data)
{
ILuint x, c, NewBps, NewOff, PixBpp;
ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
if (ilIsEnabled(IL_ORIGIN_SET)) {
if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
TempData = iGetFlipped(iCurImage);
if (TempData == NULL)
return IL_FALSE;
}
}
PixBpp = iCurImage->Bpp * iCurImage->Bpc;
if (iCurImage->Width < XOff + Width) {
NewBps = (iCurImage->Width - XOff) * PixBpp;
}
else {
NewBps = Width * PixBpp;
}
NewOff = XOff * PixBpp;
for (x = 0; x < NewBps; x += PixBpp) {
for (c = 0; c < PixBpp; c++) {
Temp[x + c] = TempData[(x + NewOff) + c];
}
}
if (TempData != iCurImage->Data)
ifree(TempData);
return IL_TRUE;
}
// Copies a 2d block of pixels to the buffer pointed to by Data.
ILboolean ilCopyPixels2D(ILuint XOff, ILuint YOff, ILuint Width, ILuint Height, ILvoid *Data)
{
ILuint x, y, c, NewBps, DataBps, NewXOff, NewHeight, PixBpp;
ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
if (ilIsEnabled(IL_ORIGIN_SET)) {
if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
TempData = iGetFlipped(iCurImage);
if (TempData == NULL)
return IL_FALSE;
}
}
PixBpp = iCurImage->Bpp * iCurImage->Bpc;
if (iCurImage->Width < XOff + Width)
NewBps = (iCurImage->Width - XOff) * PixBpp;
else
NewBps = Width * PixBpp;
if (iCurImage->Height < YOff + Height)
NewHeight = iCurImage->Height - YOff;
else
NewHeight = Height;
DataBps = Width * PixBpp;
NewXOff = XOff * PixBpp;
for (y = 0; y < NewHeight; y++) {
for (x = 0; x < NewBps; x += PixBpp) {
for (c = 0; c < PixBpp; c++) {
Temp[y * DataBps + x + c] =
TempData[(y + YOff) * iCurImage->Bps + x + NewXOff + c];
}
}
}
if (TempData != iCurImage->Data)
ifree(TempData);
return IL_TRUE;
}
// Copies a 3d block of pixels to the buffer pointed to by Data.
ILboolean ilCopyPixels3D(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILvoid *Data)
{
ILuint x, y, z, c, NewBps, DataBps, NewSizePlane, NewH, NewD, NewXOff, PixBpp;
ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
if (ilIsEnabled(IL_ORIGIN_SET)) {
if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
TempData = iGetFlipped(iCurImage);
if (TempData == NULL)
return IL_FALSE;
}
}
PixBpp = iCurImage->Bpp * iCurImage->Bpc;
if (iCurImage->Width < XOff + Width)
NewBps = (iCurImage->Width - XOff) * PixBpp;
else
NewBps = Width * PixBpp;
if (iCurImage->Height < YOff + Height)
NewH = iCurImage->Height - YOff;
else
NewH = Height;
if (iCurImage->Depth < ZOff + Depth)
NewD = iCurImage->Depth - ZOff;
else
NewD = Depth;
DataBps = Width * PixBpp;
NewSizePlane = NewBps * NewH;
NewXOff = XOff * PixBpp;
for (z = 0; z < NewD; z++) {
for (y = 0; y < NewH; y++) {
for (x = 0; x < NewBps; x += PixBpp) {
for (c = 0; c < PixBpp; c++) {
Temp[z * NewSizePlane + y * DataBps + x + c] =
TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + x + NewXOff + c];
//TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + (x + XOff) * iCurImage->Bpp + c];
}
}
}
}
if (TempData != iCurImage->Data)
ifree(TempData);
return IL_TRUE;
}
ILuint ILAPIENTRY ilCopyPixels(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, ILvoid *Data)
{
ILvoid *Converted = NULL;
ILubyte *TempBuff = NULL;
ILuint SrcSize, DestSize;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return 0;
}
DestSize = Width * Height * Depth * ilGetBppFormat(Format) * ilGetBpcType(Type);
if (DestSize == 0) {
return DestSize;
}
if (Data == NULL) {
ilSetError(IL_INVALID_PARAM);
return 0;
}
SrcSize = Width * Height * Depth * iCurImage->Bpp * iCurImage->Bpc;
if (Format == iCurImage->Format && Type == iCurImage->Type) {
TempBuff = (ILubyte*)Data;
}
else {
TempBuff = (ILubyte*)ialloc(SrcSize);
if (TempBuff == NULL) {
return 0;
}
}
if (YOff + Height <= 1) {
if (!ilCopyPixels1D(XOff, Width, TempBuff)) {
goto failed;
}
}
else if (ZOff + Depth <= 1) {
if (!ilCopyPixels2D(XOff, YOff, Width, Height, TempBuff)) {
goto failed;
}
}
else {
if (!ilCopyPixels3D(XOff, YOff, ZOff, Width, Height, Depth, TempBuff)) {
goto failed;
}
}
if (Format == iCurImage->Format && Type == iCurImage->Type) {
return IL_TRUE;
}
Converted = ilConvertBuffer(SrcSize, iCurImage->Format, Format, iCurImage->Type, Type, TempBuff);
if (Converted == NULL)
goto failed;
memcpy(Data, Converted, DestSize);
ifree(Converted);
if (TempBuff != Data)
ifree(TempBuff);
return DestSize;
failed:
if (TempBuff != Data)
ifree(TempBuff);
ifree(Converted);
return 0;
}
ILboolean ilSetPixels1D(ILint XOff, ILuint Width, ILvoid *Data)
{
ILuint c, SkipX = 0, PixBpp;
ILint x, NewWidth;
ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
if (ilIsEnabled(IL_ORIGIN_SET)) {
if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
TempData = iGetFlipped(iCurImage);
if (TempData == NULL)
return IL_FALSE;
}
}
PixBpp = iCurImage->Bpp * iCurImage->Bpc;
if (XOff < 0) {
SkipX = abs(XOff);
XOff = 0;
}
if (iCurImage->Width < XOff + Width) {
NewWidth = iCurImage->Width - XOff;
}
else {
NewWidth = Width;
}
NewWidth -= SkipX;
for (x = 0; x < NewWidth; x++) {
for (c = 0; c < PixBpp; c++) {
TempData[(x + XOff) * PixBpp + c] = Temp[(x + SkipX) * PixBpp + c];
}
}
if (TempData != iCurImage->Data) {
ifree(iCurImage->Data);
iCurImage->Data = TempData;
}
return IL_TRUE;
}
ILboolean ilSetPixels2D(ILint XOff, ILint YOff, ILuint Width, ILuint Height, ILvoid *Data)
{
ILuint c, SkipX = 0, SkipY = 0, NewBps, PixBpp;
ILint x, y, NewWidth, NewHeight;
ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
if (ilIsEnabled(IL_ORIGIN_SET)) {
if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
TempData = iGetFlipped(iCurImage);
if (TempData == NULL)
return IL_FALSE;
}
}
PixBpp = iCurImage->Bpp * iCurImage->Bpc;
if (XOff < 0) {
SkipX = abs(XOff);
XOff = 0;
}
if (YOff < 0) {
SkipY = abs(YOff);
YOff = 0;
}
if (iCurImage->Width < XOff + Width)
NewWidth = iCurImage->Width - XOff;
else
NewWidth = Width;
NewBps = Width * PixBpp;
if (iCurImage->Height < YOff + Height)
NewHeight = iCurImage->Height - YOff;
else
NewHeight = Height;
NewWidth -= SkipX;
NewHeight -= SkipY;
for (y = 0; y < NewHeight; y++) {
for (x = 0; x < NewWidth; x++) {
for (c = 0; c < PixBpp; c++) {
TempData[(y + YOff) * iCurImage->Bps + (x + XOff) * PixBpp + c] =
Temp[(y + SkipY) * NewBps + (x + SkipX) * PixBpp + c];
}
}
}
if (TempData != iCurImage->Data) {
ifree(iCurImage->Data);
iCurImage->Data = TempData;
}
return IL_TRUE;
}
ILboolean ilSetPixels3D(ILint XOff, ILint YOff, ILint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILvoid *Data)
{
ILuint SkipX = 0, SkipY = 0, SkipZ = 0, c, NewBps, NewSizePlane, PixBpp;
ILint x, y, z, NewW, NewH, NewD;
ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
if (ilIsEnabled(IL_ORIGIN_SET)) {
if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
TempData = iGetFlipped(iCurImage);
if (TempData == NULL)
return IL_FALSE;
}
}
PixBpp = iCurImage->Bpp * iCurImage->Bpc;
if (XOff < 0) {
SkipX = abs(XOff);
XOff = 0;
}
if (YOff < 0) {
SkipY = abs(YOff);
YOff = 0;
}
if (ZOff < 0) {
SkipZ = abs(ZOff);
ZOff = 0;
}
if (iCurImage->Width < XOff + Width)
NewW = iCurImage->Width - XOff;
else
NewW = Width;
NewBps = Width * PixBpp;
if (iCurImage->Height < YOff + Height)
NewH = iCurImage->Height - YOff;
else
NewH = Height;
if (iCurImage->Depth < ZOff + Depth)
NewD = iCurImage->Depth - ZOff;
else
NewD = Depth;
NewSizePlane = NewBps * Height;
NewW -= SkipX;
NewH -= SkipY;
NewD -= SkipZ;
for (z = 0; z < NewD; z++) {
for (y = 0; y < NewH; y++) {
for (x = 0; x < NewW; x++) {
for (c = 0; c < PixBpp; c++) {
TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + (x + XOff) * PixBpp + c] =
Temp[(z + SkipZ) * NewSizePlane + (y + SkipY) * NewBps + (x + SkipX) * PixBpp + c];
}
}
}
}
if (TempData != iCurImage->Data) {
ifree(iCurImage->Data);
iCurImage->Data = TempData;
}
return IL_TRUE;
}
ILvoid ILAPIENTRY ilSetPixels(ILint XOff, ILint YOff, ILint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, ILvoid *Data)
{
ILvoid *Converted;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return;
}
if (Data == NULL) {
ilSetError(IL_INVALID_PARAM);
return;
}
if (Format == iCurImage->Format && Type == iCurImage->Type) {
Converted = (ILvoid*)Data;
}
else {
Converted = ilConvertBuffer(Width * Height * Depth * ilGetBppFormat(Format) * ilGetBpcType(Type), Format, iCurImage->Format, iCurImage->Type, Type, Data);
if (!Converted)
return;
}
if (YOff + Height <= 1) {
ilSetPixels1D(XOff, Width, Converted);
}
else if (ZOff + Depth <= 1) {
ilSetPixels2D(XOff, YOff, Width, Height, Converted);
}
else {
ilSetPixels3D(XOff, YOff, ZOff, Width, Height, Depth, Converted);
}
if (Format == iCurImage->Format && Type == iCurImage->Type) {
return;
}
if (Converted != Data)
ifree(Converted);
return;
}
// Ripped from Platinum (DooMWiz's sources)
// This could very well easily be changed to a 128x128 image instead...needed?
//! Creates an ugly 64x64 black and yellow checkerboard image.
ILboolean ILAPIENTRY ilDefaultImage()
{
ILubyte *TempData;
ILubyte Yellow[3] = { 18, 246, 243 };
ILubyte Black[3] = { 0, 0, 0 };
ILubyte *ColorPtr = Yellow; // The start color
ILboolean Color = IL_TRUE;
// Loop Variables
ILint v, w, x, y;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!ilTexImage(64, 64, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
TempData = iCurImage->Data;
for (v = 0; v < 8; v++) {
// We do this because after a "block" line ends, the next row of blocks
// above starts with the ending colour, but the very inner loop switches them.
if (Color) {
Color = IL_FALSE;
ColorPtr = Black;
}
else {
Color = IL_TRUE;
ColorPtr = Yellow;
}
for (w = 0; w < 8; w++) {
for (x = 0; x < 8; x++) {
for (y = 0; y < 8; y++, TempData += iCurImage->Bpp) {
TempData[0] = ColorPtr[0];
TempData[1] = ColorPtr[1];
TempData[2] = ColorPtr[2];
}
// Switch to alternate between black and yellow
if (Color) {
Color = IL_FALSE;
ColorPtr = Black;
}
else {
Color = IL_TRUE;
ColorPtr = Yellow;
}
}
}
}
return IL_TRUE;
}
ILubyte* ILAPIENTRY ilGetAlpha(ILenum Type)
{
ILimage *TempImage;
ILubyte *Alpha;
ILushort *AlphaShort;
ILuint *AlphaInt;
ILdouble *AlphaDbl;
ILuint i, j, Bpc, Size, AlphaOff;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
Bpc = ilGetBpcType(Type);
if (Bpc == 0) {
ilSetError(IL_INVALID_PARAM);
return NULL;
}
if (iCurImage->Type == Type) {
TempImage = iCurImage;
} else {
TempImage = iConvertImage(iCurImage, iCurImage->Format, Type);
if (TempImage == NULL)
return NULL;
}
Size = iCurImage->Width * iCurImage->Height * iCurImage->Depth * TempImage->Bpp;
Alpha = (ILubyte*)ialloc(Size / TempImage->Bpp * Bpc);
if (Alpha == NULL) {
if (TempImage != iCurImage)
ilCloseImage(TempImage);
return NULL;
}
switch (TempImage->Format)
{
case IL_RGB:
case IL_BGR:
case IL_LUMINANCE:
case IL_COLOUR_INDEX: // @TODO: Make IL_COLOUR_INDEX separate.
memset(Alpha, 0xFF, Size / TempImage->Bpp * Bpc);
if (TempImage != iCurImage)
ilCloseImage(TempImage);
return Alpha;
}
if (TempImage->Format == IL_LUMINANCE_ALPHA)
AlphaOff = 2;
else
AlphaOff = 4;
switch (TempImage->Type)
{
case IL_BYTE:
case IL_UNSIGNED_BYTE:
for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
Alpha[j] = TempImage->Data[i];
break;
case IL_SHORT:
case IL_UNSIGNED_SHORT:
AlphaShort = (ILushort*)Alpha;
for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
AlphaShort[j] = ((ILushort*)TempImage->Data)[i];
break;
case IL_INT:
case IL_UNSIGNED_INT:
case IL_FLOAT: // Can throw float in here, because it's the same size.
AlphaInt = (ILuint*)Alpha;
for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
AlphaInt[j] = ((ILuint*)TempImage->Data)[i];
break;
case IL_DOUBLE:
AlphaDbl = (ILdouble*)Alpha;
for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
AlphaDbl[j] = ((ILdouble*)TempImage->Data)[i];
break;
}
if (TempImage != iCurImage)
ilCloseImage(TempImage);
return Alpha;
}
// sets the Alpha value to a specific value for each pixel in the image
ILboolean ILAPIENTRY ilSetAlpha( ILdouble AlphaValue ) {
ILboolean ret = IL_TRUE;
ILuint i,Size;
ILimage *image = iCurImage;
ILuint AlphaOff;
if( image == NULL )
{
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
AlphaValue = clamp(AlphaValue);
switch( image->Format ) {
case IL_RGB:
ret = ilConvertImage(IL_RGBA,image->Type);
case IL_RGBA:
AlphaOff = 4;
break;
case IL_BGR:
ret = ilConvertImage(IL_BGRA,image->Type);
case IL_BGRA:
AlphaOff = 4;
break;
case IL_LUMINANCE:
ret = ilConvertImage(IL_LUMINANCE_ALPHA,image->Type);
case IL_LUMINANCE_ALPHA:
AlphaOff = 2;
break;
case IL_COLOUR_INDEX: //@TODO use palette with alpha
ret = ilConvertImage(IL_RGBA,image->Type);
AlphaOff = 4;
break;
}
if( ret == IL_FALSE ) {
return IL_FALSE;
// error has been set by ilConvertImage
}
Size = image->Width * image->Height * image->Depth * image->Bpp;
switch( iCurImage->Type ) {
case IL_BYTE:
case IL_UNSIGNED_BYTE: {
const ILbyte alpha = (ILubyte)(AlphaValue * IL_MAX_UNSIGNED_BYTE + .5);
for( i = AlphaOff-1; i < Size; i += AlphaOff)
image->Data[i] = alpha;
break; }
case IL_SHORT:
case IL_UNSIGNED_SHORT: {
const ILushort alpha = (ILushort)(AlphaValue * IL_MAX_UNSIGNED_SHORT + .5);
for( i = AlphaOff-1; i < Size; i += AlphaOff)
((ILushort*)image->Data)[i] = alpha;
break; }
case IL_INT:
case IL_UNSIGNED_INT: {
const ILushort alpha = (ILushort)(AlphaValue * IL_MAX_UNSIGNED_INT + .5);
for( i = AlphaOff-1; i < Size; i += AlphaOff)
((ILushort*)image->Data)[i] = alpha;
break; }
case IL_FLOAT: {
const ILfloat alpha = (ILfloat)AlphaValue;
for( i = AlphaOff-1; i < Size; i += AlphaOff )
((ILfloat*)image->Data)[i] = alpha;
break; }
case IL_DOUBLE: {
const ILdouble alpha = AlphaValue;
for( i = AlphaOff-1; i < Size; i += AlphaOff )
((ILdouble*)image->Data)[i] = alpha;
break; }
}
return IL_TRUE;
}
ILvoid ILAPIENTRY ilModAlpha( ILdouble AlphaValue ) {
ILuint AlphaOff = 0;
ILboolean ret = IL_FALSE;
ILuint i,j,Size;
union {
ILubyte alpha_byte;
ILushort alpha_short;
ILuint alpha_int;
ILfloat alpha_float;
ILdouble alpha_double;
} Alpha;
if( iCurImage == NULL ) {
ilSetError(IL_ILLEGAL_OPERATION);
return;
}
switch( iCurImage->Format ) {
case IL_RGB:
ret = ilConvertImage(IL_RGBA,iCurImage->Type);
AlphaOff = 4;
break;
case IL_BGR:
ret = ilConvertImage(IL_BGRA,iCurImage->Type);
AlphaOff = 4;
break;
case IL_LUMINANCE:
ret = ilConvertImage(IL_LUMINANCE_ALPHA,iCurImage->Type);
AlphaOff = 2;
break;
case IL_COLOUR_INDEX:
ret = ilConvertImage(IL_RGBA,iCurImage->Type);
AlphaOff = 4;
break;
}
Size = iCurImage->Width * iCurImage->Height * iCurImage->Depth * iCurImage->Bpp;
if( !ret ) return;
switch (iCurImage->Type) {
case IL_BYTE:
case IL_UNSIGNED_BYTE:
Alpha.alpha_byte = (ILubyte)(AlphaValue * 0x000000FF + .5);
for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
iCurImage->Data[i] = Alpha.alpha_byte;
break;
case IL_SHORT:
case IL_UNSIGNED_SHORT:
Alpha.alpha_short = (ILushort)(AlphaValue * 0x0000FFFF + .5);
for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
((ILushort*)iCurImage->Data)[i] = Alpha.alpha_short;
break;
case IL_INT:
case IL_UNSIGNED_INT:
Alpha.alpha_int = (ILuint)(AlphaValue * 0xFFFFFFFF + .5);
for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
((ILuint*)iCurImage->Data)[i] = Alpha.alpha_int;
break;
case IL_FLOAT:
Alpha.alpha_float = (ILfloat)AlphaValue;
for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
((ILfloat*)iCurImage->Data)[i] = Alpha.alpha_float;
break;
case IL_DOUBLE:
Alpha.alpha_double = AlphaValue;
for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
((ILdouble*)iCurImage->Data)[i] = Alpha.alpha_double;
break;
}
}

View File

@@ -0,0 +1,157 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_mdl.c
//
// Description: Reads a Half-Life model file (.mdl).
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_MDL
#include "il_mdl.h"
ILboolean iLoadMdlInternal(ILvoid);
//! Reads a .Mdl file
ILboolean ilLoadMdl(ILconst_string FileName)
{
ILHANDLE MdlFile;
ILboolean bMdl = IL_FALSE;
MdlFile = iopenr(FileName);
if (MdlFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bMdl;
}
bMdl = ilLoadMdlF(MdlFile);
icloser(MdlFile);
return bMdl;
}
//! Reads an already-opened .Mdl file
ILboolean ilLoadMdlF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadMdlInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a .Mdl
ILboolean ilLoadMdlL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadMdlInternal();
}
ILboolean iLoadMdlInternal()
{
ILuint Id, Version, NumTex, TexOff, TexDataOff, Position, ImageNum;
ILubyte *TempPal;
TEX_HEAD TexHead;
ILimage *BaseImage=NULL;
ILboolean BaseCreated = IL_FALSE;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
Id = GetLittleUInt();
Version = GetLittleUInt();
// 0x54534449 == "IDST"
if (Id != 0x54534449 || Version != 10) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
// Skips the actual model header.
iseek(172, IL_SEEK_CUR);
NumTex = GetLittleUInt();
TexOff = GetLittleUInt();
TexDataOff = GetLittleUInt();
if (NumTex == 0 || TexOff == 0 || TexDataOff == 0) {
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
iseek(TexOff, IL_SEEK_SET);
for (ImageNum = 0; ImageNum < NumTex; ImageNum++) {
if (iread(TexHead.Name, 1, 64) != 64)
return IL_FALSE;
TexHead.Flags = GetLittleUInt();
TexHead.Width = GetLittleUInt();
TexHead.Height = GetLittleUInt();
TexHead.Offset = GetLittleUInt();
Position = itell();
if (TexHead.Offset == 0) {
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
if (!BaseCreated) {
ilTexImage(TexHead.Width, TexHead.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL);
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
BaseCreated = IL_TRUE;
BaseImage = iCurImage;
//iCurImage->NumNext = NumTex - 1; // Don't count the first image.
}
else {
//iCurImage->Next = ilNewImage(TexHead.Width, TexHead.Height, 1, 1, 1);
iCurImage = iCurImage->Next;
iCurImage->Format = IL_COLOUR_INDEX;
iCurImage->Type = IL_UNSIGNED_BYTE;
}
TempPal = (ILubyte*)ialloc(768);
if (TempPal == NULL) {
iCurImage = BaseImage;
return IL_FALSE;
}
iCurImage->Pal.Palette = TempPal;
iCurImage->Pal.PalSize = 768;
iCurImage->Pal.PalType = IL_PAL_RGB24;
iseek(TexHead.Offset, IL_SEEK_SET);
if (iread(iCurImage->Data, TexHead.Width * TexHead.Height, 1) != 1)
return IL_FALSE;
if (iread(iCurImage->Pal.Palette, 1, 768) != 768)
return IL_FALSE;
if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) {
ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
}
iseek(Position, IL_SEEK_SET);
}
iCurImage = BaseImage;
ilFixImage();
return IL_TRUE;
}
#endif//IL_NO_MDL

View File

@@ -0,0 +1,349 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_mng.c
//
// Description: Multiple Network Graphics (.mng) functions
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_MNG
#define MNG_SUPPORT_READ
#define MNG_SUPPORT_WRITE
#define MNG_SUPPORT_DISPLAY
#ifdef _WIN32
//#define MNG_USE_SO
#endif
#ifdef _WIN32
#if (defined(IL_USE_PRAGMA_LIBS))
#if defined(_MSC_VER) || defined(__BORLANDC__)
#pragma comment(lib, "DevIL_libmng.lib")
#pragma comment(lib, "DevIL_lcms.lib")
#pragma comment(lib, "DevIL_libjpeg.lib")
#pragma comment(lib, "DevIL_zlib.lib")
#endif
#endif
#endif
#include <libmng.h>
//---------------------------------------------------------------------------------------------
// memory allocation; data must be zeroed
//---------------------------------------------------------------------------------------------
mng_ptr MNG_DECL mymngalloc(mng_size_t size)
{
return (mng_ptr)icalloc(1, size);
}
//---------------------------------------------------------------------------------------------
// memory deallocation
//---------------------------------------------------------------------------------------------
void MNG_DECL mymngfree(mng_ptr p, mng_size_t size)
{
ifree(p);
}
//---------------------------------------------------------------------------------------------
// Stream open:
//---------------------------------------------------------------------------------------------
mng_bool MNG_DECL mymngopenstream(mng_handle mng)
{
return MNG_TRUE;
}
//---------------------------------------------------------------------------------------------
// Stream open for Writing:
//---------------------------------------------------------------------------------------------
mng_bool MNG_DECL mymngopenstreamwrite(mng_handle mng)
{
return MNG_TRUE;
}
//---------------------------------------------------------------------------------------------
// Stream close:
//---------------------------------------------------------------------------------------------
mng_bool MNG_DECL mymngclosestream(mng_handle mng)
{
return MNG_TRUE; // We close the file ourself, mng_cleanup doesnt seem to do it...
}
//---------------------------------------------------------------------------------------------
// feed data to the decoder
//---------------------------------------------------------------------------------------------
mng_bool MNG_DECL mymngreadstream(mng_handle mng, mng_ptr buffer, mng_size_t size, mng_uint32 *bytesread)
{
// read the requested amount of data from the file
*bytesread = iread(buffer, 1, size);
return MNG_TRUE;
}
//---------------------------------------------------------------------------------------------
// callback for writing data
//---------------------------------------------------------------------------------------------
mng_bool MNG_DECL mymngwritedata(mng_handle mng, mng_ptr buffer, mng_size_t size, mng_uint32 *byteswritten)
{
*byteswritten = iwrite(buffer, 1, size);
if (*byteswritten < size) {
ilSetError(IL_FILE_WRITE_ERROR);
return MNG_FALSE;
}
return MNG_TRUE;
}
//---------------------------------------------------------------------------------------------
// the header's been read. set up the display stuff
//---------------------------------------------------------------------------------------------
mng_bool MNG_DECL mymngprocessheader(mng_handle mng, mng_uint32 width, mng_uint32 height)
{
ILuint AlphaDepth;
AlphaDepth = mng_get_alphadepth(mng);
if (AlphaDepth == 0) {
ilTexImage(width, height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL);
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
mng_set_canvasstyle(mng, MNG_CANVAS_BGR8);
}
else { // Use alpha channel
ilTexImage(width, height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL);
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8);
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
return MNG_TRUE;
}
//---------------------------------------------------------------------------------------------
// return a row pointer for the decoder to fill
//---------------------------------------------------------------------------------------------
mng_ptr MNG_DECL mymnggetcanvasline(mng_handle mng, mng_uint32 line)
{
return (mng_ptr)(iCurImage->Data + iCurImage->Bps * line);
}
//---------------------------------------------------------------------------------------------
// timer
//---------------------------------------------------------------------------------------------
mng_uint32 MNG_DECL mymnggetticks(mng_handle mng)
{
return 0;
}
//---------------------------------------------------------------------------------------------
// Refresh:
//---------------------------------------------------------------------------------------------
mng_bool MNG_DECL mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)
{
return MNG_TRUE;
}
//---------------------------------------------------------------------------------------------
// interframe delay callback
//---------------------------------------------------------------------------------------------
mng_bool MNG_DECL mymngsettimer(mng_handle mng, mng_uint32 msecs)
{
return MNG_TRUE;
}
// Make this do something different soon!
//---------------------------------------------------------------------------------------------
// Error Callback;
//---------------------------------------------------------------------------------------------
mng_bool MNG_DECL mymngerror(
mng_handle mng, mng_int32 code, mng_int8 severity,
mng_chunkid chunktype, mng_uint32 chunkseq,
mng_int32 extra1, mng_int32 extra2, mng_pchar text
)
{
// error occured;
return MNG_FALSE;
}
ILboolean iLoadMngInternal(ILvoid);
// Reads a file
ILboolean ilLoadMng(ILconst_string FileName)
{
ILHANDLE MngFile;
ILboolean bMng = IL_FALSE;
MngFile = iopenr(FileName);
if (MngFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bMng;
}
bMng = ilLoadMngF(MngFile);
icloser(MngFile);
return bMng;
}
// Reads an already-opened file
ILboolean ilLoadMngF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadMngInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
// Reads from a memory "lump"
ILboolean ilLoadMngL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadMngInternal();
}
ILboolean iLoadMngInternal()
{
mng_handle mng;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
mng = mng_initialize(MNG_NULL, mymngalloc, mymngfree, MNG_NULL);
if (mng == MNG_NULL) {
ilSetError(IL_LIB_MNG_ERROR);
return IL_FALSE;
}
// If .mng background is available, use it.
mng_set_usebkgd(mng, MNG_TRUE);
// Set the callbacks.
mng_setcb_errorproc(mng, mymngerror);
mng_setcb_openstream(mng, mymngopenstream);
mng_setcb_closestream(mng, mymngclosestream);
mng_setcb_readdata(mng, (mng_readdata)mymngreadstream);
mng_setcb_gettickcount(mng, mymnggetticks);
mng_setcb_settimer(mng, mymngsettimer);
mng_setcb_processheader(mng, mymngprocessheader);
mng_setcb_getcanvasline(mng, mymnggetcanvasline);
mng_setcb_refresh(mng, mymngrefresh);
mng_read(mng);
mng_display(mng);
ilFixImage();
return IL_TRUE;
}
ILboolean iSaveMngInternal(ILvoid);
//! Writes a Mng file
ILboolean ilSaveMng(ILconst_string FileName)
{
ILHANDLE MngFile;
ILboolean bMng = IL_FALSE;
if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
if (iFileExists(FileName)) {
ilSetError(IL_FILE_ALREADY_EXISTS);
return IL_FALSE;
}
}
MngFile = iopenw(FileName);
if (MngFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bMng;
}
bMng = ilSaveMngF(MngFile);
iclosew(MngFile);
return bMng;
}
//! Writes a Mng to an already-opened file
ILboolean ilSaveMngF(ILHANDLE File)
{
iSetOutputFile(File);
return iSaveMngInternal();
}
//! Writes a Mng to a memory "lump"
ILboolean ilSaveMngL(ILvoid *Lump, ILuint Size)
{
iSetOutputLump(Lump, Size);
return iSaveMngInternal();
}
// Internal function used to save the Mng.
ILboolean iSaveMngInternal()
{
/*mng_handle mng;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
mng = mng_initialize(MNG_NULL, mymngalloc, mymngfree, MNG_NULL);
if (mng == MNG_NULL) {
ilSetError(IL_LIB_MNG_ERROR);
return IL_FALSE;
}
mng_setcb_openstream(mng, mymngopenstreamwrite);
mng_setcb_closestream(mng, mymngclosestream);
mng_setcb_writedata(mng, mymngwritedata);
// Write File:
mng_create(mng);
// Just a single Frame (save a normal PNG):
//WritePNG( mng, 0, 1 );
// Now write file:
mng_write(mng);
mng_cleanup(&mng);*/
return IL_TRUE;
}
#endif//IL_NO_MNG

View File

@@ -0,0 +1,462 @@
/* NeuQuant Neural-Net Quantization Algorithm
* ------------------------------------------
*
* Copyright (c) 1994 Anthony Dekker
*
* NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
* See "Kohonen neural networks for optimal colour quantization"
* in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
* for a discussion of the algorithm.
* See also http://www.acm.org/~dekker/NEUQUANT.HTML
*
* Any party obtaining a copy of these files from the author, directly or
* indirectly, is granted, free of charge, a full and unrestricted irrevocable,
* world-wide, paid up, royalty-free, nonexclusive right and license to deal
* in this software and documentation files (the "Software"), including without
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons who receive
* copies from any such party to do so, with the only requirement being
* that this copyright notice remain intact.
*/
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// by Denton Woods
// Last modified: 02/02/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_neuquant.c
//
// Description: Heavily modified by Denton Woods.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
// Function definitions
ILvoid initnet(ILubyte *thepic, ILint len, ILint sample);
ILvoid unbiasnet();
ILvoid inxbuild();
ILubyte inxsearch(ILint b, ILint g, ILint r);
ILvoid learn();
// four primes near 500 - assume no image has a length so large
// that it is divisible by all four primes
#define prime1 499
#define prime2 491
#define prime3 487
#define prime4 503
#define minpicturebytes (3*prime4) // minimum size for input image
// Network Definitions
// -------------------
#define netsize 256 // number of colours used
#define maxnetpos (netsizethink-1)
#define netbiasshift 4 // bias for colour values
#define ncycles 100 // no. of learning cycles
// defs for freq and bias
#define intbiasshift 16 // bias for fractions
#define intbias (((ILint) 1)<<intbiasshift)
#define gammashift 10 // gamma = 1024
#define gamma (((ILint) 1)<<gammashift)
#define betashift 10
#define beta (intbias>>betashift)// beta = 1/1024
#define betagamma (intbias<<(gammashift-betashift))
// defs for decreasing radius factor
#define initrad (netsize>>3) // for 256 cols, radius starts
#define radiusbiasshift 6 // at 32.0 biased by 6 bits
#define radiusbias (((ILint) 1)<<radiusbiasshift)
#define initradius (initrad*radiusbias) // and decreases by a
#define radiusdec 30 // factor of 1/30 each cycle
// defs for decreasing alpha factor
#define alphabiasshift 10 // alpha starts at 1.0
#define initalpha (((ILint) 1)<<alphabiasshift)
ILint alphadec; // biased by 10 bits
// radbias and alpharadbias used for radpower calculation
#define radbiasshift 8
#define radbias (((ILint) 1)<<radbiasshift)
#define alpharadbshift (alphabiasshift+radbiasshift)
#define alpharadbias (((ILint) 1)<<alpharadbshift)
// Types and Global Variables
// --------------------------
unsigned char *thepicture; // the input image itself
int lengthcount; // lengthcount = H*W*3
int samplefac; // sampling factor 1..30
typedef int pixel[4]; // BGRc
static pixel network[netsize]; // the network itself
int netindex[256]; // for network lookup - really 256
int bias [netsize]; // bias and freq arrays for learning
int freq [netsize];
int radpower[initrad]; // radpower for precomputation
int netsizethink; // number of colors we want to reduce to, 2-256
// Initialise network in range (0,0,0) to (255,255,255) and set parameters
// -----------------------------------------------------------------------
ILvoid initnet(ILubyte *thepic, ILint len, ILint sample)
{
ILint i;
ILint *p;
thepicture = thepic;
lengthcount = len;
samplefac = sample;
for (i=0; i<netsizethink; i++) {
p = network[i];
p[0] = p[1] = p[2] = (i << (netbiasshift+8))/netsize;
freq[i] = intbias/netsizethink; // 1/netsize
bias[i] = 0;
}
return;
}
// Unbias network to give byte values 0..255 and record position i to prepare for sort
// -----------------------------------------------------------------------------------
ILvoid unbiasnet()
{
ILint i,j;
for (i=0; i<netsizethink; i++) {
for (j=0; j<3; j++)
network[i][j] >>= netbiasshift;
network[i][3] = i; // record colour no
}
return;
}
// Insertion sort of network and building of netindex[0..255] (to do after unbias)
// -------------------------------------------------------------------------------
ILvoid inxbuild()
{
ILint i,j,smallpos,smallval;
ILint *p,*q;
ILint previouscol,startpos;
previouscol = 0;
startpos = 0;
for (i=0; i<netsizethink; i++) {
p = network[i];
smallpos = i;
smallval = p[1]; // index on g
// find smallest in i..netsize-1
for (j=i+1; j<netsizethink; j++) {
q = network[j];
if (q[1] < smallval) { // index on g
smallpos = j;
smallval = q[1]; // index on g
}
}
q = network[smallpos];
// swap p (i) and q (smallpos) entries
if (i != smallpos) {
j = q[0]; q[0] = p[0]; p[0] = j;
j = q[1]; q[1] = p[1]; p[1] = j;
j = q[2]; q[2] = p[2]; p[2] = j;
j = q[3]; q[3] = p[3]; p[3] = j;
}
// smallval entry is now in position i
if (smallval != previouscol) {
netindex[previouscol] = (startpos+i)>>1;
for (j=previouscol+1; j<smallval; j++) netindex[j] = i;
previouscol = smallval;
startpos = i;
}
}
netindex[previouscol] = (startpos+maxnetpos)>>1;
for (j=previouscol+1; j<256; j++) netindex[j] = maxnetpos; // really 256
return;
}
// Search for BGR values 0..255 (after net is unbiased) and return colour index
// ----------------------------------------------------------------------------
ILubyte inxsearch(ILint b, ILint g, ILint r)
{
ILint i,j,dist,a,bestd;
ILint *p;
ILint best;
bestd = 1000; // biggest possible dist is 256*3
best = -1;
i = netindex[g]; // index on g
j = i-1; // start at netindex[g] and work outwards
while ((i<netsizethink) || (j>=0)) {
if (i<netsizethink) {
p = network[i];
dist = p[1] - g; // inx key
if (dist >= bestd) i = netsizethink; // stop iter
else {
i++;
if (dist<0) dist = -dist;
a = p[0] - b; if (a<0) a = -a;
dist += a;
if (dist<bestd) {
a = p[2] - r; if (a<0) a = -a;
dist += a;
if (dist<bestd) {bestd=dist; best=p[3];}
}
}
}
if (j>=0) {
p = network[j];
dist = g - p[1]; // inx key - reverse dif
if (dist >= bestd) j = -1; // stop iter
else {
j--;
if (dist<0) dist = -dist;
a = p[0] - b; if (a<0) a = -a;
dist += a;
if (dist<bestd) {
a = p[2] - r; if (a<0) a = -a;
dist += a;
if (dist<bestd) {bestd=dist; best=p[3];}
}
}
}
}
return (ILubyte)best;
}
// Search for biased BGR values
// ----------------------------
ILint contest(ILint b, ILint g, ILint r)
{
// finds closest neuron (min dist) and updates freq
// finds best neuron (min dist-bias) and returns position
// for frequently chosen neurons, freq[i] is high and bias[i] is negative
// bias[i] = gamma*((1/netsize)-freq[i])
ILint i,dist,a,biasdist,betafreq;
ILint bestpos,bestbiaspos,bestd,bestbiasd;
ILint *p,*f, *n;
bestd = ~(((ILint) 1)<<31);
bestbiasd = bestd;
bestpos = -1;
bestbiaspos = bestpos;
p = bias;
f = freq;
for (i=0; i<netsizethink; i++) {
n = network[i];
dist = n[0] - b; if (dist<0) dist = -dist;
a = n[1] - g; if (a<0) a = -a;
dist += a;
a = n[2] - r; if (a<0) a = -a;
dist += a;
if (dist<bestd) {bestd=dist; bestpos=i;}
biasdist = dist - ((*p)>>(intbiasshift-netbiasshift));
if (biasdist<bestbiasd) {bestbiasd=biasdist; bestbiaspos=i;}
betafreq = (*f >> betashift);
*f++ -= betafreq;
*p++ += (betafreq<<gammashift);
}
freq[bestpos] += beta;
bias[bestpos] -= betagamma;
return(bestbiaspos);
}
// Move neuron i towards biased (b,g,r) by factor alpha
// ----------------------------------------------------
ILvoid altersingle(ILint alpha, ILint i, ILint b, ILint g, ILint r)
{
ILint *n;
n = network[i]; // alter hit neuron
*n -= (alpha*(*n - b)) / initalpha;
n++;
*n -= (alpha*(*n - g)) / initalpha;
n++;
*n -= (alpha*(*n - r)) / initalpha;
return;
}
// Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in radpower[|i-j|]
// ---------------------------------------------------------------------------------
ILvoid alterneigh(ILint rad, ILint i, ILint b, ILint g, ILint r)
{
ILint j,k,lo,hi,a;
ILint *p, *q;
lo = i-rad; if (lo<-1) lo=-1;
hi = i+rad; if (hi>netsizethink) hi=netsizethink;
j = i+1;
k = i-1;
q = radpower;
while ((j<hi) || (k>lo)) {
a = (*(++q));
if (j<hi) {
p = network[j];
*p -= (a*(*p - b)) / alpharadbias;
p++;
*p -= (a*(*p - g)) / alpharadbias;
p++;
*p -= (a*(*p - r)) / alpharadbias;
j++;
}
if (k>lo) {
p = network[k];
*p -= (a*(*p - b)) / alpharadbias;
p++;
*p -= (a*(*p - g)) / alpharadbias;
p++;
*p -= (a*(*p - r)) / alpharadbias;
k--;
}
}
return;
}
// Main Learning Loop
// ------------------
ILvoid learn()
{
ILint i,j,b,g,r;
ILint radius,rad,alpha,step,delta,samplepixels;
ILubyte *p;
ILubyte *lim;
alphadec = 30 + ((samplefac-1)/3);
p = thepicture;
lim = thepicture + lengthcount;
samplepixels = lengthcount/(3*samplefac);
delta = samplepixels/ncycles;
alpha = initalpha;
radius = initradius;
rad = radius >> radiusbiasshift;
if (rad <= 1) rad = 0;
for (i=0; i<rad; i++)
radpower[i] = alpha*(((rad*rad - i*i)*radbias)/(rad*rad));
// beginning 1D learning: initial radius=rad
if ((lengthcount%prime1) != 0) step = 3*prime1;
else {
if ((lengthcount%prime2) !=0) step = 3*prime2;
else {
if ((lengthcount%prime3) !=0) step = 3*prime3;
else step = 3*prime4;
}
}
i = 0;
while (i < samplepixels) {
b = p[0] << netbiasshift;
g = p[1] << netbiasshift;
r = p[2] << netbiasshift;
j = contest(b,g,r);
altersingle(alpha,j,b,g,r);
if (rad) alterneigh(rad,j,b,g,r); // alter neighbours
p += step;
if (p >= lim) p -= lengthcount;
i++;
if (i%delta == 0) {
alpha -= alpha / alphadec;
radius -= radius / radiusdec;
rad = radius >> radiusbiasshift;
if (rad <= 1) rad = 0;
for (j=0; j<rad; j++)
radpower[j] = alpha*(((rad*rad - j*j)*radbias)/(rad*rad));
}
}
// finished 1D learning: final alpha=alpha/initalpha;
return;
}
ILimage *iNeuQuant(ILimage *Image)
{
ILimage *TempImage, *NewImage;
ILuint sample, i, j;
netsizethink=iGetInt(IL_MAX_QUANT_INDEXS);
NewImage = iCurImage;
iCurImage = Image;
TempImage = iConvertImage(iCurImage, IL_BGR, IL_UNSIGNED_BYTE);
iCurImage = NewImage;
sample = ilGetInteger(IL_NEU_QUANT_SAMPLE);
if (TempImage == NULL)
return NULL;
initnet(TempImage->Data, TempImage->SizeOfData, sample);
learn();
unbiasnet();
NewImage = (ILimage*)icalloc(sizeof(ILimage), 1);
if (NewImage == NULL) {
ilCloseImage(TempImage);
return NULL;
}
NewImage->Data = (ILubyte*)ialloc(TempImage->SizeOfData / 3);
if (NewImage->Data == NULL) {
ilCloseImage(TempImage);
ifree(NewImage);
return NULL;
}
ilCopyImageAttr(NewImage, Image);
NewImage->Bpp = 1;
NewImage->Bps = Image->Width;
NewImage->SizeOfPlane = NewImage->Bps * Image->Height;
NewImage->SizeOfData = NewImage->SizeOfPlane;
NewImage->Format = IL_COLOUR_INDEX;
NewImage->Type = IL_UNSIGNED_BYTE;
NewImage->Pal.PalSize = netsizethink * 3;
NewImage->Pal.PalType = IL_PAL_BGR24;
NewImage->Pal.Palette = (ILubyte*)ialloc(256*3);
if (NewImage->Pal.Palette == NULL) {
ilCloseImage(TempImage);
ilCloseImage(NewImage);
return NULL;
}
for (i = 0, j = 0; i < (unsigned)netsizethink; i++, j += 3) {
NewImage->Pal.Palette[j ] = network[i][0];
NewImage->Pal.Palette[j+1] = network[i][1];
NewImage->Pal.Palette[j+2] = network[i][2];
}
inxbuild();
for (i = 0, j = 0; j < TempImage->SizeOfData; i++, j += 3) {
NewImage->Data[i] = inxsearch(
TempImage->Data[j], TempImage->Data[j+1], TempImage->Data[j+2]);
}
ilCloseImage(TempImage);
return NewImage;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,206 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/19/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_pcd.c
//
// Description: Reads from a Kodak PhotoCD (.pcd) file.
// Note: The code here is sloppy - I had to convert it from Pascal,
// which I've never even attempted to read before...enjoy! =)
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_PCD
#include "il_manip.h"
ILboolean iLoadPcdInternal(ILvoid);
//! Reads a .pcd file
ILboolean ilLoadPcd(ILconst_string FileName)
{
ILHANDLE PcdFile;
ILboolean bPcd = IL_FALSE;
PcdFile = iopenr(FileName);
if (PcdFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPcd;
}
bPcd = ilLoadPcdF(PcdFile);
icloser(PcdFile);
return bPcd;
}
//! Reads an already-opened .pcd file
ILboolean ilLoadPcdF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadPcdInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a .pcd file
ILboolean ilLoadPcdL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadPcdInternal();
}
ILvoid YCbCr2RGB(ILubyte Y, ILubyte Cb, ILubyte Cr, ILubyte *r, ILubyte *g, ILubyte *b)
{
static const ILdouble c11 = 0.0054980*256;
static const ILdouble c12 = 0.0000000*256;
static const ILdouble c13 = 0.0051681*256;
static const ILdouble c21 = 0.0054980*256;
static const ILdouble c22 =-0.0015446*256;
static const ILdouble c23 =-0.0026325*256;
static const ILdouble c31 = 0.0054980*256;
static const ILdouble c32 = 0.0079533*256;
static const ILdouble c33 = 0.0000000*256;
ILint r1, g1, b1;
r1 = (ILint)(c11*Y + c12*(Cb-156) + c13*(Cr-137));
g1 = (ILint)(c21*Y + c22*(Cb-156) + c23*(Cr-137));
b1 = (ILint)(c31*Y + c32*(Cb-156) + c33*(Cr-137));
if (r1 < 0)
*r = 0;
else if (r1 > 255)
*r = 255;
else
*r = r1;
if (g1 < 0)
*g = 0;
else if (g1 > 255)
*g = 255;
else
*g = g1;
if (b1 < 0)
*b = 0;
else if (b1 > 255)
*b = 255;
else
*b = b1;
return;
}
ILboolean iLoadPcdInternal()
{
ILubyte VertOrientation;
ILuint Width, Height, i, Total, x, CurPos = 0;
ILubyte *Y1=NULL, *Y2=NULL, *CbCr=NULL, r = 0, g = 0, b = 0;
ILuint PicNum;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
iseek(72, IL_SEEK_CUR);
if (iread(&VertOrientation, 1, 1) != 1)
return IL_FALSE;
iseek(-72, IL_SEEK_CUR); // Can't rewind
PicNum = iGetInt(IL_PCD_PICNUM);
switch (PicNum)
{
case 0:
iseek(0x02000, IL_SEEK_CUR);
Width = 192;
Height = 128;
break;
case 1:
iseek(0x0b800, IL_SEEK_CUR);
Width = 384;
Height = 256;
break;
case 2:
iseek(0x30000, IL_SEEK_CUR);
Width = 768;
Height = 512;
break;
default:
ilSetError(IL_INVALID_PARAM);
return IL_FALSE;
}
Y1 = (ILubyte*)ialloc(Width);
Y2 = (ILubyte*)ialloc(Width);
CbCr = (ILubyte*)ialloc(Width);
if (Y1 == NULL || Y2 == NULL || CbCr == NULL) {
ifree(Y1);
ifree(Y2);
ifree(CbCr);
return IL_FALSE;
}
if (!ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
Total = Height >> 1;
for (i = 0; i < Total; i++) {
iread(Y1, 1, Width);
iread(Y2, 1, Width);
if (iread(CbCr, 1, Width) != Width) { // Only really need to check the last one.
ifree(Y1);
ifree(Y2);
ifree(CbCr);
return IL_FALSE;
}
for (x = 0; x < Width; x++) {
YCbCr2RGB(Y1[x], CbCr[x / 2], CbCr[(Width / 2) + (x / 2)], &r, &g, &b);
iCurImage->Data[CurPos++] = r;
iCurImage->Data[CurPos++] = g;
iCurImage->Data[CurPos++] = b;
}
for (x = 0; x < Width; x++) {
YCbCr2RGB(Y2[x], CbCr[x / 2], CbCr[(Width / 2) + (x / 2)], &r, &g, &b);
iCurImage->Data[CurPos++] = r;
iCurImage->Data[CurPos++] = g;
iCurImage->Data[CurPos++] = b;
}
}
ifree(Y1);
ifree(Y2);
ifree(CbCr);
// Not sure how it is...the documentation is hard to understand
if ((VertOrientation & 0x3F) != 8)
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
else
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
ilFixImage();
return IL_TRUE;
}
#endif//IL_NO_PCD

View File

@@ -0,0 +1,733 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 09/01/2003 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_pcx.c
//
// Description: Reads and writes from/to a .pcx file.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_PCX
#include "il_pcx.h"
#include "il_manip.h"
//! Checks if the file specified in FileName is a valid .pcx file.
ILboolean ilIsValidPcx(ILconst_string FileName) {
ILHANDLE PcxFile;
ILboolean bPcx = IL_FALSE;
if (!iCheckExtension(FileName, IL_TEXT("pcx"))) {
ilSetError(IL_INVALID_EXTENSION);
return bPcx;
}
PcxFile = iopenr(FileName);
if (PcxFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPcx;
}
bPcx = ilIsValidPcxF(PcxFile);
icloser(PcxFile);
return bPcx;
}
//! Checks if the ILHANDLE contains a valid .pcx file at the current position.
ILboolean ilIsValidPcxF(ILHANDLE File) {
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iIsValidPcx();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Checks if Lump is a valid .pcx lump.
ILboolean ilIsValidPcxL(const ILvoid *Lump, ILuint Size) {
iSetInputLump(Lump, Size);
return iIsValidPcx();
}
// Internal function obtain the .pcx header from the current file.
ILboolean iGetPcxHead(PCXHEAD *Head) {
Head->Manufacturer = igetc();
Head->Version = igetc();
Head->Encoding = igetc();
Head->Bpp = igetc();
Head->Xmin = GetLittleUShort();
Head->Ymin = GetLittleUShort();
Head->Xmax = GetLittleUShort();
Head->Ymax = GetLittleUShort();
Head->HDpi = GetLittleUShort();
Head->VDpi = GetLittleUShort();
iread(Head->ColMap, 1, 48);
Head->Reserved = igetc();
Head->NumPlanes = igetc();
Head->Bps = GetLittleUShort();
Head->PaletteInfo = GetLittleUShort();
Head->HScreenSize = GetLittleUShort();
Head->VScreenSize = GetLittleUShort();
iread(Head->Filler, 1, 54);
return IL_TRUE;
}
// Internal function to get the header and check it.
ILboolean iIsValidPcx() {
PCXHEAD Head;
if (!iGetPcxHead(&Head))
return IL_FALSE;
iseek(-(ILint)sizeof(PCXHEAD), IL_SEEK_CUR);
return iCheckPcx(&Head);
}
// Internal function used to check if the HEADER is a valid .pcx header.
// Should we also do a check on Header->Bpp?
ILboolean iCheckPcx(PCXHEAD *Header) {
ILuint Test;
// Got rid of the Reserved check, because I've seen some .pcx files with invalid values in it.
if (Header->Manufacturer != 10 || Header->Encoding != 1/* || Header->Reserved != 0*/)
return IL_FALSE;
// Try to support all pcx versions, as they only differ in allowed formats...
// Let's hope it works.
if(Header->Version != 5 && Header->Version != 0 && Header->Version != 2 &&
Header->VDpi != 3 && Header->VDpi != 4)
return IL_FALSE;
// See if the padding size is correct
Test = Header->Xmax - Header->Xmin + 1;
if (Header->Bpp >= 8) {
if (Test & 1) {
if (Header->Bps != Test + 1)
return IL_FALSE;
}
else {
if (Header->Bps != Test) // No padding
return IL_FALSE;
}
}
/* for (i = 0; i < 54; i++) { useless check
if (Header->Filler[i] != 0)
return IL_FALSE;
} */
return IL_TRUE;
}
//! Reads a .pcx file
ILboolean ilLoadPcx(ILconst_string FileName) {
ILHANDLE PcxFile;
ILboolean bPcx = IL_FALSE;
PcxFile = iopenr(FileName);
if (PcxFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPcx;
}
bPcx = ilLoadPcxF(PcxFile);
icloser(PcxFile);
return bPcx;
}
//! Reads an already-opened .pcx file
ILboolean ilLoadPcxF(ILHANDLE File) {
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadPcxInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a .pcx
ILboolean ilLoadPcxL(const ILvoid *Lump, ILuint Size) {
iSetInputLump(Lump, Size);
return iLoadPcxInternal();
}
// Internal function used to load the .pcx.
ILboolean iLoadPcxInternal() {
PCXHEAD Header;
ILboolean bPcx = IL_FALSE;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return bPcx;
}
if (!iGetPcxHead(&Header))
return IL_FALSE;
if (!iCheckPcx(&Header)) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
bPcx = iUncompressPcx(&Header);
ilFixImage();
return bPcx;
}
// Internal function to uncompress the .pcx (all .pcx files are rle compressed)
ILboolean iUncompressPcx(PCXHEAD *Header) {
//changed decompression loop 2003-09-01
//From the pcx spec: "There should always
//be a decoding break at the end of each scan line.
//But there will not be a decoding break at the end of
//each plane within each scan line."
//This is now handled correctly (hopefully ;) )
ILubyte ByteHead, Colour, *ScanLine /* For all planes */;
ILuint ScanLineSize;
ILuint c, i, x, y;
if (Header->Bpp < 8) {
/*ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;*/
return iUncompressSmall(Header);
}
if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL))
return IL_FALSE;
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
switch (iCurImage->Bpp)
{
case 1:
iCurImage->Format = IL_COLOUR_INDEX;
iCurImage->Pal.PalType = IL_PAL_RGB24;
iCurImage->Pal.PalSize = 256 * 3; // Need to find out for sure...
iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
if (iCurImage->Pal.Palette == NULL) {
return IL_FALSE;
}
break;
//case 2: // No 16-bit images in the pcx format!
case 3:
iCurImage->Format = IL_RGB;
iCurImage->Pal.Palette = NULL;
iCurImage->Pal.PalSize = 0;
iCurImage->Pal.PalType = IL_PAL_NONE;
break;
case 4:
iCurImage->Format = IL_RGBA;
iCurImage->Pal.Palette = NULL;
iCurImage->Pal.PalSize = 0;
iCurImage->Pal.PalType = IL_PAL_NONE;
break;
default:
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
ScanLineSize = iCurImage->Bpp*Header->Bps;
ScanLine = (ILubyte*)ialloc(ScanLineSize);
if (ScanLine == NULL) {
return IL_FALSE;
}
//changed 2003-09-01
//having the decoding code twice is error-prone,
//so I made iUnCache() smart enough to grasp
//if iPreCache() wasn't called and call it
//anyways.
if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
iPreCache(iCurImage->SizeOfData / 4);
for (y = 0; y < iCurImage->Height; y++) {
x = 0;
//read scanline
while (x < ScanLineSize) {
if (iread(&ByteHead, 1, 1) != 1) {
iUnCache();
goto file_read_error;
}
if ((ByteHead & 0xC0) == 0xC0) {
ByteHead &= 0x3F;
if (iread(&Colour, 1, 1) != 1) {
iUnCache();
goto file_read_error;
}
if (x + ByteHead > ScanLineSize) {
iUnCache();
goto file_read_error;
}
for (i = 0; i < ByteHead; i++) {
ScanLine[x++] = Colour;
}
}
else {
ScanLine[x++] = ByteHead;
}
}
//convert plane-separated scanline into index, rgb or rgba pixels.
//there might be a padding byte at the end of each scanline...
for (x = 0; x < iCurImage->Width; x++) {
for(c = 0; c < iCurImage->Bpp; c++) {
iCurImage->Data[y * iCurImage->Bps + x * iCurImage->Bpp + c] =
ScanLine[x + c * Header->Bps];
}
}
}
iUnCache();
// Read in the palette
if (Header->Version == 5 && iCurImage->Bpp == 1) {
x = itell();
if (iread(&ByteHead, 1, 1) == 0) { // If true, assume that we have a luminance image.
ilGetError(); // Get rid of the IL_FILE_READ_ERROR.
iCurImage->Format = IL_LUMINANCE;
if (iCurImage->Pal.Palette)
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.PalSize = 0;
iCurImage->Pal.PalType = IL_PAL_NONE;
}
else {
if (ByteHead != 12) // Some Quake2 .pcx files don't have this byte for some reason.
iseek(-1, IL_SEEK_CUR);
if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize)
goto file_read_error;
}
}
ifree(ScanLine);
return IL_TRUE;
file_read_error:
ifree(ScanLine);
//added 2003-09-01
ilSetError(IL_FILE_READ_ERROR);
return IL_FALSE;
}
ILboolean iUncompressSmall(PCXHEAD *Header) {
ILuint i = 0, j, k, c, d, x, y, Bps;
ILubyte HeadByte, Colour, Data = 0, *ScanLine;
if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
switch (Header->NumPlanes)
{
case 1:
iCurImage->Format = IL_LUMINANCE;
break;
case 4:
iCurImage->Format = IL_COLOUR_INDEX;
break;
default:
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
if (Header->NumPlanes == 1 && Header->Bpp == 1) {
for (j = 0; j < iCurImage->Height; j++) {
i = 0; //number of written pixels
while (i < iCurImage->Width) {
if (iread(&HeadByte, 1, 1) != 1)
return IL_FALSE;
if (HeadByte >= 192) {
HeadByte -= 192;
if (iread(&Data, 1, 1) != 1)
return IL_FALSE;
for (c = 0; c < HeadByte; c++) {
k = 128;
for (d = 0; d < 8 && i < iCurImage->Width; d++) {
iCurImage->Data[j * iCurImage->Width + i++] = ((Data & k) != 0 ? 255 : 0);
k >>= 1;
}
}
}
else {
k = 128;
for (c = 0; c < 8 && i < iCurImage->Width; c++) {
iCurImage->Data[j * iCurImage->Width + i++] = ((HeadByte & k) != 0 ? 255 : 0);
k >>= 1;
}
}
}
//if(Data != 0)
//changed 2003-09-01:
//There has to be an even number of bytes per line in a pcx.
//One byte can hold up to 8 bits, so Width/8 bytes
//are needed to hold a 1 bit per pixel image line.
//If Width/8 is even no padding is needed,
//one pad byte has to be read otherwise.
//(let's hope the above is true ;-))
if(!((iCurImage->Width >> 3) & 0x1))
igetc(); // Skip pad byte
}
}
else if (Header->NumPlanes == 4 && Header->Bpp == 1){ // 4-bit images
//changed decoding 2003-09-10 (was buggy)...could need a speedup
Bps = Header->Bps * Header->NumPlanes * 8;
iCurImage->Pal.Palette = (ILubyte*)ialloc(16 * 3); // Size of palette always (48 bytes).
ScanLine = (ILubyte*)ialloc(Bps);
if (iCurImage->Pal.Palette == NULL || ScanLine == NULL) {
ifree(ScanLine);
ifree(iCurImage->Pal.Palette);
return IL_FALSE;
}
memcpy(iCurImage->Pal.Palette, Header->ColMap, 16 * 3);
iCurImage->Pal.PalSize = 16 * 3;
iCurImage->Pal.PalType = IL_PAL_RGB24;
memset(iCurImage->Data, 0, iCurImage->SizeOfData);
if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
iPreCache(iCurImage->SizeOfData / 4);
for (y = 0; y < iCurImage->Height; y++) {
x = 0;
while (x < Bps) {
if (iread(&HeadByte, 1, 1) != 1) {
iUnCache();
ifree(ScanLine);
return IL_FALSE;
}
if ((HeadByte & 0xC0) == 0xC0) {
HeadByte &= 0x3F;
if (iread(&Colour, 1, 1) != 1) {
iUnCache();
ifree(ScanLine);
return IL_FALSE;
}
for (i = 0; i < HeadByte; i++) {
k = 128;
for (j = 0; j < 8 && x < Bps; j++) {
ScanLine[x++] = (Colour & k)?1:0;
k >>= 1;
}
}
}
else {
k = 128;
for (j = 0; j < 8 && x < Bps; j++) {
ScanLine[x++] = (HeadByte & k)?1:0;
k >>= 1;
}
}
}
for (x = 0; x < iCurImage->Width; x++) { // 'Cleverly' ignores the pad bytes. ;)
for(c = 0; c < Header->NumPlanes; c++)
iCurImage->Data[y * iCurImage->Width + x] |= ScanLine[x + c*Header->Bps*8] << c;
}
}
iUnCache();
ifree(ScanLine);
}
else {
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
return IL_TRUE;
}
//! Writes a .pcx file
ILboolean ilSavePcx(ILconst_string FileName) {
ILHANDLE PcxFile;
ILboolean bPcx = IL_FALSE;
if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
if (iFileExists(FileName)) {
ilSetError(IL_FILE_ALREADY_EXISTS);
return IL_FALSE;
}
}
PcxFile = iopenw(FileName);
if (PcxFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPcx;
}
bPcx = ilSavePcxF(PcxFile);
iclosew(PcxFile);
return bPcx;
}
//! Writes a .pcx to an already-opened file
ILboolean ilSavePcxF(ILHANDLE File) {
iSetOutputFile(File);
return iSavePcxInternal();
}
//! Writes a .pcx to a memory "lump"
ILboolean ilSavePcxL(ILvoid *Lump, ILuint Size) {
iSetOutputLump(Lump, Size);
return iSavePcxInternal();
}
// Internal function used to save the .pcx.
ILboolean iSavePcxInternal() {
ILuint i, c, PalSize;
ILpal *TempPal;
ILimage *TempImage = iCurImage;
ILubyte *TempData;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
switch (iCurImage->Format)
{
case IL_LUMINANCE:
TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE);
if (TempImage == NULL)
return IL_FALSE;
break;
case IL_BGR:
TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
if (TempImage == NULL)
return IL_FALSE;
break;
case IL_BGRA:
TempImage = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE);
if (TempImage == NULL)
return IL_FALSE;
break;
default:
if (iCurImage->Bpc > 1) {
TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE);
if (TempImage == NULL)
return IL_FALSE;
}
}
if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) {
TempData = iGetFlipped(TempImage);
if (TempData == NULL) {
if (TempImage != iCurImage) {
ilCloseImage(TempImage);
}
return IL_FALSE;
}
}
else {
TempData = TempImage->Data;
}
iputc(0xA); // Manufacturer - always 10
iputc(0x5); // Version Number - always 5
iputc(0x1); // Encoding - always 1
iputc(0x8); // Bits per channel
SaveLittleUShort(0); // X Minimum
SaveLittleUShort(0); // Y Minimum
SaveLittleUShort((ILushort)(iCurImage->Width - 1));
SaveLittleUShort((ILushort)(iCurImage->Height - 1));
SaveLittleUShort(0);
SaveLittleUShort(0);
// Useless palette info?
for (i = 0; i < 48; i++) {
iputc(0);
}
iputc(0x0); // Reserved - always 0
iputc(iCurImage->Bpp); // Number of planes - only 1 is supported right now
SaveLittleUShort((ILushort)(iCurImage->Width & 1 ? iCurImage->Width + 1 : iCurImage->Width)); // Bps
SaveLittleUShort(0x1); // Palette type - ignored?
// Mainly filler info
for (i = 0; i < 58; i++) {
iputc(0x0);
}
// Output data
for (i = 0; i < TempImage->Height; i++) {
for (c = 0; c < TempImage->Bpp; c++) {
encLine(TempData + TempImage->Bps * i + c, TempImage->Width, (ILubyte)(TempImage->Bpp - 1));
}
}
// Automatically assuming we have a palette...dangerous!
// Also assuming 3 bpp palette
iputc(0xC); // Pad byte must have this value
// If the current image has a palette, take care of it
if (TempImage->Format == IL_COLOUR_INDEX) {
// If the palette in .pcx format, write it directly
if (TempImage->Pal.PalType == IL_PAL_RGB24) {
iwrite(TempImage->Pal.Palette, 1, TempImage->Pal.PalSize);
}
else {
TempPal = iConvertPal(&TempImage->Pal, IL_PAL_RGB24);
if (TempPal == NULL) {
if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
ifree(TempData);
if (TempImage != iCurImage)
ilCloseImage(TempImage);
return IL_FALSE;
}
iwrite(TempPal->Palette, 1, TempPal->PalSize);
ifree(TempPal->Palette);
ifree(TempPal);
}
}
// If the palette is not all 256 colours, we have to pad it.
PalSize = 768 - iCurImage->Pal.PalSize;
for (i = 0; i < PalSize; i++) {
iputc(0x0);
}
if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
ifree(TempData);
if (TempImage != iCurImage)
ilCloseImage(TempImage);
return IL_TRUE;
}
// Routine used from ZSoft's pcx documentation
ILuint encput(ILubyte byt, ILubyte cnt) {
if (cnt) {
if ((cnt == 1) && (0xC0 != (0xC0 & byt))) {
if (IL_EOF == iputc(byt))
return(0); /* disk write error (probably full) */
return(1);
}
else {
if (IL_EOF == iputc((ILubyte)((ILuint)0xC0 | cnt)))
return (0); /* disk write error */
if (IL_EOF == iputc(byt))
return (0); /* disk write error */
return (2);
}
}
return (0);
}
/* This subroutine encodes one scanline and writes it to a file.
It returns number of bytes written into outBuff, 0 if failed. */
ILuint encLine(ILubyte *inBuff, ILint inLen, ILubyte Stride)
{
ILubyte _this, last;
ILint srcIndex, i;
ILint total;
ILubyte runCount; // max single runlength is 63
total = 0;
runCount = 1;
last = *(inBuff);
// Find the pixel dimensions of the image by calculating
//[XSIZE = Xmax - Xmin + 1] and [YSIZE = Ymax - Ymin + 1].
//Then calculate how many bytes are in a "run"
for (srcIndex = 1; srcIndex < inLen; srcIndex++) {
inBuff += Stride;
_this = *(++inBuff);
if (_this == last) { // There is a "run" in the data, encode it
runCount++;
if (runCount == 63) {
if (! (i = encput(last, runCount)))
return (0);
total += i;
runCount = 0;
}
}
else { // No "run" - _this != last
if (runCount) {
if (! (i = encput(last, runCount)))
return(0);
total += i;
}
last = _this;
runCount = 1;
}
} // endloop
if (runCount) { // finish up
if (! (i = encput(last, runCount)))
return (0);
if (inLen % 2)
iputc(0);
return (total + i);
}
else {
if (inLen % 2)
iputc(0);
}
return (total);
}
#endif//IL_NO_PCX

View File

@@ -0,0 +1,432 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/21/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_pic.c
//
// Description: Softimage Pic (.pic) functions
//
//-----------------------------------------------------------------------------
// @TODO: Test these extensively...haven't even been tested yet!!!
#include "il_internal.h"
#ifndef IL_NO_PIC
#include "il_pic.h"
#include "il_manip.h"
#include <string.h>
//! Checks if the file specified in FileName is a valid .pic file.
ILboolean ilIsValidPic(ILconst_string FileName)
{
ILHANDLE PicFile;
ILboolean bPic = IL_FALSE;
if (!iCheckExtension(FileName, IL_TEXT("pic"))) {
ilSetError(IL_INVALID_EXTENSION);
return bPic;
}
PicFile = iopenr(FileName);
if (PicFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPic;
}
bPic = ilIsValidPicF(PicFile);
icloser(PicFile);
return bPic;
}
//! Checks if the ILHANDLE contains a valid .pic file at the current position.
ILboolean ilIsValidPicF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iIsValidPic();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Checks if Lump is a valid .pic lump.
ILboolean ilIsValidPicL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iIsValidPic();
}
// Internal function used to get the .pic header from the current file.
ILboolean iGetPicHead(PIC_HEAD *Header)
{
Header->Magic = GetLittleInt();
Header->Version = GetLittleFloat();
iread(Header->Comment, 1, 80);
iread(Header->Id, 1, 4);
Header->Width = GetLittleShort();
Header->Height = GetLittleShort();
Header->Ratio = GetLittleFloat();
Header->Fields = GetLittleShort();
Header->Padding = GetLittleShort();
return IL_TRUE;
}
// Internal function to get the header and check it.
ILboolean iIsValidPic()
{
PIC_HEAD Head;
if (!iGetPicHead(&Head))
return IL_FALSE;
iseek(-(ILint)sizeof(PIC_HEAD), IL_SEEK_CUR); // Go ahead and restore to previous state
return iCheckPic(&Head);
}
// Internal function used to check if the header is a valid .pic header.
ILboolean iCheckPic(PIC_HEAD *Header)
{
if (Header->Magic != 0x5380F634)
return IL_FALSE;
if (strncmp((const char*)Header->Id, "PICT", 4))
return IL_FALSE;
if (Header->Width == 0)
return IL_FALSE;
if (Header->Height == 0)
return IL_FALSE;
return IL_TRUE;
}
//! Reads a .pic file
ILboolean ilLoadPic(ILconst_string FileName)
{
ILHANDLE PicFile;
ILboolean bPic = IL_FALSE;
PicFile = iopenr(FileName);
if (PicFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPic;
}
bPic = ilLoadPicF(PicFile);
icloser(PicFile);
return bPic;
}
//! Reads an already-opened .pic file
ILboolean ilLoadPicF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadPicInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a .pic
ILboolean ilLoadPicL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadPicInternal();
}
// Internal function used to load the .pic
ILboolean iLoadPicInternal()
{
ILuint Alpha = IL_FALSE;
ILubyte Chained;
CHANNEL *Channel = NULL, *Channels = NULL, *Prev;
PIC_HEAD Header;
ILboolean Read;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!iGetPicHead(&Header))
return IL_FALSE;
if (!iCheckPic(&Header)) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
if (!ilTexImage(Header.Width, Header.Height, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
// Read channels
do {
if (Channel == NULL) {
Channel = Channels = (CHANNEL*)ialloc(sizeof(CHANNEL));
if (Channels == NULL)
return IL_FALSE;
}
else {
Channels->Next = (CHANNEL*)ialloc(sizeof(CHANNEL));
if (Channels->Next == NULL) {
// Clean up the list before erroring out.
while (Channel) {
Prev = Channel;
Channel = (CHANNEL*)Channel->Next;
ifree(Prev);
}
return IL_FALSE;
}
Channels = (CHANNEL*)Channels->Next;
}
Channels->Next = NULL;
Chained = igetc();
Channels->Size = igetc();
Channels->Type = igetc();
Channels->Chan = igetc();
if (ieof()) {
Read = IL_FALSE;
goto finish;
}
// See if we have an alpha channel in there
if (Channels->Chan & PIC_ALPHA_CHANNEL)
Alpha = IL_TRUE;
} while (Chained);
Read = readScanlines((ILuint*)iCurImage->Data, Header.Width, Header.Height, Channel, Alpha);
finish:
// Destroy channels
while (Channel) {
Prev = Channel;
Channel = (CHANNEL*)Channel->Next;
ifree(Prev);
}
if (Read == IL_FALSE)
return IL_FALSE;
ilFixImage();
return IL_TRUE;
}
ILboolean readScanlines(ILuint *image, ILint width, ILint height, CHANNEL *channel, ILuint alpha)
{
ILint i;
ILuint *scan;
(ILvoid)alpha;
for (i = height - 1; i >= 0; i--) {
scan = image + i * width;
if (!readScanline((ILubyte *)scan, width, channel, 4)) {
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
}
return IL_TRUE;
}
ILuint readScanline(ILubyte *scan, ILint width, CHANNEL *channel, ILint bytes)
{
ILint noCol;
ILint off[4];
ILuint status=0;
while (channel) {
noCol = 0;
//#ifndef sgi
if(channel->Chan & PIC_RED_CHANNEL) {
off[noCol] = 0;
noCol++;
}
if(channel->Chan & PIC_GREEN_CHANNEL) {
off[noCol] = 1;
noCol++;
}
if(channel->Chan & PIC_BLUE_CHANNEL) {
off[noCol] = 2;
noCol++;
}
if(channel->Chan & PIC_ALPHA_CHANNEL) {
off[noCol] = 3;
noCol++;
}
/*#else
if(channel->channels & PIC_RED_CHANNEL) {
off[noCol] = 3;
noCol++;
}
if(channel->channels & PIC_GREEN_CHANNEL) {
off[noCol] = 2;
noCol++;
}
if(channel->channels & PIC_BLUE_CHANNEL) {
off[noCol] = 1;
noCol++;
}
if(channel->channels & PIC_ALPHA_CHANNEL) {
off[noCol] = 0;
noCol++;
}
#endif*/
switch(channel->Type & 0x0F) {
case PIC_UNCOMPRESSED:
status = channelReadRaw(scan, width, noCol, off, bytes);
break;
case PIC_PURE_RUN_LENGTH:
status = channelReadPure(scan, width, noCol, off, bytes);
break;
case PIC_MIXED_RUN_LENGTH:
status = channelReadMixed(scan, width, noCol, off, bytes);
break;
}
if (!status)
break;
channel = (CHANNEL*)channel->Next;
}
return status;
}
ILboolean channelReadRaw(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes)
{
ILint i, j;
for (i = 0; i < width; i++) {
if (ieof())
return IL_FALSE;
for (j = 0; j < noCol; j++)
if (iread(&scan[off[j]], 1, 1) != 1)
return IL_FALSE;
scan += bytes;
}
return IL_TRUE;
}
ILboolean channelReadPure(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes)
{
ILubyte col[4];
ILint count;
int i, j, k;
for (i = width; i > 0; ) {
count = igetc();
if (count == IL_EOF)
return IL_FALSE;
if (count > width)
count = width;
i -= count;
if (ieof())
return IL_FALSE;
for (j = 0; j < noCol; j++)
if (iread(&col[j], 1, 1) != 1)
return IL_FALSE;
for (k = 0; k < count; k++, scan += bytes) {
for(j = 0; j < noCol; j++)
scan[off[j] + k] = col[j];
}
}
return IL_TRUE;
}
ILboolean channelReadMixed(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes)
{
ILint count;
int i, j, k;
ILubyte col[4];
for(i = 0; i < width; i += count) {
if (ieof())
return IL_FALSE;
count = igetc();
if (count == IL_EOF)
return IL_FALSE;
if (count >= 128) { // Repeated sequence
if (count == 128) { // Long run
count = GetLittleUShort();
if (ieof())
return IL_FALSE;
}
else
count -= 127;
// We've run past...
if ((i + count) > width) {
//fprintf(stderr, "ERROR: FF_PIC_load(): Overrun scanline (Repeat) [%d + %d > %d] (NC=%d)\n", i, count, width, noCol);
return IL_FALSE;
}
for (j = 0; j < noCol; j++)
if (iread(&col[j], 1, 1) != 1)
return IL_FALSE;
for (k = 0; k < count; k++, scan += bytes) {
for (j = 0; j < noCol; j++)
scan[off[j]] = col[j];
}
} else { // Raw sequence
count++;
if ((i + count) > width) {
//fprintf(stderr, "ERROR: FF_PIC_load(): Overrun scanline (Raw) [%d + %d > %d] (NC=%d)\n", i, count, width, noCol);
return IL_FALSE;
}
for (k = count; k > 0; k--, scan += bytes) {
for (j = 0; j < noCol; j++)
if (iread(&scan[off[j]], 1, 1) != 1)
return IL_FALSE;
}
}
}
return IL_TRUE;
}
#endif//IL_NO_PIC

View File

@@ -0,0 +1,164 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/26/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_pix.c
//
// Description: Reads from an Alias | Wavefront .pix file.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_PIX
#include "il_manip.h"
#include "il_endian.h"
#ifdef _MSC_VER
#pragma pack(push, pix_struct, 1)
#endif
typedef struct PIXHEAD
{
ILushort Width;
ILushort Height;
ILushort OffX;
ILushort OffY;
ILushort Bpp;
} IL_PACKSTRUCT PIXHEAD;
#ifdef _MSC_VER
#pragma pack(pop, pix_struct)
#endif
ILboolean iCheckPix(PIXHEAD *Header);
ILboolean iLoadPixInternal(ILvoid);
// Internal function used to get the Pix header from the current file.
ILboolean iGetPixHead(PIXHEAD *Header) {
Header->Width = GetBigUShort();
Header->Height = GetBigUShort();
Header->OffX = GetBigUShort();
Header->OffY = GetBigUShort();
Header->Bpp = GetBigUShort();
return IL_TRUE;
}
// Internal function to get the header and check it.
ILboolean iIsValidPix()
{
PIXHEAD Head;
if (!iGetPixHead(&Head))
return IL_FALSE;
iseek(-(ILint)sizeof(PIXHEAD), IL_SEEK_CUR);
return iCheckPix(&Head);
}
// Internal function used to check if the HEADER is a valid Pix header.
ILboolean iCheckPix(PIXHEAD *Header)
{
if (Header->Width == 0 || Header->Height == 0)
return IL_FALSE;
if (Header->Bpp != 24)
return IL_FALSE;
//if (Header->OffY != Header->Height)
// return IL_FALSE;
return IL_TRUE;
}
//! Reads a Pix file
ILboolean ilLoadPix(ILconst_string FileName)
{
ILHANDLE PixFile;
ILboolean bPix = IL_FALSE;
PixFile = iopenr(FileName);
if (PixFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPix;
}
bPix = ilLoadPixF(PixFile);
icloser(PixFile);
return bPix;
}
//! Reads an already-opened Pix file
ILboolean ilLoadPixF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadPixInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a Pix
ILboolean ilLoadPixL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadPixInternal();
}
// Internal function used to load the Pix.
ILboolean iLoadPixInternal()
{
PIXHEAD Header;
ILuint i, j;
ILubyte ByteHead, Colour[3];
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!iGetPixHead(&Header))
return IL_FALSE;
if (!iCheckPix(&Header)) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL))
return IL_FALSE;
for (i = 0; i < iCurImage->SizeOfData; ) {
ByteHead = igetc();
if (iread(Colour, 1, 3) != 3)
return IL_FALSE;
for (j = 0; j < ByteHead; j++) {
iCurImage->Data[i++] = Colour[0];
iCurImage->Data[i++] = Colour[1];
iCurImage->Data[i++] = Colour[2];
}
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
ilFixImage();
return IL_TRUE;
}
#endif//IL_NO_PIX

View File

@@ -0,0 +1,713 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 02/01/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_png.c
//
// Description: Portable network graphics file (.png) functions
//
// 20040223 XIX : now may spit out pngs with a transparent index, this is mostly a hack
// but the proper way of doing it would be to change the pal stuff to think in argb rather than rgb
// which is something of a bigger job.
//
//-----------------------------------------------------------------------------
// Most of the comments are left in this file from libpng's excellent example.c
#include "il_internal.h"
#ifndef IL_NO_PNG
#include <png.h>
#include "il_manip.h"
#include <stdlib.h>
#if PNG_LIBPNG_VER < 10200
#warning DevIL was designed with libpng 1.2.0 or higher in mind. Consider upgrading at www.libpng.org
#endif
#ifdef _WIN32
#if (defined(IL_USE_PRAGMA_LIBS))
#if defined(_MSC_VER) || defined(__BORLANDC__)
#pragma comment(lib, "DevIL_libpng.lib")
#pragma comment(lib, "DevIL_zlib.lib")
#endif
#endif
#endif
ILboolean iIsValidPng(ILvoid);
ILboolean iLoadPngInternal(ILvoid);
ILboolean iSavePngInternal(ILvoid);
ILint readpng_init(ILvoid);
ILboolean readpng_get_image(ILdouble display_exponent);
ILvoid readpng_cleanup(ILvoid);
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
ILint color_type;
#define GAMMA_CORRECTION 1.0 // Doesn't seem to be doing anything...
ILboolean ilIsValidPng(ILconst_string FileName)
{
ILHANDLE PngFile;
ILboolean bPng = IL_FALSE;
if (!iCheckExtension(FileName, IL_TEXT( "png" ))) {
ilSetError(IL_INVALID_EXTENSION);
return bPng;
}
PngFile = iopenr(FileName);
if (PngFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPng;
}
bPng = ilIsValidPngF(PngFile);
icloser(PngFile);
return bPng;
}
ILboolean ilIsValidPngF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iIsValidPng();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
ILboolean ilIsValidPngL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iIsValidPng();
}
ILboolean iIsValidPng()
{
ILubyte Signature[8];
ILint Read;
Read = iread(Signature, 1, 8);
iseek(-Read, IL_SEEK_CUR);
return png_check_sig(Signature, 8);
}
// Reads a file
ILboolean ilLoadPng(ILconst_string FileName)
{
ILHANDLE PngFile;
ILboolean bPng = IL_FALSE;
PngFile = iopenr(FileName);
if (PngFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPng;
}
bPng = ilLoadPngF(PngFile);
icloser(PngFile);
return bPng;
}
// Reads an already-opened file
ILboolean ilLoadPngF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadPngInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
// Reads from a memory "lump"
ILboolean ilLoadPngL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadPngInternal();
}
ILboolean iLoadPngInternal()
{
png_ptr = NULL;
info_ptr = NULL;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!iIsValidPng()) {
ilSetError(IL_INVALID_VALUE);
return IL_FALSE;
}
if (readpng_init())
return IL_FALSE;
if (!readpng_get_image(GAMMA_CORRECTION))
return IL_FALSE;
readpng_cleanup();
ilFixImage();
return IL_TRUE;
}
static ILvoid png_read(png_structp png_ptr, png_bytep data, png_size_t length)
{
(ILvoid)png_ptr;
iread(data, 1, length);
return;
}
static void png_error_func(png_structp png_ptr, png_const_charp message)
{
ilSetError(IL_LIB_PNG_ERROR);
/*
changed 20040224
From the libpng docs:
"Errors handled through png_error() are fatal, meaning that png_error()
should never return to its caller. Currently, this is handled via
setjmp() and longjmp()"
*/
//return;
longjmp(png_jmpbuf(png_ptr), 1);
}
static void png_warn_func(png_structp png_ptr, png_const_charp message)
{
return;
}
ILint readpng_init()
{
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_func, png_warn_func);
if (!png_ptr)
return 4; /* out of memory */
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, NULL, NULL);
return 4; /* out of memory */
}
/* we could create a second info struct here (end_info), but it's only
* useful if we want to keep pre- and post-IDAT chunk info separated
* (mainly for PNG-aware image editors and converters) */
/* setjmp() must be called in every function that calls a PNG-reading
* libpng function */
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return 2;
}
png_set_read_fn(png_ptr, NULL, png_read);
png_set_error_fn(png_ptr, NULL, png_error_func, png_warn_func);
// png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
/* alternatively, could make separate calls to png_get_image_width(),
* etc., but want bit_depth and color_type for later [don't care about
* compression_type and filter_type => NULLs] */
/* OK, that's all we need for now; return happy */
return 0;
}
/* display_exponent == LUT_exponent * CRT_exponent */
ILboolean readpng_get_image(ILdouble display_exponent)
{
png_bytepp row_pointers = NULL;
png_uint_32 width, height; // Changed the type to fix AMD64 bit problems, thanks to Eric Werness
ILdouble screen_gamma = 1.0;
ILuint i, channels;
ILenum format;
png_colorp palette;
ILint num_palette, j, bit_depth;
#if _WIN32 || DJGPP
ILdouble image_gamma;
#endif
/* setjmp() must be called in every function that calls a PNG-reading
* libpng function */
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return IL_FALSE;
}
png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&width, (png_uint_32*)&height,
&bit_depth, &color_type, NULL, NULL, NULL);
// Expand low-bit-depth grayscale images to 8 bits
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
png_set_gray_1_2_4_to_8(png_ptr);
}
// Expand RGB images with transparency to full alpha channels
// so the data will be available as RGBA quartets.
// But don't expand paletted images, since we want alpha palettes!
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) && !(png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)))
png_set_tRNS_to_alpha(png_ptr);
//refresh information (added 20040224)
png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&width, (png_uint_32*)&height,
&bit_depth, &color_type, NULL, NULL, NULL);
if (bit_depth < 8) { // Expanded earlier for grayscale, now take care of palette and rgb
bit_depth = 8;
png_set_packing(png_ptr);
}
// Perform gamma correction.
// @TODO: Determine if we should call png_set_gamma if image_gamma is 1.0.
#if _WIN32 || DJGPP
screen_gamma = 2.2;
if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
png_set_gamma(png_ptr, screen_gamma, image_gamma);
#else
screen_gamma = screen_gamma;
#endif
//fix endianess
#ifdef __LITTLE_ENDIAN__
if (bit_depth == 16)
png_set_swap(png_ptr);
#endif
png_read_update_info(png_ptr, info_ptr);
channels = (ILint)png_get_channels(png_ptr, info_ptr);
//added 20040224: update color_type so that it has the correct value
//in iLoadPngInternal (globals rule...)
color_type = png_get_color_type(png_ptr, info_ptr);
//determine internal format
switch(color_type)
{
case PNG_COLOR_TYPE_PALETTE:
format = IL_COLOUR_INDEX;
break;
case PNG_COLOR_TYPE_GRAY:
format = IL_LUMINANCE;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
format = IL_LUMINANCE_ALPHA;
break;
case PNG_COLOR_TYPE_RGB:
format = IL_RGB;
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
format = IL_RGBA;
break;
default:
ilSetError(IL_ILLEGAL_FILE_VALUE);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return IL_FALSE;
}
if (!ilTexImage(width, height, 1, (ILubyte)channels, format, ilGetTypeBpc((ILubyte)(bit_depth >> 3)), NULL)) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
//copy palette
if (format == IL_COLOUR_INDEX) {
int chans;
png_bytep trans = NULL;
int num_trans = -1;
if (!png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) {
ilSetError(IL_ILLEGAL_FILE_VALUE);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return IL_FALSE;
}
chans = 3;
iCurImage->Pal.PalType = IL_PAL_RGB24;
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
iCurImage->Pal.PalType = IL_PAL_RGBA32;
chans = 4;
}
iCurImage->Pal.PalSize = num_palette * chans;
iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
for (j = 0; j < num_palette; ++j) {
iCurImage->Pal.Palette[chans*j + 0] = palette[j].red;
iCurImage->Pal.Palette[chans*j + 1] = palette[j].green;
iCurImage->Pal.Palette[chans*j + 2] = palette[j].blue;
if (trans!=NULL) {
if (j<num_trans)
iCurImage->Pal.Palette[chans*j + 3] = trans[j];
else
iCurImage->Pal.Palette[chans*j + 3] = 255;
}
}
}
//allocate row pointers
if ((row_pointers = (png_bytepp)ialloc(height * sizeof(png_bytep))) == NULL) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return IL_FALSE;
}
// Set the individual row_pointers to point at the correct offsets */
for (i = 0; i < height; i++)
row_pointers[i] = iCurImage->Data + i * iCurImage->Bps;
// Now we can go ahead and just read the whole image
png_read_image(png_ptr, row_pointers);
/* and we're done! (png_read_end() can be omitted if no processing of
* post-IDAT text/time/etc. is desired) */
//png_read_end(png_ptr, NULL);
ifree(row_pointers);
return IL_TRUE;
}
ILvoid readpng_cleanup()
{
if (png_ptr && info_ptr) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
png_ptr = NULL;
info_ptr = NULL;
}
}
//! Writes a Png file
ILboolean ilSavePng(ILconst_string FileName)
{
ILHANDLE PngFile;
ILboolean bPng = IL_FALSE;
if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
if (iFileExists(FileName)) {
ilSetError(IL_FILE_ALREADY_EXISTS);
return IL_FALSE;
}
}
PngFile = iopenw(FileName);
if (PngFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPng;
}
bPng = ilSavePngF(PngFile);
iclosew(PngFile);
return bPng;
}
//! Writes a Png to an already-opened file
ILboolean ilSavePngF(ILHANDLE File)
{
iSetOutputFile(File);
return iSavePngInternal();
}
//! Writes a Png to a memory "lump"
ILboolean ilSavePngL(ILvoid *Lump, ILuint Size)
{
iSetOutputLump(Lump, Size);
return iSavePngInternal();
}
ILvoid png_write(png_structp png_ptr, png_bytep data, png_size_t length)
{
(ILvoid)png_ptr;
iwrite(data, 1, length);
return;
}
ILvoid flush_data(png_structp png_ptr)
{
return;
}
// Internal function used to save the Png.
ILboolean iSavePngInternal()
{
png_structp png_ptr;
png_infop info_ptr;
png_text text[3];
ILenum PngType;
ILuint BitDepth, i, j;
ILubyte **RowPtr = NULL;
ILimage *Temp = NULL;
ILpal *TempPal = NULL;
//XIX alpha
ILubyte transpart[1];
ILint trans;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
/* Create and initialize the png_struct with the desired error handler
* functions. If you want to use the default stderr and longjump method,
* you can supply NULL for the last three parameters. We also check that
* the library version is compatible with the one used at compile time,
* in case we are using dynamically linked libraries. REQUIRED.
*/
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_func, png_warn_func);
if (png_ptr == NULL) {
ilSetError(IL_LIB_PNG_ERROR);
return IL_FALSE;
}
// Allocate/initialize the image information data. REQUIRED
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
ilSetError(IL_LIB_PNG_ERROR);
goto error_label;
}
/*// Set error handling. REQUIRED if you aren't supplying your own
// error handling functions in the png_create_write_struct() call.
if (setjmp(png_jmpbuf(png_ptr))) {
// If we get here, we had a problem reading the file
png_destroy_write_struct(&png_ptr, &info_ptr);
ilSetError(IL_LIB_PNG_ERROR);
return IL_FALSE;
}*/
// png_init_io(png_ptr, PngFile);
png_set_write_fn(png_ptr, NULL, png_write, flush_data);
switch (iCurImage->Type)
{
case IL_BYTE:
case IL_UNSIGNED_BYTE:
Temp = iCurImage;
BitDepth = 8;
break;
case IL_SHORT:
case IL_UNSIGNED_SHORT:
Temp = iCurImage;
BitDepth = 16;
break;
case IL_INT:
case IL_UNSIGNED_INT:
Temp = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_SHORT);
if (Temp == NULL) {
png_destroy_write_struct(&png_ptr, &info_ptr);
return IL_FALSE;
}
BitDepth = 16;
break;
default:
ilSetError(IL_INTERNAL_ERROR);
goto error_label;
}
switch (iCurImage->Format)
{
case IL_COLOUR_INDEX:
PngType = PNG_COLOR_TYPE_PALETTE;
break;
case IL_LUMINANCE:
PngType = PNG_COLOR_TYPE_GRAY;
break;
case IL_LUMINANCE_ALPHA: //added 20050328
PngType = PNG_COLOR_TYPE_GRAY_ALPHA;
break;
case IL_RGB:
case IL_BGR:
PngType = PNG_COLOR_TYPE_RGB;
break;
case IL_RGBA:
case IL_BGRA:
PngType = PNG_COLOR_TYPE_RGB_ALPHA;
break;
default:
ilSetError(IL_INTERNAL_ERROR);
goto error_label;
}
// Set the image information here. Width and height are up to 2^31,
// bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
// the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
// PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
// or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
// PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
// currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
if (iGetInt(IL_PNG_INTERLACE) == IL_TRUE) {
png_set_IHDR(png_ptr, info_ptr, iCurImage->Width, iCurImage->Height, BitDepth, PngType,
PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
}
else {
png_set_IHDR(png_ptr, info_ptr, iCurImage->Width, iCurImage->Height, BitDepth, PngType,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
}
if (iCurImage->Format == IL_COLOUR_INDEX) {
// set the palette if there is one. REQUIRED for indexed-color images.
TempPal = iConvertPal(&iCurImage->Pal, IL_PAL_RGB24);
png_set_PLTE(png_ptr, info_ptr, (png_colorp)TempPal->Palette,
ilGetInteger(IL_PALETTE_NUM_COLS));
//XIX alpha
trans=iGetInt(IL_PNG_ALPHA_INDEX);
if ( trans>=0)
{
transpart[0]=(ILubyte)trans;
png_set_tRNS(png_ptr, info_ptr, transpart, 1, 0);
}
}
/*
// optional significant bit chunk
// if we are dealing with a grayscale image then
sig_bit.gray = true_bit_depth;
// otherwise, if we are dealing with a color image then
sig_bit.red = true_red_bit_depth;
sig_bit.green = true_green_bit_depth;
sig_bit.blue = true_blue_bit_depth;
// if the image has an alpha channel then
sig_bit.alpha = true_alpha_bit_depth;
png_set_sBIT(png_ptr, info_ptr, sig_bit);*/
/* Optional gamma chunk is strongly suggested if you have any guess
* as to the correct gamma of the image.
*/
//png_set_gAMA(png_ptr, info_ptr, gamma);
// Optionally write comments into the image.
imemclear(text, sizeof(png_text) * 3);
text[0].key = "Generated by";
text[0].text = "Generated by the Developer's Image Library (DevIL)";
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
text[1].key = "Author's name";
text[1].text = iGetString(IL_PNG_AUTHNAME_STRING);
text[1].compression = PNG_TEXT_COMPRESSION_NONE;
text[2].key = "Author's comments";
text[2].text = iGetString(IL_PNG_AUTHNAME_STRING);
text[2].compression = PNG_TEXT_COMPRESSION_NONE;
png_set_text(png_ptr, info_ptr, text, 3);
// Write the file header information. REQUIRED.
png_write_info(png_ptr, info_ptr);
// Free up our user-defined text.
if (text[1].text)
ifree(text[1].text);
if (text[2].text)
ifree(text[2].text);
/* Shift the pixels up to a legal bit depth and fill in
* as appropriate to correctly scale the image.
*/
//png_set_shift(png_ptr, &sig_bit);
/* pack pixels into bytes */
//png_set_packing(png_ptr);
// swap location of alpha bytes from ARGB to RGBA
//png_set_swap_alpha(png_ptr);
// flip BGR pixels to RGB
if (iCurImage->Format == IL_BGR || iCurImage->Format == IL_BGRA)
png_set_bgr(png_ptr);
// swap bytes of 16-bit files to most significant byte first
#ifdef __LITTLE_ENDIAN__
png_set_swap(png_ptr);
#endif//__LITTLE_ENDIAN__
RowPtr = (ILubyte**)ialloc(iCurImage->Height * sizeof(ILubyte*));
if (RowPtr == NULL)
goto error_label;
if (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT) {
for (i = 0; i < iCurImage->Height; i++) {
RowPtr[i] = Temp->Data + i * Temp->Bps;
}
}
else {
j = iCurImage->Height - 1;
for (i = 0; i < iCurImage->Height; i++, j--) {
RowPtr[i] = Temp->Data + j * Temp->Bps;
}
}
// Writes the image.
png_write_image(png_ptr, RowPtr);
// It is REQUIRED to call this to finish writing the rest of the file
png_write_end(png_ptr, info_ptr);
// clean up after the write, and ifree any memory allocated
png_destroy_write_struct(&png_ptr, &info_ptr);
ifree(RowPtr);
if (Temp != iCurImage)
ilCloseImage(Temp);
ilClosePal(TempPal);
return IL_TRUE;
error_label:
png_destroy_write_struct(&png_ptr, &info_ptr);
ifree(RowPtr);
if (Temp != iCurImage)
ilCloseImage(Temp);
ilClosePal(TempPal);
return IL_FALSE;
}
#endif//IL_NO_PNG

View File

@@ -0,0 +1,682 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/21/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_pnm.c
//
// Description: Reads/writes to/from pbm/pgm/ppm formats (enough slashes? =)
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_PNM
#include "il_pnm.h"
#include <limits.h> // for maximum values
#include <ctype.h>
#include "il_manip.h"
#include "il_bits.h"
// According to the ppm specs, it's 70, but PSP
// likes to output longer lines...
#define MAX_BUFFER 180
static ILbyte LineBuffer[MAX_BUFFER];
static ILbyte SmallBuff[MAX_BUFFER];
// Can't read direct bits from a lump yet
ILboolean IsLump = IL_FALSE;
//! Checks if the file specified in FileName is a valid .pnm file.
ILboolean ilIsValidPnm(ILconst_string FileName)
{
ILHANDLE PnmFile;
ILboolean bPnm = IL_FALSE;
if ( !iCheckExtension(FileName, IL_TEXT("pbm"))
&& !iCheckExtension(FileName, IL_TEXT("pgm"))
&& !iCheckExtension(FileName, IL_TEXT("ppm"))
&& !iCheckExtension(FileName, IL_TEXT("pnm"))) {
ilSetError(IL_INVALID_EXTENSION);
return bPnm;
}
PnmFile = iopenr(FileName);
if (PnmFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPnm;
}
bPnm = ilIsValidPnmF(PnmFile);
icloser(PnmFile);
return bPnm;
}
//! Checks if the ILHANDLE contains a valid .pnm file at the current position.
ILboolean ilIsValidPnmF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iIsValidPnm();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Checks if Lump is a valid .pnm lump.
ILboolean ilIsValidPnmL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iIsValidPnm();
}
// Internal function to get the header and check it.
ILboolean iIsValidPnm()
{
char Head[2];
ILint Read;
Read = iread(Head, 1, 2);
iseek(-Read, IL_SEEK_CUR); // Go ahead and restore to previous state
if (Read != 2)
return IL_FALSE;
return iCheckPnm(Head);
}
// Internal function used to check if the HEADER is a valid .pnm header.
ILboolean iCheckPnm(char Header[2])
{
if (Header[0] != 'P')
return IL_FALSE;
switch (Header[1])
{
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
return IL_TRUE;
}
return IL_FALSE;
}
// Reads a file
ILboolean ilLoadPnm(ILconst_string FileName)
{
ILHANDLE PnmFile;
ILboolean bPnm = IL_FALSE;
PnmFile = iopenr(FileName);
if (PnmFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPnm;
}
bPnm = ilLoadPnmF(PnmFile);
icloser(PnmFile);
return bPnm;
}
// Reads an already-opened file
ILboolean ilLoadPnmF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadPnmInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
// Reads from a memory "lump"
ILboolean ilLoadPnmL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadPnmInternal();
}
// Load either a pgm or a ppm
ILboolean iLoadPnmInternal()
{
ILimage *PmImage = NULL;
PPMINFO Info;
// ILuint LineInc = 0, SmallInc = 0;
Info.Type = 0;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
// Find out what type of pgm/ppm this is
if (iGetWord() == IL_FALSE)
return IL_FALSE;
if (SmallBuff[0] != 'P') {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
if (SmallBuff[1] == '1') {
Info.Type = IL_PBM_ASCII;
}
else if (SmallBuff[1] == '2') {
Info.Type = IL_PGM_ASCII;
}
else if (SmallBuff[1] == '3') {
Info.Type = IL_PPM_ASCII;
}
else if (SmallBuff[1] == '4') {
Info.Type = IL_PBM_BINARY;
if (IsLump) {
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
}
else if (SmallBuff[1] == '5') {
Info.Type = IL_PGM_BINARY;
}
else if (SmallBuff[1] == '6') {
Info.Type = IL_PPM_BINARY;
}
else {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
// Retrieve the width and height
if (iGetWord() == IL_FALSE)
return IL_FALSE;
Info.Width = atoi((const char*)SmallBuff);
if (Info.Width == 0) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
if (iGetWord() == IL_FALSE)
return IL_FALSE;
Info.Height = atoi((const char*)SmallBuff);
if (Info.Height == 0) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
// Retrieve the maximum colour component value
if (Info.Type != IL_PBM_ASCII && Info.Type != IL_PBM_BINARY) {
if (iGetWord() == IL_FALSE)
return IL_FALSE;
if ((Info.MaxColour = atoi((const char*)SmallBuff)) == 0) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
}
else
Info.MaxColour = 1;
if (Info.Type == IL_PBM_ASCII || Info.Type == IL_PBM_BINARY ||
Info.Type == IL_PGM_ASCII || Info.Type == IL_PGM_BINARY) {
if (Info.Type == IL_PGM_ASCII) {
if (Info.MaxColour < 256)
Info.Bpp = 1;
else
Info.Bpp = 2;
}
else
Info.Bpp = 1;
}
else {
Info.Bpp = 3;
}
switch (Info.Type)
{
case IL_PBM_ASCII:
case IL_PGM_ASCII:
case IL_PPM_ASCII:
PmImage = ilReadAsciiPpm(&Info);
break;
case IL_PBM_BINARY:
PmImage = ilReadBitPbm(&Info);
break;
case IL_PGM_BINARY:
case IL_PPM_BINARY:
PmImage = ilReadBinaryPpm(&Info);
break;
default:
return IL_FALSE;
}
if (PmImage == NULL) {
iCurImage->Format = ilGetFormatBpp(iCurImage->Bpp);
ilSetError(IL_FILE_READ_ERROR);
return IL_FALSE;
}
// Is this conversion needed? Just 0's and 1's shows up as all black
if (Info.Type == IL_PBM_ASCII) {
PbmMaximize(PmImage);
}
if (Info.MaxColour > 255)
PmImage->Type = IL_UNSIGNED_SHORT;
PmImage->Origin = IL_ORIGIN_UPPER_LEFT;
if (Info.Type == IL_PBM_ASCII || Info.Type == IL_PBM_BINARY ||
Info.Type == IL_PGM_ASCII || Info.Type == IL_PGM_BINARY)
PmImage->Format = IL_LUMINANCE;
else
PmImage->Format = IL_RGB;
PmImage->Origin = IL_ORIGIN_UPPER_LEFT;
ilFixImage();
if (PmImage == NULL)
return IL_FALSE;
return IL_TRUE;
}
ILimage *ilReadAsciiPpm(PPMINFO *Info)
{
ILint LineInc = 0, SmallInc = 0, DataInc = 0, Size;
// ILint BytesRead = 0;
if (Info->MaxColour > 255)
Info->Bpp *= 2;
Size = Info->Width * Info->Height * Info->Bpp;
if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
if (Info->MaxColour > 255)
iCurImage->Type = IL_UNSIGNED_SHORT;
while (DataInc < Size) { // && !feof(File)) {
LineInc = 0;
if (iFgets((char *)LineBuffer, MAX_BUFFER) == NULL) {
//ilSetError(IL_ILLEGAL_FILE_VALUE);
//return NULL;
//return iCurImage;
break;
}
if (LineBuffer[0] == '#') { // Comment
continue;
}
while ((LineBuffer[LineInc] != NUL) && (LineBuffer[LineInc] != '\n')) {
SmallInc = 0;
while (!isalnum(LineBuffer[LineInc])) { // Skip any whitespace
LineInc++;
}
while (isalnum(LineBuffer[LineInc])) {
SmallBuff[SmallInc] = LineBuffer[LineInc];
SmallInc++;
LineInc++;
}
SmallBuff[SmallInc] = NUL;
iCurImage->Data[DataInc] = atoi((const char*)SmallBuff); // Convert from string to colour
// PSP likes to put whitespace at the end of lines...figures. =/
while (!isalnum(LineBuffer[LineInc]) && LineBuffer[LineInc] != NUL) { // Skip any whitespace
LineInc++;
}
// We should set some kind of state flag that enables this
//Image->Data[DataInc] *= (ILubyte)(255 / Info->MaxColour); // Scales to 0-255
if (Info->MaxColour > 255)
DataInc++;
DataInc++;
}
}
// If we read less than what we should have...
if (DataInc < Size) {
//ilCloseImage(iCurImage);
//ilSetCurImage(NULL);
ilSetError(IL_ILLEGAL_FILE_VALUE);
return NULL;
}
return iCurImage;
}
ILimage *ilReadBinaryPpm(PPMINFO *Info)
{
ILuint Size;
Size = Info->Width * Info->Height * Info->Bpp;
if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
if (iread(iCurImage->Data, 1, Size) != Size)
return NULL;
return iCurImage;
}
ILimage *ilReadBitPbm(PPMINFO *Info)
{
ILuint m, j, x, CurrByte;
if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
x = 0;
for (j = 0; j < iCurImage->SizeOfData;) {
CurrByte = igetc();
for (m = 128; m > 0 && x < Info->Width; m >>= 1, ++x, ++j) {
iCurImage->Data[j] = (CurrByte & m)?255:0;
}
if (x == Info->Width)
x = 0;
}
return iCurImage;
}
ILboolean iGetWord(ILvoid)
{
ILint WordPos = 0;
ILint Current = 0;
ILboolean Started = IL_FALSE;
ILboolean Looping = IL_TRUE;
if (ieof())
return IL_FALSE;
while (Looping) {
while ((Current = igetc()) != IL_EOF && Current != '\n' && Current != '#' && Current != ' ') {
if (Current == IL_EOF)
return IL_FALSE;
if (!isalnum(Current)) {
if (Started) {
Looping = IL_FALSE;
break;
}
continue;
}
if (Looping)
SmallBuff[WordPos++] = Current;
}
SmallBuff[WordPos] = NUL;
if (!Looping)
break;
if (Current == '#') { // '#' is a comment...read until end of line
while ((Current = igetc()) != IL_EOF && Current != '\n');
}
// Get rid of any erroneous spaces
while ((Current = igetc()) != IL_EOF) {
if (Current != ' ')
break;
}
iseek(-1, IL_SEEK_CUR);
if (WordPos > 0)
break;
}
if (Current == -1 || WordPos == 0) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
return IL_TRUE;
}
ILstring FName;
//! Writes a Pnm file
ILboolean ilSavePnm(ILconst_string FileName)
{
ILHANDLE PnmFile;
ILboolean bPnm = IL_FALSE;
FName = (ILstring)FileName;
if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
if (iFileExists(FileName)) {
ilSetError(IL_FILE_ALREADY_EXISTS);
return IL_FALSE;
}
}
PnmFile = iopenw(FileName);
if (PnmFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPnm;
}
bPnm = ilSavePnmF(PnmFile);
iclosew(PnmFile);
return bPnm;
}
//! Writes a Pnm to an already-opened file
ILboolean ilSavePnmF(ILHANDLE File)
{
iSetOutputFile(File);
return iSavePnmInternal();
}
//! Writes a Pnm to a memory "lump"
ILboolean ilSavePnmL(ILvoid *Lump, ILuint Size)
{
FName = NULL;
iSetOutputLump(Lump, Size);
return iSavePnmInternal();
}
// Internal function used to save the Pnm.
ILboolean iSavePnmInternal()
{
ILuint Bpp, MaxVal = UCHAR_MAX, i = 0, j, k;
ILenum Type = 0;
ILuint LinePos = 0; // Cannot exceed 70 for pnm's!
ILboolean Binary;
ILimage *TempImage;
ILubyte *TempData;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (iCheckExtension(FName, IL_TEXT("pbm")))
Type = IL_PBM_ASCII;
else if (iCheckExtension(FName, IL_TEXT("pgm")))
Type = IL_PGM_ASCII;
else if (iCheckExtension(FName, IL_TEXT("ppm")))
Type = IL_PPM_ASCII;
else
Type = IL_PPM_ASCII;
/*if (!Type) {
ilSetError(IL_INVALID_EXTENSION);
return IL_FALSE;
}*/
if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) {
Type += 3;
Binary = IL_TRUE;
}
else {
Binary = IL_FALSE;
}
if (iCurImage->Type == IL_UNSIGNED_BYTE) {
MaxVal = UCHAR_MAX;
}
else if (iCurImage->Type == IL_UNSIGNED_SHORT) {
MaxVal = USHRT_MAX;
}
else {
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
if (MaxVal > UCHAR_MAX && Type >= IL_PBM_BINARY) { // binary cannot be higher than 255
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
switch (Type)
{
case IL_PBM_ASCII:
Bpp = 1;
ilprintf("P1\n");
TempImage = iConvertImage(iCurImage, IL_LUMINANCE, IL_UNSIGNED_BYTE);
break;
//case IL_PBM_BINARY: // Don't want to mess with saving bits just yet...
//Bpp = 1;
//ilprintf("P4\n");
//break;
case IL_PBM_BINARY:
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
case IL_PGM_ASCII:
Bpp = 1;
ilprintf("P2\n");
TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE);
break;
case IL_PGM_BINARY:
Bpp = 1;
ilprintf("P5\n");
TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE);
break;
case IL_PPM_ASCII:
Bpp = 3;
ilprintf("P3\n");
TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
break;
case IL_PPM_BINARY:
Bpp = 3;
ilprintf("P6\n");
TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
break;
default:
ilSetError(IL_INTERNAL_ERROR);
return IL_FALSE;
}
if (TempImage == NULL)
return IL_FALSE;
if (Bpp != TempImage->Bpp) {
ilSetError(IL_INVALID_CONVERSION);
return IL_FALSE;
}
if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) {
TempData = iGetFlipped(TempImage);
if (TempData == NULL) {
ilCloseImage(TempImage);
return IL_FALSE;
}
}
else {
TempData = TempImage->Data;
}
ilprintf("%d %d\n", TempImage->Width, TempImage->Height);
if (Type != IL_PBM_BINARY && Type != IL_PBM_ASCII) // not needed for .pbm's (only 0 and 1)
ilprintf("%d\n", MaxVal);
while (i < TempImage->SizeOfPlane) {
for (j = 0; j < Bpp; j++) {
if (Binary) {
if (Type == IL_PBM_BINARY) {
iputc((ILubyte)(TempData[i] > 127 ? 1 : 0));
}
else {
iputc(TempData[i]);
}
}
else {
if (TempImage->Type == IL_UNSIGNED_BYTE)
k = TempData[i];
else // IL_UNSIGNED_SHORT
k = *((ILushort*)TempData + i);
if (Type == IL_PBM_ASCII) {
LinePos += ilprintf("%d ", TempData[i] > 127 ? 1 : 0);
}
else {
LinePos += ilprintf("%d ", TempData[i]);
}
}
if (TempImage->Type == IL_UNSIGNED_SHORT)
i++;
i++;
}
if (LinePos > 65) { // Just a good number =]
ilprintf("\n");
LinePos = 0;
}
}
if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT)
ifree(TempData);
ilCloseImage(TempImage);
return IL_TRUE;
}
// Converts a .pbm to something viewable.
ILvoid PbmMaximize(ILimage *Image)
{
ILuint i = 0;
for (i = 0; i < Image->SizeOfPlane; i++)
if (Image->Data[i] == 1)
Image->Data[i] = 0xFF;
return;
}
#endif//IL_NO_PNM

View File

@@ -0,0 +1,169 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 01/23/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_profiles.c
//
// Description: Colour profile handler
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_LCMS
#ifdef PACKAGE_NAME
#define IL_PACKAGE_NAME PACKAGE_NAME;
#undef PACKAGE_NAME
#endif
#ifndef _WIN32
#define NON_WINDOWS 1
#ifndef LCMS_NODIRINCLUDE
#include <lcms.h>
#else
#include <lcms/lcms.h>
#endif
#else
// #ifndef IL_DEBUG
// pragma comment(lib, "lcms108.lib")
// #else
// pragma comment(lib, "debug/lcms108.lib")
// #endif
#include <lcms.h>
#endif//_WIN32
#ifdef PACKAGE_NAME
#undef PACKAGE_NAME
#endif
#ifdef IL_PACKAGE_NAME
#define PACKAGE_NAME IL_PACKAGE_NAME
#undef IL_PACKAGE_NAME
#endif
#endif//IL_NO_LCMS
ILboolean ILAPIENTRY ilApplyProfile(ILstring InProfile, ILstring OutProfile)
{
#ifndef IL_NO_LCMS
cmsHPROFILE hInProfile, hOutProfile;
cmsHTRANSFORM hTransform;
ILubyte *Temp;
ILint Format=0;
#ifdef _UNICODE
char AnsiName[512];
#endif//_UNICODE
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
switch (iCurImage->Type)
{
case IL_BYTE:
case IL_UNSIGNED_BYTE:
switch (iCurImage->Format)
{
case IL_LUMINANCE:
Format = TYPE_GRAY_8;
break;
case IL_RGB:
Format = TYPE_RGB_8;
break;
case IL_BGR:
Format = TYPE_BGR_8;
break;
case IL_RGBA:
Format = TYPE_RGBA_8;
break;
case IL_BGRA:
Format = TYPE_BGRA_8;
break;
default:
ilSetError(IL_INTERNAL_ERROR);
return IL_FALSE;
}
break;
case IL_SHORT:
case IL_UNSIGNED_SHORT:
switch (iCurImage->Format)
{
case IL_LUMINANCE:
Format = TYPE_GRAY_16;
break;
case IL_RGB:
Format = TYPE_RGB_16;
break;
case IL_BGR:
Format = TYPE_BGR_16;
break;
case IL_RGBA:
Format = TYPE_RGBA_16;
break;
case IL_BGRA:
Format = TYPE_BGRA_16;
break;
default:
ilSetError(IL_INTERNAL_ERROR);
return IL_FALSE;
}
break;
// These aren't supported right now.
case IL_INT:
case IL_UNSIGNED_INT:
case IL_FLOAT:
case IL_DOUBLE:
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (InProfile == NULL) {
if (!iCurImage->Profile || !iCurImage->ProfileSize) {
ilSetError(IL_INVALID_PARAM);
return IL_FALSE;
}
hInProfile = iCurImage->Profile;
}
else {
#ifndef _UNICODE
hInProfile = cmsOpenProfileFromFile(InProfile, "r");
#else
wcstombs(AnsiName, InProfile, 512);
hInProfile = cmsOpenProfileFromFile(AnsiName, "r");
#endif//_UNICODE
}
#ifndef _UNICODE
hOutProfile = cmsOpenProfileFromFile(OutProfile, "r");
#else
wcstombs(AnsiName, OutProfile, 512);
hOutProfile = cmsOpenProfileFromFile(AnsiName, "r");
#endif//_UNICODE
hTransform = cmsCreateTransform(hInProfile, Format, hOutProfile, Format, INTENT_PERCEPTUAL, 0);
Temp = (ILubyte*)ialloc(iCurImage->SizeOfData);
if (Temp == NULL) {
return IL_FALSE;
}
cmsDoTransform(hTransform, iCurImage->Data, Temp, iCurImage->SizeOfData / 3);
ifree(iCurImage->Data);
iCurImage->Data = Temp;
cmsDeleteTransform(hTransform);
if (InProfile != NULL)
cmsCloseProfile(hInProfile);
cmsCloseProfile(hOutProfile);
#endif//IL_NO_LCMS
return IL_TRUE;
}

View File

@@ -0,0 +1,935 @@
// Information about the .psd format was taken from Adobe's PhotoShop SDK at
// http://partners.adobe.com/asn/developer/gapsdk/PhotoshopSDK.html
// Information about the Packbits compression scheme was found at
// http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf
#include "il_internal.h"
#ifndef IL_NO_PSD
#include "il_psd.h"
//! Checks if the file specified in FileName is a valid Psd file.
ILboolean ilIsValidPsd(ILconst_string FileName)
{
ILHANDLE PsdFile;
ILboolean bPsd = IL_FALSE;
if (!iCheckExtension(FileName, IL_TEXT("psd")) &&
!iCheckExtension(FileName, IL_TEXT("pdd"))) {
ilSetError(IL_INVALID_EXTENSION);
return bPsd;
}
PsdFile = iopenr(FileName);
if (PsdFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPsd;
}
bPsd = ilIsValidPsdF(PsdFile);
icloser(PsdFile);
return bPsd;
}
//! Checks if the ILHANDLE contains a valid Psd file at the current position.
ILboolean ilIsValidPsdF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iIsValidPsd();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Checks if Lump is a valid Psd lump.
ILboolean ilIsValidPsdL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iIsValidPsd();
}
// Internal function used to get the Psd header from the current file.
ILboolean iGetPsdHead(PSDHEAD *Header)
{
iread(Header->Signature, 1, 4);
Header->Version = GetBigUShort();
iread(Header->Reserved, 1, 6);
Header->Channels = GetBigUShort();
Header->Height = GetBigUInt();
Header->Width = GetBigUInt();
Header->Depth = GetBigUShort();
Header->Mode = GetBigUShort();
return IL_TRUE;
}
// Internal function to get the header and check it.
ILboolean iIsValidPsd()
{
PSDHEAD Head;
iGetPsdHead(&Head);
iseek(-(ILint)sizeof(PSDHEAD), IL_SEEK_CUR);
return iCheckPsd(&Head);
}
// Internal function used to check if the HEADER is a valid Psd header.
ILboolean iCheckPsd(PSDHEAD *Header)
{
ILuint i;
if (strncmp((char*)Header->Signature, "8BPS", 4))
return IL_FALSE;
if (Header->Version != 1)
return IL_FALSE;
for (i = 0; i < 6; i++) {
if (Header->Reserved[i] != 0)
return IL_FALSE;
}
if (Header->Channels < 1 || Header->Channels > 24)
return IL_FALSE;
if (Header->Height < 1 || Header->Width < 1)
return IL_FALSE;
if (Header->Depth != 1 && Header->Depth != 8 && Header->Depth != 16)
return IL_FALSE;
return IL_TRUE;
}
//! Reads a Psd file
ILboolean ilLoadPsd(ILconst_string FileName)
{
ILHANDLE PsdFile;
ILboolean bPsd = IL_FALSE;
PsdFile = iopenr(FileName);
if (PsdFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPsd;
}
bPsd = ilLoadPsdF(PsdFile);
icloser(PsdFile);
return bPsd;
}
//! Reads an already-opened Psd file
ILboolean ilLoadPsdF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadPsdInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a Psd
ILboolean ilLoadPsdL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadPsdInternal();
}
// Internal function used to load the Psd.
ILboolean iLoadPsdInternal()
{
PSDHEAD Header;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
iGetPsdHead(&Header);
if (!iCheckPsd(&Header)) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
if (!ReadPsd(&Header))
return IL_FALSE;
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
ilFixImage();
return IL_TRUE;
}
ILboolean ReadPsd(PSDHEAD *Head)
{
switch (Head->Mode)
{
case 1: // Greyscale
return ReadGrey(Head);
case 2: // Indexed
return ReadIndexed(Head);
case 3: // RGB
return ReadRGB(Head);
case 4: // CMYK
return ReadCMYK(Head);
}
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
ILboolean ReadGrey(PSDHEAD *Head)
{
ILuint ColorMode, ResourceSize, MiscInfo;
ILushort Compressed;
ILenum Type;
ILubyte *Resources = NULL;
ColorMode = GetBigUInt(); // Skip over the 'color mode data section'
iseek(ColorMode, IL_SEEK_CUR);
ResourceSize = GetBigUInt(); // Read the 'image resources section'
Resources = (ILubyte*)ialloc(ResourceSize);
if (Resources == NULL) {
return IL_FALSE;
}
if (iread(Resources, 1, ResourceSize) != ResourceSize)
goto cleanup_error;
MiscInfo = GetBigUInt();
iseek(MiscInfo, IL_SEEK_CUR);
Compressed = GetBigUShort();
ChannelNum = Head->Channels;
Head->Channels = 1; // Temporary to read only one channel...some greyscale .psd files have 2.
if (Head->Channels != 1) {
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
switch (Head->Depth)
{
case 8:
Type = IL_UNSIGNED_BYTE;
break;
case 16:
Type = IL_UNSIGNED_SHORT;
break;
default:
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
if (!ilTexImage(Head->Width, Head->Height, 1, 1, IL_LUMINANCE, Type, NULL))
goto cleanup_error;
if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed))
goto cleanup_error;
if (!ParseResources(ResourceSize, Resources))
goto cleanup_error;
ifree(Resources);
return IL_TRUE;
cleanup_error:
ifree(Resources);
return IL_FALSE;
}
ILboolean ReadIndexed(PSDHEAD *Head)
{
ILuint ColorMode, ResourceSize, MiscInfo, i, j, NumEnt;
ILushort Compressed;
ILubyte *Palette = NULL, *Resources = NULL;
ColorMode = GetBigUInt(); // Skip over the 'color mode data section'
if (ColorMode % 3 != 0) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
Palette = (ILubyte*)ialloc(ColorMode);
if (Palette == NULL)
return IL_FALSE;
if (iread(Palette, 1, ColorMode) != ColorMode)
goto cleanup_error;
ResourceSize = GetBigUInt(); // Read the 'image resources section'
Resources = (ILubyte*)ialloc(ResourceSize);
if (Resources == NULL) {
return IL_FALSE;
}
if (iread(Resources, 1, ResourceSize) != ResourceSize)
goto cleanup_error;
MiscInfo = GetBigUInt();
if (ieof())
goto cleanup_error;
iseek(MiscInfo, IL_SEEK_CUR);
Compressed = GetBigUShort();
if (ieof())
goto cleanup_error;
if (Head->Channels != 1 || Head->Depth != 8) {
ilSetError(IL_FORMAT_NOT_SUPPORTED);
goto cleanup_error;
}
ChannelNum = Head->Channels;
if (!ilTexImage(Head->Width, Head->Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL))
goto cleanup_error;
iCurImage->Pal.Palette = (ILubyte*)ialloc(ColorMode);
if (iCurImage->Pal.Palette == NULL) {
goto cleanup_error;
}
iCurImage->Pal.PalSize = ColorMode;
iCurImage->Pal.PalType = IL_PAL_RGB24;
NumEnt = iCurImage->Pal.PalSize / 3;
for (i = 0, j = 0; i < iCurImage->Pal.PalSize; i += 3, j++) {
iCurImage->Pal.Palette[i ] = Palette[j];
iCurImage->Pal.Palette[i+1] = Palette[j+NumEnt];
iCurImage->Pal.Palette[i+2] = Palette[j+NumEnt*2];
}
ifree(Palette);
Palette = NULL;
if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed))
goto cleanup_error;
ParseResources(ResourceSize, Resources);
ifree(Resources);
Resources = NULL;
return IL_TRUE;
cleanup_error:
ifree(Palette);
ifree(Resources);
return IL_FALSE;
}
ILboolean ReadRGB(PSDHEAD *Head)
{
ILuint ColorMode, ResourceSize, MiscInfo;
ILushort Compressed;
ILenum Format, Type;
ILubyte *Resources = NULL;
ColorMode = GetBigUInt(); // Skip over the 'color mode data section'
iseek(ColorMode, IL_SEEK_CUR);
ResourceSize = GetBigUInt(); // Read the 'image resources section'
Resources = (ILubyte*)ialloc(ResourceSize);
if (Resources == NULL)
return IL_FALSE;
if (iread(Resources, 1, ResourceSize) != ResourceSize)
goto cleanup_error;
MiscInfo = GetBigUInt();
iseek(MiscInfo, IL_SEEK_CUR);
Compressed = GetBigUShort();
ChannelNum = Head->Channels;
switch (Head->Channels)
{
case 3:
Format = IL_RGB;
break;
case 4:
Format = IL_RGBA;
break;
default:
// ilSetError(IL_FORMAT_NOT_SUPPORTED);
// return IL_FALSE;
//drop additional channels. This is not the 100% correct
//way of loading the image, but it is better than loading
//the image not at all.
Format = IL_RGBA;
Head->Channels = 4;
}
switch (Head->Depth)
{
case 8:
Type = IL_UNSIGNED_BYTE;
break;
case 16:
Type = IL_UNSIGNED_SHORT;
break;
default:
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
if (!ilTexImage(Head->Width, Head->Height, 1, (ILubyte)Head->Channels, Format, Type, NULL))
goto cleanup_error;
if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed))
goto cleanup_error;
if (!ParseResources(ResourceSize, Resources))
goto cleanup_error;
ifree(Resources);
return IL_TRUE;
cleanup_error:
ifree(Resources);
return IL_FALSE;
}
ILboolean ReadCMYK(PSDHEAD *Head)
{
ILuint ColorMode, ResourceSize, MiscInfo, Size, i, j;
ILushort Compressed;
ILenum Format, Type;
ILubyte *Resources = NULL, *KChannel = NULL;
ColorMode = GetBigUInt(); // Skip over the 'color mode data section'
iseek(ColorMode, IL_SEEK_CUR);
ResourceSize = GetBigUInt(); // Read the 'image resources section'
Resources = (ILubyte*)ialloc(ResourceSize);
if (Resources == NULL) {
return IL_FALSE;
}
if (iread(Resources, 1, ResourceSize) != ResourceSize)
goto cleanup_error;
MiscInfo = GetBigUInt();
iseek(MiscInfo, IL_SEEK_CUR);
Compressed = GetBigUShort();
switch (Head->Channels)
{
case 4:
Format = IL_RGB;
ChannelNum = 4;
Head->Channels = 3;
break;
case 5:
Format = IL_RGBA;
ChannelNum = 5;
Head->Channels = 4;
break;
default:
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
switch (Head->Depth)
{
case 8:
Type = IL_UNSIGNED_BYTE;
break;
case 16:
Type = IL_UNSIGNED_SHORT;
break;
default:
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
if (!ilTexImage(Head->Width, Head->Height, 1, (ILubyte)Head->Channels, Format, Type, NULL))
goto cleanup_error;
if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed))
goto cleanup_error;
Size = iCurImage->Bpc * iCurImage->Width * iCurImage->Height;
KChannel = (ILubyte*)ialloc(Size);
if (KChannel == NULL)
goto cleanup_error;
if (!GetSingleChannel(Head, KChannel, (ILboolean)Compressed))
goto cleanup_error;
if (Format == IL_RGB) {
for (i = 0, j = 0; i < iCurImage->SizeOfData; i += 3, j++) {
iCurImage->Data[i ] = (iCurImage->Data[i ] * KChannel[j]) >> 8;
iCurImage->Data[i+1] = (iCurImage->Data[i+1] * KChannel[j]) >> 8;
iCurImage->Data[i+2] = (iCurImage->Data[i+2] * KChannel[j]) >> 8;
}
}
else { // IL_RGBA
// The KChannel array really holds the alpha channel on this one.
for (i = 0, j = 0; i < iCurImage->SizeOfData; i += 4, j++) {
iCurImage->Data[i ] = (iCurImage->Data[i ] * iCurImage->Data[i+3]) >> 8;
iCurImage->Data[i+1] = (iCurImage->Data[i+1] * iCurImage->Data[i+3]) >> 8;
iCurImage->Data[i+2] = (iCurImage->Data[i+2] * iCurImage->Data[i+3]) >> 8;
iCurImage->Data[i+3] = KChannel[j]; // Swap 'K' with alpha channel.
}
}
if (!ParseResources(ResourceSize, Resources))
goto cleanup_error;
ifree(Resources);
ifree(KChannel);
return IL_TRUE;
cleanup_error:
ifree(Resources);
ifree(KChannel);
return IL_FALSE;
}
ILuint *GetCompChanLen(PSDHEAD *Head)
{
ILushort *RleTable;
ILuint *ChanLen, c, i, j;
RleTable = (ILushort*)ialloc(Head->Height * ChannelNum * sizeof(ILushort));
ChanLen = (ILuint*)ialloc(ChannelNum * sizeof(ILuint));
if (RleTable == NULL || ChanLen == NULL) {
return NULL;
}
if (iread(RleTable, sizeof(ILushort), Head->Height * ChannelNum) != Head->Height * ChannelNum) {
ifree(RleTable);
ifree(ChanLen);
return NULL;
}
#ifdef __LITTLE_ENDIAN__
for (i = 0; i < Head->Height * ChannelNum; i++) {
iSwapUShort(&RleTable[i]);
}
#endif
imemclear(ChanLen, ChannelNum * sizeof(ILuint));
for (c = 0; c < ChannelNum; c++) {
j = c * Head->Height;
for (i = 0; i < Head->Height; i++) {
ChanLen[c] += RleTable[i + j];
}
}
ifree(RleTable);
return ChanLen;
}
ILboolean PsdGetData(PSDHEAD *Head, ILvoid *Buffer, ILboolean Compressed)
{
ILuint c, x, y, i, Size;
ILubyte *Channel = NULL;
ILushort *ShortPtr;
ILbyte HeadByte;
ILint Run;
ILuint *ChanLen = NULL;
ILboolean PreCache = IL_FALSE;
Channel = (ILubyte*)ialloc(Head->Width * Head->Height * iCurImage->Bpc);
if (Channel == NULL) {
return IL_FALSE;
}
ShortPtr = (ILushort*)Channel;
// @TODO: Add support for this in, though I have yet to run across a .psd
// file that uses this.
if (Compressed && iCurImage->Type == IL_UNSIGNED_SHORT) {
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
if (!Compressed) {
if (iCurImage->Bpc == 1) {
for (c = 0; c < Head->Channels; c++) {
i = 0;
if (iread(Channel, Head->Width * Head->Height, 1) != 1) {
ifree(Channel);
return IL_FALSE;
}
for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) {
for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) {
iCurImage->Data[y + x + c] = Channel[i];
}
}
}
}
else { // iCurImage->Bpc == 2
for (c = 0; c < Head->Channels; c++) {
i = 0;
if (iread(Channel, Head->Width * Head->Height * 2, 1) != 1) {
ifree(Channel);
return IL_FALSE;
}
iCurImage->Bps /= 2;
for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) {
for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) {
#ifndef WORDS_BIGENDIAN
iSwapUShort(ShortPtr+i);
#endif
((ILushort*)iCurImage->Data)[y + x + c] = ShortPtr[i];
}
}
iCurImage->Bps *= 2;
}
}
}
else {
ChanLen = GetCompChanLen(Head);
if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
PreCache = IL_TRUE;
Size = Head->Width * Head->Height;
for (c = 0; c < Head->Channels; c++) {
if (PreCache)
iPreCache(ChanLen[c]);
for (i = 0; i < Size; ) {
HeadByte = igetc();
if (HeadByte >= 0) { // && HeadByte <= 127
if (i + HeadByte > Size)
goto file_corrupt;
if (iread(Channel + i, HeadByte + 1, 1) != 1)
goto file_read_error;
i += HeadByte + 1;
}
if (HeadByte >= -127 && HeadByte <= -1) {
Run = igetc();
if (Run == IL_EOF)
goto file_read_error;
if (i + (-HeadByte + 1) > Size)
goto file_corrupt;
memset(Channel + i, Run, -HeadByte + 1);
i += -HeadByte + 1;
}
if (HeadByte == -128)
{ } // Noop
}
if (PreCache)
iUnCache();
i = 0;
for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) {
for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) {
iCurImage->Data[y + x + c] = Channel[i];
}
}
}
ifree(ChanLen);
}
ifree(Channel);
return IL_TRUE;
file_corrupt:
ifree(ChanLen);
ifree(Channel);
if (PreCache)
iUnCache();
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
file_read_error:
ifree(ChanLen);
ifree(Channel);
if (PreCache)
iUnCache();
return IL_FALSE;
}
ILboolean ParseResources(ILuint ResourceSize, ILubyte *Resources)
{
ILushort ID;
ILubyte NameLen;
ILuint Size;
if (Resources == NULL) {
ilSetError(IL_INTERNAL_ERROR);
return IL_FALSE;
}
while (ResourceSize) {
if (strncmp("8BIM", (const char*)Resources, 4)) {
//return IL_FALSE;
return IL_TRUE; // 05-30-2002: May not necessarily mean corrupt data...
}
Resources += 4;
ID = *((ILushort*)Resources);
BigUShort(&ID);
Resources += 2;
NameLen = *Resources++;
// NameLen + the byte it occupies must be padded to an even number, so NameLen must be odd.
NameLen = NameLen + (NameLen & 1 ? 0 : 1);
Resources += NameLen;
// Get the resource data size.
Size = *((ILuint*)Resources);
BigUInt(&Size);
Resources += 4;
ResourceSize -= (4 + 2 + 1 + NameLen);
switch (ID)
{
case 0x040F: // ICC Profile
iCurImage->Profile = (ILubyte*)ialloc(Size);
if (iCurImage->Profile == NULL) {
return IL_FALSE;
}
memcpy(iCurImage->Profile, Resources, Size);
iCurImage->ProfileSize = Size;
break;
default:
break;
}
if (Size & 1) // Must be an even number.
Size++;
ResourceSize -= Size;
Resources += Size;
}
return IL_TRUE;
}
ILboolean GetSingleChannel(PSDHEAD *Head, ILubyte *Buffer, ILboolean Compressed)
{
ILuint i;
ILushort *ShortPtr;
ILbyte HeadByte;
ILint Run;
ShortPtr = (ILushort*)Buffer;
if (!Compressed) {
if (iCurImage->Bpc == 1) {
if (iread(Buffer, Head->Width * Head->Height, 1) != 1)
return IL_FALSE;
}
else { // iCurImage->Bpc == 2
if (iread(Buffer, Head->Width * Head->Height * 2, 1) != 1)
return IL_FALSE;
}
}
else {
for (i = 0; i < Head->Width * Head->Height; ) {
HeadByte = igetc();
if (HeadByte >= 0) { // && HeadByte <= 127
if (iread(Buffer + i, HeadByte + 1, 1) != 1)
return IL_FALSE;
i += HeadByte + 1;
}
if (HeadByte >= -127 && HeadByte <= -1) {
Run = igetc();
if (Run == IL_EOF)
return IL_FALSE;
memset(Buffer + i, Run, -HeadByte + 1);
i += -HeadByte + 1;
}
if (HeadByte == -128)
{ } // Noop
}
}
return IL_TRUE;
}
//! Writes a Psd file
ILboolean ilSavePsd(ILconst_string FileName)
{
ILHANDLE PsdFile;
ILboolean bPsd = IL_FALSE;
if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
if (iFileExists(FileName)) {
ilSetError(IL_FILE_ALREADY_EXISTS);
return IL_FALSE;
}
}
PsdFile = iopenw(FileName);
if (PsdFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPsd;
}
bPsd = ilSavePsdF(PsdFile);
iclosew(PsdFile);
return bPsd;
}
//! Writes a Psd to an already-opened file
ILboolean ilSavePsdF(ILHANDLE File)
{
iSetOutputFile(File);
return iSavePsdInternal();
}
//! Writes a Psd to a memory "lump"
ILboolean ilSavePsdL(ILvoid *Lump, ILuint Size)
{
iSetOutputLump(Lump, Size);
return iSavePsdInternal();
}
// Internal function used to save the Psd.
ILboolean iSavePsdInternal()
{
ILubyte *Signature = (ILubyte*)"8BPS";
ILimage *TempImage;
ILpal *TempPal;
ILuint c, i;
ILubyte *TempData;
ILushort *ShortPtr;
ILenum Format, Type;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
Format = iCurImage->Format;
Type = iCurImage->Type;
// All of these comprise the actual signature.
iwrite(Signature, 1, 4);
SaveBigShort(1);
SaveBigInt(0);
SaveBigShort(0);
SaveBigShort(iCurImage->Bpp);
SaveBigInt(iCurImage->Height);
SaveBigInt(iCurImage->Width);
if (iCurImage->Bpc > 2)
Type = IL_UNSIGNED_SHORT;
if (iCurImage->Format == IL_BGR)
Format = IL_RGB;
else if (iCurImage->Format == IL_BGRA)
Format = IL_RGBA;
if (Format != iCurImage->Format || Type != iCurImage->Type) {
TempImage = iConvertImage(iCurImage, Format, Type);
if (TempImage == NULL)
return IL_FALSE;
}
else {
TempImage = iCurImage;
}
SaveBigShort((ILushort)(TempImage->Bpc * 8));
// @TODO: Put the other formats here.
switch (TempImage->Format)
{
case IL_COLOUR_INDEX:
SaveBigShort(2);
break;
case IL_LUMINANCE:
SaveBigShort(1);
break;
case IL_RGB:
case IL_RGBA:
SaveBigShort(3);
break;
default:
ilSetError(IL_INTERNAL_ERROR);
return IL_FALSE;
}
if (TempImage->Format == IL_COLOUR_INDEX) {
// @TODO: We're currently making a potentially fatal assumption that
// iConvertImage was not called if the format is IL_COLOUR_INDEX.
TempPal = iConvertPal(&TempImage->Pal, IL_PAL_RGB24);
if (TempPal == NULL)
return IL_FALSE;
SaveBigInt(768);
// Have to save the palette in a planar format.
for (c = 0; c < 3; c++) {
for (i = c; i < TempPal->PalSize; i += 3) {
iputc(TempPal->Palette[i]);
}
}
ifree(TempPal->Palette);
}
else {
SaveBigInt(0); // No colour mode data.
}
SaveBigInt(0); // No image resources.
SaveBigInt(0); // No layer information.
SaveBigShort(0); // Raw data, no compression.
// @TODO: Add RLE compression.
if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) {
TempData = iGetFlipped(TempImage);
if (TempData == NULL) {
ilCloseImage(TempImage);
return IL_FALSE;
}
}
else {
TempData = TempImage->Data;
}
if (TempImage->Bpc == 1) {
for (c = 0; c < TempImage->Bpp; c++) {
for (i = c; i < TempImage->SizeOfPlane; i += TempImage->Bpp) {
iputc(TempData[i]);
}
}
}
else { // TempImage->Bpc == 2
ShortPtr = (ILushort*)TempData;
TempImage->SizeOfPlane /= 2;
for (c = 0; c < TempImage->Bpp; c++) {
for (i = c; i < TempImage->SizeOfPlane; i += TempImage->Bpp) {
SaveBigUShort(ShortPtr[i]);
}
}
TempImage->SizeOfPlane *= 2;
}
if (TempData != TempImage->Data)
ifree(TempData);
if (TempImage != iCurImage)
ilCloseImage(TempImage);
return IL_TRUE;
}
#endif//IL_NO_PSD

View File

@@ -0,0 +1,713 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/04/2002 <--Y2K Compliant! =]
//
// 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 ILvoid *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 ILvoid *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();
ilFixImage();
return IL_TRUE;
}
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;
// 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

View File

@@ -0,0 +1,120 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/26/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_pxr.c
//
// Description: Reads from a Pxrar (.pxr) file.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_PXR
#include "il_manip.h"
#include "il_endian.h"
#ifdef _MSC_VER
#pragma pack(push, pxr_struct, 1)
#endif
typedef struct PIXHEAD
{
ILushort Signature;
ILubyte Reserved1[413];
ILushort Height;
ILushort Width;
ILubyte Reserved2[4];
ILubyte BppInfo;
ILubyte Reserved3[598];
} IL_PACKSTRUCT PIXHEAD;
#ifdef _MSC_VER
#pragma pack(pop, pxr_struct)
#endif
ILboolean iLoadPxrInternal(ILvoid);
//! Reads a Pxr file
ILboolean ilLoadPxr(ILconst_string FileName)
{
ILHANDLE PxrFile;
ILboolean bPxr = IL_FALSE;
PxrFile = iopenr(FileName);
if (PxrFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bPxr;
}
bPxr = ilLoadPxrF(PxrFile);
icloser(PxrFile);
return bPxr;
}
//! Reads an already-opened Pxr file
ILboolean ilLoadPxrF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadPxrInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a Pxr
ILboolean ilLoadPxrL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadPxrInternal();
}
// Internal function used to load the Pxr.
ILboolean iLoadPxrInternal()
{
ILushort Width, Height;
ILubyte Bpp;
Width = sizeof(PIXHEAD);
iseek(416, IL_SEEK_SET);
Height = GetLittleUShort();
Width = GetLittleUShort();
iseek(424, IL_SEEK_SET);
Bpp = igetc();
switch (Bpp)
{
case 0x08:
ilTexImage(Width, Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL);
break;
case 0x0E:
ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL);
break;
case 0x0F:
ilTexImage(Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL);
break;
default:
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
iseek(1024, IL_SEEK_SET);
iread(iCurImage->Data, 1, iCurImage->SizeOfData);
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
return IL_TRUE;
}
#endif//IL_NO_PXR

View File

@@ -0,0 +1,640 @@
//-----------------------------------------------------------------------
// Color Quantization Demo
//
// Author: Roman Podobedov
// Email: romka@ut.ee
// Romka Graphics: www.ut.ee/~romka
//
// Also in this file implemented Wu's Color Quantizer algorithm (v. 2)
// For details see Graphics Gems vol. II, pp. 126-133
//
// Wu's Color Quantizer Algorithm:
// Author: Xiaolin Wu
// Dept. of Computer Science
// Univ. of Western Ontario
// London, Ontario N6A 5B7
// wu@csd.uwo.ca
// http://www.csd.uwo.ca/faculty/wu/
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// by Denton Woods
// Last modified: 02/02/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_quantizer.c
//
// Description: Heavily modified by Denton Woods.
//
// 20040223 XIX : Modified so it works better with color requests < 256
// pallete always has memory space for 256 entries
// used so we can quant down to 255 colors then add a transparent color in there.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#define MAXCOLOR 256
#define RED 2
#define GREEN 1
#define BLUE 0
typedef struct Box
{
ILint r0; // min value, exclusive
ILint r1; // max value, inclusive
ILint g0;
ILint g1;
ILint b0;
ILint b1;
ILint vol;
} Box;
/* Histogram is in elements 1..HISTSIZE along each axis,
* element 0 is for base or marginal value
* NB: these must start out 0!
*/
ILfloat gm2[33][33][33];
ILint wt[33][33][33], mr[33][33][33], mg[33][33][33], mb[33][33][33];
ILuint size; //image size
ILint K; //colour look-up table size
ILushort *Qadd;
ILint WindW, WindH, WindD;
ILint i;
ILubyte *buffer;
static ILint Width, Height, Depth, Comp;
/*ILint TotalColors;
ILint a, b;
ILubyte *buf1, *buf2;*/
ILuint n2(ILint s)
{
ILint i;
ILint res;
res = 1;
for (i = 0; i < s; i++) {
res = res*2;
}
return res;
}
// Build 3-D color histogram of counts, r/g/b, c^2
ILboolean Hist3d(ILubyte *Ir, ILubyte *Ig, ILubyte *Ib, ILint *vwt, ILint *vmr, ILint *vmg, ILint *vmb, ILfloat *m2)
{
ILint ind, r, g, b;
ILint inr, ing, inb, table[2560];
ILuint i;
for (i = 0; i < 256; i++) {
table[i] = i * i;
}
Qadd = (ILushort*)ialloc(sizeof(ILushort) * size);
if (Qadd == NULL) {
return IL_FALSE;
}
imemclear(Qadd, sizeof(ILushort) * size);
for (i = 0; i < size; i++) {
r = Ir[i]; g = Ig[i]; b = Ib[i];
inr = (r>>3) + 1;
ing = (g>>3) + 1;
inb = (b>>3) + 1;
Qadd[i] = ind = (inr<<10)+(inr<<6)+inr+(ing<<5)+ing+inb;
//[inr][ing][inb]
vwt[ind]++;
vmr[ind] += r;
vmg[ind] += g;
vmb[ind] += b;
m2[ind] += (ILfloat)(table[r]+table[g]+table[b]);
}
return IL_TRUE;
}
/* At conclusion of the histogram step, we can interpret
* wt[r][g][b] = sum over voxel of P(c)
* mr[r][g][b] = sum over voxel of r*P(c) , similarly for mg, mb
* m2[r][g][b] = sum over voxel of c^2*P(c)
* Actually each of these should be divided by 'size' to give the usual
* interpretation of P() as ranging from 0 to 1, but we needn't do that here.
*/
/* We now convert histogram into moments so that we can rapidly calculate
* the sums of the above quantities over any desired Box.
*/
// Compute cumulative moments
ILvoid M3d(ILint *vwt, ILint *vmr, ILint *vmg, ILint *vmb, ILfloat *m2)
{
ILushort ind1, ind2;
ILubyte i, r, g, b;
ILint line, line_r, line_g, line_b, area[33], area_r[33], area_g[33], area_b[33];
ILfloat line2, area2[33];
for (r = 1; r <= 32; r++) {
for (i = 0; i <= 32; i++) {
area2[i] = 0.0f;
area[i]=area_r[i]=area_g[i]=area_b[i]=0;
}
for (g = 1; g <= 32; g++) {
line2 = 0.0f;
line = line_r = line_g = line_b = 0;
for (b = 1; b <= 32; b++) {
ind1 = (r<<10) + (r<<6) + r + (g<<5) + g + b; // [r][g][b]
line += vwt[ind1];
line_r += vmr[ind1];
line_g += vmg[ind1];
line_b += vmb[ind1];
line2 += m2[ind1];
area[b] += line;
area_r[b] += line_r;
area_g[b] += line_g;
area_b[b] += line_b;
area2[b] += line2;
ind2 = ind1 - 1089; // [r-1][g][b]
vwt[ind1] = vwt[ind2] + area[b];
vmr[ind1] = vmr[ind2] + area_r[b];
vmg[ind1] = vmg[ind2] + area_g[b];
vmb[ind1] = vmb[ind2] + area_b[b];
m2[ind1] = m2[ind2] + area2[b];
}
}
}
return;
}
// Compute sum over a Box of any given statistic
ILint Vol(Box *cube, ILint mmt[33][33][33])
{
return( mmt[cube->r1][cube->g1][cube->b1]
-mmt[cube->r1][cube->g1][cube->b0]
-mmt[cube->r1][cube->g0][cube->b1]
+mmt[cube->r1][cube->g0][cube->b0]
-mmt[cube->r0][cube->g1][cube->b1]
+mmt[cube->r0][cube->g1][cube->b0]
+mmt[cube->r0][cube->g0][cube->b1]
-mmt[cube->r0][cube->g0][cube->b0] );
}
/* The next two routines allow a slightly more efficient calculation
* of Vol() for a proposed subBox of a given Box. The sum of Top()
* and Bottom() is the Vol() of a subBox split in the given direction
* and with the specified new upper bound.
*/
// Compute part of Vol(cube, mmt) that doesn't depend on r1, g1, or b1
// (depending on dir)
ILint Bottom(Box *cube, ILubyte dir, ILint mmt[33][33][33])
{
switch(dir)
{
case RED:
return( -mmt[cube->r0][cube->g1][cube->b1]
+mmt[cube->r0][cube->g1][cube->b0]
+mmt[cube->r0][cube->g0][cube->b1]
-mmt[cube->r0][cube->g0][cube->b0] );
break;
case GREEN:
return( -mmt[cube->r1][cube->g0][cube->b1]
+mmt[cube->r1][cube->g0][cube->b0]
+mmt[cube->r0][cube->g0][cube->b1]
-mmt[cube->r0][cube->g0][cube->b0] );
break;
case BLUE:
return( -mmt[cube->r1][cube->g1][cube->b0]
+mmt[cube->r1][cube->g0][cube->b0]
+mmt[cube->r0][cube->g1][cube->b0]
-mmt[cube->r0][cube->g0][cube->b0] );
break;
}
return 0;
}
// Compute remainder of Vol(cube, mmt), substituting pos for
// r1, g1, or b1 (depending on dir)
ILint Top(Box *cube, ILubyte dir, ILint pos, ILint mmt[33][33][33])
{
switch (dir)
{
case RED:
return( mmt[pos][cube->g1][cube->b1]
-mmt[pos][cube->g1][cube->b0]
-mmt[pos][cube->g0][cube->b1]
+mmt[pos][cube->g0][cube->b0] );
break;
case GREEN:
return( mmt[cube->r1][pos][cube->b1]
-mmt[cube->r1][pos][cube->b0]
-mmt[cube->r0][pos][cube->b1]
+mmt[cube->r0][pos][cube->b0] );
break;
case BLUE:
return( mmt[cube->r1][cube->g1][pos]
-mmt[cube->r1][cube->g0][pos]
-mmt[cube->r0][cube->g1][pos]
+mmt[cube->r0][cube->g0][pos] );
break;
}
return 0;
}
// Compute the weighted variance of a Box
// NB: as with the raw statistics, this is really the variance * size
ILfloat Var(Box *cube)
{
ILfloat dr, dg, db, xx;
dr = (ILfloat)Vol(cube, mr);
dg = (ILfloat)Vol(cube, mg);
db = (ILfloat)Vol(cube, mb);
xx = gm2[cube->r1][cube->g1][cube->b1]
-gm2[cube->r1][cube->g1][cube->b0]
-gm2[cube->r1][cube->g0][cube->b1]
+gm2[cube->r1][cube->g0][cube->b0]
-gm2[cube->r0][cube->g1][cube->b1]
+gm2[cube->r0][cube->g1][cube->b0]
+gm2[cube->r0][cube->g0][cube->b1]
-gm2[cube->r0][cube->g0][cube->b0];
return xx - (dr*dr+dg*dg+db*db) / (ILfloat)Vol(cube, wt);
}
/* We want to minimize the sum of the variances of two subBoxes.
* The sum(c^2) terms can be ignored since their sum over both subBoxes
* is the same (the sum for the whole Box) no matter where we split.
* The remaining terms have a minus sign in the variance formula,
* so we drop the minus sign and MAXIMIZE the sum of the two terms.
*/
ILfloat Maximize(Box *cube, ILubyte dir, ILint first, ILint last, ILint *cut,
ILint whole_r, ILint whole_g, ILint whole_b, ILint whole_w)
{
ILint half_r, half_g, half_b, half_w;
ILint base_r, base_g, base_b, base_w;
ILint i;
ILfloat temp, max;
base_r = Bottom(cube, dir, mr);
base_g = Bottom(cube, dir, mg);
base_b = Bottom(cube, dir, mb);
base_w = Bottom(cube, dir, wt);
max = 0.0;
*cut = -1;
for (i = first; i < last; ++i) {
half_r = base_r + Top(cube, dir, i, mr);
half_g = base_g + Top(cube, dir, i, mg);
half_b = base_b + Top(cube, dir, i, mb);
half_w = base_w + Top(cube, dir, i, wt);
// Now half_x is sum over lower half of Box, if split at i
if (half_w == 0) { // subBox could be empty of pixels!
continue; // never split into an empty Box
}
else {
temp = ((ILfloat)half_r*half_r + (ILfloat)half_g * half_g +
(ILfloat)half_b*half_b) / half_w;
}
half_r = whole_r - half_r;
half_g = whole_g - half_g;
half_b = whole_b - half_b;
half_w = whole_w - half_w;
if (half_w == 0) { // subBox could be empty of pixels!
continue; // never split into an empty Box
}
else {
temp += ((ILfloat)half_r*half_r + (ILfloat)half_g * half_g +
(ILfloat)half_b*half_b) / half_w;
}
if (temp > max) {
max = temp;
*cut = i;
}
}
return max;
}
ILint Cut(Box *set1, Box *set2)
{
ILubyte dir;
ILint cutr, cutg, cutb;
ILfloat maxr, maxg, maxb;
ILint whole_r, whole_g, whole_b, whole_w;
whole_r = Vol(set1, mr);
whole_g = Vol(set1, mg);
whole_b = Vol(set1, mb);
whole_w = Vol(set1, wt);
maxr = Maximize(set1, RED, set1->r0+1, set1->r1, &cutr, whole_r, whole_g, whole_b, whole_w);
maxg = Maximize(set1, GREEN, set1->g0+1, set1->g1, &cutg, whole_r, whole_g, whole_b, whole_w);
maxb = Maximize(set1, BLUE, set1->b0+1, set1->b1, &cutb, whole_r, whole_g, whole_b, whole_w);
if ((maxr >= maxg) && (maxr >= maxb)) {
dir = RED;
if (cutr < 0)
return 0; // can't split the Box
}
else if ((maxg >= maxr) && (maxg >= maxb))
dir = GREEN;
else
dir = BLUE;
set2->r1 = set1->r1;
set2->g1 = set1->g1;
set2->b1 = set1->b1;
switch (dir)
{
case RED:
set2->r0 = set1->r1 = cutr;
set2->g0 = set1->g0;
set2->b0 = set1->b0;
break;
case GREEN:
set2->g0 = set1->g1 = cutg;
set2->r0 = set1->r0;
set2->b0 = set1->b0;
break;
case BLUE:
set2->b0 = set1->b1 = cutb;
set2->r0 = set1->r0;
set2->g0 = set1->g0;
break;
}
set1->vol = (set1->r1-set1->r0) * (set1->g1-set1->g0) * (set1->b1-set1->b0);
set2->vol = (set2->r1-set2->r0) * (set2->g1-set2->g0) * (set2->b1-set2->b0);
return 1;
}
void Mark(struct Box *cube, int label, unsigned char *tag)
{
ILint r, g, b;
for (r = cube->r0 + 1; r <= cube->r1; r++) {
for (g = cube->g0 + 1; g <= cube->g1; g++) {
for (b = cube->b0 + 1; b <= cube->b1; b++) {
tag[(r<<10) + (r<<6) + r + (g<<5) + g + b] = label;
}
}
}
return;
}
ILimage *iQuantizeImage(ILimage *Image, ILuint NumCols)
{
Box cube[MAXCOLOR];
ILubyte *tag = NULL;
ILubyte lut_r[MAXCOLOR], lut_g[MAXCOLOR], lut_b[MAXCOLOR];
ILint next;
ILint weight;
ILuint k;
ILfloat vv[MAXCOLOR], temp;
//ILint color_num;
ILubyte *NewData = NULL, *Palette = NULL;
ILimage *TempImage = NULL, *NewImage = NULL;
ILubyte *Ir = NULL, *Ig = NULL, *Ib = NULL;
ILint num_alloced_colors; // number of colors we allocated space for in palette, as NumCols but eill not be less than 256
num_alloced_colors=NumCols;
if(num_alloced_colors<256) { num_alloced_colors=256; }
NewImage = iCurImage;
iCurImage = Image;
TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
iCurImage = NewImage;
if (TempImage == NULL)
return NULL;
buffer = Image->Data;
WindW = Width = Image->Width;
WindH = Height = Image->Height;
WindD = Depth = Image->Depth;
Comp = Image->Bpp;
Qadd = NULL;
//color_num = ImagePrecalculate(Image);
NewData = (ILubyte*)ialloc(Image->Width * Image->Height * Image->Depth);
Palette = (ILubyte*)ialloc(3 * num_alloced_colors);
if (!NewData || !Palette) {
ifree(NewData);
ifree(Palette);
return NULL;
}
Ir = (ILubyte*)ialloc(Width * Height * Depth);
Ig = (ILubyte*)ialloc(Width * Height * Depth);
Ib = (ILubyte*)ialloc(Width * Height * Depth);
if (!Ir || !Ig || !Ib) {
ifree(Ir);
ifree(Ig);
ifree(Ib);
ifree(NewData);
ifree(Palette);
return NULL;
}
size = Width * Height * Depth;
#ifdef ALTIVEC_GCC
register ILuint v_size = size>>4;
register ILuint pos = 0;
v_size = v_size /3;
register vector unsigned char d0,d1,d2;
register vector unsigned char red[3],blu[3],green[3];
register union{
vector unsigned char vec;
vector unsigned int load;
} mask_1, mask_2, mask_3;
mask_1.load = (vector unsigned int){0xFF0000FF,0x0000FF00,0x00FF0000,0xFF0000FF};
mask_2.load = (vector unsigned int){0x00FF0000,0xFF0000FF,0x0000FF00,0x00FF0000};
mask_2.load = (vector unsigned int){0x0000FF00,0x00FF0000,0xFF0000FF,0x0000FF00};
while( v_size >= 0 ) {
d0 = vec_ld(pos,TempImage->Data);
d1 = vec_ld(pos+16,TempImage->Data);
d2 = vec_ld(pos+32,TempImage->Data);
red[0] = vec_and(d0,mask_1.vec);
green[0] = vec_and(d0,mask_2.vec);
blu[0] = vec_and(d0,mask_3.vec);
red[1] = vec_and(d1,mask_3.vec);
green[1] = vec_and(d1,mask_1.vec);
blu[1] = vec_and(d1,mask_2.vec);
red[2] = vec_and(d2,mask_2.vec);
green[2] = vec_and(d2,mask_3.vec);
blu[2] = vec_and(d2,mask_1.vec);
vec_st(red[0],pos,Ir);
vec_st(red[1],pos+16,Ir);
vec_st(red[2],pos+32,Ir);
vec_st(blu[0],pos,Ib);
vec_st(blu[1],pos+16,Ib);
vec_st(blu[2],pos+32,Ib);
vec_st(green[0],pos,Ig);
vec_st(green[1],pos+16,Ig);
vec_st(green[2],pos+32,Ig);
pos += 48;
}
size -= pos;
#endif
for (k = 0; k < size; k++) {
Ir[k] = TempImage->Data[k * 3];
Ig[k] = TempImage->Data[k * 3 + 1];
Ib[k] = TempImage->Data[k * 3 + 2];
}
#ifdef ALTIVEC_GCC
size = Width * Height * Depth;
#endif
// Set new colors number
K = NumCols;
if (K <= 256) {
// Begin Wu's color quantization algorithm
// May have "leftovers" from a previous run.
imemclear(gm2, 33 * 33 * 33 * sizeof(ILfloat));
imemclear(wt, 33 * 33 * 33 * sizeof(ILint));
imemclear(mr, 33 * 33 * 33 * sizeof(ILint));
imemclear(mg, 33 * 33 * 33 * sizeof(ILint));
imemclear(mb, 33 * 33 * 33 * sizeof(ILint));
if (!Hist3d(Ir, Ig, Ib, (ILint*)wt, (ILint*)mr, (ILint*)mg, (ILint*)mb, (ILfloat*)gm2))
goto error_label;
M3d((ILint*)wt, (ILint*)mr, (ILint*)mg, (ILint*)mb, (ILfloat*)gm2);
cube[0].r0 = cube[0].g0 = cube[0].b0 = 0;
cube[0].r1 = cube[0].g1 = cube[0].b1 = 32;
next = 0;
for (i = 1; i < K; ++i) {
if (Cut(&cube[next], &cube[i])) { // volume test ensures we won't try to cut one-cell Box */
vv[next] = (cube[next].vol>1) ? Var(&cube[next]) : 0.0f;
vv[i] = (cube[i].vol>1) ? Var(&cube[i]) : 0.0f;
}
else {
vv[next] = 0.0; // don't try to split this Box again
i--; // didn't create Box i
}
next = 0;
temp = vv[0];
for (k = 1; (ILint)k <= i; ++k) {
if (vv[k] > temp) {
temp = vv[k]; next = k;
}
}
if (temp <= 0.0) {
K = i+1;
// Only got K Boxes
break;
}
}
tag = (ILubyte*)ialloc(33 * 33 * 33 * sizeof(ILubyte));
if (tag == NULL)
goto error_label;
for (k = 0; (ILint)k < K; k++) {
Mark(&cube[k], k, tag);
weight = Vol(&cube[k], wt);
if (weight) {
lut_r[k] = (ILubyte)(Vol(&cube[k], mr) / weight);
lut_g[k] = (ILubyte)(Vol(&cube[k], mg) / weight);
lut_b[k] = (ILubyte)(Vol(&cube[k], mb) / weight);
}
else {
// Bogus Box
lut_r[k] = lut_g[k] = lut_b[k] = 0;
}
}
for (i = 0; i < (ILint)size; i++) {
NewData[i] = tag[Qadd[i]];
}
ifree(tag);
ifree(Qadd);
for (k = 0; k < NumCols; k++) {
Palette[k * 3] = lut_b[k];
Palette[k * 3 + 1] = lut_g[k];
Palette[k * 3 + 2] = lut_r[k];
}
}
else { // If colors more than 256
// Begin Octree quantization
//Quant_Octree(Image->Width, Image->Height, Image->Bpp, buffer2, NewData, Palette, K);
ilSetError(IL_INTERNAL_ERROR); // Can't get much more specific than this.
goto error_label;
}
ifree(Ig);
ifree(Ib);
ifree(Ir);
ilCloseImage(TempImage);
NewImage = (ILimage*)icalloc(sizeof(ILimage), 1);
if (NewImage == NULL) {
return NULL;
}
ilCopyImageAttr(NewImage, Image);
NewImage->Bpp = 1;
NewImage->Bps = Image->Width;
NewImage->SizeOfPlane = NewImage->Bps * Image->Height;
NewImage->SizeOfData = NewImage->SizeOfPlane;
NewImage->Format = IL_COLOUR_INDEX;
NewImage->Type = IL_UNSIGNED_BYTE;
NewImage->Pal.Palette = Palette;
NewImage->Pal.PalSize = 256 * 3;
NewImage->Pal.PalType = IL_PAL_BGR24;
NewImage->Data = NewData;
return NewImage;
error_label:
ifree(NewData);
ifree(Palette);
ifree(Ig);
ifree(Ib);
ifree(Ir);
ifree(tag);
ifree(Qadd);
return NULL;
}

View File

@@ -0,0 +1,180 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2001 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_raw.c
//
// Description: "Raw" file functions
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_RAW
ILboolean iLoadRawInternal(ILvoid);
ILboolean iSaveRawInternal(ILvoid);
//! Reads a raw file
ILboolean ilLoadRaw(ILconst_string FileName)
{
ILHANDLE RawFile;
ILboolean bRaw = IL_FALSE;
// No need to check for raw
/*if (!iCheckExtension(FileName, "raw")) {
ilSetError(IL_INVALID_EXTENSION);
return bRaw;
}*/
RawFile = iopenr(FileName);
if (RawFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bRaw;
}
bRaw = ilLoadRawF(RawFile);
icloser(RawFile);
return bRaw;
}
//! Reads an already-opened raw file
ILboolean ilLoadRawF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadRawInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a raw memory "lump"
ILboolean ilLoadRawL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadRawInternal();
}
// Internal function to load a raw image
ILboolean iLoadRawInternal()
{
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
iCurImage->Width = GetLittleUInt();
iCurImage->Height = GetLittleUInt();
iCurImage->Depth = GetLittleUInt();
iCurImage->Bpp = igetc();
if (iread(&iCurImage->Bpc, 1, 1) != 1)
return IL_FALSE;
if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, iCurImage->Bpp, 0, ilGetTypeBpc(iCurImage->Bpc), NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
// Tries to read the correct amount of data
if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) < iCurImage->SizeOfData)
return IL_FALSE;
if (ilIsEnabled(IL_ORIGIN_SET)) {
iCurImage->Origin = ilGetInteger(IL_ORIGIN_MODE);
}
else {
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
}
if (iCurImage->Bpp == 1)
iCurImage->Format = IL_LUMINANCE;
else if (iCurImage->Bpp == 3)
iCurImage->Format = IL_RGB;
else // 4
iCurImage->Format = IL_RGBA;
ilFixImage();
return IL_TRUE;
}
//! Writes a Raw file
ILboolean ilSaveRaw(ILconst_string FileName)
{
ILHANDLE RawFile;
ILboolean bRaw = IL_FALSE;
if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
if (iFileExists(FileName)) {
ilSetError(IL_FILE_ALREADY_EXISTS);
return IL_FALSE;
}
}
RawFile = iopenw(FileName);
if (RawFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bRaw;
}
bRaw = ilSaveRawF(RawFile);
iclosew(RawFile);
return bRaw;
}
//! Writes raw data to an already-opened file
ILboolean ilSaveRawF(ILHANDLE File)
{
iSetOutputFile(File);
return iSaveRawInternal();
}
//! Writes raw data to a memory "lump"
ILboolean ilSaveRawL(ILvoid *Lump, ILuint Size)
{
iSetOutputLump(Lump, Size);
return iSaveRawInternal();
}
// Internal function used to load the raw data.
ILboolean iSaveRawInternal()
{
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
SaveLittleUInt(iCurImage->Width);
SaveLittleUInt(iCurImage->Height);
SaveLittleUInt(iCurImage->Depth);
iputc(iCurImage->Bpp);
iputc(iCurImage->Bpc);
iwrite(iCurImage->Data, 1, iCurImage->SizeOfData);
return IL_TRUE;
}
#endif//IL_NO_RAW

View File

@@ -0,0 +1,123 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2001 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/rawdata.c
//
// Description: "Raw" file functions
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
//#ifndef IL_NO_DATA
#include "il_manip.h"
ILboolean iLoadDataInternal(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp);
//! Reads a raw data file
ILboolean ILAPIENTRY ilLoadData(ILconst_string FileName, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp)
{
ILHANDLE RawFile;
ILboolean bRaw = IL_FALSE;
// No need to check for raw data
/*if (!iCheckExtension(FileName, "raw")) {
ilSetError(IL_INVALID_EXTENSION);
return bRaw;
}*/
RawFile = iopenr(FileName);
if (RawFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bRaw;
}
bRaw = ilLoadDataF(RawFile, Width, Height, Depth, Bpp);
icloser(RawFile);
return bRaw;
}
//! Reads an already-opened raw data file
ILboolean ILAPIENTRY ilLoadDataF(ILHANDLE File, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadDataInternal(Width, Height, Depth, Bpp);
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a raw data memory "lump"
ILboolean ILAPIENTRY ilLoadDataL(ILvoid *Lump, ILuint Size, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp)
{
iSetInputLump(Lump, Size);
return iLoadDataInternal(Width, Height, Depth, Bpp);
}
// Internal function to load a raw data image
ILboolean iLoadDataInternal(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp)
{
if (iCurImage == NULL || ((Bpp != 1) && (Bpp != 3) && (Bpp != 4))) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!ilTexImage(Width, Height, Depth, Bpp, 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
// Tries to read the correct amount of data
if (iread(iCurImage->Data, Width * Height * Depth * Bpp, 1) != 1)
return IL_FALSE;
if (iCurImage->Bpp == 1)
iCurImage->Format = IL_LUMINANCE;
else if (iCurImage->Bpp == 3)
iCurImage->Format = IL_RGB;
else // 4
iCurImage->Format = IL_RGBA;
ilFixImage();
return IL_TRUE;
}
//! Save the current image to FileName as raw data
ILboolean ILAPIENTRY ilSaveData(ILconst_string FileName)
{
ILHANDLE DataFile;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
DataFile = iopenr(FileName);
if (DataFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return IL_FALSE;
}
iwrite(iCurImage->Data, 1, iCurImage->SizeOfData);
icloser(DataFile);
return IL_TRUE;
}
//#endif//IL_NO_DATA

View File

@@ -0,0 +1,429 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 10/20/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_register.c
//
// Description: Allows the caller to specify user-defined callback functions
// to open files DevIL does not support, to parse files
// differently, or anything else a person can think up.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#include "il_register.h"
#include <string.h>
// Linked lists of registered formats
iFormatL *LoadProcs = NULL;
iFormatS *SaveProcs = NULL;
ILboolean ILAPIENTRY ilRegisterLoad(ILconst_string Ext, IL_LOADPROC Load) {
iFormatL *TempNode, *NewNode;
TempNode = LoadProcs;
if (TempNode != NULL) {
while (TempNode->Next != NULL) {
TempNode = TempNode->Next;
#ifndef _UNICODE
if (!stricmp(TempNode->Ext, Ext)) { // already registered
#else
if (!wcsicmp(TempNode->Ext, Ext)) {
#endif//_UNICODE
return IL_TRUE;
}
}
}
NewNode = (iFormatL*)ialloc(sizeof(iFormatL));
if (NewNode == NULL) {
return IL_FALSE;
}
if (LoadProcs == NULL) {
LoadProcs = NewNode;
}
else {
TempNode->Next = NewNode;
}
#ifndef _UNICODE
NewNode->Ext = ilStrDup(Ext);
#else
NewNode->Ext = _wcsdup(Ext);
#endif//_UNICODE
NewNode->Load = Load;
NewNode->Next = NULL;
return IL_TRUE;
}
ILboolean ILAPIENTRY ilRegisterSave(ILconst_string Ext, IL_SAVEPROC Save)
{
iFormatS *TempNode, *NewNode;
TempNode = SaveProcs;
if (TempNode != NULL) {
while (TempNode->Next != NULL) {
TempNode = TempNode->Next;
#ifndef _UNICODE
if (!stricmp(TempNode->Ext, Ext)) { // already registered
#else
if (!_wcsicmp(TempNode->Ext, Ext)) {
#endif//_UNICODE
return IL_TRUE;
}
}
}
NewNode = (iFormatS*)ialloc(sizeof(iFormatL));
if (NewNode == NULL) {
return IL_FALSE;
}
if (SaveProcs == NULL) {
SaveProcs = NewNode;
}
else {
TempNode->Next = NewNode;
}
#ifndef _UNICODE
NewNode->Ext = ilStrDup(Ext);
#else
NewNode->Ext = _wcsdup(Ext);
#endif//_UNICODE
NewNode->Save = Save;
NewNode->Next = NULL;
return IL_TRUE;
}
//! Unregisters a load extension - doesn't have to be called.
ILboolean ILAPIENTRY ilRemoveLoad(ILconst_string Ext)
{
iFormatL *TempNode = LoadProcs, *PrevNode = NULL;
while (TempNode != NULL) {
#ifndef _UNICODE
if (!stricmp(Ext, TempNode->Ext)) {
#else
if (_wcsicmp(Ext, TempNode->Ext)) {
#endif//_UNICODE
if (PrevNode == NULL) { // first node in the list
LoadProcs = TempNode->Next;
ifree((void*)TempNode->Ext);
ifree(TempNode);
}
else {
PrevNode->Next = TempNode->Next;
ifree((void*)TempNode->Ext);
ifree(TempNode);
}
return IL_TRUE;
}
PrevNode = TempNode;
TempNode = TempNode->Next;
}
return IL_FALSE;
}
//! Unregisters a save extension - doesn't have to be called.
ILboolean ILAPIENTRY ilRemoveSave(ILconst_string Ext)
{
iFormatS *TempNode = SaveProcs, *PrevNode = NULL;
while (TempNode != NULL) {
#ifndef _UNICODE
if (!stricmp(Ext, TempNode->Ext)) {
#else
if (_wcsicmp(Ext, TempNode->Ext)) {
#endif//_UNICODE
if (PrevNode == NULL) { // first node in the list
SaveProcs = TempNode->Next;
ifree((void*)TempNode->Ext);
ifree(TempNode);
}
else {
PrevNode->Next = TempNode->Next;
ifree((void*)TempNode->Ext);
ifree(TempNode);
}
return IL_TRUE;
}
PrevNode = TempNode;
TempNode = TempNode->Next;
}
return IL_FALSE;
}
// Automatically removes all registered formats.
ILvoid ilRemoveRegistered()
{
iFormatL *TempNodeL = LoadProcs;
iFormatS *TempNodeS = SaveProcs;
while (LoadProcs != NULL) {
TempNodeL = LoadProcs->Next;
ifree((void*)LoadProcs->Ext);
ifree(LoadProcs);
LoadProcs = TempNodeL;
}
while (SaveProcs != NULL) {
TempNodeS = SaveProcs->Next;
ifree((void*)SaveProcs->Ext);
ifree(SaveProcs);
SaveProcs = TempNodeS;
}
return;
}
ILboolean iRegisterLoad(ILconst_string FileName)
{
iFormatL *TempNode = LoadProcs;
ILstring Ext = iGetExtension(FileName);
ILenum Error;
if (!Ext)
return IL_FALSE;
while (TempNode != NULL) {
#ifndef _UNICODE
if (!stricmp(Ext, TempNode->Ext)) {
#else
if (_wcsicmp(Ext, TempNode->Ext)) {
#endif//_UNICODE
Error = TempNode->Load(FileName);
if (Error == IL_NO_ERROR || Error == 0) { // 0 and IL_NO_ERROR are both valid.
return IL_TRUE;
}
else {
ilSetError(Error);
return IL_FALSE;
}
}
TempNode = TempNode->Next;
}
return IL_FALSE;
}
ILboolean iRegisterSave(ILconst_string FileName)
{
iFormatS *TempNode = SaveProcs;
ILstring Ext = iGetExtension(FileName);
ILenum Error;
if (!Ext)
return IL_FALSE;
while (TempNode != NULL) {
#ifndef _UNICODE
if (!stricmp(Ext, TempNode->Ext)) {
#else
if (_wcsicmp(Ext, TempNode->Ext)) {
#endif//_UNICODE
Error = TempNode->Save(FileName);
if (Error == IL_NO_ERROR || Error == 0) { // 0 and IL_NO_ERROR are both valid.
return IL_TRUE;
}
else {
ilSetError(Error);
return IL_FALSE;
}
}
TempNode = TempNode->Next;
}
return IL_FALSE;
}
//
// "Reporting" functions
//
ILvoid ILAPIENTRY ilRegisterOrigin(ILenum Origin)
{
switch (Origin)
{
case IL_ORIGIN_LOWER_LEFT:
case IL_ORIGIN_UPPER_LEFT:
iCurImage->Origin = Origin;
break;
default:
ilSetError(IL_INVALID_ENUM);
}
return;
}
ILvoid ILAPIENTRY ilRegisterFormat(ILenum Format)
{
switch (Format)
{
case IL_COLOUR_INDEX:
case IL_RGB:
case IL_RGBA:
case IL_BGR:
case IL_BGRA:
case IL_LUMINANCE:
case IL_LUMINANCE_ALPHA:
iCurImage->Format = Format;
break;
default:
ilSetError(IL_INVALID_ENUM);
}
return;
}
ILboolean ILAPIENTRY ilRegisterMipNum(ILuint Num)
{
ILimage *Next, *Prev;
ilBindImage(ilGetCurName()); // Make sure the current image is actually bound.
ilCloseImage(iCurImage->Mipmaps); // Close any current mipmaps.
iCurImage->Mipmaps = NULL;
if (Num == 0) // Just gets rid of all the mipmaps.
return IL_TRUE;
iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1);
if (iCurImage->Mipmaps == NULL)
return IL_FALSE;
Next = iCurImage->Mipmaps;
Num--;
while (Num) {
Next->Next = ilNewImage(1, 1, 1, 1, 1);
if (Next->Next == NULL) {
// Clean up before we error out.
Prev = iCurImage->Mipmaps;
while (Prev) {
Next = Prev->Next;
ilCloseImage(Prev);
Prev = Next;
}
return IL_FALSE;
}
Next = Next->Next;
Num--;
}
return IL_TRUE;
}
ILboolean ILAPIENTRY ilRegisterNumImages(ILuint Num)
{
ILimage *Next, *Prev;
ilBindImage(ilGetCurName()); // Make sure the current image is actually bound.
ilCloseImage(iCurImage->Next); // Close any current "next" images.
iCurImage->Next = NULL;
if (Num == 0) // Just gets rid of all the "next" images.
return IL_TRUE;
iCurImage->Next = ilNewImage(1, 1, 1, 1, 1);
if (iCurImage->Next == NULL)
return IL_FALSE;
Next = iCurImage->Next;
Num--;
while (Num) {
Next->Next = ilNewImage(1, 1, 1, 1, 1);
if (Next->Next == NULL) {
// Clean up before we error out.
Prev = iCurImage->Next;
while (Prev) {
Next = Prev->Next;
ilCloseImage(Prev);
Prev = Next;
}
return IL_FALSE;
}
Next = Next->Next;
Num--;
}
return IL_TRUE;
}
ILvoid ILAPIENTRY ilRegisterType(ILenum Type)
{
switch (Type)
{
case IL_BYTE:
case IL_UNSIGNED_BYTE:
case IL_SHORT:
case IL_UNSIGNED_SHORT:
case IL_INT:
case IL_UNSIGNED_INT:
case IL_FLOAT:
case IL_DOUBLE:
iCurImage->Type = Type;
break;
default:
ilSetError(IL_INVALID_ENUM);
}
return;
}
ILvoid ILAPIENTRY ilRegisterPal(ILvoid *Pal, ILuint Size, ILenum Type)
{
if (!iCurImage->Pal.Palette || !iCurImage->Pal.PalSize || iCurImage->Pal.PalType != IL_PAL_NONE) {
ifree(iCurImage->Pal.Palette);
}
iCurImage->Pal.PalSize = Size;
iCurImage->Pal.PalType = Type;
iCurImage->Pal.Palette = (ILubyte*)ialloc(Size);
if (iCurImage->Pal.Palette == NULL)
return;
if (Pal != NULL) {
memcpy(iCurImage->Pal.Palette, Pal, Size);
}
else {
ilSetError(IL_INVALID_PARAM);
}
return;
}
ILboolean ILAPIENTRY ilSetDuration(ILuint Duration)
{
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
iCurImage->Duration = Duration;
return IL_TRUE;
}

View File

@@ -0,0 +1,153 @@
//-----------------------------------------------------------------------------
// Description: Functions for run-length encoding
//-----------------------------------------------------------------------------
// RLE code from TrueVision's TGA sample code available as Tgautils.zip at
// ftp://ftp.truevision.com/pub/TGA.File.Format.Spec/PC.Version
#define IL_RLE_C
#include "il_internal.h"
#include "il_rle.h"
ILboolean ilRleCompressLine(ILubyte *p, ILuint n, ILubyte bpp,
ILubyte *q, ILuint *DestWidth, ILenum CompressMode) {
ILint DiffCount; // pixel count until two identical
ILint SameCount; // number of identical adjacent pixels
ILint RLEBufSize = 0; // count of number of bytes encoded
ILint MaxRun;
const ILint bmp_pad_to_even = 1 - ((long)q - *DestWidth) % 2;
switch( CompressMode ) {
case IL_TGACOMP:
MaxRun = TGA_MAX_RUN;
break;
case IL_SGICOMP:
MaxRun = SGI_MAX_RUN;
break;
case IL_BMPCOMP:
MaxRun = BMP_MAX_RUN;
break;
default:
ilSetError(IL_INVALID_PARAM);
return IL_FALSE;
}
while( n > 0 ) {
// Analyze pixels
DiffCount = CountDiffPixels(p, bpp, n > MaxRun ? MaxRun : n);
SameCount = CountSamePixels(p, bpp, n > MaxRun ? MaxRun : n);
if( CompressMode == IL_BMPCOMP ) {
ILint remaining_data = n - DiffCount - SameCount;
if( remaining_data < 3 ) { // check if the run has gone near the end
// no absolute run can be done
// complete the line adding 0x01 + pixel, for each pixel
while( remaining_data > 0 ) {
*q++ = 0x01;
*q++ = *p++;
remaining_data--;
}
DiffCount = 0;
SameCount = 0;
n = 0;
}
}
if( DiffCount > 0 ) { // create a raw packet (bmp absolute run)
switch(CompressMode) {
case IL_TGACOMP:
*q++ = (ILbyte)(DiffCount - 1);
break;
case IL_BMPCOMP:
*q++ = 0x00; RLEBufSize++;
*q++ = (ILbyte)DiffCount;
break;
case IL_SGICOMP:
*q++ = (ILbyte)(DiffCount | 0x80);
break;
}
n -= DiffCount;
RLEBufSize += (DiffCount * bpp) + 1;
while( DiffCount > 0 ) {
switch(bpp) {
case 4: *q++ = *p++;
case 3: *q++ = *p++;
case 2: *q++ = *p++;
case 1: *q++ = *p++;
}
DiffCount--;
}
if( CompressMode == IL_BMPCOMP ) {
if( (long)q % 2 == bmp_pad_to_even ) {
*q++ = 0x00; // insert padding
}
}
}
if( SameCount > 1 ) { // create a RLE packet
switch(CompressMode) {
case IL_TGACOMP:
*q++ = (ILbyte)((SameCount - 1) | 0x80);
break;
case IL_SGICOMP:
case IL_BMPCOMP:
*q++ = (ILbyte)(SameCount);
break;
}
n -= SameCount;
RLEBufSize += bpp + 1;
p += (SameCount - 1) * bpp;
*q++ = *p++;
switch(bpp) {
case 4: *q++ = *p++;
case 3: *q++ = *p++;
case 2: *q++ = *p++;
case 1: *q++ = *p++;
}
}
}
// write line termination code
switch(CompressMode) {
case IL_SGICOMP:
++RLEBufSize;
*q++ = 0;
break;
case IL_BMPCOMP:
*q++ = 0x00; RLEBufSize++;
*q++ = 0x00; RLEBufSize++;
break;
}
*DestWidth = RLEBufSize;
return IL_TRUE;
}
// Compresses an entire image using run-length encoding
ILuint ilRleCompress(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp,
ILubyte *Dest, ILenum CompressMode, ILuint *ScanTable) {
ILuint DestW = 0, i, j, LineLen, Bps = Width * Bpp, SizeOfPlane = Width * Height * Bpp;
if( ScanTable )
imemclear(ScanTable,Depth*Height*sizeof(ILuint));
for( j = 0; j < Depth; j++ ) {
for( i = 0; i < Height; i++ ) {
if( ScanTable )
*ScanTable++ = DestW;
ilRleCompressLine(Data + j * SizeOfPlane + i * Bps, Width, Bpp, Dest + DestW, &LineLen, CompressMode);
DestW += LineLen;
}
}
if( CompressMode == IL_BMPCOMP ) { // add end of image
*(Data+DestW) = 0x00; DestW++;
*(Data+DestW) = 0x01; DestW++;
}
return DestW;
}

View File

@@ -0,0 +1,737 @@
#include "il_internal.h"
#ifndef IL_NO_SGI
#include "il_sgi.h"
#include "il_manip.h"
#include <limits.h>
static char *FName = NULL;
/*----------------------------------------------------------------------------*/
/*! Checks if the file specified in FileName is a valid .sgi file. */
ILboolean ilIsValidSgi(ILconst_string FileName)
{
ILHANDLE SgiFile;
ILboolean bSgi = IL_FALSE;
if (!iCheckExtension(FileName, IL_TEXT("sgi"))) {
ilSetError(IL_INVALID_EXTENSION);
return bSgi;
}
FName = (char*) FileName;
SgiFile = iopenr(FileName);
if (SgiFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bSgi;
}
bSgi = ilIsValidSgiF(SgiFile);
icloser(SgiFile);
return bSgi;
}
/*----------------------------------------------------------------------------*/
/*! Checks if the ILHANDLE contains a valid .sgi file at the current position.*/
ILboolean ilIsValidSgiF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iIsValidSgi();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
/*----------------------------------------------------------------------------*/
//! Checks if Lump is a valid .sgi lump.
ILboolean ilIsValidSgiL(const ILvoid *Lump, ILuint Size)
{
FName = NULL;
iSetInputLump(Lump, Size);
return iIsValidSgi();
}
/*----------------------------------------------------------------------------*/
// Internal function used to get the .sgi header from the current file.
ILboolean iGetSgiHead(iSgiHeader *Header)
{
Header->MagicNum = GetBigUShort();
Header->Storage = igetc();
Header->Bpc = igetc();
Header->Dim = GetBigUShort();
Header->XSize = GetBigUShort();
Header->YSize = GetBigUShort();
Header->ZSize = GetBigUShort();
Header->PixMin = GetBigInt();
Header->PixMax = GetBigInt();
Header->Dummy1 = GetBigInt();
iread(Header->Name, 1, 80);
Header->ColMap = GetBigInt();
iread(Header->Dummy, 1, 404);
return IL_TRUE;
}
/*----------------------------------------------------------------------------*/
/* Internal function to get the header and check it. */
ILboolean iIsValidSgi()
{
iSgiHeader Head;
if (!iGetSgiHead(&Head))
return IL_FALSE;
iseek(-(ILint)sizeof(iSgiHeader), IL_SEEK_CUR); // Go ahead and restore to previous state
return iCheckSgi(&Head);
}
/*----------------------------------------------------------------------------*/
/* Internal function used to check if the HEADER is a valid .sgi header. */
ILboolean iCheckSgi(iSgiHeader *Header)
{
if (Header->MagicNum != SGI_MAGICNUM)
return IL_FALSE;
if (Header->Storage != SGI_RLE && Header->Storage != SGI_VERBATIM)
return IL_FALSE;
if (Header->Bpc == 0 || Header->Dim == 0)
return IL_FALSE;
if (Header->XSize == 0 || Header->YSize == 0 || Header->ZSize == 0)
return IL_FALSE;
return IL_TRUE;
}
/*----------------------------------------------------------------------------*/
/*! Reads a SGI file */
ILboolean ilLoadSgi(ILconst_string FileName)
{
ILHANDLE SgiFile;
ILboolean bSgi = IL_FALSE;
SgiFile = iopenr(FileName);
if (SgiFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bSgi;
}
bSgi = ilLoadSgiF(SgiFile);
icloser(SgiFile);
return bSgi;
}
/*----------------------------------------------------------------------------*/
/*! Reads an already-opened SGI file */
ILboolean ilLoadSgiF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadSgiInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
/*----------------------------------------------------------------------------*/
/*! Reads from a memory "lump" that contains a SGI image */
ILboolean ilLoadSgiL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadSgiInternal();
}
/*----------------------------------------------------------------------------*/
/* Internal function used to load the SGI image */
ILboolean iLoadSgiInternal()
{
iSgiHeader Header;
ILboolean bSgi;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!iGetSgiHead(&Header))
return IL_FALSE;
if (!iCheckSgi(&Header)) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
if (Header.Storage == SGI_RLE) { // RLE
bSgi = iReadRleSgi(&Header);
}
else { // Non-RLE //(Header.Storage == SGI_VERBATIM)
bSgi = iReadNonRleSgi(&Header);
}
ilFixImage();
return bSgi;
}
/*----------------------------------------------------------------------------*/
ILboolean iReadRleSgi(iSgiHeader *Head)
{
#ifdef __LITTLE_ENDIAN__
ILuint ixTable;
#endif
ILuint ChanInt = 0;
ILuint ixPlane, ixHeight,ixPixel, RleOff, RleLen;
ILuint *OffTable=NULL, *LenTable=NULL, TableSize, Cur;
ILubyte **TempData=NULL;
if (!iNewSgi(Head))
return IL_FALSE;
TableSize = Head->YSize * Head->ZSize;
OffTable = (ILuint*)ialloc(TableSize * sizeof(ILuint));
LenTable = (ILuint*)ialloc(TableSize * sizeof(ILuint));
if (OffTable == NULL || LenTable == NULL)
goto cleanup_error;
if (iread(OffTable, TableSize * sizeof(ILuint), 1) != 1)
goto cleanup_error;
if (iread(LenTable, TableSize * sizeof(ILuint), 1) != 1)
goto cleanup_error;
#ifdef __LITTLE_ENDIAN__
// Fix the offset/len table (it's big endian format)
for (ixTable = 0; ixTable < TableSize; ixTable++) {
iSwapUInt(OffTable + ixTable);
iSwapUInt(LenTable + ixTable);
}
#endif //__LITTLE_ENDIAN__
// We have to create a temporary buffer for the image, because SGI
// images are plane-separated. */
TempData = (ILubyte**)ialloc(Head->ZSize * sizeof(ILubyte*));
if (TempData == NULL)
goto cleanup_error;
imemclear(TempData, Head->ZSize * sizeof(ILubyte*)); // Just in case ialloc fails then cleanup_error.
for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) {
TempData[ixPlane] = (ILubyte*)ialloc(Head->XSize * Head->YSize * Head->Bpc);
if (TempData[ixPlane] == NULL)
goto cleanup_error;
}
// Read the Planes into the temporary memory
for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) {
for (ixHeight = 0, Cur = 0; ixHeight < Head->YSize;
ixHeight++, Cur += Head->XSize * Head->Bpc) {
RleOff = OffTable[ixHeight + ixPlane * Head->YSize];
RleLen = LenTable[ixHeight + ixPlane * Head->YSize];
// Seeks to the offset table position
iseek(RleOff, IL_SEEK_SET);
if (iGetScanLine((TempData[ixPlane]) + (ixHeight * Head->XSize * Head->Bpc),
Head, RleLen) != Head->XSize * Head->Bpc) {
ilSetError(IL_ILLEGAL_FILE_VALUE);
goto cleanup_error;
}
}
}
// DW: Removed on 05/25/2002.
/*// Check if an alphaplane exists and invert it
if (Head->ZSize == 4) {
for (ixPixel=0; (ILint)ixPixel<Head->XSize * Head->YSize; ixPixel++) {
TempData[3][ixPixel] = TempData[3][ixPixel] ^ 255;
}
}*/
// Assemble the image from its planes
for (ixPixel = 0; ixPixel < iCurImage->SizeOfData;
ixPixel += Head->ZSize * Head->Bpc, ChanInt += Head->Bpc) {
for (ixPlane = 0; (ILint)ixPlane < Head->ZSize * Head->Bpc; ixPlane += Head->Bpc) {
iCurImage->Data[ixPixel + ixPlane] = TempData[ixPlane][ChanInt];
if (Head->Bpc == 2)
iCurImage->Data[ixPixel + ixPlane + 1] = TempData[ixPlane][ChanInt + 1];
}
}
#ifdef __LITTLE_ENDIAN__
if (Head->Bpc == 2)
sgiSwitchData(iCurImage->Data, iCurImage->SizeOfData);
#endif
ifree(OffTable);
ifree(LenTable);
for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) {
ifree(TempData[ixPlane]);
}
ifree(TempData);
return IL_TRUE;
cleanup_error:
ifree(OffTable);
ifree(LenTable);
if (TempData) {
for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) {
ifree(TempData[ixPlane]);
}
ifree(TempData);
}
return IL_FALSE;
}
/*----------------------------------------------------------------------------*/
ILint iGetScanLine(ILubyte *ScanLine, iSgiHeader *Head, ILuint Length)
{
ILushort Pixel, Count; // For current pixel
ILuint BppRead = 0, CurPos = 0, Bps = Head->XSize * Head->Bpc;
while (BppRead < Length && CurPos < Bps)
{
Pixel = 0;
if (iread(&Pixel, Head->Bpc, 1) != 1)
return -1;
#ifndef __LITTLE_ENDIAN__
iSwapUShort(&Pixel);
#endif
if (!(Count = (Pixel & 0x7f))) // If 0, line ends
return CurPos;
if (Pixel & 0x80) { // If top bit set, then it is a "run"
if (iread(ScanLine, Head->Bpc, Count) != Count)
return -1;
BppRead += Head->Bpc * Count + Head->Bpc;
ScanLine += Head->Bpc * Count;
CurPos += Head->Bpc * Count;
}
else {
if (iread(&Pixel, Head->Bpc, 1) != 1)
return -1;
#ifndef __LITTLE_ENDIAN__
iSwapUShort(&Pixel);
#endif
if (Head->Bpc == 1) {
while (Count--) {
*ScanLine = (ILubyte)Pixel;
ScanLine++;
CurPos++;
}
}
else {
while (Count--) {
*(ILushort*)ScanLine = Pixel;
ScanLine += 2;
CurPos += 2;
}
}
BppRead += Head->Bpc + Head->Bpc;
}
}
return CurPos;
}
/*----------------------------------------------------------------------------*/
// Much easier to read - just assemble from planes, no decompression
ILboolean iReadNonRleSgi(iSgiHeader *Head)
{
ILuint i, c;
// ILint ChanInt = 0; Unused
ILint ChanSize;
ILboolean Cache = IL_FALSE;
if (!iNewSgi(Head)) {
return IL_FALSE;
}
if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) {
Cache = IL_TRUE;
ChanSize = Head->XSize * Head->YSize * Head->Bpc;
iPreCache(ChanSize);
}
for (c = 0; c < iCurImage->Bpp; c++) {
for (i = c; i < iCurImage->SizeOfData; i += iCurImage->Bpp) {
if (iread(iCurImage->Data + i, 1, 1) != 1) {
if (Cache)
iUnCache();
return IL_FALSE;
}
}
}
if (Cache)
iUnCache();
return IL_TRUE;
}
/*----------------------------------------------------------------------------*/
ILvoid sgiSwitchData(ILubyte *Data, ILuint SizeOfData)
{
ILubyte Temp;
ILuint i;
#ifdef ALTIVEC_GCC
i = 0;
union {
vector unsigned char vec;
vector unsigned int load;
}inversion_vector;
inversion_vector.load = (vector unsigned int)\
{0x01000302,0x05040706,0x09080B0A,0x0D0C0F0E};
while( i <= SizeOfData-16 ) {
vector unsigned char data = vec_ld(i,Data);
vec_perm(data,data,inversion_vector.vec);
vec_st(data,i,Data);
i+=16;
}
SizeOfData -= i;
#endif
for (i = 0; i < SizeOfData; i += 2) {
Temp = Data[i];
Data[i] = Data[i+1];
Data[i+1] = Temp;
}
return;
}
/*----------------------------------------------------------------------------*/
// Just an internal convenience function for reading SGI files
ILboolean iNewSgi(iSgiHeader *Head)
{
if (!ilTexImage(Head->XSize, Head->YSize, Head->Bpc, (ILubyte)Head->ZSize, 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
switch (Head->ZSize)
{
case 1:
iCurImage->Format = IL_LUMINANCE;
break;
case 2:
iCurImage->Format = IL_LUMINANCE_ALPHA;
break;
case 3:
iCurImage->Format = IL_RGB;
break;
case 4:
iCurImage->Format = IL_RGBA;
break;
default:
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
switch (Head->Bpc)
{
case 1:
if (Head->PixMin < 0)
iCurImage->Type = IL_BYTE;
else
iCurImage->Type = IL_UNSIGNED_BYTE;
break;
case 2:
if (Head->PixMin < 0)
iCurImage->Type = IL_SHORT;
else
iCurImage->Type = IL_UNSIGNED_SHORT;
break;
default:
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
return IL_TRUE;
}
/*----------------------------------------------------------------------------*/
//! Writes a SGI file
ILboolean ilSaveSgi(ILconst_string FileName)
{
ILHANDLE SgiFile;
ILboolean bSgi = IL_FALSE;
if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
if (iFileExists(FileName)) {
ilSetError(IL_FILE_ALREADY_EXISTS);
return IL_FALSE;
}
}
SgiFile = iopenw(FileName);
if (SgiFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bSgi;
}
bSgi = ilSaveSgiF(SgiFile);
iclosew(SgiFile);
return bSgi;
}
/*----------------------------------------------------------------------------*/
//! Writes a SGI to an already-opened file
ILboolean ilSaveSgiF(ILHANDLE File)
{
iSetOutputFile(File);
return iSaveSgiInternal();
}
/*----------------------------------------------------------------------------*/
//! Writes a SGI to a memory "lump"
ILboolean ilSaveSgiL(ILvoid *Lump, ILuint Size)
{
iSetOutputLump(Lump, Size);
return iSaveSgiInternal();
}
ILenum DetermineSgiType(ILenum Type)
{
if (Type > IL_UNSIGNED_SHORT) {
if (iCurImage->Type == IL_INT)
return IL_SHORT;
return IL_UNSIGNED_SHORT;
}
return Type;
}
/*----------------------------------------------------------------------------*/
// Rle does NOT work yet.
// Internal function used to save the Sgi.
ILboolean iSaveSgiInternal()
{
ILuint i, c;
ILboolean Compress;
ILimage *Temp = iCurImage;
ILubyte *TempData;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (iCurImage->Format != IL_LUMINANCE
//while the sgi spec doesn't directly forbid rgb files with 2
//channels, they are quite uncommon and most apps don't support
//them. so convert lum_a images to rgba before writing.
//&& iCurImage->Format != IL_LUMINANCE_ALPHA
&& iCurImage->Format != IL_RGB
&& iCurImage->Format != IL_RGBA) {
if (iCurImage->Format == IL_BGRA || iCurImage->Format == IL_LUMINANCE_ALPHA)
Temp = iConvertImage(iCurImage, IL_RGBA, DetermineSgiType(iCurImage->Type));
else
Temp = iConvertImage(iCurImage, IL_RGB, DetermineSgiType(iCurImage->Type));
}
else if (iCurImage->Type > IL_UNSIGNED_SHORT) {
Temp = iConvertImage(iCurImage, iCurImage->Format, DetermineSgiType(iCurImage->Type));
}
//compression of images with 2 bytes per channel doesn't work yet
Compress = iGetInt(IL_SGI_RLE) && Temp->Bpc == 1;
if (Temp == NULL)
return IL_FALSE;
SaveBigUShort(SGI_MAGICNUM); // 'Magic' number
if (Compress)
iputc(1);
else
iputc(0);
if (Temp->Type == IL_UNSIGNED_BYTE)
iputc(1);
else if (Temp->Type == IL_UNSIGNED_SHORT)
iputc(2);
// Need to error here if not one of the two...
if (Temp->Format == IL_LUMINANCE || Temp->Format == IL_COLOUR_INDEX)
SaveBigUShort(2);
else
SaveBigUShort(3);
SaveBigUShort((ILushort)Temp->Width);
SaveBigUShort((ILushort)Temp->Height);
SaveBigUShort((ILushort)Temp->Bpp);
switch (Temp->Type)
{
case IL_BYTE:
SaveBigInt(SCHAR_MIN); // Minimum pixel value
SaveBigInt(SCHAR_MAX); // Maximum pixel value
break;
case IL_UNSIGNED_BYTE:
SaveBigInt(0); // Minimum pixel value
SaveBigInt(UCHAR_MAX); // Maximum pixel value
break;
case IL_SHORT:
SaveBigInt(SHRT_MIN); // Minimum pixel value
SaveBigInt(SHRT_MAX); // Maximum pixel value
break;
case IL_UNSIGNED_SHORT:
SaveBigInt(0); // Minimum pixel value
SaveBigInt(USHRT_MAX); // Maximum pixel value
break;
}
SaveBigInt(0); // Dummy value
if (FName) {
c = strlen(FName);
c = c < 79 ? 79 : c;
iwrite(FName, 1, c);
c = 80 - c;
for (i = 0; i < c; i++) {
iputc(0);
}
}
else {
for (i = 0; i < 80; i++) {
iputc(0);
}
}
SaveBigUInt(0); // Colormap
// Padding
for (i = 0; i < 101; i++) {
SaveLittleInt(0);
}
if (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT) {
TempData = iGetFlipped(Temp);
if (TempData == NULL) {
if (Temp!= iCurImage)
ilCloseImage(Temp);
return IL_FALSE;
}
}
else {
TempData = Temp->Data;
}
if (!Compress) {
for (c = 0; c < Temp->Bpp; c++) {
for (i = c; i < Temp->SizeOfData; i += Temp->Bpp) {
iputc(TempData[i]); // Have to save each colour plane separately.
}
}
}
else {
iSaveRleSgi(TempData, Temp->Width, Temp->Height, Temp->Bpp, Temp->Bps);
}
if (TempData != Temp->Data)
ifree(TempData);
if (Temp != iCurImage)
ilCloseImage(Temp);
return IL_TRUE;
}
/*----------------------------------------------------------------------------*/
ILboolean iSaveRleSgi(ILubyte *Data, ILuint w, ILuint h, ILuint numChannels,
ILuint bps)
{
//works only for sgi files with only 1 bpc
ILuint c, i, y, j;
ILubyte *ScanLine = NULL, *CompLine = NULL;
ILuint *StartTable = NULL, *LenTable = NULL;
ILuint TableOff, DataOff = 0;
ScanLine = (ILubyte*)ialloc(w);
CompLine = (ILubyte*)ialloc(w * 2 + 1); // Absolute worst case.
StartTable = (ILuint*)ialloc(h * numChannels * sizeof(ILuint));
LenTable = (ILuint*)icalloc(h * numChannels, sizeof(ILuint));
if (!ScanLine || !CompLine || !StartTable || !LenTable) {
ifree(ScanLine);
ifree(CompLine);
ifree(StartTable);
ifree(LenTable);
return IL_FALSE;
}
// These just contain dummy values at this point.
TableOff = itellw();
iwrite(StartTable, sizeof(ILuint), h * numChannels);
iwrite(LenTable, sizeof(ILuint), h * numChannels);
DataOff = itellw();
for (c = 0; c < numChannels; c++) {
for (y = 0; y < h; y++) {
i = y * bps + c;
for (j = 0; j < w; j++, i += numChannels) {
ScanLine[j] = Data[i];
}
ilRleCompressLine(ScanLine, w, 1, CompLine, LenTable + h * c + y, IL_SGICOMP);
iwrite(CompLine, 1, *(LenTable + h * c + y));
}
}
iseekw(TableOff, IL_SEEK_SET);
j = h * numChannels;
for (y = 0; y < j; y++) {
StartTable[y] = DataOff;
DataOff += LenTable[y];
#ifdef __LITTLE_ENDIAN__
iSwapUInt(&StartTable[y]);
iSwapUInt(&LenTable[y]);
#endif
}
iwrite(StartTable, sizeof(ILuint), h * numChannels);
iwrite(LenTable, sizeof(ILuint), h * numChannels);
ifree(ScanLine);
ifree(CompLine);
ifree(StartTable);
ifree(LenTable);
return IL_TRUE;
}
/*----------------------------------------------------------------------------*/
#endif//IL_NO_SGI

View File

@@ -0,0 +1,605 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2001 by Denton Woods
// Last modified: 12/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_stack.c
//
// Description: The main image stack
//
//-----------------------------------------------------------------------------
// Credit goes to John Villar (johnny@reliaschev.com) for making the suggestion
// of not letting the user use ILimage structs but instead binding images
// like OpenGL.
#include "il_internal.h"
#include "il_stack.h"
//! Creates Num images and puts their index in Images - similar to glGenTextures().
ILvoid ILAPIENTRY ilGenImages(ILsizei Num, ILuint *Images)
{
ILsizei Index = 0;
iFree *TempFree = FreeNames;
if (Num < 1 || Images == NULL) {
ilSetError(IL_INVALID_VALUE);
return;
}
// No images have been generated yet, so create the image stack.
if (ImageStack == NULL)
if (!iEnlargeStack())
return;
do {
if (FreeNames != NULL) { // If any have been deleted, then reuse their image names.
TempFree = (iFree*)FreeNames->Next;
Images[Index] = FreeNames->Name;
ImageStack[FreeNames->Name] = ilNewImage(1, 1, 1, 1, 1);
ifree(FreeNames);
FreeNames = TempFree;
} else {
if (LastUsed >= StackSize)
if (!iEnlargeStack())
return;
Images[Index] = LastUsed;
// Must be all 1's instead of 0's, because some functions would divide by 0.
ImageStack[LastUsed] = ilNewImage(1, 1, 1, 1, 1);
LastUsed++;
}
} while (++Index < Num);
return;
}
ILint ILAPIENTRY ilGenImage() {
ILuint i;
ilGenImages(1,&i);
return i;
}
//! Makes Image the current active image - similar to glBindTexture().
ILvoid ILAPIENTRY ilBindImage(ILuint Image)
{
if (ImageStack == NULL || StackSize == 0) {
if (!iEnlargeStack()) {
return;
}
}
// If the user requests a high image name.
while (Image >= StackSize) {
if (!iEnlargeStack()) {
return;
}
}
if (ImageStack[Image] == NULL) {
ImageStack[Image] = ilNewImage(1, 1, 1, 1, 1);
if (Image >= LastUsed) // >= ?
LastUsed = Image + 1;
}
iCurImage = ImageStack[Image];
CurName = Image;
ParentImage = IL_TRUE;
return;
}
//! Deletes Num images from the image stack - similar to glDeleteTextures().
ILvoid ILAPIENTRY ilDeleteImages(ILsizei Num, const ILuint *Images)
{
iFree *Temp = FreeNames;
ILuint Index = 0;
if (Num < 1) {
//ilSetError(IL_INVALID_VALUE);
return;
}
if (StackSize == 0)
return;
do {
if (Images[Index] > 0 && Images[Index] < LastUsed) { // <= ?
/*if (FreeNames != NULL) { // Terribly inefficient
Temp = FreeNames;
do {
if (Temp->Name == Images[Index]) {
continue; // Sufficient?
}
} while ((Temp = Temp->Next));
}*/
// Already has been deleted or was never used.
if (ImageStack[Images[Index]] == NULL)
continue;
// Find out if current image - if so, set to default image zero.
if (Images[Index] == CurName || Images[Index] == 0) {
iCurImage = ImageStack[0];
CurName = 0;
}
// Should *NOT* be NULL here!
ilCloseImage(ImageStack[Images[Index]]);
ImageStack[Images[Index]] = NULL;
// Add to head of list - works for empty and non-empty lists
Temp = (iFree*)ialloc(sizeof(iFree));
if (!Temp) {
return;
}
Temp->Name = Images[Index];
Temp->Next = FreeNames;
FreeNames = Temp;
}
/*else { // Shouldn't set an error...just continue onward.
ilSetError(IL_ILLEGAL_OPERATION);
}*/
} while (++Index < (ILuint)Num);
}
ILvoid ILAPIENTRY ilDeleteImage(const ILuint Num) {
ilDeleteImages(1,&Num);
}
//! Checks if Image is a valid ilGenImages-generated image (like glIsTexture()).
ILboolean ILAPIENTRY ilIsImage(ILuint Image)
{
//iFree *Temp = FreeNames;
if (ImageStack == NULL)
return IL_FALSE;
if (Image >= LastUsed || Image == 0)
return IL_FALSE;
/*do {
if (Temp->Name == Image)
return IL_FALSE;
} while ((Temp = Temp->Next));*/
if (ImageStack[Image] == NULL) // Easier check.
return IL_FALSE;
return IL_TRUE;
}
//! Closes Image and frees all memory associated with it.
ILAPI ILvoid ILAPIENTRY ilCloseImage(ILimage *Image)
{
if (Image == NULL)
return;
if (Image->Data != NULL) {
ifree(Image->Data);
Image->Data = NULL;
}
if (Image->Pal.Palette != NULL && Image->Pal.PalSize > 0 && Image->Pal.PalType != IL_PAL_NONE) {
ifree(Image->Pal.Palette);
Image->Pal.Palette = NULL;
}
if (Image->Next != NULL) {
ilCloseImage(Image->Next);
Image->Next = NULL;
}
if (Image->Mipmaps != NULL) {
ilCloseImage(Image->Mipmaps);
Image->Mipmaps = NULL;
}
if (Image->Layers != NULL) {
ilCloseImage(Image->Layers);
Image->Layers = NULL;
}
if (Image->AnimList != NULL && Image->AnimSize != 0) {
ifree(Image->AnimList);
Image->AnimList = NULL;
}
if (Image->Profile != NULL && Image->ProfileSize != 0) {
ifree(Image->Profile);
Image->Profile = NULL;
Image->ProfileSize = 0;
}
if (Image->DxtcData != NULL && Image->DxtcFormat != IL_DXT_NO_COMP) {
ifree(Image->DxtcData);
Image->DxtcData = NULL;
Image->DxtcFormat = IL_DXT_NO_COMP;
Image->DxtcSize = 0;
}
ifree(Image);
Image = NULL;
return;
}
ILAPI ILboolean ILAPIENTRY ilIsValidPal(ILpal *Palette)
{
if (Palette == NULL)
return IL_FALSE;
if (Palette->PalSize == 0 || Palette->Palette == NULL)
return IL_FALSE;
switch (Palette->PalType)
{
case IL_PAL_RGB24:
case IL_PAL_RGB32:
case IL_PAL_RGBA32:
case IL_PAL_BGR24:
case IL_PAL_BGR32:
case IL_PAL_BGRA32:
return IL_TRUE;
}
return IL_FALSE;
}
//! Closes Palette and frees all memory associated with it.
ILAPI ILvoid ILAPIENTRY ilClosePal(ILpal *Palette)
{
if (Palette == NULL)
return;
if (!ilIsValidPal(Palette))
return;
ifree(Palette->Palette);
ifree(Palette);
return;
}
ILimage *iGetBaseImage()
{
return ImageStack[ilGetCurName()];
}
//! Sets the current mipmap level
ILboolean ILAPIENTRY ilActiveMipmap(ILuint Number)
{
ILuint Current;
ILimage *iTempImage;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (Number == 0) {
return IL_TRUE;
}
iTempImage = iCurImage;
iCurImage = iCurImage->Mipmaps;
for (Current = 1; Current < Number; Current++) {
iCurImage = iCurImage->Next;
if (iCurImage == NULL) {
ilSetError(IL_INTERNAL_ERROR);
iCurImage = iTempImage;
return IL_FALSE;
}
}
ParentImage = IL_FALSE;
return IL_TRUE;
}
//! Used for setting the current image if it is an animation.
ILboolean ILAPIENTRY ilActiveImage(ILuint Number)
{
ILuint Current;
ILimage *iTempImage;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (Number == 0) {
return IL_TRUE;
}
iTempImage = iCurImage;
iCurImage = iCurImage->Next;
Number--; // Skip 0 (parent image)
for (Current = 0; Current < Number; Current++) {
iCurImage = iCurImage->Next;
if (iCurImage == NULL) {
ilSetError(IL_INTERNAL_ERROR);
iCurImage = iTempImage;
return IL_FALSE;
}
}
ParentImage = IL_FALSE;
return IL_TRUE;
}
//! Used for setting the current layer if layers exist.
ILboolean ILAPIENTRY ilActiveLayer(ILuint Number)
{
ILuint Current;
ILimage *iTempImage;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (Number == 0) {
return IL_TRUE;
}
iTempImage = iCurImage;
iCurImage = iCurImage->Layers;
//Number--; // Skip 0 (parent image)
for (Current = 1; Current < Number; Current++) {
iCurImage = iCurImage->Layers;
if (iCurImage == NULL) {
ilSetError(IL_INTERNAL_ERROR);
iCurImage = iTempImage;
return IL_FALSE;
}
}
ParentImage = IL_FALSE;
return IL_TRUE;
}
ILuint ILAPIENTRY ilCreateSubImage(ILenum Type, ILuint Num)
{
ILimage *SubImage;
ILuint Count ; // Create one before we go in the loop.
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return 0;
}
if (Num == 0) {
return 0;
}
switch (Type)
{
case IL_SUB_NEXT:
if (iCurImage->Next)
ilCloseImage(iCurImage->Next);
iCurImage->Next = ilNewImage(1, 1, 1, 1, 1);
SubImage = iCurImage->Next;
break;
case IL_SUB_MIPMAP:
if (iCurImage->Mipmaps)
ilCloseImage(iCurImage->Mipmaps);
iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1);
SubImage = iCurImage->Mipmaps;
break;
case IL_SUB_LAYER:
if (iCurImage->Layers)
ilCloseImage(iCurImage->Layers);
iCurImage->Layers = ilNewImage(1, 1, 1, 1, 1);
SubImage = iCurImage->Layers;
break;
default:
ilSetError(IL_INVALID_ENUM);
return IL_FALSE;
}
if (SubImage == NULL) {
return 0;
}
for (Count = 1; Count < Num; Count++) {
SubImage->Next = ilNewImage(1, 1, 1, 1, 1);
SubImage = SubImage->Next;
if (SubImage == NULL)
return Count;
}
return Count;
}
// Returns the current index.
ILAPI ILuint ILAPIENTRY ilGetCurName()
{
if (iCurImage == NULL || ImageStack == NULL || StackSize == 0)
return 0;
return CurName;
}
// Returns the current image.
ILAPI ILimage* ILAPIENTRY ilGetCurImage()
{
return iCurImage;
}
// To be only used when the original image is going to be set back almost immediately.
ILAPI ILvoid ILAPIENTRY ilSetCurImage(ILimage *Image)
{
iCurImage = Image;
return;
}
// Completely replaces the current image and the version in the image stack.
ILAPI ILvoid ILAPIENTRY ilReplaceCurImage(ILimage *Image)
{
if (iCurImage) {
ilActiveImage(0);
ilCloseImage(iCurImage);
}
ImageStack[ilGetCurName()] = Image;
iCurImage = Image;
ParentImage = IL_TRUE;
return;
}
// Like realloc but sets new memory to 0.
ILvoid* ILAPIENTRY ilRecalloc(ILvoid *Ptr, ILuint OldSize, ILuint NewSize)
{
ILvoid *Temp = ialloc(NewSize);
ILuint CopySize = (OldSize < NewSize) ? OldSize : NewSize;
if (Temp != NULL) {
if (Ptr != NULL) {
memcpy(Temp, Ptr, CopySize);
ifree(Ptr);
}
Ptr = Temp;
if (OldSize < NewSize)
imemclear((ILubyte*)Temp + OldSize, NewSize - OldSize);
}
return Temp;
}
// Internal function to enlarge the image stack by I_STACK_INCREMENT members.
ILboolean iEnlargeStack()
{
// 02-05-2001: Moved from ilGenImages().
// Puts the cleanup function on the exit handler once.
if (!OnExit) {
#ifdef _MEM_DEBUG
AddToAtexit(); // So iFreeMem doesn't get called after unfreed information.
#endif//_MEM_DEBUG
#if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB))
atexit((void*)ilShutDown);
#endif
OnExit = IL_TRUE;
}
if (!(ImageStack = (ILimage**)ilRecalloc(ImageStack, StackSize * sizeof(ILimage*), (StackSize + I_STACK_INCREMENT) * sizeof(ILimage*)))) {
return IL_FALSE;
}
StackSize += I_STACK_INCREMENT;
return IL_TRUE;
}
static ILboolean IsInit = IL_FALSE;
// ONLY call at startup.
ILvoid ILAPIENTRY ilInit()
{
// if it is already initialized skip initialization
if (IsInit == IL_TRUE )
return;
//ilSetMemory(NULL, NULL); Now useless 3/4/2006 (due to modification in il_alloc.c)
ilSetError(IL_NO_ERROR);
ilDefaultStates(); // Set states to their defaults.
// Sets default file-reading callbacks.
ilResetRead();
ilResetWrite();
#if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB))
atexit((void*)ilRemoveRegistered);
#endif
//_WIN32_WCE
//ilShutDown();
iSetImage0(); // Beware! Clears all existing textures!
iBindImageTemp(); // Go ahead and create the temporary image.
IsInit = IL_TRUE;
return;
}
// Frees any extra memory in the stack.
// - Called on exit
ILvoid ILAPIENTRY ilShutDown()
{
// if it is not initialized do not shutdown
iFree* TempFree = (iFree*)FreeNames;
ILuint i;
if (!IsInit)
return;
if (!IsInit) { // Prevent from being called when not initialized.
ilSetError(IL_ILLEGAL_OPERATION);
return;
}
while (TempFree != NULL) {
FreeNames = (iFree*)TempFree->Next;
ifree(TempFree);
TempFree = FreeNames;
}
//for (i = 0; i < LastUsed; i++) {
for (i = 0; i < StackSize; i++) {
if (ImageStack[i] != NULL)
ilCloseImage(ImageStack[i]);
}
if (ImageStack)
ifree(ImageStack);
ImageStack = NULL;
LastUsed = 0;
StackSize = 0;
IsInit = IL_FALSE;
return;
}
// Initializes the image stack's first entry (default image) -- ONLY CALL ONCE!
ILvoid iSetImage0()
{
if (ImageStack == NULL)
if (!iEnlargeStack())
return;
LastUsed = 1;
CurName = 0;
ParentImage = IL_TRUE;
if (!ImageStack[0])
ImageStack[0] = ilNewImage(1, 1, 1, 1, 1);
iCurImage = ImageStack[0];
ilDefaultImage();
return;
}
ILAPI ILvoid ILAPIENTRY iBindImageTemp()
{
if (ImageStack == NULL || StackSize <= 1)
if (!iEnlargeStack())
return;
if (LastUsed <2 )
LastUsed = 2;
CurName = 1;
ParentImage = IL_TRUE;
if (!ImageStack[1])
ImageStack[1] = ilNewImage(1, 1, 1, 1, 1);
iCurImage = ImageStack[1];
return;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,886 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/22/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_targa.c
//
// Description: Reads from and writes to a targa (.tga) file.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_TGA
#include "il_targa.h"
//#include <time.h> // for ilMakeString()
#include <string.h>
#include "il_manip.h"
#include "il_bits.h"
#ifdef DJGPP
#include <dos.h>
#endif
//! Checks if the file specified in FileName is a valid Targa file.
ILboolean ilIsValidTga(ILconst_string FileName)
{
ILHANDLE TargaFile;
ILboolean bTarga = IL_FALSE;
if (!iCheckExtension(FileName, IL_TEXT("tga")) &&
!iCheckExtension(FileName, IL_TEXT("vda")) &&
!iCheckExtension(FileName, IL_TEXT("icb")) &&
!iCheckExtension(FileName, IL_TEXT("vst"))) {
ilSetError(IL_INVALID_EXTENSION);
return bTarga;
}
TargaFile = iopenr(FileName);
if (TargaFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bTarga;
}
bTarga = ilIsValidTgaF(TargaFile);
icloser(TargaFile);
return bTarga;
}
//! Checks if the ILHANDLE contains a valid Targa file at the current position.
ILboolean ilIsValidTgaF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iIsValidTarga();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Checks if Lump is a valid Targa lump.
ILboolean ilIsValidTgaL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iIsValidTarga();
}
// Internal function used to get the Targa header from the current file.
ILboolean iGetTgaHead(TARGAHEAD *Header)
{
Header->IDLen = igetc();
Header->ColMapPresent = igetc();
Header->ImageType = igetc();
Header->FirstEntry = GetLittleShort();
Header->ColMapLen = GetLittleShort();
Header->ColMapEntSize = igetc();
Header->OriginX = GetLittleShort();
Header->OriginY = GetLittleShort();
Header->Width = GetLittleUShort();
Header->Height = GetLittleUShort();
Header->Bpp = igetc();
Header->ImageDesc = igetc();
return IL_TRUE;
}
// Internal function to get the header and check it.
ILboolean iIsValidTarga()
{
TARGAHEAD Head;
if (!iGetTgaHead(&Head))
return IL_FALSE;
iseek(-(ILint)sizeof(TARGAHEAD), IL_SEEK_CUR);
return iCheckTarga(&Head);
}
// Internal function used to check if the HEADER is a valid Targa header.
ILboolean iCheckTarga(TARGAHEAD *Header)
{
if (Header->Width == 0 || Header->Height == 0)
return IL_FALSE;
if (Header->Bpp != 8 && Header->Bpp != 15 && Header->Bpp != 16
&& Header->Bpp != 24 && Header->Bpp != 32)
return IL_FALSE;
if (Header->ImageDesc & BIT_4) // Supposed to be set to 0
return IL_FALSE;
// check type (added 20040218)
if(Header->ImageType != TGA_NO_DATA
&& Header->ImageType != TGA_COLMAP_UNCOMP
&& Header->ImageType != TGA_UNMAP_UNCOMP
&& Header->ImageType != TGA_BW_UNCOMP
&& Header->ImageType != TGA_COLMAP_COMP
&& Header->ImageType != TGA_UNMAP_COMP
&& Header->ImageType != TGA_BW_COMP)
return IL_FALSE;
// Doesn't work well with the bitshift so change it.
if (Header->Bpp == 15)
Header->Bpp = 16;
return IL_TRUE;
}
//! Reads a Targa file
ILboolean ilLoadTarga(ILconst_string FileName)
{
ILHANDLE TargaFile;
ILboolean bTarga = IL_FALSE;
TargaFile = iopenr(FileName);
if (TargaFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bTarga;
}
bTarga = ilLoadTargaF(TargaFile);
icloser(TargaFile);
return bTarga;
}
//! Reads an already-opened Targa file
ILboolean ilLoadTargaF(ILHANDLE File) {
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadTargaInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a Targa
ILboolean ilLoadTargaL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadTargaInternal();
}
// Internal function used to load the Targa.
ILboolean iLoadTargaInternal()
{
TARGAHEAD Header;
ILboolean bTarga;
ILenum iOrigin;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (!iGetTgaHead(&Header))
return IL_FALSE;
if (!iCheckTarga(&Header)) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
switch (Header.ImageType)
{
case TGA_NO_DATA:
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
case TGA_COLMAP_UNCOMP:
case TGA_COLMAP_COMP:
bTarga = iReadColMapTga(&Header);
break;
case TGA_UNMAP_UNCOMP:
case TGA_UNMAP_COMP:
bTarga = iReadUnmapTga(&Header);
break;
case TGA_BW_UNCOMP:
case TGA_BW_COMP:
bTarga = iReadBwTga(&Header);
break;
default:
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
// @JASON Extra Code to manipulate the image depending on
// the Image Descriptor's origin bits.
iOrigin = Header.ImageDesc & IMAGEDESC_ORIGIN_MASK;
switch (iOrigin)
{
case IMAGEDESC_TOPLEFT:
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
break;
case IMAGEDESC_TOPRIGHT:
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
iMirror();
break;
case IMAGEDESC_BOTLEFT:
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
break;
case IMAGEDESC_BOTRIGHT:
iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
iMirror();
break;
}
ilFixImage();
return bTarga;
}
ILboolean iReadColMapTga(TARGAHEAD *Header)
{
char ID[255];
ILuint i;
ILushort Pixel;
if (iread(ID, 1, Header->IDLen) != Header->IDLen)
return IL_FALSE;
if (!ilTexImage(Header->Width, Header->Height, 1, (ILubyte)(Header->Bpp >> 3), 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize)
ifree(iCurImage->Pal.Palette);
iCurImage->Format = IL_COLOUR_INDEX;
iCurImage->Pal.PalSize = Header->ColMapLen * (Header->ColMapEntSize >> 3);
switch (Header->ColMapEntSize)
{
case 16:
iCurImage->Pal.PalType = IL_PAL_BGRA32;
iCurImage->Pal.PalSize = Header->ColMapLen * 4;
break;
case 24:
iCurImage->Pal.PalType = IL_PAL_BGR24;
break;
case 32:
iCurImage->Pal.PalType = IL_PAL_BGRA32;
break;
default:
// Should *never* reach here
ilSetError(IL_ILLEGAL_FILE_VALUE);
return IL_FALSE;
}
iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
if (iCurImage->Pal.Palette == NULL) {
return IL_FALSE;
}
// Do we need to do something with FirstEntry? Like maybe:
// iread(Image->Pal + Targa->FirstEntry, 1, Image->Pal.PalSize); ??
if (Header->ColMapEntSize != 16) {
if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize)
return IL_FALSE;
}
else {
// 16 bit palette, so we have to break it up.
for (i = 0; i < iCurImage->Pal.PalSize; i += 4) {
Pixel = GetBigUShort();
if (ieof())
return IL_FALSE;
iCurImage->Pal.Palette[3] = (Pixel & 0x8000) >> 12;
iCurImage->Pal.Palette[0] = (Pixel & 0xFC00) >> 7;
iCurImage->Pal.Palette[1] = (Pixel & 0x03E0) >> 2;
iCurImage->Pal.Palette[2] = (Pixel & 0x001F) << 3;
}
}
if (Header->ImageType == TGA_COLMAP_COMP) {
if (!iUncompressTgaData(iCurImage)) {
return IL_FALSE;
}
}
else {
if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) {
return IL_FALSE;
}
}
return IL_TRUE;
}
ILboolean iReadUnmapTga(TARGAHEAD *Header)
{
ILubyte Bpp;
char ID[255];
if (iread(ID, 1, Header->IDLen) != Header->IDLen)
return IL_FALSE;
/*if (Header->Bpp == 16)
Bpp = 3;
else*/
Bpp = (ILubyte)(Header->Bpp >> 3);
if (!ilTexImage(Header->Width, Header->Height, 1, Bpp, 0, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
switch (iCurImage->Bpp)
{
case 1:
iCurImage->Format = IL_COLOUR_INDEX; // wtf? How is this possible?
break;
case 2: // 16-bit is not supported directly!
//iCurImage->Format = IL_RGB5_A1;
/*iCurImage->Format = IL_RGBA;
iCurImage->Type = IL_UNSIGNED_SHORT_5_5_5_1_EXT;*/
//iCurImage->Type = IL_UNSIGNED_SHORT_5_6_5_REV;
// Remove?
//ilCloseImage(iCurImage);
//ilSetError(IL_FORMAT_NOT_SUPPORTED);
//return IL_FALSE;
/*iCurImage->Bpp = 4;
iCurImage->Format = IL_BGRA;
iCurImage->Type = IL_UNSIGNED_SHORT_1_5_5_5_REV;*/
iCurImage->Format = IL_BGR;
break;
case 3:
iCurImage->Format = IL_BGR;
break;
case 4:
iCurImage->Format = IL_BGRA;
break;
default:
ilSetError(IL_INVALID_VALUE);
return IL_FALSE;
}
// @TODO: Determine this:
// We assume that no palette is present, but it's possible...
// Should we mess with it or not?
if (Header->ImageType == TGA_UNMAP_COMP) {
if (!iUncompressTgaData(iCurImage)) {
return IL_FALSE;
}
}
else {
if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) {
return IL_FALSE;
}
}
// Go ahead and expand it to 24-bit.
if (Header->Bpp == 16) {
if (!i16BitTarga(iCurImage))
return IL_FALSE;
return IL_TRUE;
}
return IL_TRUE;
}
ILboolean iReadBwTga(TARGAHEAD *Header)
{
char ID[255];
if (iread(ID, 1, Header->IDLen) != Header->IDLen)
return IL_FALSE;
// We assume that no palette is present, but it's possible...
// Should we mess with it or not?
if (!ilTexImage(Header->Width, Header->Height, 1, (ILubyte)(Header->Bpp >> 3), IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) {
return IL_FALSE;
}
if (Header->ImageType == TGA_BW_COMP) {
if (!iUncompressTgaData(iCurImage)) {
return IL_FALSE;
}
}
else {
if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) {
return IL_FALSE;
}
}
return IL_TRUE;
}
ILboolean iUncompressTgaData(ILimage *Image)
{
ILuint BytesRead = 0, Size, RunLen, i;
ILubyte Header, Color[4];
ILint c;
Size = Image->Width * Image->Height * Image->Depth * Image->Bpp;
if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
iPreCache(iCurImage->SizeOfData / 2);
while (BytesRead < Size) {
Header = igetc();
if (Header & BIT_7) {
ClearBits(Header, BIT_7);
if (iread(Color, 1, Image->Bpp) != Image->Bpp) {
iUnCache();
return IL_FALSE;
}
RunLen = (Header+1) * Image->Bpp;
for (i = 0; i < RunLen; i += Image->Bpp) {
for (c = 0; c < Image->Bpp; c++) {
Image->Data[BytesRead+i+c] = Color[c];
}
}
BytesRead += RunLen;
}
else {
RunLen = (Header+1) * Image->Bpp;
if (iread(Image->Data + BytesRead, 1, RunLen) != RunLen) {
iUnCache();
return IL_FALSE;
}
BytesRead += RunLen;
}
}
iUnCache();
return IL_TRUE;
}
// Pretty damn unoptimized
ILboolean i16BitTarga(ILimage *Image)
{
ILushort *Temp1;
ILubyte *Data, *Temp2;
ILuint x, PixSize = Image->Width * Image->Height;
Data = (ILubyte*)ialloc(Image->Width * Image->Height * 3);
Temp1 = (ILushort*)Image->Data;
Temp2 = Data;
if (Data == NULL)
return IL_FALSE;
for (x = 0; x < PixSize; x++) {
*Temp2++ = (*Temp1 & 0x001F) << 3; // Blue
*Temp2++ = (*Temp1 & 0x03E0) >> 2; // Green
*Temp2++ = (*Temp1 & 0x7C00) >> 7; // Red
Temp1++;
/*s = *Temp;
s = SwapShort(s);
a = !!(s & BIT_15);
s = s << 1;
//if (a) {
SetBits(s, BIT_0);
//}
//SetBits(s, BIT_15);
*Temp++ = s;*/
}
if (!ilTexImage(Image->Width, Image->Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, Data)) {
ifree(Data);
return IL_FALSE;
}
ifree(Data);
return IL_TRUE;
}
//! Writes a Targa file
ILboolean ilSaveTarga(ILconst_string FileName)
{
ILHANDLE TargaFile;
ILboolean bTarga = IL_FALSE;
if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
if (iFileExists(FileName)) {
ilSetError(IL_FILE_ALREADY_EXISTS);
return IL_FALSE;
}
}
TargaFile = iopenw(FileName);
if (TargaFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bTarga;
}
bTarga = ilSaveTargaF(TargaFile);
iclosew(TargaFile);
return bTarga;
}
//! Writes a Targa to an already-opened file
ILboolean ilSaveTargaF(ILHANDLE File)
{
iSetOutputFile(File);
return iSaveTargaInternal();
}
//! Writes a Targa to a memory "lump"
ILboolean ilSaveTargaL(ILvoid *Lump, ILuint Size)
{
iSetOutputLump(Lump, Size);
return iSaveTargaInternal();
}
// Internal function used to save the Targa.
ILboolean iSaveTargaInternal()
{
char *ID = iGetString(IL_TGA_ID_STRING);
char *AuthName = iGetString(IL_TGA_AUTHNAME_STRING);
char *AuthComment = iGetString(IL_TGA_AUTHCOMMENT_STRING);
ILubyte IDLen = 0, UsePal, Type, PalEntSize;
ILshort ColMapStart = 0, PalSize;
ILubyte Temp;
ILenum Format;
ILboolean Compress;
ILuint RleLen;
ILubyte *Rle;
ILpal *TempPal = NULL;
ILimage *TempImage = NULL;
ILuint ExtOffset, i;
char *Footer = "TRUEVISION-XFILE.\0";
char *idString = "Developer's Image Library (DevIL)";
ILuint Day, Month, Year, Hour, Minute, Second;
char *TempData;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (iGetInt(IL_TGA_RLE) == IL_TRUE)
Compress = IL_TRUE;
else
Compress = IL_FALSE;
if (ID)
IDLen = (ILubyte)strlen(ID);
if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE)
UsePal = IL_TRUE;
else
UsePal = IL_FALSE;
iwrite(&IDLen, sizeof(ILubyte), 1);
iwrite(&UsePal, sizeof(ILubyte), 1);
Format = iCurImage->Format;
switch (Format) {
case IL_COLOUR_INDEX:
if (Compress)
Type = 9;
else
Type = 1;
break;
case IL_BGR:
case IL_BGRA:
if (Compress)
Type = 10;
else
Type = 2;
break;
case IL_RGB:
case IL_RGBA:
ilSwapColours();
if (Compress)
Type = 10;
else
Type = 2;
break;
case IL_LUMINANCE:
if (Compress)
Type = 11;
else
Type = 3;
break;
default:
// Should convert the types here...
ilSetError(IL_INVALID_VALUE);
ifree(ID);
ifree(AuthName);
ifree(AuthComment);
return IL_FALSE;
}
iwrite(&Type, sizeof(ILubyte), 1);
SaveLittleShort(ColMapStart);
switch (iCurImage->Pal.PalType)
{
case IL_PAL_NONE:
PalSize = 0;
PalEntSize = 0;
break;
case IL_PAL_BGR24:
PalSize = iCurImage->Pal.PalSize / 3;
PalEntSize = 24;
TempPal = &iCurImage->Pal;
break;
case IL_PAL_RGB24:
case IL_PAL_RGB32:
case IL_PAL_RGBA32:
case IL_PAL_BGR32:
case IL_PAL_BGRA32:
TempPal = iConvertPal(&iCurImage->Pal, IL_PAL_BGR24);
if (TempPal == NULL)
return IL_FALSE;
PalSize = TempPal->PalSize / 3;
PalEntSize = 24;
break;
default:
ilSetError(IL_INVALID_VALUE);
ifree(ID);
ifree(AuthName);
ifree(AuthComment);
PalSize = 0;
PalEntSize = 0;
return IL_FALSE;
}
SaveLittleShort(PalSize);
iwrite(&PalEntSize, sizeof(ILubyte), 1);
if (iCurImage->Bpc > 1) {
TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE);
if (TempImage == NULL) {
ifree(ID);
ifree(AuthName);
ifree(AuthComment);
return IL_FALSE;
}
}
else {
TempImage = iCurImage;
}
if (TempImage->Origin != IL_ORIGIN_LOWER_LEFT)
TempData = (char*)iGetFlipped(TempImage);
else
TempData = (char*)TempImage->Data;
// Write out the origin stuff.
Temp = 0;
iwrite(&Temp, sizeof(ILshort), 1);
iwrite(&Temp, sizeof(ILshort), 1);
Temp = iCurImage->Bpp << 3; // Changes to bits per pixel
SaveLittleUShort((ILushort)iCurImage->Width);
SaveLittleUShort((ILushort)iCurImage->Height);
iwrite(&Temp, sizeof(ILubyte), 1);
// Still don't know what exactly this is for...
Temp = 0;
iwrite(&Temp, sizeof(ILubyte), 1);
iwrite(ID, sizeof(char), IDLen);
ifree(ID);
//iwrite(ID, sizeof(ILbyte), IDLen - sizeof(ILuint));
//iwrite(&iCurImage->Depth, sizeof(ILuint), 1);
// Write out the colormap
if (UsePal)
iwrite(TempPal->Palette, sizeof(ILubyte), TempPal->PalSize);
// else do nothing
if (!Compress)
iwrite(TempData, sizeof(ILubyte), TempImage->SizeOfData);
else {
Rle = (ILubyte*)ialloc(TempImage->SizeOfData + TempImage->SizeOfData / 2 + 1); // max
if (Rle == NULL) {
ifree(AuthName);
ifree(AuthComment);
return IL_FALSE;
}
RleLen = ilRleCompress((unsigned char*)TempData, TempImage->Width, TempImage->Height,
TempImage->Depth, TempImage->Bpp, Rle, IL_TGACOMP, NULL);
iwrite(Rle, 1, RleLen);
ifree(Rle);
}
// Write the extension area.
ExtOffset = itellw();
SaveLittleUShort(495); // Number of bytes in the extension area (TGA 2.0 spec)
iwrite(AuthName, 1, ilStrLen(AuthName));
ipad(41 - ilStrLen(AuthName));
iwrite(AuthComment, 1, ilStrLen(AuthComment));
ipad(324 - ilStrLen(AuthComment));
ifree(AuthName);
ifree(AuthComment);
// Write time/date
iGetDateTime(&Month, &Day, &Year, &Hour, &Minute, &Second);
SaveLittleUShort((ILushort)Month);
SaveLittleUShort((ILushort)Day);
SaveLittleUShort((ILushort)Year);
SaveLittleUShort((ILushort)Hour);
SaveLittleUShort((ILushort)Minute);
SaveLittleUShort((ILushort)Second);
for (i = 0; i < 6; i++) { // Time created
SaveLittleUShort(0);
}
for (i = 0; i < 41; i++) { // Job name/ID
iputc(0);
}
for (i = 0; i < 3; i++) { // Job time
SaveLittleUShort(0);
}
iwrite(idString, 1, strlen(idString)); // Software ID
for (i = 0; i < 41 - strlen(idString); i++) {
iputc(0);
}
SaveLittleUShort(IL_VERSION); // Software version
iputc(' '); // Release letter (not beta anymore, so use a space)
SaveLittleUInt(0); // Key colour
SaveLittleUInt(0); // Pixel aspect ratio
SaveLittleUInt(0); // Gamma correction offset
SaveLittleUInt(0); // Colour correction offset
SaveLittleUInt(0); // Postage stamp offset
SaveLittleUInt(0); // Scan line offset
iputc(3); // Attributes type
// Write the footer.
SaveLittleUInt(ExtOffset); // No extension area
SaveLittleUInt(0); // No developer directory
iwrite(Footer, 1, strlen(Footer));
if (TempImage->Origin != IL_ORIGIN_LOWER_LEFT) {
ifree(TempData);
}
if (Format == IL_RGB || Format == IL_RGBA) {
ilSwapColours();
}
if (TempPal != &iCurImage->Pal && TempPal != NULL) {
ifree(TempPal->Palette);
ifree(TempPal);
}
if (TempImage != iCurImage)
ilCloseImage(TempImage);
return IL_TRUE;
}
/*// Makes a neat string to go into the id field of the .tga
ILvoid iMakeString(char *Str)
{
char *PSG = "Generated by Developer's Image Library: ";
char TimeStr[255];
time_t Time;
struct tm *CurTime;
time(&Time);
#ifdef _WIN32
_tzset();
#endif
CurTime = localtime(&Time);
strftime(TimeStr, 255 - strlen(PSG), "%#c (%z)", CurTime);
//strftime(TimeStr, 255 - strlen(PSG), "%C (%Z)", CurTime);
sprintf(Str, "%s%s", PSG, TimeStr);
return;
}*/
//changed name to iGetDateTime on 20031221 to fix bug 830196
ILvoid iGetDateTime(ILuint *Month, ILuint *Day, ILuint *Yr, ILuint *Hr, ILuint *Min, ILuint *Sec)
{
#ifdef DJGPP
struct date day;
struct time curtime;
gettime(&curtime);
getdate(&day);
*Month = day.da_mon;
*Day = day.da_day;
*Yr = day.da_year;
*Hr = curtime.ti_hour;
*Min = curtime.ti_min;
*Sec = curtime.ti_sec;
return;
#else
#ifdef _WIN32
SYSTEMTIME Time;
GetSystemTime(&Time);
*Month = Time.wMonth;
*Day = Time.wDay;
*Yr = Time.wYear;
*Hr = Time.wHour;
*Min = Time.wMinute;
*Sec = Time.wSecond;
return;
#else
*Month = 0;
*Day = 0;
*Yr = 0;
*Hr = 0;
*Min = 0;
*Sec = 0;
return;
#endif
#endif
}
#endif//IL_NO_TGA

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,155 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_utility.c
//
// Description: Utility functions
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
// Returns the bpp of any Format
ILAPI ILubyte ILAPIENTRY ilGetBppFormat(ILenum Format) {
switch (Format) {
case IL_COLOUR_INDEX:
case IL_LUMINANCE:
return 1;
case IL_LUMINANCE_ALPHA:
return 2;
case IL_RGB:
case IL_BGR:
return 3;
case IL_RGBA:
case IL_BGRA:
return 4;
}
return 0;
}
// Returns the format of any bpp
ILAPI ILenum ILAPIENTRY ilGetFormatBpp(ILubyte Bpp) {
switch (Bpp) {
case 1:
return IL_LUMINANCE;
case 2:
return IL_LUMINANCE_ALPHA;
case 3:
return IL_RGB;
case 4:
return IL_RGBA;
}
return 0;
}
// Returns the bpc of any Type
ILAPI ILubyte ILAPIENTRY ilGetBpcType(ILenum Type) {
switch (Type) {
case IL_BYTE:
case IL_UNSIGNED_BYTE:
return 1;
case IL_SHORT:
case IL_UNSIGNED_SHORT:
case IL_HALF:
return 2;
case IL_INT:
case IL_UNSIGNED_INT:
case IL_FLOAT:
return 4;
case IL_DOUBLE:
return 8;
}
return 0;
}
// Returns the type matching a bpc
ILAPI ILenum ILAPIENTRY ilGetTypeBpc(ILubyte Bpc) {
switch (Bpc) {
case 1:
return IL_UNSIGNED_BYTE;
case 2:
return IL_UNSIGNED_SHORT;
case 4:
return IL_UNSIGNED_INT;
case 8:
return IL_DOUBLE;
}
return 0;
}
// Returns the bpp of any palette type (PalType)
ILAPI ILubyte ILAPIENTRY ilGetBppPal(ILenum PalType) {
switch (PalType) {
case IL_PAL_RGB24:
case IL_PAL_BGR24:
return 3;
case IL_PAL_RGB32:
case IL_PAL_RGBA32:
case IL_PAL_BGR32:
case IL_PAL_BGRA32:
return 4;
}
return 0;
}
// Returns the base format of a palette type (PalType)
ILAPI ILenum ILAPIENTRY ilGetPalBaseType(ILenum PalType) {
switch (PalType) {
case IL_PAL_RGB24:
return IL_RGB;
case IL_PAL_RGB32:
return IL_RGBA; // Not sure
case IL_PAL_RGBA32:
return IL_RGBA;
case IL_PAL_BGR24:
return IL_BGR;
case IL_PAL_BGR32:
return IL_BGRA; // Not sure
case IL_PAL_BGRA32:
return IL_BGRA;
}
return 0;
}
// Returns the next power of 2 if Num isn't 2^n or returns Num if Num is 2^n
ILAPI ILuint ILAPIENTRY ilNextPower2(ILuint n) {
ILuint power = 1;
while( power < n ) {
power <<= 1;
}
return power;
}
ILAPI ILvoid ILAPIENTRY iMemSwap( ILubyte *s1, ILubyte *s2, const ILuint size ) {
const ILuint block_size = 4096;
const ILuint blocks = size/block_size;
ILuint i;
ILubyte *block = (ILubyte*)ialloc(block_size);
if(block == NULL) return;
for( i = 0; i < blocks; i++ ) {
memcpy(block,s1,block_size);
memcpy(s1,s2,block_size);
memcpy(s2,block,block_size);
s2 += block_size;
s1 += block_size;
}
i = size - i*block_size;
if( i > 0 ) {
memcpy(block,s1,i);
memcpy(s1,s2,i);
memcpy(s2,block,i);
}
ifree(block);
}

View File

@@ -0,0 +1,179 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_wal.c
//
// Description: Loads a Quake .wal texture.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_WAL
#include "il_manip.h"
#include "il_q2pal.h"
typedef struct WALHEAD
{
ILbyte FileName[32]; // Image name
ILuint Width; // Width of first image
ILuint Height; // Height of first image
ILuint Offsets[4]; // Offsets to image data
ILbyte AnimName[32]; // Name of next frame
ILuint Flags; // ??
ILuint Contents; // ??
ILuint Value; // ??
} WALHEAD;
ILboolean iLoadWalInternal(ILvoid);
//! Reads a .wal file
ILboolean ilLoadWal(ILconst_string FileName)
{
ILHANDLE WalFile;
ILboolean bWal = IL_FALSE;
WalFile = iopenr(FileName);
if (WalFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bWal;
}
bWal = ilLoadWalF(WalFile);
icloser(WalFile);
return bWal;
}
//! Reads an already-opened .wal file
ILboolean ilLoadWalF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadWalInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains a .wal file
ILboolean ilLoadWalL(const ILvoid *Lump, ILuint Size)
{
iSetInputLump(Lump, Size);
return iLoadWalInternal();
}
ILboolean iLoadWalInternal()
{
WALHEAD Header;
ILimage *Mipmaps[3], *CurImage;
ILuint i, NewW, NewH;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
CurImage = iCurImage;
//read header
iread(&Header.FileName, 1, 32);
Header.Width = GetLittleUInt();
Header.Height = GetLittleUInt();
for (i = 0; i < 4; i++)
Header.Offsets[i] = GetLittleUInt();
iread(Header.AnimName, 1, 32);
Header.Flags = GetLittleUInt();
Header.Contents = GetLittleUInt();
Header.Value = GetLittleUInt();
if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL))
return IL_FALSE;
for (i = 0; i < 3; i++) {
Mipmaps[i] = (ILimage*)icalloc(sizeof(ILimage), 1);
if (Mipmaps[i] == NULL)
goto cleanup_error;
Mipmaps[i]->Pal.Palette = (ILubyte*)ialloc(768);
if (Mipmaps[i]->Pal.Palette == NULL)
goto cleanup_error;
memcpy(Mipmaps[i]->Pal.Palette, ilDefaultQ2Pal, 768);
Mipmaps[i]->Pal.PalType = IL_PAL_RGB24;
}
NewW = Header.Width;
NewH = Header.Height;
for (i = 0; i < 3; i++) {
NewW /= 2;
NewH /= 2;
iCurImage = Mipmaps[i];
if (!ilTexImage(NewW, NewH, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL))
goto cleanup_error;
// Don't set until now so ilTexImage won't get rid of the palette.
Mipmaps[i]->Pal.PalSize = 768;
Mipmaps[i]->Origin = IL_ORIGIN_UPPER_LEFT;
}
iCurImage = CurImage;
ilCloseImage(iCurImage->Mipmaps);
iCurImage->Mipmaps = Mipmaps[0];
Mipmaps[0]->Next = Mipmaps[1];
Mipmaps[1]->Next = Mipmaps[2];
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE)
ifree(iCurImage->Pal.Palette);
iCurImage->Pal.Palette = (ILubyte*)ialloc(768);
if (iCurImage->Pal.Palette == NULL)
goto cleanup_error;
iCurImage->Pal.PalSize = 768;
iCurImage->Pal.PalType = IL_PAL_RGB24;
memcpy(iCurImage->Pal.Palette, ilDefaultQ2Pal, 768);
iseek(Header.Offsets[0], IL_SEEK_SET);
if (iread(iCurImage->Data, Header.Width * Header.Height, 1) != 1)
goto cleanup_error;
for (i = 0; i < 3; i++) {
iseek(Header.Offsets[i+1], IL_SEEK_SET);
if (iread(Mipmaps[i]->Data, Mipmaps[i]->Width * Mipmaps[i]->Height, 1) != 1)
goto cleanup_error;
}
// Fixes all images, even mipmaps.
ilFixImage();
return IL_TRUE;
cleanup_error:
for (i = 0; i < 3; i++) {
ilCloseImage(Mipmaps[i]);
}
return IL_FALSE;
}
#endif//IL_NO_WAL

View File

@@ -0,0 +1,789 @@
//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2002 by Denton Woods
// Last modified: 05/27/2002 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_xpm.c
//
// Description: Reads from an .xpm file.
//
//-----------------------------------------------------------------------------
#include "il_internal.h"
#ifndef IL_NO_XPM
#include <ctype.h>
//If this is defined, only xpm files with 1 char/pixel
//can be loaded. They load somewhat faster then, though
//(not much).
//#define XPM_DONT_USE_HASHTABLE
ILboolean iLoadXpmInternal(ILvoid);
// Reads an .xpm file
ILboolean ilLoadXpm(ILconst_string FileName)
{
ILHANDLE XpmFile;
ILboolean bXpm = IL_FALSE;
XpmFile = iopenr(FileName);
if (XpmFile == NULL) {
ilSetError(IL_COULD_NOT_OPEN_FILE);
return bXpm;
}
iSetInputFile(XpmFile);
bXpm = ilLoadXpmF(XpmFile);
icloser(XpmFile);
return bXpm;
}
//! Reads an already-opened .xpm file
ILboolean ilLoadXpmF(ILHANDLE File)
{
ILuint FirstPos;
ILboolean bRet;
iSetInputFile(File);
FirstPos = itell();
bRet = iLoadXpmInternal();
iseek(FirstPos, IL_SEEK_SET);
return bRet;
}
//! Reads from a memory "lump" that contains an .xpm
ILboolean ilLoadXpmL( const ILvoid *Lump, ILuint Size) {
iSetInputLump(Lump, Size);
return iLoadXpmInternal();
}
typedef ILubyte XpmPixel[4];
#define XPM_MAX_CHAR_PER_PIXEL 2
#ifndef XPM_DONT_USE_HASHTABLE
//The following hash table code was inspired by the xpm
//loading code of xv, one of the best image viewers of X11
//For xpm files with more than one character/pixel, it is
//impractical to use a simple lookup table for the
//character-to-color mapping (because the table requires
//2^(chars/pixel) entries, this is quite big).
//Because of that, a hash table is used for the mapping.
//The hash table has 257 entries, and collisions are
//resolved by chaining.
//257 is the smallest prime > 256
#define XPM_HASH_LEN 257
typedef struct XPMHASHENTRY
{
ILubyte ColourName[XPM_MAX_CHAR_PER_PIXEL];
XpmPixel ColourValue;
struct XPMHASHENTRY *Next;
} XPMHASHENTRY;
static ILuint XpmHash(const ILubyte* name, int len)
{
ILint i, sum;
for (sum = i = 0; i < len; ++i)
sum += name[i];
return sum % XPM_HASH_LEN;
}
XPMHASHENTRY** XpmCreateHashTable()
{
XPMHASHENTRY** Table =
(XPMHASHENTRY**)ialloc(XPM_HASH_LEN*sizeof(XPMHASHENTRY*));
if (Table != NULL)
memset(Table, 0, XPM_HASH_LEN*sizeof(XPMHASHENTRY*));
return Table;
}
void XpmDestroyHashTable(XPMHASHENTRY **Table)
{
ILint i;
XPMHASHENTRY* Entry;
for (i = 0; i < XPM_HASH_LEN; ++i) {
while (Table[i] != NULL) {
Entry = Table[i]->Next;
ifree(Table[i]);
Table[i] = Entry;
}
}
ifree(Table);
}
void XpmInsertEntry(XPMHASHENTRY **Table, const ILubyte* Name, int Len, XpmPixel Colour)
{
XPMHASHENTRY* NewEntry;
ILuint Index;
Index = XpmHash(Name, Len);
NewEntry = (XPMHASHENTRY*)ialloc(sizeof(XPMHASHENTRY));
if (NewEntry != NULL) {
NewEntry->Next = Table[Index];
memcpy(NewEntry->ColourName, Name, Len);
memcpy(NewEntry->ColourValue, Colour, sizeof(Colour));
Table[Index] = NewEntry;
}
}
void XpmGetEntry(XPMHASHENTRY **Table, const ILubyte* Name, int Len, XpmPixel Colour)
{
XPMHASHENTRY* Entry;
ILuint Index;
Index = XpmHash(Name, Len);
Entry = Table[Index];
while (Entry != NULL && strncmp((char*)(Entry->ColourName), (char*)Name, Len) != 0)
Entry = Entry->Next;
if (Entry != NULL)
memcpy(Colour, Entry->ColourValue, sizeof(Colour));
}
#endif //XPM_DONT_USE_HASHTABLE
ILint XpmGetsInternal(ILubyte *Buffer, ILint MaxLen)
{
ILint i = 0, Current;
if (ieof())
return IL_EOF;
while ((Current = igetc()) != IL_EOF && i < MaxLen - 1) {
if (Current == IL_EOF)
return 0;
if (Current == '\n') //unix line ending
break;
if (Current == '\r') { //dos/mac line ending
Current = igetc();
if (Current == '\n') //dos line ending
break;
if (Current == IL_EOF)
break;
Buffer[i++] = Current;
continue;
}
Buffer[i++] = Current;
}
Buffer[i++] = 0;
return i;
}
ILint XpmGets(ILubyte *Buffer, ILint MaxLen)
{
ILint Size, i, j;
ILboolean NotComment = IL_FALSE, InsideComment = IL_FALSE;
do {
Size = XpmGetsInternal(Buffer, MaxLen);
if (Size == IL_EOF)
return IL_EOF;
//stip leading whitespace (sometimes there's whitespace
//before a comment or before the pixel data)
for(i = 0; i < Size && isspace(Buffer[i]); ++i) ;
Size = Size - i;
for(j = 0; j < Size; ++j)
Buffer[j] = Buffer[j + i];
if (Size == 0)
continue;
if (Buffer[0] == '/' && Buffer[1] == '*') {
for (i = 2; i < Size; i++) {
if (Buffer[i] == '*' && Buffer[i+1] == '/') {
break;
}
}
if (i >= Size)
InsideComment = IL_TRUE;
}
else if (InsideComment) {
for (i = 0; i < Size; i++) {
if (Buffer[i] == '*' && Buffer[i+1] == '/') {
break;
}
}
if (i < Size)
InsideComment = IL_FALSE;
}
else {
NotComment = IL_TRUE;
}
} while (!NotComment);
return Size;
}
ILint XpmGetInt(ILubyte *Buffer, ILint Size, ILint *Position)
{
char Buff[1024];
ILint i, j;
ILboolean IsInNum = IL_FALSE;
for (i = *Position, j = 0; i < Size; i++) {
if (isdigit(Buffer[i])) {
IsInNum = IL_TRUE;
Buff[j++] = Buffer[i];
}
else {
if (IsInNum) {
Buff[j] = 0;
*Position = i;
return atoi(Buff);
}
}
}
return -1;
}
ILboolean XpmPredefCol(char *Buff, XpmPixel *Colour)
{
ILint len;
ILint val = 128;
if (!stricmp(Buff, "none")) {
(*Colour)[0] = 0;
(*Colour)[1] = 0;
(*Colour)[2] = 0;
(*Colour)[3] = 0;
return IL_TRUE;
}
(*Colour)[3] = 255;
if (!stricmp(Buff, "black")) {
(*Colour)[0] = 0;
(*Colour)[1] = 0;
(*Colour)[2] = 0;
return IL_TRUE;
}
if (!stricmp(Buff, "white")) {
(*Colour)[0] = 255;
(*Colour)[1] = 255;
(*Colour)[2] = 255;
return IL_TRUE;
}
if (!stricmp(Buff, "red")) {
(*Colour)[0] = 255;
(*Colour)[1] = 0;
(*Colour)[2] = 0;
return IL_TRUE;
}
if (!stricmp(Buff, "green")) {
(*Colour)[0] = 0;
(*Colour)[1] = 255;
(*Colour)[2] = 0;
return IL_TRUE;
}
if (!stricmp(Buff, "blue")) {
(*Colour)[0] = 0;
(*Colour)[1] = 0;
(*Colour)[2] = 255;
return IL_TRUE;
}
if (!stricmp(Buff, "yellow")) {
(*Colour)[0] = 255;
(*Colour)[1] = 255;
(*Colour)[2] = 0;
return IL_TRUE;
}
if (!stricmp(Buff, "cyan")) {
(*Colour)[0] = 0;
(*Colour)[1] = 255;
(*Colour)[2] = 255;
return IL_TRUE;
}
if (!stricmp(Buff, "gray")) {
(*Colour)[0] = 128;
(*Colour)[1] = 128;
(*Colour)[2] = 128;
return IL_TRUE;
}
//check for grayXXX codes (added 20040218)
len = strlen(Buff);
if (len >= 4) {
if (Buff[0] == 'g' || Buff[0] == 'G'
|| Buff[1] == 'r' || Buff[1] == 'R'
|| Buff[2] == 'a' || Buff[2] == 'A'
|| Buff[3] == 'y' || Buff[3] == 'Y') {
if (isdigit(Buff[4])) { // isdigit returns false on '\0'
val = Buff[4] - '0';
if (isdigit(Buff[5])) {
val = val*10 + Buff[5] - '0';
if (isdigit(Buff[6]))
val = val*10 + Buff[6] - '0';
}
val = (255*val)/100;
}
(*Colour)[0] = val;
(*Colour)[1] = val;
(*Colour)[2] = val;
return IL_TRUE;
}
}
// Unknown colour string, so use black
// (changed 20040218)
(*Colour)[0] = 0;
(*Colour)[1] = 0;
(*Colour)[2] = 0;
return IL_FALSE;
}
#ifndef XPM_DONT_USE_HASHTABLE
ILboolean XpmGetColour(ILubyte *Buffer, ILint Size, int Len, XPMHASHENTRY **Table)
#else
ILboolean XpmGetColour(ILubyte *Buffer, ILint Size, int Len, XpmPixel* Colours)
#endif
{
ILint i = 0, j, strLen = 0;
ILubyte ColBuff[3];
char Buff[1024];
XpmPixel Colour;
ILubyte Name[XPM_MAX_CHAR_PER_PIXEL];
for ( ; i < Size; i++) {
if (Buffer[i] == '\"')
break;
}
i++; // Skip the quotes.
if (i >= Size)
return IL_FALSE;
// Get the characters.
for (j = 0; j < Len; ++j) {
Name[j] = Buffer[i++];
}
// Skip to the colour definition.
for ( ; i < Size; i++) {
if (Buffer[i] == 'c')
break;
}
i++; // Skip the 'c'.
if (i >= Size || Buffer[i] != ' ') { // no 'c' found...assume black
#ifndef XPM_DONT_USE_HASHTABLE
memset(Colour, 0, sizeof(Colour));
Colour[3] = 255;
XpmInsertEntry(Table, Name, Len, Colour);
#else
memset(Colours[Name[0]], 0, sizeof(Colour));
Colours[Name[0]][3] = 255;
#endif
return IL_TRUE;
}
for ( ; i < Size; i++) {
if (Buffer[i] != ' ')
break;
}
if (i >= Size)
return IL_FALSE;
if (Buffer[i] == '#') {
// colour string may 4 digits/color or 1 digit/color
// (added 20040218) TODO: is isxdigit() ANSI???
++i;
while (i + strLen < Size && isxdigit(Buffer[i + strLen]))
++strLen;
for (j = 0; j < 3; j++) {
if (strLen >= 10) { // 4 digits
ColBuff[0] = Buffer[i + j*4];
ColBuff[1] = Buffer[i + j*4 + 1];
}
else if (strLen >= 8) { // 3 digits
ColBuff[0] = Buffer[i + j*3];
ColBuff[1] = Buffer[i + j*3 + 1];
}
else if (strLen >= 6) { // 2 digits
ColBuff[0] = Buffer[i + j*2];
ColBuff[1] = Buffer[i + j*2 + 1];
}
else if(j < strLen) { // 1 digit, strLen >= 1
ColBuff[0] = Buffer[i + j];
ColBuff[1] = 0;
}
ColBuff[2] = 0; // add terminating '\0' char
Colour[j] = (ILubyte)strtol((char*)ColBuff, NULL, 16);
}
Colour[3] = 255; // Full alpha.
}
else {
for (j = 0; i < Size; i++) {
if (!isalnum(Buffer[i]))
break;
Buff[j++] = Buffer[i];
}
Buff[j] = 0;
if (i >= Size)
return IL_FALSE;
if (!XpmPredefCol(Buff, &Colour))
return IL_FALSE;
}
#ifndef XPM_DONT_USE_HASHTABLE
XpmInsertEntry(Table, Name, Len, Colour);
#else
memcpy(Colours[Name[0]], Colour, sizeof(Colour));
#endif
return IL_TRUE;
}
ILboolean iLoadXpmInternal()
{
#define BUFFER_SIZE 2000
ILubyte Buffer[BUFFER_SIZE], *Data;
ILint Size, Pos, Width, Height, NumColours, i, x, y;
ILint CharsPerPixel;
#ifndef XPM_DONT_USE_HASHTABLE
XPMHASHENTRY **HashTable;
#else
XpmPixel *Colours;
ILint Offset;
#endif
Size = XpmGetsInternal(Buffer, BUFFER_SIZE);
if (strncmp("/* XPM */", (char*)Buffer, strlen("/* XPM */"))) {
ilSetError(IL_INVALID_FILE_HEADER);
return IL_FALSE;
}
Size = XpmGets(Buffer, BUFFER_SIZE);
// @TODO: Actually check the variable name here.
Size = XpmGets(Buffer, BUFFER_SIZE);
Pos = 0;
Width = XpmGetInt(Buffer, Size, &Pos);
Height = XpmGetInt(Buffer, Size, &Pos);
NumColours = XpmGetInt(Buffer, Size, &Pos);
CharsPerPixel = XpmGetInt(Buffer, Size, &Pos);
#ifdef XPM_DONT_USE_HASHTABLE
if (CharsPerPixel != 1) {
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
#endif
if (CharsPerPixel > XPM_MAX_CHAR_PER_PIXEL
|| Width*CharsPerPixel > BUFFER_SIZE) {
ilSetError(IL_FORMAT_NOT_SUPPORTED);
return IL_FALSE;
}
#ifndef XPM_DONT_USE_HASHTABLE
HashTable = XpmCreateHashTable();
if (HashTable == NULL)
return IL_FALSE;
#else
Colours = ialloc(256 * sizeof(XpmPixel));
if (Colours == NULL)
return IL_FALSE;
#endif
for (i = 0; i < NumColours; i++) {
Size = XpmGets(Buffer, BUFFER_SIZE);
#ifndef XPM_DONT_USE_HASHTABLE
if (!XpmGetColour(Buffer, Size, CharsPerPixel, HashTable)) {
XpmDestroyHashTable(HashTable);
#else
if (!XpmGetColour(Buffer, Size, CharsPerPixel, Colours)) {
ifree(Colours);
#endif
return IL_FALSE;
}
}
if (!ilTexImage(Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
#ifndef XPM_DONT_USE_HASHTABLE
XpmDestroyHashTable(HashTable);
#else
ifree(Colours);
#endif
return IL_FALSE;
}
Data = iCurImage->Data;
for (y = 0; y < Height; y++) {
Size = XpmGets(Buffer, BUFFER_SIZE);
for (x = 0; x < Width; x++) {
#ifndef XPM_DONT_USE_HASHTABLE
XpmGetEntry(HashTable, &Buffer[1 + x*CharsPerPixel], CharsPerPixel, &Data[(x << 2)]);
#else
Offset = (x << 2);
Data[Offset + 0] = Colours[Buffer[x + 1]][0];
Data[Offset + 1] = Colours[Buffer[x + 1]][1];
Data[Offset + 2] = Colours[Buffer[x + 1]][2];
Data[Offset + 3] = Colours[Buffer[x + 1]][3];
#endif
}
Data += iCurImage->Bps;
}
//added 20040218
iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
#ifndef XPM_DONT_USE_HASHTABLE
XpmDestroyHashTable(HashTable);
#else
ifree(Colours);
#endif
return IL_TRUE;
#undef BUFFER_SIZE
}
#endif//IL_NO_XPM