- Added partially (IImageCompressed part) support for compressed textures. Currently only DDS format is supported.
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4448 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
4250b6f7d3
commit
6f278dd40f
|
@ -148,6 +148,56 @@ public:
|
|||
|
||||
};
|
||||
|
||||
//! Interface for software compressed image data.
|
||||
/** Image loaders create these images from files. IVideoDrivers convert
|
||||
these images into their (hardware) textures.
|
||||
*/
|
||||
class IImageCompressed : public virtual IReferenceCounted
|
||||
{
|
||||
public:
|
||||
|
||||
//! Use this to get a pointer to the image data.
|
||||
virtual const void* getData() const = 0;
|
||||
|
||||
//! Returns width and height of image data.
|
||||
virtual const core::dimension2d<u32>& getDimension() const = 0;
|
||||
|
||||
//! Returns bits per pixel.
|
||||
virtual u32 getBitsPerPixel() const = 0;
|
||||
|
||||
//! Returns bytes per pixel
|
||||
virtual u32 getBytesPerPixel() const = 0;
|
||||
|
||||
//! Returns image data size in bytes
|
||||
virtual u32 getImageDataSizeInBytes() const = 0;
|
||||
|
||||
//! Returns image data size in pixels
|
||||
virtual u32 getImageDataSizeInPixels() const = 0;
|
||||
|
||||
//! Returns the color format
|
||||
virtual ECOLOR_FORMAT getColorFormat() const = 0;
|
||||
|
||||
//! Returns pitch of image
|
||||
virtual u32 getPitch() const = 0;
|
||||
|
||||
//! get the amount of Bits per Pixel of the given color format
|
||||
static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format)
|
||||
{
|
||||
switch(format)
|
||||
{
|
||||
case ECF_DXT1:
|
||||
return 16;
|
||||
case ECF_DXT2:
|
||||
case ECF_DXT3:
|
||||
case ECF_DXT4:
|
||||
case ECF_DXT5:
|
||||
return 32;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
|
|
@ -43,6 +43,15 @@ public:
|
|||
/** \param file File handle to check.
|
||||
\return Pointer to newly created image, or 0 upon error. */
|
||||
virtual IImage* loadImage(io::IReadFile* file) const = 0;
|
||||
|
||||
//! Creates a compressed surface from the file
|
||||
/** \param file File handle to check.
|
||||
\return Pointer to newly created image, or 0 upon error. */
|
||||
virtual IImageCompressed* loadImageCompressed(io::IReadFile* file) const
|
||||
{
|
||||
// The most of supported file formats are uncompressed, so we define it here.
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1218,6 +1218,18 @@ namespace video
|
|||
bool ownForeignMemory=false,
|
||||
bool deleteMemory = true) =0;
|
||||
|
||||
//! Creates a compressed software image from a file.
|
||||
virtual IImageCompressed* createImageCompressedFromFile(const io::path& filename) = 0;
|
||||
|
||||
//! Creates a compressed software image from a file.
|
||||
virtual IImageCompressed* createImageCompressedFromFile(io::IReadFile* file) = 0;
|
||||
|
||||
//! Creates a software compressed image from a byte array.
|
||||
virtual IImageCompressed* createImageCompressedFromData(ECOLOR_FORMAT format,
|
||||
const core::dimension2d<u32>& size, void *data,
|
||||
bool ownForeignMemory=false,
|
||||
bool deleteMemory = true) = 0;
|
||||
|
||||
//! Creates an empty software image.
|
||||
/**
|
||||
\param format Desired color format of the image.
|
||||
|
|
|
@ -532,14 +532,24 @@ B3D, MS3D or X meshes */
|
|||
#ifdef NO_IRR_COMPILE_WITH_PSD_LOADER_
|
||||
#undef _IRR_COMPILE_WITH_PSD_LOADER_
|
||||
#endif
|
||||
//! Define _IRR_COMPILE_WITH_DDS_LOADER_ if you want to load .dds files
|
||||
//! Define _IRR_COMPILE_WITH_DDS_LOADER_ if you want to load compressed .dds files
|
||||
// Patent problem isn't related to this loader.
|
||||
#define _IRR_COMPILE_WITH_DDS_LOADER_
|
||||
#ifdef NO_IRR_COMPILE_WITH_DDS_LOADER_
|
||||
#undef _IRR_COMPILE_WITH_DDS_LOADER_
|
||||
#endif
|
||||
//! Define _IRR_COMPILE_WITH_DDS_DECODER_LOADER_ if you want to load .dds files
|
||||
//! loader will decompress these files and will send to the memory as uncompressed files.
|
||||
// Outcommented because
|
||||
// a) it doesn't compile on 64-bit currently
|
||||
// b) anyone enabling it should be aware that S3TC compression algorithm which might be used in that loader
|
||||
// is patented in the US by S3 and they do collect license fees when it's used in applications.
|
||||
// So if you are unfortunate enough to develop applications for US market and their broken patent system be careful.
|
||||
// #define _IRR_COMPILE_WITH_DDS_LOADER_
|
||||
#ifdef NO_IRR_COMPILE_WITH_DDS_LOADER_
|
||||
// #define _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
|
||||
#ifdef NO_IRR_COMPILE_WITH_DDS_DECODER_LOADER_
|
||||
#undef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
|
||||
#endif
|
||||
#ifdef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
|
||||
#undef _IRR_COMPILE_WITH_DDS_LOADER_
|
||||
#endif
|
||||
//! Define _IRR_COMPILE_WITH_TGA_LOADER_ if you want to load .tga files
|
||||
|
|
|
@ -31,6 +31,23 @@ namespace video
|
|||
//! Default 32 bit color format. 8 bits are used for every component: red, green, blue and alpha.
|
||||
ECF_A8R8G8B8,
|
||||
|
||||
/** Compressed image formats. **/
|
||||
|
||||
//! DXT1 color format.
|
||||
ECF_DXT1,
|
||||
|
||||
//! DXT2 color format.
|
||||
ECF_DXT2,
|
||||
|
||||
//! DXT3 color format.
|
||||
ECF_DXT3,
|
||||
|
||||
//! DXT4 color format.
|
||||
ECF_DXT4,
|
||||
|
||||
//! DXT5 color format.
|
||||
ECF_DXT5,
|
||||
|
||||
/** Floating Point formats. The following formats may only be used for render target textures. */
|
||||
|
||||
//! 16 bit floating point format using 16 bits for the red channel.
|
||||
|
|
|
@ -458,5 +458,111 @@ inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) cons
|
|||
}
|
||||
|
||||
|
||||
/** Compressed image **/
|
||||
|
||||
|
||||
//! Constructor
|
||||
CImageCompressed::CImageCompressed(ECOLOR_FORMAT format, const core::dimension2d<u32>& size, void* data,
|
||||
bool ownForeignMemory, bool deleteForeignMemory)
|
||||
: Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory)
|
||||
{
|
||||
if (ownForeignMemory)
|
||||
{
|
||||
Data = (u8*)0xbadf00d;
|
||||
initData();
|
||||
Data = (u8*)data;
|
||||
}
|
||||
else
|
||||
{
|
||||
Data = 0;
|
||||
initData();
|
||||
memcpy(Data, data, Size.Height * Pitch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CImageCompressed::~CImageCompressed()
|
||||
{
|
||||
if (DeleteMemory)
|
||||
delete [] Data;
|
||||
}
|
||||
|
||||
|
||||
//! assumes format and size has been set and creates the rest
|
||||
void CImageCompressed::initData()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CImageCompressed");
|
||||
#endif
|
||||
BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8;
|
||||
|
||||
// Pitch should be aligned...
|
||||
Pitch = BytesPerPixel * Size.Width;
|
||||
|
||||
if (!Data)
|
||||
{
|
||||
DeleteMemory=true;
|
||||
Data = new u8[Size.Height * Pitch];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Use this to get a pointer to the image data.
|
||||
const void* CImageCompressed::getData() const
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
|
||||
|
||||
//! Returns width and height of image data.
|
||||
const core::dimension2d<u32>& CImageCompressed::getDimension() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
//! Returns bits per pixel.
|
||||
u32 CImageCompressed::getBitsPerPixel() const
|
||||
{
|
||||
return getBitsPerPixelFromFormat(Format);
|
||||
}
|
||||
|
||||
|
||||
//! Returns bytes per pixel
|
||||
u32 CImageCompressed::getBytesPerPixel() const
|
||||
{
|
||||
return BytesPerPixel;
|
||||
}
|
||||
|
||||
|
||||
//! Returns image data size in bytes
|
||||
u32 CImageCompressed::getImageDataSizeInBytes() const
|
||||
{
|
||||
return Pitch * Size.Height;
|
||||
}
|
||||
|
||||
|
||||
//! Returns image data size in pixels
|
||||
u32 CImageCompressed::getImageDataSizeInPixels() const
|
||||
{
|
||||
return Size.Width * Size.Height;
|
||||
}
|
||||
|
||||
|
||||
//! returns the color format
|
||||
ECOLOR_FORMAT CImageCompressed::getColorFormat() const
|
||||
{
|
||||
return Format;
|
||||
}
|
||||
|
||||
|
||||
//! returns pitch of image
|
||||
u32 CImageCompressed::getPitch() const
|
||||
{
|
||||
return Pitch;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
|
|
@ -119,6 +119,59 @@ private:
|
|||
bool DeleteMemory;
|
||||
};
|
||||
|
||||
//! Internal interface for software compressed image data.
|
||||
class CImageCompressed : public IImageCompressed
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
/** \param useForeignMemory: If true, the image will use the data pointer
|
||||
directly and own it from now on, which means it will also try to delete [] the
|
||||
data when the image will be destructed. If false, the memory will by copied. */
|
||||
CImageCompressed(ECOLOR_FORMAT format, const core::dimension2d<u32>& size,
|
||||
void* data, bool ownForeignMemory=true, bool deleteMemory = true);
|
||||
|
||||
//! Destructor
|
||||
virtual ~CImageCompressed();
|
||||
|
||||
//! Use this to get a pointer to the image data.
|
||||
virtual const void* getData() const;
|
||||
|
||||
//! Returns width and height of image data.
|
||||
virtual const core::dimension2d<u32>& getDimension() const;
|
||||
|
||||
//! Returns bits per pixel.
|
||||
virtual u32 getBitsPerPixel() const;
|
||||
|
||||
//! Returns bytes per pixel
|
||||
virtual u32 getBytesPerPixel() const;
|
||||
|
||||
//! Returns image data size in bytes
|
||||
virtual u32 getImageDataSizeInBytes() const;
|
||||
|
||||
//! Returns image data size in pixels
|
||||
virtual u32 getImageDataSizeInPixels() const;
|
||||
|
||||
//! returns the color format
|
||||
virtual ECOLOR_FORMAT getColorFormat() const;
|
||||
|
||||
//! returns pitch of image
|
||||
virtual u32 getPitch() const;
|
||||
|
||||
private:
|
||||
|
||||
//! assumes format and size has been set and creates the rest
|
||||
void initData();
|
||||
|
||||
u8* Data;
|
||||
core::dimension2d<u32> Size;
|
||||
u32 BytesPerPixel;
|
||||
u32 Pitch;
|
||||
ECOLOR_FORMAT Format;
|
||||
|
||||
bool DeleteMemory;
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Copyright (C) 2002-2012 Thomas Alten
|
||||
// Copyright (C) 2013 Patryk Nadrowski
|
||||
// Heavily based on the DDS loader implemented by Thomas Alten
|
||||
// and DDS loader from IrrSpintz implemented by Thomas Ince
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
|
@ -10,10 +12,9 @@
|
|||
mainly c to cpp
|
||||
*/
|
||||
|
||||
|
||||
#include "CImageLoaderDDS.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DDS_LOADER_
|
||||
#if defined(_IRR_COMPILE_WITH_DDS_LOADER_) || defined(_IRR_COMPILE_WITH_DDS_DECODER_LOADER_)
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "os.h"
|
||||
|
@ -21,6 +22,38 @@
|
|||
#include "CImage.h"
|
||||
#include "irrString.h"
|
||||
|
||||
// Header flag values
|
||||
#define DDSD_CAPS 0x00000001
|
||||
#define DDSD_HEIGHT 0x00000002
|
||||
#define DDSD_WIDTH 0x00000004
|
||||
#define DDSD_PITCH 0x00000008
|
||||
#define DDSD_PIXELFORMAT 0x00001000
|
||||
#define DDSD_MIPMAPCOUNT 0x00020000
|
||||
#define DDSD_LINEARSIZE 0x00080000
|
||||
#define DDSD_DEPTH 0x00800000
|
||||
|
||||
// Pixel format flag values
|
||||
#define DDPF_ALPHAPIXELS 0x00000001
|
||||
#define DDPF_ALPHA 0x00000002
|
||||
#define DDPF_FOURCC 0x00000004
|
||||
#define DDPF_RGB 0x00000040
|
||||
#define DDPF_COMPRESSED 0x00000080
|
||||
#define DDPF_LUMINANCE 0x00020000
|
||||
|
||||
// Caps1 values
|
||||
#define DDSCAPS1_COMPLEX 0x00000008
|
||||
#define DDSCAPS1_TEXTURE 0x00001000
|
||||
#define DDSCAPS1_MIPMAP 0x00400000
|
||||
|
||||
// Caps2 values
|
||||
#define DDSCAPS2_CUBEMAP 0x00000200
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
|
||||
#define DDSCAPS2_VOLUME 0x00200000
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
@ -28,21 +61,36 @@ namespace irr
|
|||
namespace video
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/*!
|
||||
DDSDecodePixelFormat()
|
||||
determines which pixel format the dds texture is in
|
||||
/*
|
||||
DDSGetInfo()
|
||||
extracts relevant info from a dds texture, returns 0 on success
|
||||
*/
|
||||
void DDSDecodePixelFormat( ddsBuffer *dds, eDDSPixelFormat *pf )
|
||||
s32 DDSGetInfo(ddsHeader* dds, s32* width, s32* height, eDDSPixelFormat* pf)
|
||||
{
|
||||
/* dummy check */
|
||||
if( dds == NULL || pf == NULL )
|
||||
return;
|
||||
/* dummy test */
|
||||
if( dds == NULL )
|
||||
return -1;
|
||||
|
||||
/* test dds header */
|
||||
if( *((s32*) dds->Magic) != *((s32*) "DDS ") )
|
||||
return -1;
|
||||
if( DDSLittleLong( dds->Size ) != 124 )
|
||||
return -1;
|
||||
if( !(DDSLittleLong( dds->Flags ) & DDSD_PIXELFORMAT) )
|
||||
return -1;
|
||||
if( !(DDSLittleLong( dds->Flags ) & DDSD_CAPS) )
|
||||
return -1;
|
||||
|
||||
/* extract width and height */
|
||||
if( width != NULL )
|
||||
*width = DDSLittleLong( dds->Width );
|
||||
if( height != NULL )
|
||||
*height = DDSLittleLong( dds->Height );
|
||||
|
||||
/* get pixel format */
|
||||
|
||||
/* extract fourCC */
|
||||
const u32 fourCC = dds->pixelFormat.fourCC;
|
||||
const u32 fourCC = dds->PixelFormat.FourCC;
|
||||
|
||||
/* test it */
|
||||
if( fourCC == 0 )
|
||||
|
@ -59,44 +107,47 @@ void DDSDecodePixelFormat( ddsBuffer *dds, eDDSPixelFormat *pf )
|
|||
*pf = DDS_PF_DXT5;
|
||||
else
|
||||
*pf = DDS_PF_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
DDSGetInfo()
|
||||
extracts relevant info from a dds texture, returns 0 on success
|
||||
*/
|
||||
s32 DDSGetInfo( ddsBuffer *dds, s32 *width, s32 *height, eDDSPixelFormat *pf )
|
||||
{
|
||||
/* dummy test */
|
||||
if( dds == NULL )
|
||||
return -1;
|
||||
|
||||
/* test dds header */
|
||||
if( *((s32*) dds->magic) != *((s32*) "DDS ") )
|
||||
return -1;
|
||||
if( DDSLittleLong( dds->size ) != 124 )
|
||||
return -1;
|
||||
|
||||
/* extract width and height */
|
||||
if( width != NULL )
|
||||
*width = DDSLittleLong( dds->width );
|
||||
if( height != NULL )
|
||||
*height = DDSLittleLong( dds->height );
|
||||
|
||||
/* get pixel format */
|
||||
DDSDecodePixelFormat( dds, pf );
|
||||
|
||||
/* return ok */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
DDSDecompressARGB8888()
|
||||
decompresses an argb 8888 format texture
|
||||
*/
|
||||
s32 DDSDecompressARGB8888(ddsHeader* dds, u8* data, s32 width, s32 height, u8* pixels)
|
||||
{
|
||||
/* setup */
|
||||
u8* in = data;
|
||||
u8* out = pixels;
|
||||
|
||||
/* walk y */
|
||||
for(s32 y = 0; y < height; y++)
|
||||
{
|
||||
/* walk x */
|
||||
for(s32 x = 0; x < width; x++)
|
||||
{
|
||||
*out++ = *in++;
|
||||
*out++ = *in++;
|
||||
*out++ = *in++;
|
||||
*out++ = *in++;
|
||||
}
|
||||
}
|
||||
|
||||
/* return ok */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
|
||||
|
||||
/*!
|
||||
DDSGetColorBlockColors()
|
||||
extracts colors from a dds color block
|
||||
*/
|
||||
void DDSGetColorBlockColors( ddsColorBlock *block, ddsColor colors[ 4 ] )
|
||||
void DDSGetColorBlockColors(ddsColorBlock* block, ddsColor colors[4])
|
||||
{
|
||||
u16 word;
|
||||
|
||||
|
@ -192,7 +243,7 @@ decodes a dds color block
|
|||
fixme: make endian-safe
|
||||
*/
|
||||
|
||||
void DDSDecodeColorBlock( u32 *pixel, ddsColorBlock *block, s32 width, u32 colors[ 4 ] )
|
||||
void DDSDecodeColorBlock(u32* pixel, ddsColorBlock* block, s32 width, u32 colors[4])
|
||||
{
|
||||
s32 r, n;
|
||||
u32 bits;
|
||||
|
@ -247,7 +298,7 @@ void DDSDecodeColorBlock( u32 *pixel, ddsColorBlock *block, s32 width, u32 color
|
|||
DDSDecodeAlphaExplicit()
|
||||
decodes a dds explicit alpha block
|
||||
*/
|
||||
void DDSDecodeAlphaExplicit( u32 *pixel, ddsAlphaBlockExplicit *alphaBlock, s32 width, u32 alphaZero )
|
||||
void DDSDecodeAlphaExplicit(u32* pixel, ddsAlphaBlockExplicit* alphaBlock, s32 width, u32 alphaZero)
|
||||
{
|
||||
s32 row, pix;
|
||||
u16 word;
|
||||
|
@ -284,7 +335,7 @@ void DDSDecodeAlphaExplicit( u32 *pixel, ddsAlphaBlockExplicit *alphaBlock, s32
|
|||
DDSDecodeAlpha3BitLinear()
|
||||
decodes interpolated alpha block
|
||||
*/
|
||||
void DDSDecodeAlpha3BitLinear( u32 *pixel, ddsAlphaBlock3BitLinear *alphaBlock, s32 width, u32 alphaZero )
|
||||
void DDSDecodeAlpha3BitLinear(u32* pixel, ddsAlphaBlock3BitLinear* alphaBlock, s32 width, u32 alphaZero)
|
||||
{
|
||||
|
||||
s32 row, pix;
|
||||
|
@ -393,7 +444,7 @@ void DDSDecodeAlpha3BitLinear( u32 *pixel, ddsAlphaBlock3BitLinear *alphaBlock,
|
|||
DDSDecompressDXT1()
|
||||
decompresses a dxt1 format texture
|
||||
*/
|
||||
s32 DDSDecompressDXT1( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
s32 DDSDecompressDXT1(ddsHeader* dds, u8* data, s32 width, s32 height, u8* pixels)
|
||||
{
|
||||
s32 x, y, xBlocks, yBlocks;
|
||||
u32 *pixel;
|
||||
|
@ -408,7 +459,7 @@ s32 DDSDecompressDXT1( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
|||
for( y = 0; y < yBlocks; y++ )
|
||||
{
|
||||
/* 8 bytes per block */
|
||||
block = (ddsColorBlock*) (dds->data + y * xBlocks * 8);
|
||||
block = (ddsColorBlock*) (data + y * xBlocks * 8);
|
||||
|
||||
/* walk x */
|
||||
for( x = 0; x < xBlocks; x++, block++ )
|
||||
|
@ -429,7 +480,7 @@ DDSDecompressDXT3()
|
|||
decompresses a dxt3 format texture
|
||||
*/
|
||||
|
||||
s32 DDSDecompressDXT3( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
s32 DDSDecompressDXT3(ddsHeader* dds, u8* data, s32 width, s32 height, u8* pixels)
|
||||
{
|
||||
s32 x, y, xBlocks, yBlocks;
|
||||
u32 *pixel, alphaZero;
|
||||
|
@ -452,7 +503,7 @@ s32 DDSDecompressDXT3( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
|||
for( y = 0; y < yBlocks; y++ )
|
||||
{
|
||||
/* 8 bytes per block, 1 block for alpha, 1 block for color */
|
||||
block = (ddsColorBlock*) (dds->data + y * xBlocks * 16);
|
||||
block = (ddsColorBlock*) (data + y * xBlocks * 16);
|
||||
|
||||
/* walk x */
|
||||
for( x = 0; x < xBlocks; x++, block++ )
|
||||
|
@ -482,7 +533,7 @@ s32 DDSDecompressDXT3( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
|||
DDSDecompressDXT5()
|
||||
decompresses a dxt5 format texture
|
||||
*/
|
||||
s32 DDSDecompressDXT5( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
s32 DDSDecompressDXT5(ddsHeader* dds, u8* data, s32 width, s32 height, u8* pixels)
|
||||
{
|
||||
s32 x, y, xBlocks, yBlocks;
|
||||
u32 *pixel, alphaZero;
|
||||
|
@ -505,7 +556,7 @@ s32 DDSDecompressDXT5( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
|||
for( y = 0; y < yBlocks; y++ )
|
||||
{
|
||||
/* 8 bytes per block, 1 block for alpha, 1 block for color */
|
||||
block = (ddsColorBlock*) (dds->data + y * xBlocks * 16);
|
||||
block = (ddsColorBlock*) (data + y * xBlocks * 16);
|
||||
|
||||
/* walk x */
|
||||
for( x = 0; x < xBlocks; x++, block++ )
|
||||
|
@ -535,10 +586,10 @@ s32 DDSDecompressDXT5( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
|||
DDSDecompressDXT2()
|
||||
decompresses a dxt2 format texture (fixme: un-premultiply alpha)
|
||||
*/
|
||||
s32 DDSDecompressDXT2( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
s32 DDSDecompressDXT2(ddsHeader* dds, u8* data, s32 width, s32 height, u8* pixels)
|
||||
{
|
||||
/* decompress dxt3 first */
|
||||
const s32 r = DDSDecompressDXT3( dds, width, height, pixels );
|
||||
const s32 r = DDSDecompressDXT3( dds, data, width, height, pixels );
|
||||
|
||||
/* return to sender */
|
||||
return r;
|
||||
|
@ -549,49 +600,21 @@ s32 DDSDecompressDXT2( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
|||
DDSDecompressDXT4()
|
||||
decompresses a dxt4 format texture (fixme: un-premultiply alpha)
|
||||
*/
|
||||
s32 DDSDecompressDXT4( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
s32 DDSDecompressDXT4(ddsHeader* dds, u8* data, s32 width, s32 height, u8* pixels)
|
||||
{
|
||||
/* decompress dxt5 first */
|
||||
const s32 r = DDSDecompressDXT5( dds, width, height, pixels );
|
||||
const s32 r = DDSDecompressDXT5( dds, data, width, height, pixels );
|
||||
|
||||
/* return to sender */
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
DDSDecompressARGB8888()
|
||||
decompresses an argb 8888 format texture
|
||||
*/
|
||||
s32 DDSDecompressARGB8888( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
{
|
||||
/* setup */
|
||||
u8* in = dds->data;
|
||||
u8* out = pixels;
|
||||
|
||||
/* walk y */
|
||||
for(s32 y = 0; y < height; y++)
|
||||
{
|
||||
/* walk x */
|
||||
for(s32 x = 0; x < width; x++)
|
||||
{
|
||||
*out++ = *in++;
|
||||
*out++ = *in++;
|
||||
*out++ = *in++;
|
||||
*out++ = *in++;
|
||||
}
|
||||
}
|
||||
|
||||
/* return ok */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
DDSDecompress()
|
||||
decompresses a dds texture into an rgba image buffer, returns 0 on success
|
||||
*/
|
||||
s32 DDSDecompress( ddsBuffer *dds, u8 *pixels )
|
||||
s32 DDSDecompress(ddsHeader* dds, u8* data, u8* pixels)
|
||||
{
|
||||
s32 width, height;
|
||||
eDDSPixelFormat pf;
|
||||
|
@ -606,32 +629,30 @@ s32 DDSDecompress( ddsBuffer *dds, u8 *pixels )
|
|||
{
|
||||
case DDS_PF_ARGB8888:
|
||||
/* fixme: support other [a]rgb formats */
|
||||
r = DDSDecompressARGB8888( dds, width, height, pixels );
|
||||
r = DDSDecompressARGB8888( dds, data, width, height, pixels );
|
||||
break;
|
||||
|
||||
case DDS_PF_DXT1:
|
||||
r = DDSDecompressDXT1( dds, width, height, pixels );
|
||||
r = DDSDecompressDXT1( dds, data, width, height, pixels );
|
||||
break;
|
||||
|
||||
case DDS_PF_DXT2:
|
||||
r = DDSDecompressDXT2( dds, width, height, pixels );
|
||||
r = DDSDecompressDXT2( dds, data, width, height, pixels );
|
||||
break;
|
||||
|
||||
case DDS_PF_DXT3:
|
||||
r = DDSDecompressDXT3( dds, width, height, pixels );
|
||||
r = DDSDecompressDXT3( dds, data, width, height, pixels );
|
||||
break;
|
||||
|
||||
case DDS_PF_DXT4:
|
||||
r = DDSDecompressDXT4( dds, width, height, pixels );
|
||||
r = DDSDecompressDXT4( dds, data, width, height, pixels );
|
||||
break;
|
||||
|
||||
case DDS_PF_DXT5:
|
||||
r = DDSDecompressDXT5( dds, width, height, pixels );
|
||||
r = DDSDecompressDXT5( dds, data, width, height, pixels );
|
||||
break;
|
||||
|
||||
default:
|
||||
case DDS_PF_UNKNOWN:
|
||||
memset( pixels, 0xFF, width * height * 4 );
|
||||
default: // DDS_PF_UNKNOWN
|
||||
r = -1;
|
||||
break;
|
||||
}
|
||||
|
@ -640,14 +661,14 @@ s32 DDSDecompress( ddsBuffer *dds, u8 *pixels )
|
|||
return r;
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
#endif
|
||||
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".tga")
|
||||
bool CImageLoaderDDS::isALoadableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "dds" );
|
||||
return core::hasFileExtension(filename, "dds");
|
||||
}
|
||||
|
||||
|
||||
|
@ -657,44 +678,127 @@ bool CImageLoaderDDS::isALoadableFileFormat(io::IReadFile* file) const
|
|||
if (!file)
|
||||
return false;
|
||||
|
||||
ddsBuffer header;
|
||||
file->read(&header, sizeof(header));
|
||||
c8 MagicWord[4];
|
||||
file->read(&MagicWord, 4);
|
||||
|
||||
s32 width, height;
|
||||
eDDSPixelFormat pixelFormat;
|
||||
|
||||
return (0 == DDSGetInfo( &header, &width, &height, &pixelFormat));
|
||||
return (MagicWord[0] == 'D' && MagicWord[1] == 'D' && MagicWord[2] == 'S');
|
||||
}
|
||||
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* CImageLoaderDDS::loadImage(io::IReadFile* file) const
|
||||
{
|
||||
u8 *memFile = new u8 [ file->getSize() ];
|
||||
file->read ( memFile, file->getSize() );
|
||||
|
||||
ddsBuffer *header = (ddsBuffer*) memFile;
|
||||
ddsHeader header;
|
||||
IImage* image = 0;
|
||||
s32 width, height;
|
||||
eDDSPixelFormat pixelFormat;
|
||||
|
||||
if ( 0 == DDSGetInfo( header, &width, &height, &pixelFormat) )
|
||||
{
|
||||
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
|
||||
file->seek(0);
|
||||
file->read(&header, sizeof(ddsHeader));
|
||||
|
||||
if ( DDSDecompress( header, (u8*) image->lock() ) == -1)
|
||||
if (0 == DDSGetInfo(&header, &width, &height, &pixelFormat))
|
||||
{
|
||||
#ifndef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
|
||||
if(pixelFormat == DDS_PF_ARGB8888)
|
||||
#endif
|
||||
{
|
||||
image->unlock();
|
||||
image->drop();
|
||||
image = 0;
|
||||
u32 newSize = file->getSize() - sizeof(ddsHeader);
|
||||
u8* memFile = new u8[newSize];
|
||||
file->read(memFile, newSize);
|
||||
|
||||
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
|
||||
|
||||
#ifndef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
|
||||
DDSDecompressARGB8888(&header, memFile, width, height, (u8*)image->lock());
|
||||
#else
|
||||
if (DDSDecompress(&header, memFile, (u8*)image->lock()) == -1)
|
||||
{
|
||||
image->unlock();
|
||||
image->drop();
|
||||
image = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
delete[] memFile;
|
||||
|
||||
if (image)
|
||||
image->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
delete [] memFile;
|
||||
if ( image )
|
||||
image->unlock();
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
//! creates a compressed surface from the file
|
||||
IImageCompressed* CImageLoaderDDS::loadImageCompressed(io::IReadFile* file) const
|
||||
{
|
||||
#ifndef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
|
||||
ddsHeader header;
|
||||
IImageCompressed* image = 0;
|
||||
s32 width, height;
|
||||
eDDSPixelFormat pixelFormat;
|
||||
|
||||
file->seek(0);
|
||||
file->read(&header, sizeof(ddsHeader));
|
||||
|
||||
ECOLOR_FORMAT format = ECF_UNKNOWN;
|
||||
u32 dataSize = 0;
|
||||
bool is3D = false;
|
||||
|
||||
if (0 == DDSGetInfo(&header, &width, &height, &pixelFormat))
|
||||
{
|
||||
is3D = header.Depth > 0 && (header.Flags & DDSD_DEPTH);
|
||||
|
||||
if (!is3D)
|
||||
header.Depth = 1;
|
||||
|
||||
if (header.PixelFormat.Flags & DDPF_FOURCC) // Compressed formats
|
||||
{
|
||||
switch(pixelFormat)
|
||||
{
|
||||
case DDS_PF_DXT1:
|
||||
{
|
||||
dataSize = (header.Width / 4 ) * (header.Height / 4) * 8;
|
||||
format = ECF_DXT1;
|
||||
os::Printer::log("Detected ECF_DXT1 format", ELL_DEBUG);
|
||||
break;
|
||||
}
|
||||
case DDS_PF_DXT2:
|
||||
case DDS_PF_DXT3:
|
||||
{
|
||||
dataSize = (header.Width / 4 ) * (header.Height / 4) * 16;
|
||||
format = ECF_DXT3;
|
||||
os::Printer::log("Detected ECF_DXT3 format", ELL_DEBUG);
|
||||
break;
|
||||
}
|
||||
case DDS_PF_DXT4:
|
||||
case DDS_PF_DXT5:
|
||||
{
|
||||
dataSize = (header.Width / 4 ) * (header.Height / 4) * 16;
|
||||
format = ECF_DXT5;
|
||||
os::Printer::log("Detected ECF_DXT5 format", ELL_DEBUG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( format != ECF_UNKNOWN )
|
||||
{
|
||||
if (!is3D) // Currently 3D textures are unsupported.
|
||||
{
|
||||
u8* data = new u8[dataSize];
|
||||
file->read(data, dataSize);
|
||||
|
||||
image = new CImageCompressed(format, core::dimension2d<u32>(header.Width, header.Height ), data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_DDS_LOADER_)
|
||||
#if defined(_IRR_COMPILE_WITH_DDS_LOADER_) || defined(_IRR_COMPILE_WITH_DDS_DECODER_LOADER_)
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
|
@ -16,8 +16,7 @@ namespace irr
|
|||
namespace video
|
||||
{
|
||||
|
||||
/* dependencies */
|
||||
/* dds definition */
|
||||
/* dds pixel format types */
|
||||
enum eDDSPixelFormat
|
||||
{
|
||||
DDS_PF_ARGB8888,
|
||||
|
@ -29,24 +28,24 @@ enum eDDSPixelFormat
|
|||
DDS_PF_UNKNOWN
|
||||
};
|
||||
|
||||
/* 16bpp stuff */
|
||||
#define DDS_LOW_5 0x001F;
|
||||
#define DDS_MID_6 0x07E0;
|
||||
#define DDS_HIGH_5 0xF800;
|
||||
#define DDS_MID_555 0x03E0;
|
||||
#define DDS_HI_555 0x7C00;
|
||||
|
||||
|
||||
// byte-align structures
|
||||
#include "irrpack.h"
|
||||
|
||||
/* structures */
|
||||
struct ddsColorKey
|
||||
|
||||
struct ddsPixelFormat
|
||||
{
|
||||
u32 colorSpaceLowValue;
|
||||
u32 colorSpaceHighValue;
|
||||
u32 Size;
|
||||
u32 Flags;
|
||||
u32 FourCC;
|
||||
u32 RGBBitCount;
|
||||
u32 RBitMask;
|
||||
u32 GBitMask;
|
||||
u32 BBitMask;
|
||||
u32 ABitMask;
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
struct ddsCaps
|
||||
{
|
||||
u32 caps1;
|
||||
|
@ -55,108 +54,25 @@ struct ddsCaps
|
|||
u32 caps4;
|
||||
} PACK_STRUCT;
|
||||
|
||||
struct ddsMultiSampleCaps
|
||||
|
||||
struct ddsHeader
|
||||
{
|
||||
u16 flipMSTypes;
|
||||
u16 bltMSTypes;
|
||||
c8 Magic[4];
|
||||
u32 Size;
|
||||
u32 Flags;
|
||||
u32 Height;
|
||||
u32 Width;
|
||||
u32 PitchOrLinearSize;
|
||||
u32 Depth;
|
||||
u32 MipMapCount;
|
||||
u32 Reserved1[11];
|
||||
ddsPixelFormat PixelFormat;
|
||||
ddsCaps Caps;
|
||||
u32 Reserved2;
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
struct ddsPixelFormat
|
||||
{
|
||||
u32 size;
|
||||
u32 flags;
|
||||
u32 fourCC;
|
||||
union
|
||||
{
|
||||
u32 rgbBitCount;
|
||||
u32 yuvBitCount;
|
||||
u32 zBufferBitDepth;
|
||||
u32 alphaBitDepth;
|
||||
u32 luminanceBitCount;
|
||||
u32 bumpBitCount;
|
||||
u32 privateFormatBitCount;
|
||||
};
|
||||
union
|
||||
{
|
||||
u32 rBitMask;
|
||||
u32 yBitMask;
|
||||
u32 stencilBitDepth;
|
||||
u32 luminanceBitMask;
|
||||
u32 bumpDuBitMask;
|
||||
u32 operations;
|
||||
};
|
||||
union
|
||||
{
|
||||
u32 gBitMask;
|
||||
u32 uBitMask;
|
||||
u32 zBitMask;
|
||||
u32 bumpDvBitMask;
|
||||
ddsMultiSampleCaps multiSampleCaps;
|
||||
};
|
||||
union
|
||||
{
|
||||
u32 bBitMask;
|
||||
u32 vBitMask;
|
||||
u32 stencilBitMask;
|
||||
u32 bumpLuminanceBitMask;
|
||||
};
|
||||
union
|
||||
{
|
||||
u32 rgbAlphaBitMask;
|
||||
u32 yuvAlphaBitMask;
|
||||
u32 luminanceAlphaBitMask;
|
||||
u32 rgbZBitMask;
|
||||
u32 yuvZBitMask;
|
||||
};
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
struct ddsBuffer
|
||||
{
|
||||
/* magic: 'dds ' */
|
||||
c8 magic[ 4 ];
|
||||
|
||||
/* directdraw surface */
|
||||
u32 size;
|
||||
u32 flags;
|
||||
u32 height;
|
||||
u32 width;
|
||||
union
|
||||
{
|
||||
s32 pitch;
|
||||
u32 linearSize;
|
||||
};
|
||||
u32 backBufferCount;
|
||||
union
|
||||
{
|
||||
u32 mipMapCount;
|
||||
u32 refreshRate;
|
||||
u32 srcVBHandle;
|
||||
};
|
||||
u32 alphaBitDepth;
|
||||
u32 reserved;
|
||||
void *surface;
|
||||
union
|
||||
{
|
||||
ddsColorKey ckDestOverlay;
|
||||
u32 emptyFaceColor;
|
||||
};
|
||||
ddsColorKey ckDestBlt;
|
||||
ddsColorKey ckSrcOverlay;
|
||||
ddsColorKey ckSrcBlt;
|
||||
union
|
||||
{
|
||||
ddsPixelFormat pixelFormat;
|
||||
u32 fvf;
|
||||
};
|
||||
ddsCaps caps;
|
||||
u32 textureStage;
|
||||
|
||||
/* data (Varying size) */
|
||||
u8 data[ 4 ];
|
||||
} PACK_STRUCT;
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
|
||||
|
||||
struct ddsColorBlock
|
||||
{
|
||||
|
@ -184,6 +100,9 @@ struct ddsColor
|
|||
u8 r, g, b, a;
|
||||
} PACK_STRUCT;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
|
@ -285,6 +204,9 @@ public:
|
|||
|
||||
//! creates a surface from the file
|
||||
virtual IImage* loadImage(io::IReadFile* file) const;
|
||||
|
||||
//! creates a compressed surface from the file
|
||||
virtual IImageCompressed* loadImageCompressed(io::IReadFile* file) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& scre
|
|||
#ifdef _IRR_COMPILE_WITH_PSD_LOADER_
|
||||
SurfaceLoader.push_back(video::createImageLoaderPSD());
|
||||
#endif
|
||||
#ifdef _IRR_COMPILE_WITH_DDS_LOADER_
|
||||
#if defined(_IRR_COMPILE_WITH_DDS_LOADER_) || defined(_IRR_COMPILE_WITH_DDS_DECODER_LOADER_)
|
||||
SurfaceLoader.push_back(video::createImageLoaderDDS());
|
||||
#endif
|
||||
#ifdef _IRR_COMPILE_WITH_PCX_LOADER_
|
||||
|
@ -1402,6 +1402,77 @@ IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format,
|
|||
}
|
||||
|
||||
|
||||
//! Creates a compressed software image from a file.
|
||||
IImageCompressed* CNullDriver::createImageCompressedFromFile(const io::path& filename)
|
||||
{
|
||||
if (!filename.size())
|
||||
return 0;
|
||||
|
||||
IImageCompressed* image = 0;
|
||||
io::IReadFile* file = FileSystem->createAndOpenFile(filename);
|
||||
|
||||
if (file)
|
||||
{
|
||||
image = createImageCompressedFromFile(file);
|
||||
file->drop();
|
||||
}
|
||||
else
|
||||
os::Printer::log("Could not open file of image", filename, ELL_WARNING);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
//! Creates a compressed software image from a file.
|
||||
IImageCompressed* CNullDriver::createImageCompressedFromFile(io::IReadFile* file)
|
||||
{
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
IImageCompressed* image = 0;
|
||||
|
||||
s32 i;
|
||||
|
||||
// try to load file based on file extension
|
||||
for (i=SurfaceLoader.size()-1; i>=0; --i)
|
||||
{
|
||||
if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
|
||||
{
|
||||
// reset file position which might have changed due to previous loadImage calls
|
||||
file->seek(0);
|
||||
image = SurfaceLoader[i]->loadImageCompressed(file);
|
||||
if (image)
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
// try to load file based on what is in it
|
||||
for (i=SurfaceLoader.size()-1; i>=0; --i)
|
||||
{
|
||||
// dito
|
||||
file->seek(0);
|
||||
if (SurfaceLoader[i]->isALoadableFileFormat(file))
|
||||
{
|
||||
file->seek(0);
|
||||
image = SurfaceLoader[i]->loadImageCompressed(file);
|
||||
if (image)
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // failed to load
|
||||
}
|
||||
|
||||
|
||||
//! Creates a software compressed image from a byte array.
|
||||
IImageCompressed* CNullDriver::createImageCompressedFromData(ECOLOR_FORMAT format,
|
||||
const core::dimension2d<u32>& size, void *data,
|
||||
bool ownForeignMemory, bool deleteMemory)
|
||||
{
|
||||
return new CImageCompressed(format, size, data, ownForeignMemory, deleteMemory);
|
||||
}
|
||||
|
||||
|
||||
//! Creates an empty software image.
|
||||
IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size)
|
||||
{
|
||||
|
|
|
@ -352,6 +352,17 @@ namespace video
|
|||
const core::dimension2d<u32>& size, void *data,
|
||||
bool ownForeignMemory=true, bool deleteForeignMemory = true);
|
||||
|
||||
//! Creates a compressed software image from a file.
|
||||
virtual IImageCompressed* createImageCompressedFromFile(const io::path& filename);
|
||||
|
||||
//! Creates a compressed software image from a file.
|
||||
virtual IImageCompressed* createImageCompressedFromFile(io::IReadFile* file);
|
||||
|
||||
//! Creates a software compressed image from a byte array.
|
||||
virtual IImageCompressed* createImageCompressedFromData(ECOLOR_FORMAT format,
|
||||
const core::dimension2d<u32>& size, void *data,
|
||||
bool ownForeignMemory=false, bool deleteMemory = true);
|
||||
|
||||
//! Creates an empty software image.
|
||||
virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size);
|
||||
|
||||
|
|
Loading…
Reference in New Issue