added DDS Image Loader
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3334 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
7446ed9757
commit
ccfcd68a12
|
@ -10,6 +10,7 @@ Changes in 1.7.1 (05.07.2010) TA
|
|||
- Example 11.
|
||||
changed the light billboards to use the light color. ( green light, green particle, red light red particle )
|
||||
allow to disable the bump/parallax on the earth like in the room ( with transparency )
|
||||
- added DDS Image files, DXT2, DXT3, DXT4, DXT5, based on code from nvidia and Randy Reddig
|
||||
|
||||
--------------------------------------
|
||||
|
||||
|
|
|
@ -315,6 +315,8 @@ B3D, MS3D or X meshes */
|
|||
#define _IRR_COMPILE_WITH_PPM_LOADER_
|
||||
//! Define _IRR_COMPILE_WITH_PSD_LOADER_ if you want to load .psd files
|
||||
#define _IRR_COMPILE_WITH_PSD_LOADER_
|
||||
//! Define _IRR_COMPILE_WITH_DDS_LOADER_ if you want to load .dds files
|
||||
#define _IRR_COMPILE_WITH_DDS_LOADER_
|
||||
//! Define _IRR_COMPILE_WITH_TGA_LOADER_ if you want to load .tga files
|
||||
#define _IRR_COMPILE_WITH_TGA_LOADER_
|
||||
//! Define _IRR_COMPILE_WITH_WAL_LOADER_ if you want to load .wal files
|
||||
|
|
|
@ -0,0 +1,741 @@
|
|||
// Copyright (C) 2002-2009 Thomas Alten
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
/*
|
||||
Based on Code from Copyright (c) 2003 Randy Reddig
|
||||
Based on code from Nvidia's DDS example:
|
||||
http://www.nvidia.com/object/dxtc_decompression_code.html
|
||||
|
||||
mainly c to cpp
|
||||
*/
|
||||
|
||||
|
||||
#include "CImageLoaderDDS.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DDS_LOADER_
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "os.h"
|
||||
#include "CColorConverter.h"
|
||||
#include "CImage.h"
|
||||
#include "irrString.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace video
|
||||
{
|
||||
|
||||
/*!
|
||||
DDSDecodePixelFormat()
|
||||
determines which pixel format the dds texture is in
|
||||
*/
|
||||
void DDSDecodePixelFormat( ddsBuffer *dds, eDDSPixelFormat *pf )
|
||||
{
|
||||
u32 fourCC;
|
||||
|
||||
|
||||
/* dummy check */
|
||||
if( dds == NULL || pf == NULL )
|
||||
return;
|
||||
|
||||
/* extract fourCC */
|
||||
fourCC = dds->pixelFormat.fourCC;
|
||||
|
||||
/* test it */
|
||||
if( fourCC == 0 )
|
||||
*pf = DDS_PF_ARGB8888;
|
||||
else if( fourCC == *((u32*) "DXT1") )
|
||||
*pf = DDS_PF_DXT1;
|
||||
else if( fourCC == *((u32*) "DXT2") )
|
||||
*pf = DDS_PF_DXT2;
|
||||
else if( fourCC == *((u32*) "DXT3") )
|
||||
*pf = DDS_PF_DXT3;
|
||||
else if( fourCC == *((u32*) "DXT4") )
|
||||
*pf = DDS_PF_DXT4;
|
||||
else if( fourCC == *((u32*) "DXT5") )
|
||||
*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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
DDSGetColorBlockColors()
|
||||
extracts colors from a dds color block
|
||||
*/
|
||||
void DDSGetColorBlockColors( ddsColorBlock *block, ddsColor colors[ 4 ] )
|
||||
{
|
||||
u16 word;
|
||||
|
||||
|
||||
/* color 0 */
|
||||
word = DDSLittleShort( block->colors[ 0 ] );
|
||||
colors[ 0 ].a = 0xff;
|
||||
|
||||
/* extract rgb bits */
|
||||
colors[ 0 ].b = (u8) word;
|
||||
colors[ 0 ].b <<= 3;
|
||||
colors[ 0 ].b |= (colors[ 0 ].b >> 5);
|
||||
word >>= 5;
|
||||
colors[ 0 ].g = (u8) word;
|
||||
colors[ 0 ].g <<= 2;
|
||||
colors[ 0 ].g |= (colors[ 0 ].g >> 5);
|
||||
word >>= 6;
|
||||
colors[ 0 ].r = (u8) word;
|
||||
colors[ 0 ].r <<= 3;
|
||||
colors[ 0 ].r |= (colors[ 0 ].r >> 5);
|
||||
|
||||
/* same for color 1 */
|
||||
word = DDSLittleShort( block->colors[ 1 ] );
|
||||
colors[ 1 ].a = 0xff;
|
||||
|
||||
/* extract rgb bits */
|
||||
colors[ 1 ].b = (u8) word;
|
||||
colors[ 1 ].b <<= 3;
|
||||
colors[ 1 ].b |= (colors[ 1 ].b >> 5);
|
||||
word >>= 5;
|
||||
colors[ 1 ].g = (u8) word;
|
||||
colors[ 1 ].g <<= 2;
|
||||
colors[ 1 ].g |= (colors[ 1 ].g >> 5);
|
||||
word >>= 6;
|
||||
colors[ 1 ].r = (u8) word;
|
||||
colors[ 1 ].r <<= 3;
|
||||
colors[ 1 ].r |= (colors[ 1 ].r >> 5);
|
||||
|
||||
/* use this for all but the super-freak math method */
|
||||
if( block->colors[ 0 ] > block->colors[ 1 ] )
|
||||
{
|
||||
/* four-color block: derive the other two colors.
|
||||
00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3
|
||||
these two bit codes correspond to the 2-bit fields
|
||||
stored in the 64-bit block. */
|
||||
|
||||
word = ((u16) colors[ 0 ].r * 2 + (u16) colors[ 1 ].r ) / 3;
|
||||
/* no +1 for rounding */
|
||||
/* as bits have been shifted to 888 */
|
||||
colors[ 2 ].r = (u8) word;
|
||||
word = ((u16) colors[ 0 ].g * 2 + (u16) colors[ 1 ].g) / 3;
|
||||
colors[ 2 ].g = (u8) word;
|
||||
word = ((u16) colors[ 0 ].b * 2 + (u16) colors[ 1 ].b) / 3;
|
||||
colors[ 2 ].b = (u8) word;
|
||||
colors[ 2 ].a = 0xff;
|
||||
|
||||
word = ((u16) colors[ 0 ].r + (u16) colors[ 1 ].r * 2) / 3;
|
||||
colors[ 3 ].r = (u8) word;
|
||||
word = ((u16) colors[ 0 ].g + (u16) colors[ 1 ].g * 2) / 3;
|
||||
colors[ 3 ].g = (u8) word;
|
||||
word = ((u16) colors[ 0 ].b + (u16) colors[ 1 ].b * 2) / 3;
|
||||
colors[ 3 ].b = (u8) word;
|
||||
colors[ 3 ].a = 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* three-color block: derive the other color.
|
||||
00 = color 0, 01 = color 1, 10 = color 2,
|
||||
11 = transparent.
|
||||
These two bit codes correspond to the 2-bit fields
|
||||
stored in the 64-bit block */
|
||||
|
||||
word = ((u16) colors[ 0 ].r + (u16) colors[ 1 ].r) / 2;
|
||||
colors[ 2 ].r = (u8) word;
|
||||
word = ((u16) colors[ 0 ].g + (u16) colors[ 1 ].g) / 2;
|
||||
colors[ 2 ].g = (u8) word;
|
||||
word = ((u16) colors[ 0 ].b + (u16) colors[ 1 ].b) / 2;
|
||||
colors[ 2 ].b = (u8) word;
|
||||
colors[ 2 ].a = 0xff;
|
||||
|
||||
/* random color to indicate alpha */
|
||||
colors[ 3 ].r = 0x00;
|
||||
colors[ 3 ].g = 0xff;
|
||||
colors[ 3 ].b = 0xff;
|
||||
colors[ 3 ].a = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
DDSDecodeColorBlock()
|
||||
decodes a dds color block
|
||||
fixme: make endian-safe
|
||||
*/
|
||||
|
||||
static void DDSDecodeColorBlock( u32 *pixel, ddsColorBlock *block, s32 width, u32 colors[ 4 ] )
|
||||
{
|
||||
s32 r, n;
|
||||
u32 bits;
|
||||
u32 masks[] = { 3, 12, 3 << 4, 3 << 6 }; /* bit masks = 00000011, 00001100, 00110000, 11000000 */
|
||||
s32 shift[] = { 0, 2, 4, 6 };
|
||||
|
||||
|
||||
/* r steps through lines in y */
|
||||
for( r = 0; r < 4; r++, pixel += (width - 4) ) /* no width * 4 as u32 ptr inc will * 4 */
|
||||
{
|
||||
/* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
|
||||
|
||||
/* n steps through pixels */
|
||||
for( n = 0; n < 4; n++ )
|
||||
{
|
||||
bits = block->row[ r ] & masks[ n ];
|
||||
bits >>= shift[ n ];
|
||||
|
||||
switch( bits )
|
||||
{
|
||||
case 0:
|
||||
*pixel = colors[ 0 ];
|
||||
pixel++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
*pixel = colors[ 1 ];
|
||||
pixel++;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*pixel = colors[ 2 ];
|
||||
pixel++;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
*pixel = colors[ 3 ];
|
||||
pixel++;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* invalid */
|
||||
pixel++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
DDSDecodeAlphaExplicit()
|
||||
decodes a dds explicit alpha block
|
||||
*/
|
||||
|
||||
static void DDSDecodeAlphaExplicit( u32 *pixel, ddsAlphaBlockExplicit *alphaBlock, s32 width, u32 alphaZero )
|
||||
{
|
||||
s32 row, pix;
|
||||
u16 word;
|
||||
ddsColor color;
|
||||
|
||||
|
||||
/* clear color */
|
||||
color.r = 0;
|
||||
color.g = 0;
|
||||
color.b = 0;
|
||||
|
||||
/* walk rows */
|
||||
for( row = 0; row < 4; row++, pixel += (width - 4) )
|
||||
{
|
||||
word = DDSLittleShort( alphaBlock->row[ row ] );
|
||||
|
||||
/* walk pixels */
|
||||
for( pix = 0; pix < 4; pix++ )
|
||||
{
|
||||
/* zero the alpha bits of image pixel */
|
||||
*pixel &= alphaZero;
|
||||
color.a = word & 0x000F;
|
||||
color.a = color.a | (color.a << 4);
|
||||
*pixel |= *((u32*) &color);
|
||||
word >>= 4; /* move next bits to lowest 4 */
|
||||
pixel++; /* move to next pixel in the row */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
DDSDecodeAlpha3BitLinear()
|
||||
decodes interpolated alpha block
|
||||
*/
|
||||
|
||||
static void DDSDecodeAlpha3BitLinear( u32 *pixel, ddsAlphaBlock3BitLinear *alphaBlock, s32 width, u32 alphaZero )
|
||||
{
|
||||
|
||||
s32 row, pix;
|
||||
u32 stuff;
|
||||
u8 bits[ 4 ][ 4 ];
|
||||
u16 alphas[ 8 ];
|
||||
ddsColor aColors[ 4 ][ 4 ];
|
||||
|
||||
|
||||
/* get initial alphas */
|
||||
alphas[ 0 ] = alphaBlock->alpha0;
|
||||
alphas[ 1 ] = alphaBlock->alpha1;
|
||||
|
||||
/* 8-alpha block */
|
||||
if( alphas[ 0 ] > alphas[ 1 ] )
|
||||
{
|
||||
/* 000 = alpha_0, 001 = alpha_1, others are interpolated */
|
||||
alphas[ 2 ] = ( 6 * alphas[ 0 ] + alphas[ 1 ]) / 7; /* bit code 010 */
|
||||
alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 7; /* bit code 011 */
|
||||
alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 7; /* bit code 100 */
|
||||
alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ]) / 7; /* bit code 101 */
|
||||
alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ]) / 7; /* bit code 110 */
|
||||
alphas[ 7 ] = ( alphas[ 0 ] + 6 * alphas[ 1 ]) / 7; /* bit code 111 */
|
||||
}
|
||||
|
||||
/* 6-alpha block */
|
||||
else
|
||||
{
|
||||
/* 000 = alpha_0, 001 = alpha_1, others are interpolated */
|
||||
alphas[ 2 ] = (4 * alphas[ 0 ] + alphas[ 1 ]) / 5; /* bit code 010 */
|
||||
alphas[ 3 ] = (3 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 5; /* bit code 011 */
|
||||
alphas[ 4 ] = (2 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 5; /* bit code 100 */
|
||||
alphas[ 5 ] = ( alphas[ 0 ] + 4 * alphas[ 1 ]) / 5; /* bit code 101 */
|
||||
alphas[ 6 ] = 0; /* bit code 110 */
|
||||
alphas[ 7 ] = 255; /* bit code 111 */
|
||||
}
|
||||
|
||||
/* decode 3-bit fields into array of 16 bytes with same value */
|
||||
|
||||
/* first two rows of 4 pixels each */
|
||||
stuff = *((u32*) &(alphaBlock->stuff[ 0 ]));
|
||||
|
||||
bits[ 0 ][ 0 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 0 ][ 1 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 0 ][ 2 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 0 ][ 3 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 1 ][ 0 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 1 ][ 1 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 1 ][ 2 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 1 ][ 3 ] = (u8) (stuff & 0x00000007);
|
||||
|
||||
/* last two rows */
|
||||
stuff = *((u32*) &(alphaBlock->stuff[ 3 ])); /* last 3 bytes */
|
||||
|
||||
bits[ 2 ][ 0 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 2 ][ 1 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 2 ][ 2 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 2 ][ 3 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 3 ][ 0 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 3 ][ 1 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 3 ][ 2 ] = (u8) (stuff & 0x00000007);
|
||||
stuff >>= 3;
|
||||
bits[ 3 ][ 3 ] = (u8) (stuff & 0x00000007);
|
||||
|
||||
/* decode the codes into alpha values */
|
||||
for( row = 0; row < 4; row++ )
|
||||
{
|
||||
for( pix=0; pix < 4; pix++ )
|
||||
{
|
||||
aColors[ row ][ pix ].r = 0;
|
||||
aColors[ row ][ pix ].g = 0;
|
||||
aColors[ row ][ pix ].b = 0;
|
||||
aColors[ row ][ pix ].a = (u8) alphas[ bits[ row ][ pix ] ];
|
||||
}
|
||||
}
|
||||
|
||||
/* write out alpha values to the image bits */
|
||||
for( row = 0; row < 4; row++, pixel += width-4 )
|
||||
{
|
||||
for( pix = 0; pix < 4; pix++ )
|
||||
{
|
||||
/* zero the alpha bits of image pixel */
|
||||
*pixel &= alphaZero;
|
||||
|
||||
/* or the bits into the prev. nulled alpha */
|
||||
*pixel |= *((u32*) &(aColors[ row ][ pix ]));
|
||||
pixel++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
DDSDecompressDXT1()
|
||||
decompresses a dxt1 format texture
|
||||
*/
|
||||
s32 DDSDecompressDXT1( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
{
|
||||
s32 x, y, xBlocks, yBlocks;
|
||||
u32 *pixel;
|
||||
ddsColorBlock *block;
|
||||
ddsColor colors[ 4 ];
|
||||
|
||||
|
||||
/* setup */
|
||||
xBlocks = width / 4;
|
||||
yBlocks = height / 4;
|
||||
|
||||
/* walk y */
|
||||
for( y = 0; y < yBlocks; y++ )
|
||||
{
|
||||
/* 8 bytes per block */
|
||||
block = (ddsColorBlock*) ((u32) dds->data + y * xBlocks * 8);
|
||||
|
||||
/* walk x */
|
||||
for( x = 0; x < xBlocks; x++, block++ )
|
||||
{
|
||||
DDSGetColorBlockColors( block, colors );
|
||||
pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4);
|
||||
DDSDecodeColorBlock( pixel, block, width, (u32*) colors );
|
||||
}
|
||||
}
|
||||
|
||||
/* return ok */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
DDSDecompressDXT3()
|
||||
decompresses a dxt3 format texture
|
||||
*/
|
||||
|
||||
s32 DDSDecompressDXT3( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
{
|
||||
s32 x, y, xBlocks, yBlocks;
|
||||
u32 *pixel, alphaZero;
|
||||
ddsColorBlock *block;
|
||||
ddsAlphaBlockExplicit *alphaBlock;
|
||||
ddsColor colors[ 4 ];
|
||||
|
||||
|
||||
/* setup */
|
||||
xBlocks = width / 4;
|
||||
yBlocks = height / 4;
|
||||
|
||||
/* create zero alpha */
|
||||
colors[ 0 ].a = 0;
|
||||
colors[ 0 ].r = 0xFF;
|
||||
colors[ 0 ].g = 0xFF;
|
||||
colors[ 0 ].b = 0xFF;
|
||||
alphaZero = *((u32*) &colors[ 0 ]);
|
||||
|
||||
/* walk y */
|
||||
for( y = 0; y < yBlocks; y++ )
|
||||
{
|
||||
/* 8 bytes per block, 1 block for alpha, 1 block for color */
|
||||
block = (ddsColorBlock*) ((u32) dds->data + y * xBlocks * 16);
|
||||
|
||||
/* walk x */
|
||||
for( x = 0; x < xBlocks; x++, block++ )
|
||||
{
|
||||
/* get alpha block */
|
||||
alphaBlock = (ddsAlphaBlockExplicit*) block;
|
||||
|
||||
/* get color block */
|
||||
block++;
|
||||
DDSGetColorBlockColors( block, colors );
|
||||
|
||||
/* decode color block */
|
||||
pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4);
|
||||
DDSDecodeColorBlock( pixel, block, width, (u32*) colors );
|
||||
|
||||
/* overwrite alpha bits with alpha block */
|
||||
DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
|
||||
}
|
||||
}
|
||||
|
||||
/* return ok */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
DDSDecompressDXT5()
|
||||
decompresses a dxt5 format texture
|
||||
*/
|
||||
s32 DDSDecompressDXT5( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
{
|
||||
s32 x, y, xBlocks, yBlocks;
|
||||
u32 *pixel, alphaZero;
|
||||
ddsColorBlock *block;
|
||||
ddsAlphaBlock3BitLinear *alphaBlock;
|
||||
ddsColor colors[ 4 ];
|
||||
|
||||
|
||||
/* setup */
|
||||
xBlocks = width / 4;
|
||||
yBlocks = height / 4;
|
||||
|
||||
/* create zero alpha */
|
||||
colors[ 0 ].a = 0;
|
||||
colors[ 0 ].r = 0xFF;
|
||||
colors[ 0 ].g = 0xFF;
|
||||
colors[ 0 ].b = 0xFF;
|
||||
alphaZero = *((u32*) &colors[ 0 ]);
|
||||
|
||||
/* walk y */
|
||||
for( y = 0; y < yBlocks; y++ )
|
||||
{
|
||||
/* 8 bytes per block, 1 block for alpha, 1 block for color */
|
||||
block = (ddsColorBlock*) ((u32) dds->data + y * xBlocks * 16);
|
||||
|
||||
/* walk x */
|
||||
for( x = 0; x < xBlocks; x++, block++ )
|
||||
{
|
||||
/* get alpha block */
|
||||
alphaBlock = (ddsAlphaBlock3BitLinear*) block;
|
||||
|
||||
/* get color block */
|
||||
block++;
|
||||
DDSGetColorBlockColors( block, colors );
|
||||
|
||||
/* decode color block */
|
||||
pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4);
|
||||
DDSDecodeColorBlock( pixel, block, width, (u32*) colors );
|
||||
|
||||
/* overwrite alpha bits with alpha block */
|
||||
DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
|
||||
}
|
||||
}
|
||||
|
||||
/* return ok */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
DDSDecompressDXT2()
|
||||
decompresses a dxt2 format texture (fixme: un-premultiply alpha)
|
||||
*/
|
||||
s32 DDSDecompressDXT2( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
{
|
||||
s32 r;
|
||||
|
||||
|
||||
/* decompress dxt3 first */
|
||||
r = DDSDecompressDXT3( dds, width, height, pixels );
|
||||
|
||||
/* return to sender */
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
DDSDecompressDXT4()
|
||||
decompresses a dxt4 format texture (fixme: un-premultiply alpha)
|
||||
*/
|
||||
s32 DDSDecompressDXT4( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
|
||||
{
|
||||
s32 r;
|
||||
|
||||
|
||||
/* decompress dxt5 first */
|
||||
r = DDSDecompressDXT5( dds, 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 )
|
||||
{
|
||||
s32 x, y;
|
||||
u8 *in, *out;
|
||||
|
||||
|
||||
/* setup */
|
||||
in = dds->data;
|
||||
out = pixels;
|
||||
|
||||
/* walk y */
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
/* walk x */
|
||||
for( 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 width, height, r;
|
||||
eDDSPixelFormat pf;
|
||||
|
||||
|
||||
/* get dds info */
|
||||
r = DDSGetInfo( dds, &width, &height, &pf );
|
||||
if( r )
|
||||
return r;
|
||||
|
||||
/* decompress */
|
||||
switch( pf )
|
||||
{
|
||||
case DDS_PF_ARGB8888:
|
||||
/* fixme: support other [a]rgb formats */
|
||||
r = DDSDecompressARGB8888( dds, width, height, pixels );
|
||||
break;
|
||||
|
||||
case DDS_PF_DXT1:
|
||||
r = DDSDecompressDXT1( dds, width, height, pixels );
|
||||
break;
|
||||
|
||||
case DDS_PF_DXT2:
|
||||
r = DDSDecompressDXT2( dds, width, height, pixels );
|
||||
break;
|
||||
|
||||
case DDS_PF_DXT3:
|
||||
r = DDSDecompressDXT3( dds, width, height, pixels );
|
||||
break;
|
||||
|
||||
case DDS_PF_DXT4:
|
||||
r = DDSDecompressDXT4( dds, width, height, pixels );
|
||||
break;
|
||||
|
||||
case DDS_PF_DXT5:
|
||||
r = DDSDecompressDXT5( dds, width, height, pixels );
|
||||
break;
|
||||
|
||||
default:
|
||||
case DDS_PF_UNKNOWN:
|
||||
memset( pixels, 0xFF, width * height * 4 );
|
||||
r = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* return to sender */
|
||||
return r;
|
||||
}
|
||||
|
||||
//! 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" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool CImageLoaderDDS::isALoadableFileFormat(io::IReadFile* file) const
|
||||
{
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
ddsBuffer header;
|
||||
file->read(&header, sizeof(header));
|
||||
|
||||
s32 width, height;
|
||||
eDDSPixelFormat pixelFormat;
|
||||
|
||||
return 0 == DDSGetInfo( &header, &width, &height, &pixelFormat);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! 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;
|
||||
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));
|
||||
|
||||
if ( DDSDecompress( header, (u8*) image->lock() ) == -1)
|
||||
{
|
||||
image->unlock();
|
||||
image->drop();
|
||||
image = 0;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] memFile;
|
||||
if ( image )
|
||||
image->unlock();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
//! creates a loader which is able to load tgas
|
||||
IImageLoader* createImageLoaderDDS()
|
||||
{
|
||||
return new CImageLoaderDDS();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,324 @@
|
|||
// Copyright (C) 2002-2009 Thomas Alten
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_IMAGE_LOADER_DDS_H_INCLUDED__
|
||||
#define __C_IMAGE_LOADER_DDS_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_DDS_LOADER_) || defined(_IRR_COMPILE_WITH_DDS_WRITER_)
|
||||
|
||||
// byte-align structures
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
# pragma pack( push, packing )
|
||||
# pragma pack( 1 )
|
||||
# define PACK_STRUCT
|
||||
#elif defined( __GNUC__ )
|
||||
# define PACK_STRUCT __attribute__((packed))
|
||||
#else
|
||||
# define PACK_STRUCT
|
||||
#endif
|
||||
|
||||
|
||||
/* dependencies */
|
||||
/* dds definition */
|
||||
enum eDDSPixelFormat
|
||||
{
|
||||
DDS_PF_ARGB8888,
|
||||
DDS_PF_DXT1,
|
||||
DDS_PF_DXT2,
|
||||
DDS_PF_DXT3,
|
||||
DDS_PF_DXT4,
|
||||
DDS_PF_DXT5,
|
||||
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;
|
||||
|
||||
|
||||
/* structures */
|
||||
struct ddsColorKey
|
||||
{
|
||||
u32 colorSpaceLowValue;
|
||||
u32 colorSpaceHighValue;
|
||||
} PACK_STRUCT;
|
||||
|
||||
struct ddsCaps
|
||||
{
|
||||
u32 caps1;
|
||||
u32 caps2;
|
||||
u32 caps3;
|
||||
u32 caps4;
|
||||
} PACK_STRUCT;
|
||||
|
||||
struct ddsMultiSampleCaps
|
||||
{
|
||||
u16 flipMSTypes;
|
||||
u16 bltMSTypes;
|
||||
} 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 ddsCaps;
|
||||
u32 textureStage;
|
||||
|
||||
/* data (Varying size) */
|
||||
u8 data[ 4 ];
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
struct ddsColorBlock
|
||||
{
|
||||
u16 colors[ 2 ];
|
||||
u8 row[ 4 ];
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
struct ddsAlphaBlockExplicit
|
||||
{
|
||||
u16 row[ 4 ];
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
struct ddsAlphaBlock3BitLinear
|
||||
{
|
||||
u8 alpha0;
|
||||
u8 alpha1;
|
||||
u8 stuff[ 6 ];
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
struct ddsColor
|
||||
{
|
||||
u8 r, g, b, a;
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
|
||||
/* public functions */
|
||||
s32 DDSGetInfo( ddsBuffer *dds, s32 *width, s32 *height, eDDSPixelFormat *pf );
|
||||
s32 DDSDecompress( ddsBuffer *dds, u8 *pixels );
|
||||
|
||||
|
||||
|
||||
/* endian tomfoolery */
|
||||
typedef union
|
||||
{
|
||||
f32 f;
|
||||
c8 c[ 4 ];
|
||||
}
|
||||
floatSwapUnion;
|
||||
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
#ifdef _SGI_SOURCE
|
||||
#define __BIG_ENDIAN__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
|
||||
s32 DDSBigLong( s32 src ) { return src; }
|
||||
s16 DDSBigShort( s16 src ) { return src; }
|
||||
f32 DDSBigFloat( f32 src ) { return src; }
|
||||
|
||||
s32 DDSLittleLong( s32 src )
|
||||
{
|
||||
return ((src & 0xFF000000) >> 24) |
|
||||
((src & 0x00FF0000) >> 8) |
|
||||
((src & 0x0000FF00) << 8) |
|
||||
((src & 0x000000FF) << 24);
|
||||
}
|
||||
|
||||
s16 DDSLittleShort( s16 src )
|
||||
{
|
||||
return ((src & 0xFF00) >> 8) |
|
||||
((src & 0x00FF) << 8);
|
||||
}
|
||||
|
||||
f32 DDSLittleFloat( f32 src )
|
||||
{
|
||||
floatSwapUnion in,out;
|
||||
in.f = src;
|
||||
out.c[ 0 ] = in.c[ 3 ];
|
||||
out.c[ 1 ] = in.c[ 2 ];
|
||||
out.c[ 2 ] = in.c[ 1 ];
|
||||
out.c[ 3 ] = in.c[ 0 ];
|
||||
return out.f;
|
||||
}
|
||||
|
||||
#else /*__BIG_ENDIAN__*/
|
||||
|
||||
s32 DDSLittleLong( s32 src ) { return src; }
|
||||
s16 DDSLittleShort( s16 src ) { return src; }
|
||||
f32 DDSLittleFloat( f32 src ) { return src; }
|
||||
|
||||
s32 DDSBigLong( s32 src )
|
||||
{
|
||||
return ((src & 0xFF000000) >> 24) |
|
||||
((src & 0x00FF0000) >> 8) |
|
||||
((src & 0x0000FF00) << 8) |
|
||||
((src & 0x000000FF) << 24);
|
||||
}
|
||||
|
||||
s16 DDSBigShort( s16 src )
|
||||
{
|
||||
return ((src & 0xFF00) >> 8) |
|
||||
((src & 0x00FF) << 8);
|
||||
}
|
||||
|
||||
f32 DDSBigFloat( f32 src )
|
||||
{
|
||||
floatSwapUnion in,out;
|
||||
in.f = src;
|
||||
out.c[ 0 ] = in.c[ 3 ];
|
||||
out.c[ 1 ] = in.c[ 2 ];
|
||||
out.c[ 2 ] = in.c[ 1 ];
|
||||
out.c[ 3 ] = in.c[ 0 ];
|
||||
return out.f;
|
||||
}
|
||||
|
||||
#endif /*__BIG_ENDIAN__*/
|
||||
|
||||
|
||||
// Default alignment
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
# pragma pack( pop, packing )
|
||||
#endif
|
||||
|
||||
#undef PACK_STRUCT
|
||||
|
||||
#endif // compiled with loader or reader
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DDS_LOADER_
|
||||
|
||||
/*!
|
||||
Surface Loader for targa images
|
||||
*/
|
||||
class CImageLoaderDDS : public IImageLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".tga")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const;
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
|
||||
|
||||
//! creates a surface from the file
|
||||
virtual IImage* loadImage(io::IReadFile* file) const;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif // compiled with loader
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
|
@ -33,6 +33,9 @@ IImageLoader* createImageLoaderTGA();
|
|||
//! creates a loader which is able to load psd images
|
||||
IImageLoader* createImageLoaderPSD();
|
||||
|
||||
//! creates a loader which is able to load dds images
|
||||
IImageLoader* createImageLoaderDDS();
|
||||
|
||||
//! creates a loader which is able to load pcx images
|
||||
IImageLoader* createImageLoaderPCX();
|
||||
|
||||
|
@ -108,6 +111,9 @@ 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_
|
||||
SurfaceLoader.push_back(video::createImageLoaderDDS());
|
||||
#endif
|
||||
#ifdef _IRR_COMPILE_WITH_PCX_LOADER_
|
||||
SurfaceLoader.push_back(video::createImageLoaderPCX());
|
||||
#endif
|
||||
|
|
|
@ -2342,6 +2342,14 @@
|
|||
RelativePath="CImageLoaderBMP.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CImageLoaderDDS.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CImageLoaderDDS.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="CImageLoaderJPG.cpp"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue