mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-07-16 14:22:24 +08:00
+ Added support for DXT1 and DXT5 (not tested yet)
+ Added support for textures with normal images in them (bmp. png and jpg) Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
This commit is contained in:
parent
ae9665772a
commit
e5affb470d
@ -1,6 +1,3 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageLoaderTEX.h"
|
||||
|
||||
@ -31,34 +28,34 @@ namespace irr {
|
||||
IImage *CImageLoaderTex::loadImage (io::IReadFile *input) const
|
||||
{
|
||||
if (!input)
|
||||
return 0;
|
||||
return nullptr;
|
||||
|
||||
video::IImage *image = 0;
|
||||
video::IImage *image = nullptr;
|
||||
|
||||
char buffer [1024];
|
||||
|
||||
if (input->read (buffer, 9) != 9)
|
||||
{
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot read header\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (memcmp (buffer, "TEXV0005", 9) != 0)
|
||||
{
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: not really a tex\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (input->read (buffer, 9) != 9)
|
||||
{
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot read second header\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (memcmp (buffer, "TEXI0001", 9) != 0)
|
||||
{
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: not really a tex\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u32 width;
|
||||
@ -66,6 +63,8 @@ namespace irr {
|
||||
u32 texture_width;
|
||||
u32 texture_height;
|
||||
u32 format;
|
||||
u32 imageFormat = FREE_IMAGE_FORMAT::FIF_UNKNOWN;
|
||||
u8 containerVersion = 0;
|
||||
|
||||
input->read (&format, 4);
|
||||
input->seek (4, true); // ignore bytes
|
||||
@ -78,23 +77,32 @@ namespace irr {
|
||||
|
||||
if (memcmp (buffer, "TEXB0003", 9) == 0)
|
||||
{
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: TEXB0003 container not supported yet\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return 0;
|
||||
containerVersion = 3;
|
||||
input->seek (4, true);
|
||||
input->read (&imageFormat, 4);
|
||||
}
|
||||
else if (memcmp (buffer, "TEXB0002", 9) == 0)
|
||||
{
|
||||
containerVersion = 2;
|
||||
|
||||
input->seek (4, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: Unknown container type\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (format != TextureFormat::ARGB8888)
|
||||
if (format == TextureFormat::A8)
|
||||
{
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: Only ARGB8888 supported\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return 0;
|
||||
wp::irrlicht::device->getLogger ()-> log ("LOAD TEX: A8 not supported\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (format == TextureFormat::RA88)
|
||||
{
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: RA88 not supported\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u32 mipmap_count = 0;
|
||||
@ -128,7 +136,7 @@ namespace irr {
|
||||
delete [] decompressedBuffer;
|
||||
delete [] compressedBuffer;
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot decompress texture data\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
delete [] compressedBuffer;
|
||||
@ -138,41 +146,385 @@ namespace irr {
|
||||
input->read (decompressedBuffer, mipmap_uncompressed_size);
|
||||
}
|
||||
|
||||
image = wp::irrlicht::driver->createImage (ECF_A8R8G8B8, irr::core::dimension2d<u32> (width, height));
|
||||
|
||||
if (!image)
|
||||
if (containerVersion == 2)
|
||||
{
|
||||
delete [] decompressedBuffer;
|
||||
delete image;
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot create destination image\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
image = wp::irrlicht::driver->createImage (ECF_A8R8G8B8, irr::core::dimension2d<u32> (width, height));
|
||||
|
||||
u32 bytesPerPixel = image->getBytesPerPixel ();
|
||||
char *imagedata = (char *) image->lock ();
|
||||
|
||||
for (u32 y = 0; y < height; y ++)
|
||||
{
|
||||
u32 baseDestination = y * image->getPitch ();
|
||||
u32 baseOrigin = y * (mipmap_width * 4);
|
||||
|
||||
for (u32 x = 0; x < width; x ++)
|
||||
if (!image)
|
||||
{
|
||||
imagedata [baseDestination + (x * bytesPerPixel) + 2] = decompressedBuffer [baseOrigin + ((width - x) * 4) + 0]; // r
|
||||
imagedata [baseDestination + (x * bytesPerPixel) + 1] = decompressedBuffer [baseOrigin + ((width - x) * 4) + 1]; // g
|
||||
imagedata [baseDestination + (x * bytesPerPixel) + 0] = decompressedBuffer [baseOrigin + ((width - x) * 4) + 2]; // b
|
||||
imagedata [baseDestination + (x * bytesPerPixel) + 3] = decompressedBuffer [baseOrigin + ((width - x) * 4) + 3]; // alpha
|
||||
delete [] decompressedBuffer;
|
||||
delete image;
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot create destination image\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case TextureFormat::ARGB8888:
|
||||
this->loadImageFromARGB8Data (image, decompressedBuffer, width, height, mipmap_width);
|
||||
break;
|
||||
case TextureFormat::DXT5:
|
||||
this->loadImageFromDXT5 (image, decompressedBuffer, width, height, mipmap_width, mipmap_height);
|
||||
break;
|
||||
case TextureFormat::DXT1:
|
||||
this->loadImageFromDXT1 (image, decompressedBuffer, width, height, mipmap_width, mipmap_height);
|
||||
break;
|
||||
case TextureFormat::DXT3:
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: DXT3 textures not supported yet\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
delete [] decompressedBuffer;
|
||||
delete image;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy the buffer to a new address
|
||||
char* filebuffer = new char [mipmap_uncompressed_size];
|
||||
char tmpname [TMP_MAX];
|
||||
|
||||
image->unlock ();
|
||||
// copy file data to the final file buffer to be used
|
||||
memcpy (filebuffer, decompressedBuffer, mipmap_uncompressed_size);
|
||||
// generate temporal name
|
||||
std::tmpnam (tmpname);
|
||||
// store it in a std::string
|
||||
std::string filename = tmpname;
|
||||
irr::io::IReadFile* file;
|
||||
|
||||
// free image format
|
||||
switch (imageFormat)
|
||||
{
|
||||
case FREE_IMAGE_FORMAT::FIF_BMP:
|
||||
// add extension to the file
|
||||
filename += ".bmp";
|
||||
file = wp::irrlicht::device->getFileSystem ()->createMemoryReadFile (filebuffer, mipmap_uncompressed_size, filename.c_str (), true);
|
||||
break;
|
||||
case FREE_IMAGE_FORMAT::FIF_PNG:
|
||||
// add extension to the file
|
||||
filename += ".png";
|
||||
file = wp::irrlicht::device->getFileSystem ()->createMemoryReadFile (filebuffer, mipmap_uncompressed_size, filename.c_str (), true);
|
||||
break;
|
||||
case FREE_IMAGE_FORMAT::FIF_JPEG:
|
||||
// add extension to the file
|
||||
filename += ".jpg";
|
||||
file = wp::irrlicht::device->getFileSystem ()->createMemoryReadFile (filebuffer, mipmap_uncompressed_size, filename.c_str (), true);
|
||||
break;
|
||||
default:
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: detected unsupported free-image format\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
delete [] decompressedBuffer;
|
||||
delete [] filebuffer;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
image = wp::irrlicht::driver->createImageFromFile (file);
|
||||
|
||||
if (!image)
|
||||
{
|
||||
file->drop ();
|
||||
|
||||
delete [] decompressedBuffer;
|
||||
delete image;
|
||||
wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot create destination image\n", input->getFileName ().c_str (), irr::ELL_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] decompressedBuffer;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void CImageLoaderTex::loadImageFromARGB8Data (IImage* output, const char* input, u32 width, u32 height, u32 mipmap_width) const
|
||||
{
|
||||
u32 bytesPerPixel = output->getBytesPerPixel ();
|
||||
char *imagedata = (char *) output->lock ();
|
||||
|
||||
for (u32 y = 0; y < height; y ++)
|
||||
{
|
||||
u32 baseDestination = y * output->getPitch ();
|
||||
u32 baseOrigin = y * (mipmap_width * 4);
|
||||
|
||||
for (u32 x = 0; x < width; x ++)
|
||||
{
|
||||
imagedata [baseDestination + (x * bytesPerPixel) + 2] = input [baseOrigin + ((width - x) * 4) + 0]; // r
|
||||
imagedata [baseDestination + (x * bytesPerPixel) + 1] = input [baseOrigin + ((width - x) * 4) + 1]; // g
|
||||
imagedata [baseDestination + (x * bytesPerPixel) + 0] = input [baseOrigin + ((width - x) * 4) + 2]; // b
|
||||
imagedata [baseDestination + (x * bytesPerPixel) + 3] = input [baseOrigin + ((width - x) * 4) + 3]; // alpha
|
||||
}
|
||||
}
|
||||
|
||||
output->unlock ();
|
||||
}
|
||||
|
||||
void CImageLoaderTex::loadImageFromDXT1 (IImage* output, const char* input, u32 destination_width, u32 destination_height, u32 origin_width, u32 origin_height) const
|
||||
{
|
||||
char* decompressedBuffer = new char [origin_width * origin_height * 4];
|
||||
|
||||
this->BlockDecompressImageDXT1 (origin_width, origin_height, (const unsigned char*) input, (unsigned long*) decompressedBuffer);
|
||||
this->loadImageFromARGB8Data (output, decompressedBuffer, destination_width, destination_height, origin_width);
|
||||
|
||||
delete [] decompressedBuffer;
|
||||
}
|
||||
|
||||
void CImageLoaderTex::loadImageFromDXT5 (IImage* output, const char* input, u32 destination_width, u32 destination_height, u32 origin_width, u32 origin_height) const
|
||||
{
|
||||
char* decompressedBuffer = new char [origin_width * origin_height * 4];
|
||||
|
||||
this->BlockDecompressImageDXT5 (origin_width, origin_height, (const unsigned char*) input, (unsigned long*) decompressedBuffer);
|
||||
this->loadImageFromARGB8Data (output, decompressedBuffer, destination_width, destination_height, origin_width);
|
||||
|
||||
delete [] decompressedBuffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// The following code is a slightly modified version of this repository
|
||||
// https://github.com/Benjamin-Dobell/s3tc-dxt-decompression
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
// unsigned long PackRGBA(): Helper method that packs RGBA channels into a single 4 byte pixel.
|
||||
//
|
||||
// unsigned char r: red channel.
|
||||
// unsigned char g: green channel.
|
||||
// unsigned char b: blue channel.
|
||||
// unsigned char a: alpha channel.
|
||||
|
||||
unsigned long CImageLoaderTex::PackRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const
|
||||
{
|
||||
return ((r << 24) | (g << 16) | (b << 8) | a);
|
||||
}
|
||||
|
||||
// void DecompressBlockDXT1(): Decompresses one block of a DXT1 texture and stores the resulting pixels at the appropriate offset in 'image'.
|
||||
//
|
||||
// unsigned long x: x-coordinate of the first pixel in the block.
|
||||
// unsigned long y: y-coordinate of the first pixel in the block.
|
||||
// unsigned long width: width of the texture being decompressed.
|
||||
// unsigned long height: height of the texture being decompressed.
|
||||
// const unsigned char *blockStorage: pointer to the block to decompress.
|
||||
// unsigned long *image: pointer to image where the decompressed pixel data should be stored.
|
||||
|
||||
void CImageLoaderTex::DecompressBlockDXT1(unsigned long x, unsigned long y, unsigned long width, const unsigned char *blockStorage, unsigned long *image) const
|
||||
{
|
||||
unsigned short color0 = *reinterpret_cast<const unsigned short *>(blockStorage);
|
||||
unsigned short color1 = *reinterpret_cast<const unsigned short *>(blockStorage + 2);
|
||||
|
||||
unsigned long temp;
|
||||
|
||||
temp = (color0 >> 11) * 255 + 16;
|
||||
unsigned char r0 = (unsigned char)((temp/32 + temp)/32);
|
||||
temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
|
||||
unsigned char g0 = (unsigned char)((temp/64 + temp)/64);
|
||||
temp = (color0 & 0x001F) * 255 + 16;
|
||||
unsigned char b0 = (unsigned char)((temp/32 + temp)/32);
|
||||
|
||||
temp = (color1 >> 11) * 255 + 16;
|
||||
unsigned char r1 = (unsigned char)((temp/32 + temp)/32);
|
||||
temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
|
||||
unsigned char g1 = (unsigned char)((temp/64 + temp)/64);
|
||||
temp = (color1 & 0x001F) * 255 + 16;
|
||||
unsigned char b1 = (unsigned char)((temp/32 + temp)/32);
|
||||
|
||||
unsigned long code = *reinterpret_cast<const unsigned long *>(blockStorage + 4);
|
||||
|
||||
for (int j=0; j < 4; j++)
|
||||
{
|
||||
for (int i=0; i < 4; i++)
|
||||
{
|
||||
unsigned long finalColor = 0;
|
||||
unsigned char positionCode = (code >> 2*(4*j+i)) & 0x03;
|
||||
|
||||
if (color0 > color1)
|
||||
{
|
||||
switch (positionCode)
|
||||
{
|
||||
case 0:
|
||||
finalColor = PackRGBA(r0, g0, b0, 255);
|
||||
break;
|
||||
case 1:
|
||||
finalColor = PackRGBA(r1, g1, b1, 255);
|
||||
break;
|
||||
case 2:
|
||||
finalColor = PackRGBA((2*r0+r1)/3, (2*g0+g1)/3, (2*b0+b1)/3, 255);
|
||||
break;
|
||||
case 3:
|
||||
finalColor = PackRGBA((r0+2*r1)/3, (g0+2*g1)/3, (b0+2*b1)/3, 255);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (positionCode)
|
||||
{
|
||||
case 0:
|
||||
finalColor = PackRGBA(r0, g0, b0, 255);
|
||||
break;
|
||||
case 1:
|
||||
finalColor = PackRGBA(r1, g1, b1, 255);
|
||||
break;
|
||||
case 2:
|
||||
finalColor = PackRGBA((r0+r1)/2, (g0+g1)/2, (b0+b1)/2, 255);
|
||||
break;
|
||||
case 3:
|
||||
finalColor = PackRGBA(0, 0, 0, 255);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (x + i < width)
|
||||
image[(y + j)*width + (x + i)] = finalColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void BlockDecompressImageDXT1(): Decompresses all the blocks of a DXT1 compressed texture and stores the resulting pixels in 'image'.
|
||||
//
|
||||
// unsigned long width: Texture width.
|
||||
// unsigned long height: Texture height.
|
||||
// const unsigned char *blockStorage: pointer to compressed DXT1 blocks.
|
||||
// unsigned long *image: pointer to the image where the decompressed pixels will be stored.
|
||||
|
||||
void CImageLoaderTex::BlockDecompressImageDXT1(unsigned long width, unsigned long height, const unsigned char *blockStorage, unsigned long *image) const
|
||||
{
|
||||
unsigned long blockCountX = (width + 3) / 4;
|
||||
unsigned long blockCountY = (height + 3) / 4;
|
||||
unsigned long blockWidth = (width < 4) ? width : 4;
|
||||
unsigned long blockHeight = (height < 4) ? height : 4;
|
||||
|
||||
for (unsigned long j = 0; j < blockCountY; j++)
|
||||
{
|
||||
for (unsigned long i = 0; i < blockCountX; i++) DecompressBlockDXT1(i*4, j*4, width, blockStorage + i * 8, image);
|
||||
blockStorage += blockCountX * 8;
|
||||
}
|
||||
}
|
||||
|
||||
// void DecompressBlockDXT5(): Decompresses one block of a DXT5 texture and stores the resulting pixels at the appropriate offset in 'image'.
|
||||
//
|
||||
// unsigned long x: x-coordinate of the first pixel in the block.
|
||||
// unsigned long y: y-coordinate of the first pixel in the block.
|
||||
// unsigned long width: width of the texture being decompressed.
|
||||
// unsigned long height: height of the texture being decompressed.
|
||||
// const unsigned char *blockStorage: pointer to the block to decompress.
|
||||
// unsigned long *image: pointer to image where the decompressed pixel data should be stored.
|
||||
|
||||
void CImageLoaderTex::DecompressBlockDXT5(unsigned long x, unsigned long y, unsigned long width, const unsigned char *blockStorage, unsigned long *image) const
|
||||
{
|
||||
unsigned char alpha0 = *reinterpret_cast<const unsigned char *>(blockStorage);
|
||||
unsigned char alpha1 = *reinterpret_cast<const unsigned char *>(blockStorage + 1);
|
||||
|
||||
const unsigned char *bits = blockStorage + 2;
|
||||
unsigned long alphaCode1 = bits[2] | (bits[3] << 8) | (bits[4] << 16) | (bits[5] << 24);
|
||||
unsigned short alphaCode2 = bits[0] | (bits[1] << 8);
|
||||
|
||||
unsigned short color0 = *reinterpret_cast<const unsigned short *>(blockStorage + 8);
|
||||
unsigned short color1 = *reinterpret_cast<const unsigned short *>(blockStorage + 10);
|
||||
|
||||
unsigned long temp;
|
||||
|
||||
temp = (color0 >> 11) * 255 + 16;
|
||||
unsigned char r0 = (unsigned char)((temp/32 + temp)/32);
|
||||
temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
|
||||
unsigned char g0 = (unsigned char)((temp/64 + temp)/64);
|
||||
temp = (color0 & 0x001F) * 255 + 16;
|
||||
unsigned char b0 = (unsigned char)((temp/32 + temp)/32);
|
||||
|
||||
temp = (color1 >> 11) * 255 + 16;
|
||||
unsigned char r1 = (unsigned char)((temp/32 + temp)/32);
|
||||
temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
|
||||
unsigned char g1 = (unsigned char)((temp/64 + temp)/64);
|
||||
temp = (color1 & 0x001F) * 255 + 16;
|
||||
unsigned char b1 = (unsigned char)((temp/32 + temp)/32);
|
||||
|
||||
unsigned long code = *reinterpret_cast<const unsigned long *>(blockStorage + 12);
|
||||
|
||||
for (int j=0; j < 4; j++)
|
||||
{
|
||||
for (int i=0; i < 4; i++)
|
||||
{
|
||||
int alphaCodeIndex = 3*(4*j+i);
|
||||
int alphaCode;
|
||||
|
||||
if (alphaCodeIndex <= 12)
|
||||
{
|
||||
alphaCode = (alphaCode2 >> alphaCodeIndex) & 0x07;
|
||||
}
|
||||
else if (alphaCodeIndex == 15)
|
||||
{
|
||||
alphaCode = (alphaCode2 >> 15) | ((alphaCode1 << 1) & 0x06);
|
||||
}
|
||||
else // alphaCodeIndex >= 18 && alphaCodeIndex <= 45
|
||||
{
|
||||
alphaCode = (alphaCode1 >> (alphaCodeIndex - 16)) & 0x07;
|
||||
}
|
||||
|
||||
unsigned char finalAlpha;
|
||||
if (alphaCode == 0)
|
||||
{
|
||||
finalAlpha = alpha0;
|
||||
}
|
||||
else if (alphaCode == 1)
|
||||
{
|
||||
finalAlpha = alpha1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (alpha0 > alpha1)
|
||||
{
|
||||
finalAlpha = ((8-alphaCode)*alpha0 + (alphaCode-1)*alpha1)/7;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (alphaCode == 6)
|
||||
finalAlpha = 0;
|
||||
else if (alphaCode == 7)
|
||||
finalAlpha = 255;
|
||||
else
|
||||
finalAlpha = ((6-alphaCode)*alpha0 + (alphaCode-1)*alpha1)/5;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char colorCode = (code >> 2*(4*j+i)) & 0x03;
|
||||
|
||||
unsigned long finalColor;
|
||||
switch (colorCode)
|
||||
{
|
||||
case 0:
|
||||
finalColor = PackRGBA(r0, g0, b0, finalAlpha);
|
||||
break;
|
||||
case 1:
|
||||
finalColor = PackRGBA(r1, g1, b1, finalAlpha);
|
||||
break;
|
||||
case 2:
|
||||
finalColor = PackRGBA((2*r0+r1)/3, (2*g0+g1)/3, (2*b0+b1)/3, finalAlpha);
|
||||
break;
|
||||
case 3:
|
||||
finalColor = PackRGBA((r0+2*r1)/3, (g0+2*g1)/3, (b0+2*b1)/3, finalAlpha);
|
||||
break;
|
||||
}
|
||||
|
||||
if (x + i < width)
|
||||
image[(y + j)*width + (x + i)] = finalColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void BlockDecompressImageDXT5(): Decompresses all the blocks of a DXT5 compressed texture and stores the resulting pixels in 'image'.
|
||||
//
|
||||
// unsigned long width: Texture width.
|
||||
// unsigned long height: Texture height.
|
||||
// const unsigned char *blockStorage: pointer to compressed DXT5 blocks.
|
||||
// unsigned long *image: pointer to the image where the decompressed pixels will be stored.
|
||||
|
||||
void CImageLoaderTex::BlockDecompressImageDXT5(unsigned long width, unsigned long height, const unsigned char *blockStorage, unsigned long *image) const
|
||||
{
|
||||
unsigned long blockCountX = (width + 3) / 4;
|
||||
unsigned long blockCountY = (height + 3) / 4;
|
||||
unsigned long blockWidth = (width < 4) ? width : 4;
|
||||
unsigned long blockHeight = (height < 4) ? height : 4;
|
||||
|
||||
for (unsigned long j = 0; j < blockCountY; j++)
|
||||
{
|
||||
for (unsigned long i = 0; i < blockCountX; i++) DecompressBlockDXT5(i*4, j*4, width, blockStorage + i * 16, image);
|
||||
blockStorage += blockCountX * 16;
|
||||
}
|
||||
}
|
||||
}// end namespace irr
|
||||
}//end namespace video
|
||||
|
||||
|
@ -1,13 +1,5 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
// this file was created by rt (www.tomkorp.com), based on ttk's png-reader
|
||||
// i wanted to be able to read in PNG images with irrlicht :)
|
||||
// why? lossless compression with 8-bit alpha channel!
|
||||
|
||||
#ifndef __C_IMAGE_LOADER_TEX_H_INCLUDED__
|
||||
#define __C_IMAGE_LOADER_PNG_H_INCLUDED__
|
||||
#define __C_IMAGE_LOADER_TEX_H_INCLUDED__
|
||||
|
||||
#include <irrlicht/irrlicht.h>
|
||||
|
||||
@ -31,7 +23,18 @@ public:
|
||||
//! creates a surface from the file
|
||||
virtual IImage* loadImage(io::IReadFile* input) const;
|
||||
|
||||
virtual void loadImageFromARGB8Data (IImage* output, const char* input, u32 width, u32 height, u32 mipmap_width) const;
|
||||
|
||||
virtual void loadImageFromDXT1 (IImage* output, const char* input, u32 destination_width, u32 destination_height, u32 origin_width, u32 origin_height) const;
|
||||
virtual void loadImageFromDXT5 (IImage* output, const char* input, u32 destination_width, u32 destination_height, u32 origin_width, u32 origin_height) const;
|
||||
|
||||
private:
|
||||
void BlockDecompressImageDXT1(unsigned long width, unsigned long height, const unsigned char *blockStorage, unsigned long *image) const;
|
||||
void DecompressBlockDXT1(unsigned long x, unsigned long y, unsigned long width, const unsigned char *blockStorage, unsigned long *image) const;
|
||||
unsigned long PackRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const;
|
||||
void BlockDecompressImageDXT5(unsigned long width, unsigned long height, const unsigned char *blockStorage, unsigned long *image) const;
|
||||
void DecompressBlockDXT5(unsigned long x, unsigned long y, unsigned long width, const unsigned char *blockStorage, unsigned long *image) const;
|
||||
|
||||
enum TextureFormat
|
||||
{
|
||||
ARGB8888,
|
||||
@ -41,11 +44,54 @@ private:
|
||||
DXT3,
|
||||
DXT1
|
||||
};
|
||||
|
||||
// extracted from the free image library
|
||||
enum FREE_IMAGE_FORMAT
|
||||
{
|
||||
FIF_UNKNOWN = -1,
|
||||
FIF_BMP = 0,
|
||||
FIF_ICO = 1,
|
||||
FIF_JPEG = 2,
|
||||
FIF_JNG = 3,
|
||||
FIF_KOALA = 4,
|
||||
FIF_LBM = 5,
|
||||
FIF_IFF = FIF_LBM,
|
||||
FIF_MNG = 6,
|
||||
FIF_PBM = 7,
|
||||
FIF_PBMRAW = 8,
|
||||
FIF_PCD = 9,
|
||||
FIF_PCX = 10,
|
||||
FIF_PGM = 11,
|
||||
FIF_PGMRAW = 12,
|
||||
FIF_PNG = 13,
|
||||
FIF_PPM = 14,
|
||||
FIF_PPMRAW = 15,
|
||||
FIF_RAS = 16,
|
||||
FIF_TARGA = 17,
|
||||
FIF_TIFF = 18,
|
||||
FIF_WBMP = 19,
|
||||
FIF_PSD = 20,
|
||||
FIF_CUT = 21,
|
||||
FIF_XBM = 22,
|
||||
FIF_XPM = 23,
|
||||
FIF_DDS = 24,
|
||||
FIF_GIF = 25,
|
||||
FIF_HDR = 26,
|
||||
FIF_FAXG3 = 27,
|
||||
FIF_SGI = 28,
|
||||
FIF_EXR = 29,
|
||||
FIF_J2K = 30,
|
||||
FIF_JP2 = 31,
|
||||
FIF_PFM = 32,
|
||||
FIF_PICT = 33,
|
||||
FIF_RAW = 34,
|
||||
FIF_WEBP = 35,
|
||||
FIF_JXR = 36
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !__C_IMAGE_LOADER_TEX_H_INCLUDED__ */
|
||||
|
Loading…
Reference in New Issue
Block a user