Selaa lähdekoodia

+ 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>

Alexis Maiquez Murcia 7 vuotta sitten
vanhempi
commit
e5affb470d
2 muutettua tiedostoa jossa 440 lisäystä ja 42 poistoa
  1. 383 31
      wallpaperengine/irr/CImageLoaderTEX.cpp
  2. 57 11
      wallpaperengine/irr/CImageLoaderTEX.h

+ 383 - 31
wallpaperengine/irr/CImageLoaderTEX.cpp

@@ -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::A8)
+            {
+                wp::irrlicht::device->getLogger ()-> log ("LOAD TEX: A8 not supported\n", input->getFileName ().c_str (), irr::ELL_ERROR);
+                return nullptr;
             }
 
-            if (format != TextureFormat::ARGB8888)
+            if (format == TextureFormat::RA88)
             {
-                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: 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 (containerVersion == 2)
+            {
+                image = wp::irrlicht::driver->createImage (ECF_A8R8G8B8, irr::core::dimension2d<u32> (width, height));
 
-            if (!image)
+                if (!image)
+                {
+                    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
             {
-                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;
+                // copy the buffer to a new address
+                char* filebuffer = new char [mipmap_uncompressed_size];
+                char tmpname [TMP_MAX];
+
+                // 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;
+                }
             }
 
-            u32 bytesPerPixel = image->getBytesPerPixel ();
-            char *imagedata = (char *) image->lock ();
+            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 * image->getPitch ();
+                u32 baseDestination = y * output->getPitch ();
                 u32 baseOrigin = y * (mipmap_width * 4);
 
                 for (u32 x = 0; x < width; x ++)
                 {
-                    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
+                    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
                 }
             }
 
-            image->unlock ();
+            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;
+        }
 
-            return image;
+        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
 

+ 57 - 11
wallpaperengine/irr/CImageLoaderTEX.h

@@ -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__ */