Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
il_dds-save.c
Package: devil-1.7.99.tar.gz [view]
Upload User: wmy0603
Upload Date: 2022-05-02
Package Size: 1808k
Code Size: 34k
Category:
Compress-Decompress algrithms
Development Platform:
Visual C++
- //-----------------------------------------------------------------------------
- //
- // ImageLib Sources
- // Copyright (C) 2000-2009 by Denton Woods
- // Last modified: 02/09/2009
- //
- // Filename: src-IL/src/il_dds-save.c
- //
- // Description: Saves a DirectDraw Surface (.dds) file.
- //
- //-----------------------------------------------------------------------------
- #include "il_internal.h"
- #include "il_dds.h"
- #include "il_manip.h"
- #include <limits.h>
- #ifndef IL_NO_DDS
- //! Writes a Dds file
- ILboolean ilSave_DDS(const ILstring FileName)
- {
- ILHANDLE DdsFile;
- ILuint DdsSize;
- if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
- if (iFileExists(FileName)) {
- ilSetError(IL_FILE_ALREADY_EXISTS);
- return IL_FALSE;
- }
- }
- DdsFile = iopenw(FileName);
- if (DdsFile == NULL) {
- ilSetError(IL_COULD_NOT_OPEN_FILE);
- return IL_FALSE;
- }
- DdsSize = ilSaveF_DDS(DdsFile);
- iclosew(DdsFile);
- if (DdsSize == 0)
- return IL_FALSE;
- return IL_TRUE;
- }
- //! Writes a Dds to an already-opened file
- ILuint ilSaveF_DDS(ILHANDLE File)
- {
- ILuint Pos;
- iSetOutputFile(File);
- Pos = itellw();
- if (iSaveDdsInternal() == IL_FALSE)
- return 0; // Error occurred
- return itellw() - Pos; // Return the number of bytes written.
- }
- //! Writes a Dds to a memory "lump"
- ILuint ilSaveL_DDS(void *Lump, ILuint Size)
- {
- ILuint Pos;
- iSetOutputLump(Lump, Size);
- Pos = itellw();
- if (iSaveDdsInternal() == IL_FALSE)
- return 0; // Error occurred
- return itellw() - Pos; // Return the number of bytes written.
- }
- //! Checks if an image is a cubemap
- ILuint GetCubemapInfo(ILimage* image, ILint* faces)
- {
- ILint indices[] = { -1, -1, -1, -1, -1, -1 }, i;
- ILimage *img;
- ILuint ret = 0, srcMipmapCount, srcImagesCount, mipmapCount;
- if (image == NULL)
- return 0;
- iGetIntegervImage(image, IL_NUM_IMAGES, (ILint*) &srcImagesCount);
- if (srcImagesCount != 5) //write only complete cubemaps (TODO?)
- return 0;
- img = image;
- iGetIntegervImage(image, IL_NUM_MIPMAPS, (ILint*) &srcMipmapCount);
- mipmapCount = srcMipmapCount;
- for (i = 0; i < 6; ++i) {
- switch (img->CubeFlags)
- {
- case DDS_CUBEMAP_POSITIVEX:
- indices[i] = 0;
- break;
- case DDS_CUBEMAP_NEGATIVEX:
- indices[i] = 1;
- break;
- case DDS_CUBEMAP_POSITIVEY:
- indices[i] = 2;
- break;
- case DDS_CUBEMAP_NEGATIVEY:
- indices[i] = 3;
- break;
- case DDS_CUBEMAP_POSITIVEZ:
- indices[i] = 4;
- break;
- case DDS_CUBEMAP_NEGATIVEZ:
- indices[i] = 5;
- break;
- }
- iGetIntegervImage(img, IL_NUM_MIPMAPS, (ILint*) &srcMipmapCount);
- if (srcMipmapCount != mipmapCount)
- return 0; //equal # of mipmaps required
- ret |= img->CubeFlags;
- img = img->Next;
- }
- for (i = 0; i < 6; ++i)
- if (indices[i] == -1)
- return 0; //one face not found
- if (ret != 0) //should always be true
- ret |= DDS_CUBEMAP;
- for (i = 0; i < 6; ++i)
- faces[indices[i]] = i;
- return ret;
- }
- // Internal function used to save the Dds.
- ILboolean iSaveDdsInternal()
- {
- ILenum DXTCFormat;
- ILuint counter, numMipMaps, image, numFaces, i;
- ILubyte *CurData = NULL;
- ILint CubeTable[6] = { 0 };
- ILuint CubeFlags;
- CubeFlags = GetCubemapInfo(iCurImage, CubeTable);
- image = ilGetInteger(IL_CUR_IMAGE);
- DXTCFormat = iGetInt(IL_DXTC_FORMAT);
- WriteHeader(iCurImage, DXTCFormat, CubeFlags);
- if (CubeFlags != 0)
- numFaces = ilGetInteger(IL_NUM_FACES); // Should always be 5 for now
- else
- numFaces = 0;
- numMipMaps = ilGetInteger(IL_NUM_MIPMAPS); //this assumes all faces have same # of mipmaps
- for (i = 0; i <= numFaces; ++i) {
- for (counter = 0; counter <= numMipMaps; counter++) {
- ilBindImage(image);
- ilActiveImage(CubeTable[i]);
- ilActiveMipmap(counter);
- if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) {
- CurData = iCurImage->Data;
- iCurImage->Data = iGetFlipped(iCurImage);
- if (iCurImage->Data == NULL) {
- iCurImage->Data = CurData;
- return IL_FALSE;
- }
- }
- if (!Compress(iCurImage, DXTCFormat))
- return IL_FALSE;
- if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) {
- ifree(iCurImage->Data);
- iCurImage->Data = CurData;
- }
- }
- }
- return IL_TRUE;
- }
- // @TODO: Finish this, as it is incomplete.
- ILboolean WriteHeader(ILimage *Image, ILenum DXTCFormat, ILuint CubeFlags)
- {
- ILuint i, FourCC, Flags1 = 0, Flags2 = 0, ddsCaps1 = 0,
- LinearSize, BlockSize, ddsCaps2 = 0;
- Flags1 |= DDS_LINEARSIZE | DDS_MIPMAPCOUNT
- | DDS_WIDTH | DDS_HEIGHT | DDS_CAPS | DDS_PIXELFORMAT;
- Flags2 |= DDS_FOURCC;
- if (Image->Depth > 1)
- Flags1 |= DDS_DEPTH;
- // @TODO: Fix the pre-multiplied alpha problem.
- if (DXTCFormat == IL_DXT2)
- DXTCFormat = IL_DXT3;
- else if (DXTCFormat == IL_DXT4)
- DXTCFormat = IL_DXT5;
- switch (DXTCFormat)
- {
- case IL_DXT1:
- case IL_DXT1A:
- FourCC = IL_MAKEFOURCC('D','X','T','1');
- break;
- case IL_DXT2:
- FourCC = IL_MAKEFOURCC('D','X','T','2');
- break;
- case IL_DXT3:
- FourCC = IL_MAKEFOURCC('D','X','T','3');
- break;
- case IL_DXT4:
- FourCC = IL_MAKEFOURCC('D','X','T','4');
- break;
- case IL_DXT5:
- FourCC = IL_MAKEFOURCC('D','X','T','5');
- break;
- case IL_ATI1N:
- FourCC = IL_MAKEFOURCC('A', 'T', 'I', '1');
- break;
- case IL_3DC:
- FourCC = IL_MAKEFOURCC('A','T','I','2');
- break;
- case IL_RXGB:
- FourCC = IL_MAKEFOURCC('R','X','G','B');
- break;
- default:
- // Error!
- ilSetError(IL_INTERNAL_ERROR); // Should never happen, though.
- return IL_FALSE;
- }
- iwrite("DDS ", 1, 4);
- SaveLittleUInt(124); // Size1
- SaveLittleUInt(Flags1); // Flags1
- SaveLittleUInt(Image->Height);
- SaveLittleUInt(Image->Width);
- if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_ATI1N) {
- BlockSize = 8;
- }
- else {
- BlockSize = 16;
- }
- LinearSize = (((Image->Width + 3)/4) * ((Image->Height + 3)/4)) * BlockSize * Image->Depth;
- /*
- // doing this is actually wrong, linear size is only size of one cube face
- if (CubeFlags != 0) {
- ILint numFaces = 0;
- for (i = 0; i < 6; ++i)
- if (CubeFlags & CubemapDirections[i])
- ++numFaces;
- LinearSize *= numFaces;
- }
- */
- SaveLittleUInt(LinearSize); // LinearSize (TODO: change this when uncompressed formats are supported)
- if (Image->Depth > 1) {
- SaveLittleUInt(Image->Depth); // Depth
- ddsCaps2 |= DDS_VOLUME;
- }
- else
- SaveLittleUInt(0); // Depth
- SaveLittleUInt(ilGetInteger(IL_NUM_MIPMAPS) + 1); // MipMapCount
- SaveLittleUInt(0); // AlphaBitDepth
- for (i = 0; i < 10; i++)
- SaveLittleUInt(0); // Not used
- SaveLittleUInt(32); // Size2
- SaveLittleUInt(Flags2); // Flags2
- SaveLittleUInt(FourCC); // FourCC
- SaveLittleUInt(0); // RGBBitCount
- SaveLittleUInt(0); // RBitMask
- SaveLittleUInt(0); // GBitMask
- SaveLittleUInt(0); // BBitMask
- SaveLittleUInt(0); // RGBAlphaBitMask
- ddsCaps1 |= DDS_TEXTURE;
- //changed 20040516: set mipmap flag on mipmap images
- //(non-compressed .dds files still not supported,
- //though)
- if (ilGetInteger(IL_NUM_MIPMAPS) > 0)
- ddsCaps1 |= DDS_MIPMAP | DDS_COMPLEX;
- if (CubeFlags != 0) {
- ddsCaps1 |= DDS_COMPLEX;
- ddsCaps2 |= CubeFlags;
- }
- SaveLittleUInt(ddsCaps1); // ddsCaps1
- SaveLittleUInt(ddsCaps2); // ddsCaps2
- SaveLittleUInt(0); // ddsCaps3
- SaveLittleUInt(0); // ddsCaps4
- SaveLittleUInt(0); // TextureStage
- return IL_TRUE;
- }
- #endif//IL_NO_DDS
- ILuint ILAPIENTRY ilGetDXTCData(void *Buffer, ILuint BufferSize, ILenum DXTCFormat)
- {
- ILubyte *CurData = NULL;
- ILuint retVal;
- ILint BlockNum;
- if (Buffer == NULL) { // Return the number that will be written with a subsequent call.
- BlockNum = ((iCurImage->Width + 3)/4) * ((iCurImage->Height + 3)/4)
- * iCurImage->Depth;
- switch (DXTCFormat)
- {
- case IL_DXT1:
- case IL_DXT1A:
- case IL_ATI1N:
- return BlockNum * 8;
- case IL_DXT3:
- case IL_DXT5:
- case IL_3DC:
- case IL_RXGB:
- return BlockNum * 16;
- default:
- ilSetError(IL_FORMAT_NOT_SUPPORTED);
- return 0;
- }
- }
- if (DXTCFormat == iCurImage->DxtcFormat && iCurImage->DxtcSize && iCurImage->DxtcData) {
- memcpy(Buffer, iCurImage->DxtcData, IL_MIN(BufferSize, iCurImage->DxtcSize));
- return IL_MIN(BufferSize, iCurImage->DxtcSize);
- }
- if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) {
- CurData = iCurImage->Data;
- iCurImage->Data = iGetFlipped(iCurImage);
- if (iCurImage->Data == NULL) {
- iCurImage->Data = CurData;
- return 0;
- }
- }
- //@TODO: Is this the best way to do this?
- iSetOutputLump(Buffer, BufferSize);
- retVal = Compress(iCurImage, DXTCFormat);
- if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) {
- ifree(iCurImage->Data);
- iCurImage->Data = CurData;
- }
- return retVal;
- }
- // Added the next two functions based on Charles Bloom's rant at
- // http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html.
- // This code is by ryg and from the Molly Rocket forums:
- // https://mollyrocket.com/forums/viewtopic.php?t=392.
- static ILint Mul8Bit(ILint a, ILint b)
- {
- ILint t = a*b + 128;
- return (t + (t >> 8)) >> 8;
- }
- ILushort As16Bit(ILint r, ILint g, ILint b)
- {
- return (Mul8Bit(r,31) << 11) + (Mul8Bit(g,63) << 5) + Mul8Bit(b,31);
- }
- ILushort *CompressTo565(ILimage *Image)
- {
- ILimage *TempImage;
- ILushort *Data;
- ILuint i, j;
- if ((Image->Type != IL_UNSIGNED_BYTE && Image->Type != IL_BYTE) || Image->Format == IL_COLOUR_INDEX) {
- TempImage = iConvertImage(iCurImage, IL_BGRA, IL_UNSIGNED_BYTE); // @TODO: Needs to be BGRA.
- if (TempImage == NULL)
- return NULL;
- }
- else {
- TempImage = Image;
- }
- Data = (ILushort*)ialloc(iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth);
- if (Data == NULL) {
- if (TempImage != Image)
- ilCloseImage(TempImage);
- return NULL;
- }
- //changed 20040623: Use TempImages format :)
- switch (TempImage->Format)
- {
- case IL_RGB:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) {
- /*Data[j] = (TempImage->Data[i ] >> 3) << 11;
- Data[j] |= (TempImage->Data[i+1] >> 2) << 5;
- Data[j] |= TempImage->Data[i+2] >> 3;*/
- Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i+1], TempImage->Data[i+2]);
- }
- break;
- case IL_RGBA:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) {
- /*Data[j] = (TempImage->Data[i ] >> 3) << 11;
- Data[j] |= (TempImage->Data[i+1] >> 2) << 5;
- Data[j] |= TempImage->Data[i+2] >> 3;*/
- Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i+1], TempImage->Data[i+2]);
- }
- break;
- case IL_BGR:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) {
- /*Data[j] = (TempImage->Data[i+2] >> 3) << 11;
- Data[j] |= (TempImage->Data[i+1] >> 2) << 5;
- Data[j] |= TempImage->Data[i ] >> 3;*/
- Data[j] = As16Bit(TempImage->Data[i+2], TempImage->Data[i+1], TempImage->Data[i]);
- }
- break;
- case IL_BGRA:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) {
- /*Data[j] = (TempImage->Data[i+2] >> 3) << 11;
- Data[j] |= (TempImage->Data[i+1] >> 2) << 5;
- Data[j] |= TempImage->Data[i ] >> 3;*/
- Data[j] = As16Bit(TempImage->Data[i+2], TempImage->Data[i+1], TempImage->Data[i]);
- }
- break;
- case IL_LUMINANCE:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i++, j++) {
- //@TODO: Do better conversion here.
- /*Data[j] = (TempImage->Data[i] >> 3) << 11;
- Data[j] |= (TempImage->Data[i] >> 2) << 5;
- Data[j] |= TempImage->Data[i] >> 3;*/
- Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i], TempImage->Data[i]);
- }
- break;
- case IL_LUMINANCE_ALPHA:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 2, j++) {
- //@TODO: Do better conversion here.
- /*Data[j] = (TempImage->Data[i] >> 3) << 11;
- Data[j] |= (TempImage->Data[i] >> 2) << 5;
- Data[j] |= TempImage->Data[i] >> 3;*/
- Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i], TempImage->Data[i]);
- }
- break;
- case IL_ALPHA:
- memset(Data, 0, iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth);
- break;
- }
- if (TempImage != Image)
- ilCloseImage(TempImage);
- return Data;
- }
- ILubyte *CompressTo88(ILimage *Image)
- {
- ILimage *TempImage;
- ILubyte *Data;
- ILuint i, j;
- if ((Image->Type != IL_UNSIGNED_BYTE && Image->Type != IL_BYTE) || Image->Format == IL_COLOUR_INDEX) {
- TempImage = iConvertImage(iCurImage, IL_BGR, IL_UNSIGNED_BYTE); // @TODO: Needs to be BGRA.
- if (TempImage == NULL)
- return NULL;
- }
- else {
- TempImage = Image;
- }
- Data = (ILubyte*)ialloc(iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth);
- if (Data == NULL) {
- if (TempImage != Image)
- ilCloseImage(TempImage);
- return NULL;
- }
- //changed 20040623: Use TempImage's format :)
- switch (TempImage->Format)
- {
- case IL_RGB:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j += 2) {
- Data[j ] = TempImage->Data[i+1];
- Data[j+1] = TempImage->Data[i ];
- }
- break;
- case IL_RGBA:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j += 2) {
- Data[j ] = TempImage->Data[i+1];
- Data[j+1] = TempImage->Data[i ];
- }
- break;
- case IL_BGR:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j += 2) {
- Data[j ] = TempImage->Data[i+1];
- Data[j+1] = TempImage->Data[i+2];
- }
- break;
- case IL_BGRA:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j += 2) {
- Data[j ] = TempImage->Data[i+1];
- Data[j+1] = TempImage->Data[i+2];
- }
- break;
- case IL_LUMINANCE:
- case IL_LUMINANCE_ALPHA:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i++, j += 2) {
- Data[j ] = Data[j+1] = 0; //??? Luminance is no normal map format...
- }
- break;
- }
- if (TempImage != Image)
- ilCloseImage(TempImage);
- return Data;
- }
- void CompressToRXGB(ILimage *Image, ILushort** xgb, ILubyte** r)
- {
- ILimage *TempImage;
- ILuint i, j;
- ILushort *Data;
- ILubyte *Alpha;
- *xgb = NULL;
- *r = NULL;
- if ((Image->Type != IL_UNSIGNED_BYTE && Image->Type != IL_BYTE) || Image->Format == IL_COLOUR_INDEX) {
- TempImage = iConvertImage(iCurImage, IL_BGR, IL_UNSIGNED_BYTE); // @TODO: Needs to be BGRA.
- if (TempImage == NULL)
- return;
- }
- else {
- TempImage = Image;
- }
- *xgb = (ILushort*)ialloc(iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth);
- *r = (ILubyte*)ialloc(iCurImage->Width * iCurImage->Height * iCurImage->Depth);
- if (*xgb == NULL || *r == NULL) {
- if (TempImage != Image)
- ilCloseImage(TempImage);
- return;
- }
- //Alias pointers to be able to use copy'n'pasted code :)
- Data = *xgb;
- Alpha = *r;
- switch (TempImage->Format)
- {
- case IL_RGB:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) {
- Alpha[j] = TempImage->Data[i];
- Data[j] = (TempImage->Data[i+1] >> 2) << 5;
- Data[j] |= TempImage->Data[i+2] >> 3;
- }
- break;
- case IL_RGBA:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) {
- Alpha[j] = TempImage->Data[i];
- Data[j] = (TempImage->Data[i+1] >> 2) << 5;
- Data[j] |= TempImage->Data[i+2] >> 3;
- }
- break;
- case IL_BGR:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) {
- Alpha[j] = TempImage->Data[i+2];
- Data[j] = (TempImage->Data[i+1] >> 2) << 5;
- Data[j] |= TempImage->Data[i ] >> 3;
- }
- break;
- case IL_BGRA:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) {
- Alpha[j] = TempImage->Data[i+2];
- Data[j] = (TempImage->Data[i+1] >> 2) << 5;
- Data[j] |= TempImage->Data[i ] >> 3;
- }
- break;
- case IL_LUMINANCE:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i++, j++) {
- Alpha[j] = TempImage->Data[i];
- Data[j] = (TempImage->Data[i] >> 2) << 5;
- Data[j] |= TempImage->Data[i] >> 3;
- }
- break;
- case IL_LUMINANCE_ALPHA:
- for (i = 0, j = 0; i < TempImage->SizeOfData; i += 2, j++) {
- Alpha[j] = TempImage->Data[i];
- Data[j] = (TempImage->Data[i] >> 2) << 5;
- Data[j] |= TempImage->Data[i] >> 3;
- }
- break;
- }
- if (TempImage != Image)
- ilCloseImage(TempImage);
- }
- ILuint Compress(ILimage *Image, ILenum DXTCFormat)
- {
- ILushort *Data, Block[16], ex0, ex1, *Runner16, t0, t1;
- ILuint x, y, z, i, BitMask, DXTCSize;//, Rms1, Rms2;
- ILubyte *Alpha, AlphaBlock[16], AlphaBitMask[6], /*AlphaOut[16],*/ a0, a1;
- ILboolean HasAlpha;
- ILuint Count = 0;
- ILubyte *Data3Dc, *Runner8, *ByteData, *BlockData;
- if (DXTCFormat == IL_3DC) {
- Data3Dc = CompressTo88(Image);
- if (Data3Dc == NULL)
- return 0;
- Runner8 = Data3Dc;
- for (z = 0; z < Image->Depth; z++) {
- for (y = 0; y < Image->Height; y += 4) {
- for (x = 0; x < Image->Width; x += 4) {
- Get3DcBlock(AlphaBlock, Runner8, Image, x, y, 0);
- ChooseAlphaEndpoints(AlphaBlock, &a0, &a1);
- GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL);
- iputc(a0);
- iputc(a1);
- iwrite(AlphaBitMask, 1, 6);
- Get3DcBlock(AlphaBlock, Runner8, Image, x, y, 1);
- ChooseAlphaEndpoints(AlphaBlock, &a0, &a1);
- GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL);
- iputc(a0);
- iputc(a1);
- iwrite(AlphaBitMask, 1, 6);
- Count += 16;
- }
- }
- Runner8 += Image->Width * Image->Height * 2;
- }
- ifree(Data3Dc);
- }
- else if (DXTCFormat == IL_ATI1N)
- {
- ILimage *TempImage;
- if (Image->Bpp != 1) {
- TempImage = iConvertImage(iCurImage, IL_LUMINANCE, IL_UNSIGNED_BYTE);
- if (TempImage == NULL)
- return 0;
- }
- else {
- TempImage = Image;
- }
- Runner8 = TempImage->Data;
- for (z = 0; z < Image->Depth; z++) {
- for (y = 0; y < Image->Height; y += 4) {
- for (x = 0; x < Image->Width; x += 4) {
- GetAlphaBlock(AlphaBlock, Runner8, Image, x, y);
- ChooseAlphaEndpoints(AlphaBlock, &a0, &a1);
- GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL);
- iputc(a0);
- iputc(a1);
- iwrite(AlphaBitMask, 1, 6);
- Count += 8;
- }
- }
- Runner8 += Image->Width * Image->Height;
- }
- if (TempImage != Image)
- ilCloseImage(TempImage);
- }
- else
- {
- // We want to try nVidia compression first, because it is the fastest.
- #ifdef IL_USE_DXTC_NVIDIA
- if (ilIsEnabled(IL_NVIDIA_COMPRESS) && Image->Depth == 1) { // See if we need to use the nVidia Texture Tools library.
- if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_DXT3 || DXTCFormat == IL_DXT5) {
- // NVTT needs data as BGRA 32-bit.
- if (Image->Format != IL_BGRA || Image->Type != IL_UNSIGNED_BYTE) { // No need to convert if already this format/type.
- ByteData = ilConvertBuffer(Image->SizeOfData, Image->Format, IL_BGRA, Image->Type, IL_UNSIGNED_BYTE, NULL, Image->Data);
- if (ByteData == NULL)
- return 0;
- }
- else
- ByteData = Image->Data;
- // Here's where all the compression and writing goes on.
- if (!ilNVidiaCompressDXTFile(ByteData, Image->Width, Image->Height, 1, DXTCFormat))
- return 0;
- if (ByteData != Image->Data)
- ifree(ByteData);
- return Image->Width * Image->Height * 4; // Either compresses all or none.
- }
- }
- #endif//IL_USE_DXTC_NVIDIA
- // libsquish generates better quality output than DevIL does, so we try it next.
- #ifdef IL_USE_DXTC_SQUISH
- if (ilIsEnabled(IL_SQUISH_COMPRESS) && Image->Depth == 1) { // See if we need to use the nVidia Texture Tools library.
- if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_DXT3 || DXTCFormat == IL_DXT5) {
- // libsquish needs data as RGBA 32-bit.
- if (Image->Format != IL_RGBA || Image->Type != IL_UNSIGNED_BYTE) { // No need to convert if already this format/type.
- ByteData = ilConvertBuffer(Image->SizeOfData, Image->Format, IL_RGBA, Image->Type, IL_UNSIGNED_BYTE, NULL, Image->Data);
- if (ByteData == NULL)
- return 0;
- }
- else
- ByteData = Image->Data;
- // Get compressed data here.
- BlockData = ilSquishCompressDXT(ByteData, Image->Width, Image->Height, 1, DXTCFormat, &DXTCSize);
- if (BlockData == NULL)
- return 0;
- if (iwrite(BlockData, 1, DXTCSize) != DXTCSize) {
- if (ByteData != Image->Data)
- ifree(ByteData);
- ifree(BlockData);
- return 0;
- }
- if (ByteData != Image->Data)
- ifree(ByteData);
- ifree(BlockData);
- return Image->Width * Image->Height * 4; // Either compresses all or none.
- }
- }
- #endif//IL_USE_DXTC_SQUISH
- if (DXTCFormat != IL_RXGB) {
- Data = CompressTo565(Image);
- if (Data == NULL)
- return 0;
- Alpha = ilGetAlpha(IL_UNSIGNED_BYTE);
- if (Alpha == NULL) {
- ifree(Data);
- return 0;
- }
- }
- else {
- CompressToRXGB(Image, &Data, &Alpha);
- if (Data == NULL || Alpha == NULL) {
- if (Data != NULL)
- ifree(Data);
- if (Alpha != NULL)
- ifree(Alpha);
- return 0;
- }
- }
- Runner8 = Alpha;
- Runner16 = Data;
- switch (DXTCFormat)
- {
- case IL_DXT1:
- case IL_DXT1A:
- for (z = 0; z < Image->Depth; z++) {
- for (y = 0; y < Image->Height; y += 4) {
- for (x = 0; x < Image->Width; x += 4) {
- GetAlphaBlock(AlphaBlock, Runner8, Image, x, y);
- HasAlpha = IL_FALSE;
- for (i = 0 ; i < 16; i++) {
- if (AlphaBlock[i] < 128) {
- HasAlpha = IL_TRUE;
- break;
- }
- }
- GetBlock(Block, Runner16, Image, x, y);
- ChooseEndpoints(Block, &ex0, &ex1);
- CorrectEndDXT1(&ex0, &ex1, HasAlpha);
- SaveLittleUShort(ex0);
- SaveLittleUShort(ex1);
- if (HasAlpha)
- BitMask = GenBitMask(ex0, ex1, 3, Block, AlphaBlock, NULL);
- else
- BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
- SaveLittleUInt(BitMask);
- Count += 8;
- }
- }
- Runner16 += Image->Width * Image->Height;
- Runner8 += Image->Width * Image->Height;
- }
- break;
- /*case IL_DXT2:
- for (y = 0; y < Image->Height; y += 4) {
- for (x = 0; x < Image->Width; x += 4) {
- GetAlphaBlock(AlphaBlock, Alpha, Image, x, y);
- for (i = 0; i < 16; i += 2) {
- iputc((ILubyte)(((AlphaBlock[i] >> 4) << 4) | (AlphaBlock[i+1] >> 4)));
- }
- GetBlock(Block, Data, Image, x, y);
- PreMult(Block, AlphaBlock);
- ChooseEndpoints(Block, &ex0, &ex1);
- SaveLittleUShort(ex0);
- SaveLittleUShort(ex1);
- BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
- SaveLittleUInt(BitMask);
- }
- }
- break;*/
- case IL_DXT3:
- for (z = 0; z < Image->Depth; z++) {
- for (y = 0; y < Image->Height; y += 4) {
- for (x = 0; x < Image->Width; x += 4) {
- GetAlphaBlock(AlphaBlock, Runner8, Image, x, y);
- for (i = 0; i < 16; i += 2) {
- iputc((ILubyte)(((AlphaBlock[i+1] >> 4) << 4) | (AlphaBlock[i] >> 4)));
- }
- GetBlock(Block, Runner16, Image, x, y);
- ChooseEndpoints(Block, &t0, &t1);
- ex0 = IL_MAX(t0, t1);
- ex1 = IL_MIN(t0, t1);
- CorrectEndDXT1(&ex0, &ex1, 0);
- SaveLittleUShort(ex0);
- SaveLittleUShort(ex1);
- BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
- SaveLittleUInt(BitMask);
- Count += 16;
- }
- }
- Runner16 += Image->Width * Image->Height;
- Runner8 += Image->Width * Image->Height;
- }
- break;
- case IL_RXGB:
- case IL_DXT5:
- for (z = 0; z < Image->Depth; z++) {
- for (y = 0; y < Image->Height; y += 4) {
- for (x = 0; x < Image->Width; x += 4) {
- GetAlphaBlock(AlphaBlock, Runner8, Image, x, y);
- ChooseAlphaEndpoints(AlphaBlock, &a0, &a1);
- GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL/*AlphaOut*/);
- /*Rms2 = RMSAlpha(AlphaBlock, AlphaOut);
- GenAlphaBitMask(a0, a1, 8, AlphaBlock, AlphaBitMask, AlphaOut);
- Rms1 = RMSAlpha(AlphaBlock, AlphaOut);
- if (Rms2 <= Rms1) { // Yeah, we have to regenerate...
- GenAlphaBitMask(a0, a1, 6, AlphaBlock, AlphaBitMask, AlphaOut);
- Rms2 = a1; // Just reuse Rms2 as a temporary variable...
- a1 = a0;
- a0 = Rms2;
- }*/
- iputc(a0);
- iputc(a1);
- iwrite(AlphaBitMask, 1, 6);
- GetBlock(Block, Runner16, Image, x, y);
- ChooseEndpoints(Block, &t0, &t1);
- ex0 = IL_MAX(t0, t1);
- ex1 = IL_MIN(t0, t1);
- CorrectEndDXT1(&ex0, &ex1, 0);
- SaveLittleUShort(ex0);
- SaveLittleUShort(ex1);
- BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
- SaveLittleUInt(BitMask);
- Count += 16;
- }
- }
- Runner16 += Image->Width * Image->Height;
- Runner8 += Image->Width * Image->Height;
- }
- break;
- }
- ifree(Data);
- ifree(Alpha);
- } //else no 3DC
- return Count; // Returns 0 if no compression was done.
- }
- // Assumed to be 16-bit (5:6:5).
- ILboolean GetBlock(ILushort *Block, ILushort *Data, ILimage *Image, ILuint XPos, ILuint YPos)
- {
- ILuint x, y, i = 0, Offset = YPos * Image->Width + XPos;
- for (y = 0; y < 4; y++) {
- for (x = 0; x < 4; x++) {
- if (XPos + x < Image->Width && YPos + y < Image->Height)
- Block[i++] = Data[Offset + x];
- else
- // Variant of bugfix from https://sourceforge.net/forum/message.php?msg_id=5486779.
- // If we are out of bounds of the image, just copy the adjacent data.
- Block[i++] = Data[Offset];
- }
- // We do not want to read past the end of the image.
- if (YPos + y + 1 < Image->Height)
- Offset += Image->Width;
- }
- return IL_TRUE;
- }
- ILboolean GetAlphaBlock(ILubyte *Block, ILubyte *Data, ILimage *Image, ILuint XPos, ILuint YPos)
- {
- ILuint x, y, i = 0, Offset = YPos * Image->Width + XPos;
- for (y = 0; y < 4; y++) {
- for (x = 0; x < 4; x++) {
- if (XPos + x < Image->Width && YPos + y < Image->Height)
- Block[i++] = Data[Offset + x];
- else
- // Variant of bugfix from https://sourceforge.net/forum/message.php?msg_id=5486779.
- // If we are out of bounds of the image, just copy the adjacent data.
- Block[i++] = Data[Offset];
- }
- // We do not want to read past the end of the image.
- if (YPos + y + 1 < Image->Height)
- Offset += Image->Width;
- }
- return IL_TRUE;
- }
- ILboolean Get3DcBlock(ILubyte *Block, ILubyte *Data, ILimage *Image, ILuint XPos, ILuint YPos, int channel)
- {
- ILuint x, y, i = 0, Offset = 2*(YPos * Image->Width + XPos) + channel;
- for (y = 0; y < 4; y++) {
- for (x = 0; x < 4; x++) {
- if (x < Image->Width && y < Image->Height)
- Block[i++] = Data[Offset + 2*x];
- else
- Block[i++] = Data[Offset];
- }
- Offset += 2*Image->Width;
- }
- return IL_TRUE;
- }
- void ShortToColor565(ILushort Pixel, Color565 *Colour)
- {
- Colour->nRed = (Pixel & 0xF800) >> 11;
- Colour->nGreen = (Pixel & 0x07E0) >> 5;
- Colour->nBlue = (Pixel & 0x001F);
- return;
- }
- void ShortToColor888(ILushort Pixel, Color888 *Colour)
- {
- Colour->r = ((Pixel & 0xF800) >> 11) << 3;
- Colour->g = ((Pixel & 0x07E0) >> 5) << 2;
- Colour->b = ((Pixel & 0x001F)) << 3;
- return;
- }
- ILushort Color565ToShort(Color565 *Colour)
- {
- return (Colour->nRed << 11) | (Colour->nGreen << 5) | (Colour->nBlue);
- }
- ILushort Color888ToShort(Color888 *Colour)
- {
- return ((Colour->r >> 3) << 11) | ((Colour->g >> 2) << 5) | (Colour->b >> 3);
- }
- ILuint GenBitMask(ILushort ex0, ILushort ex1, ILuint NumCols, ILushort *In, ILubyte *Alpha, Color888 *OutCol)
- {
- ILuint i, j, Closest, Dist, BitMask = 0;
- ILubyte Mask[16];
- Color888 c, Colours[4];
- ShortToColor888(ex0, &Colours[0]);
- ShortToColor888(ex1, &Colours[1]);
- if (NumCols == 3) {
- Colours[2].r = (Colours[0].r + Colours[1].r) / 2;
- Colours[2].g = (Colours[0].g + Colours[1].g) / 2;
- Colours[2].b = (Colours[0].b + Colours[1].b) / 2;
- Colours[3].r = (Colours[0].r + Colours[1].r) / 2;
- Colours[3].g = (Colours[0].g + Colours[1].g) / 2;
- Colours[3].b = (Colours[0].b + Colours[1].b) / 2;
- }
- else { // NumCols == 4
- Colours[2].r = (2 * Colours[0].r + Colours[1].r + 1) / 3;
- Colours[2].g = (2 * Colours[0].g + Colours[1].g + 1) / 3;
- Colours[2].b = (2 * Colours[0].b + Colours[1].b + 1) / 3;
- Colours[3].r = (Colours[0].r + 2 * Colours[1].r + 1) / 3;
- Colours[3].g = (Colours[0].g + 2 * Colours[1].g + 1) / 3;
- Colours[3].b = (Colours[0].b + 2 * Colours[1].b + 1) / 3;
- }
- for (i = 0; i < 16; i++) {
- if (Alpha) { // Test to see if we have 1-bit transparency
- if (Alpha[i] < 128) {
- Mask[i] = 3; // Transparent
- if (OutCol) {
- OutCol[i].r = Colours[3].r;
- OutCol[i].g = Colours[3].g;
- OutCol[i].b = Colours[3].b;
- }
- continue;
- }
- }
- // If no transparency, try to find which colour is the closest.
- Closest = UINT_MAX;
- ShortToColor888(In[i], &c);
- for (j = 0; j < NumCols; j++) {
- Dist = Distance(&c, &Colours[j]);
- if (Dist < Closest) {
- Closest = Dist;
- Mask[i] = j;
- if (OutCol) {
- OutCol[i].r = Colours[j].r;
- OutCol[i].g = Colours[j].g;
- OutCol[i].b = Colours[j].b;
- }
- }
- }
- }
- for (i = 0; i < 16; i++) {
- BitMask |= (Mask[i] << (i*2));
- }
- return BitMask;
- }
- void GenAlphaBitMask(ILubyte a0, ILubyte a1, ILubyte *In, ILubyte *Mask, ILubyte *Out)
- {
- ILubyte Alphas[8], M[16];
- ILuint i, j, Closest, Dist;
- Alphas[0] = a0;
- Alphas[1] = a1;
- // 8-alpha or 6-alpha block?
- if (a0 > a1) {
- // 8-alpha block: derive the other six alphas.
- // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
- Alphas[2] = (6 * Alphas[0] + 1 * Alphas[1] + 3) / 7; // bit code 010
- Alphas[3] = (5 * Alphas[0] + 2 * Alphas[1] + 3) / 7; // bit code 011
- Alphas[4] = (4 * Alphas[0] + 3 * Alphas[1] + 3) / 7; // bit code 100
- Alphas[5] = (3 * Alphas[0] + 4 * Alphas[1] + 3) / 7; // bit code 101
- Alphas[6] = (2 * Alphas[0] + 5 * Alphas[1] + 3) / 7; // bit code 110
- Alphas[7] = (1 * Alphas[0] + 6 * Alphas[1] + 3) / 7; // bit code 111
- }
- else {
- // 6-alpha block.
- // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
- Alphas[2] = (4 * Alphas[0] + 1 * Alphas[1] + 2) / 5; // Bit code 010
- Alphas[3] = (3 * Alphas[0] + 2 * Alphas[1] + 2) / 5; // Bit code 011
- Alphas[4] = (2 * Alphas[0] + 3 * Alphas[1] + 2) / 5; // Bit code 100
- Alphas[5] = (1 * Alphas[0] + 4 * Alphas[1] + 2) / 5; // Bit code 101
- Alphas[6] = 0x00; // Bit code 110
- Alphas[7] = 0xFF; // Bit code 111
- }
- for (i = 0; i < 16; i++) {
- Closest = UINT_MAX;
- for (j = 0; j < 8; j++) {
- Dist = abs((ILint)In[i] - (ILint)Alphas[j]);
- if (Dist < Closest) {
- Closest = Dist;
- M[i] = j;
- }
- }
- }
- if (Out) {
- for (i = 0; i < 16; i++) {
- Out[i] = Alphas[M[i]];
- }
- }
- //this was changed 20040623. There was a shift bug in here. Now the code
- //produces much higher quality images.
- // First three bytes.
- Mask[0] = (M[0]) | (M[1] << 3) | ((M[2] & 0x03) << 6);
- Mask[1] = ((M[2] & 0x04) >> 2) | (M[3] << 1) | (M[4] << 4) | ((M[5] & 0x01) << 7);
- Mask[2] = ((M[5] & 0x06) >> 1) | (M[6] << 2) | (M[7] << 5);
- // Second three bytes.
- Mask[3] = (M[8]) | (M[9] << 3) | ((M[10] & 0x03) << 6);
- Mask[4] = ((M[10] & 0x04) >> 2) | (M[11] << 1) | (M[12] << 4) | ((M[13] & 0x01) << 7);
- Mask[5] = ((M[13] & 0x06) >> 1) | (M[14] << 2) | (M[15] << 5);
- return;
- }
- ILuint RMSAlpha(ILubyte *Orig, ILubyte *Test)
- {
- ILuint RMS = 0, i;
- ILint d;
- for (i = 0; i < 16; i++) {
- d = Orig[i] - Test[i];
- RMS += d*d;
- }
- //RMS /= 16;
- return RMS;
- }
- ILuint Distance(Color888 *c1, Color888 *c2)
- {
- return (c1->r - c2->r) * (c1->r - c2->r) +
- (c1->g - c2->g) * (c1->g - c2->g) +
- (c1->b - c2->b) * (c1->b - c2->b);
- }
- #define Sum(c) ((c)->r + (c)->g + (c)->b)
- #define NormSquared(c) ((c)->r * (c)->r + (c)->g * (c)->g + (c)->b * (c)->b)
- void ChooseEndpoints(ILushort *Block, ILushort *ex0, ILushort *ex1)
- {
- ILuint i;
- Color888 Colours[16];
- ILint Lowest=0, Highest=0;
- for (i = 0; i < 16; i++) {
- ShortToColor888(Block[i], &Colours[i]);
- if (NormSquared(&Colours[i]) < NormSquared(&Colours[Lowest]))
- Lowest = i;
- if (NormSquared(&Colours[i]) > NormSquared(&Colours[Highest]))
- Highest = i;
- }
- *ex0 = Block[Highest];
- *ex1 = Block[Lowest];
- }
- #undef Sum
- #undef NormSquared
- void ChooseAlphaEndpoints(ILubyte *Block, ILubyte *a0, ILubyte *a1)
- {
- ILuint i, Lowest = 0xFF, Highest = 0;
- for (i = 0; i < 16; i++) {
- if (Block[i] < Lowest)
- Lowest = Block[i];
- if (Block[i] > Highest)
- Highest = Block[i];
- }
- *a0 = Lowest;
- *a1 = Highest;
- }
- void CorrectEndDXT1(ILushort *ex0, ILushort *ex1, ILboolean HasAlpha)
- {
- ILushort Temp;
- if (HasAlpha) {
- if (*ex0 > *ex1) {
- Temp = *ex0;
- *ex0 = *ex1;
- *ex1 = Temp;
- }
- }
- else {
- if (*ex0 < *ex1) {
- Temp = *ex0;
- *ex0 = *ex1;
- *ex1 = Temp;
- }
- }
- return;
- }
- void PreMult(ILushort *Data, ILubyte *Alpha)
- {
- Color888 Colour;
- ILuint i;
- for (i = 0; i < 16; i++) {
- ShortToColor888(Data[i], &Colour);
- Colour.r = (ILubyte)(((ILuint)Colour.r * Alpha[i]) >> 8);
- Colour.g = (ILubyte)(((ILuint)Colour.g * Alpha[i]) >> 8);
- Colour.b = (ILubyte)(((ILuint)Colour.b * Alpha[i]) >> 8);
- /*Colour.r = (ILubyte)(Colour.r * (Alpha[i] / 255.0));
- Colour.g = (ILubyte)(Colour.g * (Alpha[i] / 255.0));
- Colour.b = (ILubyte)(Colour.b * (Alpha[i] / 255.0));*/
- Data[i] = Color888ToShort(&Colour);
- ShortToColor888(Data[i], &Colour);
- }
- return;
- }
- //! Compresses data to a DXT format using different methods.
- // The data must be in unsigned byte RGBA or BGRA format. Only DXT1, DXT3 and DXT5 are supported.
- ILAPI ILubyte* ILAPIENTRY ilCompressDXT(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILenum DXTCFormat, ILuint *DXTCSize)
- {
- ILimage *TempImage, *CurImage = iCurImage;
- ILuint BuffSize;
- ILubyte *Buffer;
- if ((DXTCFormat != IL_DXT1 && DXTCFormat != IL_DXT1A && DXTCFormat != IL_DXT3 && DXTCFormat != IL_DXT5)
- || Data == NULL || Width == 0 || Height == 0 || Depth == 0) {
- ilSetError(IL_INVALID_PARAM);
- return NULL;
- }
- // We want to try nVidia compression first, because it is the fastest.
- #ifdef IL_USE_DXTC_NVIDIA
- if (ilIsEnabled(IL_NVIDIA_COMPRESS) && Depth == 1) { // See if we need to use the nVidia Texture Tools library.
- // NVTT needs data as BGRA 32-bit.
- // Here's where all the compression and writing goes on.
- return ilNVidiaCompressDXT(Data, Width, Height, 1, DXTCFormat, DXTCSize);
- }
- #endif//IL_USE_DXTC_NVIDIA
- // libsquish generates better quality output than DevIL does, so we try it next.
- #ifdef IL_USE_DXTC_SQUISH
- if (ilIsEnabled(IL_SQUISH_COMPRESS) && Depth == 1) { // See if we need to use the nVidia Texture Tools library.
- if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_DXT3 || DXTCFormat == IL_DXT5) {
- // libsquish needs data as RGBA 32-bit.
- // Get compressed data here.
- return ilSquishCompressDXT(Data, Width, Height, 1, DXTCFormat, DXTCSize);
- }
- }
- #endif//IL_USE_DXTC_SQUISH
- TempImage = (ILimage*)ialloc(sizeof(ILimage));
- memset(TempImage, 0, sizeof(ILimage));
- TempImage->Width = Width;
- TempImage->Height = Height;
- TempImage->Depth = Depth;
- TempImage->Bpp = 4; // RGBA or BGRA
- TempImage->Format = IL_BGRA;
- TempImage->Bpc = 1; // Unsigned bytes only
- TempImage->Type = IL_UNSIGNED_BYTE;
- TempImage->SizeOfPlane = TempImage->Bps * Height;
- TempImage->SizeOfData = TempImage->SizeOfPlane * Depth;
- TempImage->Origin = IL_ORIGIN_UPPER_LEFT;
- TempImage->Data = Data;
- BuffSize = ilGetDXTCData(NULL, 0, DXTCFormat);
- if (BuffSize == 0)
- return NULL;
- Buffer = (ILubyte*)ialloc(BuffSize);
- if (Buffer == NULL)
- return NULL;
- if (ilGetDXTCData(Buffer, BuffSize, DXTCFormat) != BuffSize) {
- ifree(Buffer);
- return NULL;
- }
- *DXTCSize = BuffSize;
- // Restore backup of iCurImage.
- iCurImage = CurImage;
- TempImage->Data = NULL;
- ilCloseImage(TempImage);
- return Buffer;
- }