mirror of
https://github.com/love2d/love-android.git
synced 2026-08-19 04:05:22 +02:00
added dependencies and build files (loosely inspired by Sebastian Dorda's love-native-android)
This commit is contained in:
@@ -0,0 +1,763 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// ImageLib Sources
|
||||
// Copyright (C) 2000-2009 by Denton Woods
|
||||
// Last modified: 03/07/2009
|
||||
//
|
||||
// Filename: src-IL/src/il_sgi.c
|
||||
//
|
||||
// Description: Reads and writes Silicon Graphics Inc. (.sgi) files.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#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 void *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 = (ILbyte)igetc();
|
||||
Header->Bpc = (ILbyte)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 void *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;
|
||||
}
|
||||
|
||||
// Bugfix for #1060946.
|
||||
// The ZSize should never really be 2 by the specifications. Some
|
||||
// application is outputting these, and it looks like the ZSize
|
||||
// should really be 1.
|
||||
if (Header.ZSize == 2)
|
||||
Header.ZSize = 1;
|
||||
|
||||
if (Header.Storage == SGI_RLE) { // RLE
|
||||
bSgi = iReadRleSgi(&Header);
|
||||
}
|
||||
else { // Non-RLE //(Header.Storage == SGI_VERBATIM)
|
||||
bSgi = iReadNonRleSgi(&Header);
|
||||
}
|
||||
|
||||
if (!bSgi)
|
||||
return IL_FALSE;
|
||||
return ilFixImage();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
void 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(const ILstring FileName)
|
||||
{
|
||||
ILHANDLE SgiFile;
|
||||
ILuint SgiSize;
|
||||
|
||||
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 IL_FALSE;
|
||||
}
|
||||
|
||||
SgiSize = ilSaveSgiF(SgiFile);
|
||||
iclosew(SgiFile);
|
||||
|
||||
if (SgiSize == 0)
|
||||
return IL_FALSE;
|
||||
return IL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//! Writes a Sgi to an already-opened file
|
||||
ILuint ilSaveSgiF(ILHANDLE File)
|
||||
{
|
||||
ILuint Pos;
|
||||
iSetOutputFile(File);
|
||||
Pos = itellw();
|
||||
if (iSaveSgiInternal() == IL_FALSE)
|
||||
return 0; // Error occurred
|
||||
return itellw() - Pos; // Return the number of bytes written.
|
||||
}
|
||||
|
||||
|
||||
//! Writes a Sgi to a memory "lump"
|
||||
ILuint ilSaveSgiL(void *Lump, ILuint Size)
|
||||
{
|
||||
ILuint Pos;
|
||||
iSetOutputLump(Lump, Size);
|
||||
Pos = itellw();
|
||||
if (iSaveSgiInternal() == IL_FALSE)
|
||||
return 0; // Error occurred
|
||||
return itellw() - Pos; // Return the number of bytes written.
|
||||
}
|
||||
|
||||
|
||||
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 = ilCharStrLen(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
|
||||
Reference in New Issue
Block a user