1 /* -----------------------------------------------------------------------------
5 Based on code from Nvidia's DDS example:
6 http://www.nvidia.com/object/dxtc_decompression_code.html
8 Copyright (c) 2003 Randy Reddig
11 Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
14 Redistributions of source code must retain the above copyright notice, this list
15 of conditions and the following disclaimer.
17 Redistributions in binary form must reproduce the above copyright notice, this
18 list of conditions and the following disclaimer in the documentation and/or
19 other materials provided with the distribution.
21 Neither the names of the copyright holders nor the names of its contributors may
22 be used to endorse or promote products derived from this software without
23 specific prior written permission.
25 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
29 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
32 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 ----------------------------------------------------------------------------- */
40 #include "globaldefs.h"
42 /* endian tomfoolery */
50 #if GDEF_ARCH_ENDIAN_BIG
52 int DDSBigLong( int src ) { return src; }
53 short DDSBigShort( short src ) { return src; }
54 float DDSBigFloat( float src ) { return src; }
56 int DDSLittleLong( int src ){
57 return ( ( src & 0xFF000000 ) >> 24 ) |
58 ( ( src & 0x00FF0000 ) >> 8 ) |
59 ( ( src & 0x0000FF00 ) << 8 ) |
60 ( ( src & 0x000000FF ) << 24 );
63 short DDSLittleShort( short src ){
64 return ( ( src & 0xFF00 ) >> 8 ) |
65 ( ( src & 0x00FF ) << 8 );
68 float DDSLittleFloat( float src ){
69 floatSwapUnion in,out;
71 out.c[ 0 ] = in.c[ 3 ];
72 out.c[ 1 ] = in.c[ 2 ];
73 out.c[ 2 ] = in.c[ 1 ];
74 out.c[ 3 ] = in.c[ 0 ];
78 #else /*__BIG_ENDIAN__*/
80 int DDSLittleLong( int src ) { return src; }
81 short DDSLittleShort( short src ) { return src; }
82 float DDSLittleFloat( float src ) { return src; }
84 int DDSBigLong( int src ){
85 return ( ( src & 0xFF000000 ) >> 24 ) |
86 ( ( src & 0x00FF0000 ) >> 8 ) |
87 ( ( src & 0x0000FF00 ) << 8 ) |
88 ( ( src & 0x000000FF ) << 24 );
91 short DDSBigShort( short src ){
92 return ( ( src & 0xFF00 ) >> 8 ) |
93 ( ( src & 0x00FF ) << 8 );
96 float DDSBigFloat( float src ){
97 floatSwapUnion in,out;
99 out.c[ 0 ] = in.c[ 3 ];
100 out.c[ 1 ] = in.c[ 2 ];
101 out.c[ 2 ] = in.c[ 1 ];
102 out.c[ 3 ] = in.c[ 0 ];
106 #endif /*__BIG_ENDIAN__*/
111 DDSDecodePixelFormat()
112 determines which pixel format the dds texture is in
115 static void DDSDecodePixelFormat( ddsBuffer_t *dds, ddsPF_t *pf ){
120 if ( dds == NULL || pf == NULL ) {
125 fourCC = dds->pixelFormat.fourCC;
129 *pf = DDS_PF_ARGB8888;
131 else if ( fourCC == *( (unsigned int*) "DXT1" ) ) {
134 else if ( fourCC == *( (unsigned int*) "DXT2" ) ) {
137 else if ( fourCC == *( (unsigned int*) "DXT3" ) ) {
140 else if ( fourCC == *( (unsigned int*) "DXT4" ) ) {
143 else if ( fourCC == *( (unsigned int*) "DXT5" ) ) {
147 *pf = DDS_PF_UNKNOWN;
155 extracts relevant info from a dds texture, returns 0 on success
158 int DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf ){
164 /* test dds header */
165 if ( *( (int*) dds->magic ) != *( (int*) "DDS " ) ) {
168 if ( DDSLittleLong( dds->size ) != 124 ) {
172 /* extract width and height */
173 if ( width != NULL ) {
174 *width = DDSLittleLong( dds->width );
176 if ( height != NULL ) {
177 *height = DDSLittleLong( dds->height );
180 /* get pixel format */
181 DDSDecodePixelFormat( dds, pf );
190 DDSGetColorBlockColors()
191 extracts colors from a dds color block
194 static void DDSGetColorBlockColors( ddsColorBlock_t *block, ddsColor_t colors[ 4 ] ){
199 word = DDSLittleShort( block->colors[ 0 ] );
200 colors[ 0 ].a = 0xff;
202 /* extract rgb bits */
203 colors[ 0 ].b = (unsigned char) word;
205 colors[ 0 ].b |= ( colors[ 0 ].b >> 5 );
207 colors[ 0 ].g = (unsigned char) word;
209 colors[ 0 ].g |= ( colors[ 0 ].g >> 5 );
211 colors[ 0 ].r = (unsigned char) word;
213 colors[ 0 ].r |= ( colors[ 0 ].r >> 5 );
215 /* same for color 1 */
216 word = DDSLittleShort( block->colors[ 1 ] );
217 colors[ 1 ].a = 0xff;
219 /* extract rgb bits */
220 colors[ 1 ].b = (unsigned char) word;
222 colors[ 1 ].b |= ( colors[ 1 ].b >> 5 );
224 colors[ 1 ].g = (unsigned char) word;
226 colors[ 1 ].g |= ( colors[ 1 ].g >> 5 );
228 colors[ 1 ].r = (unsigned char) word;
230 colors[ 1 ].r |= ( colors[ 1 ].r >> 5 );
232 /* use this for all but the super-freak math method */
233 if ( block->colors[ 0 ] > block->colors[ 1 ] ) {
234 /* four-color block: derive the other two colors.
235 00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3
236 these two bit codes correspond to the 2-bit fields
237 stored in the 64-bit block. */
239 word = ( (unsigned short) colors[ 0 ].r * 2 + (unsigned short) colors[ 1 ].r ) / 3;
240 /* no +1 for rounding */
241 /* as bits have been shifted to 888 */
242 colors[ 2 ].r = (unsigned char) word;
243 word = ( (unsigned short) colors[ 0 ].g * 2 + (unsigned short) colors[ 1 ].g ) / 3;
244 colors[ 2 ].g = (unsigned char) word;
245 word = ( (unsigned short) colors[ 0 ].b * 2 + (unsigned short) colors[ 1 ].b ) / 3;
246 colors[ 2 ].b = (unsigned char) word;
247 colors[ 2 ].a = 0xff;
249 word = ( (unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r * 2 ) / 3;
250 colors[ 3 ].r = (unsigned char) word;
251 word = ( (unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g * 2 ) / 3;
252 colors[ 3 ].g = (unsigned char) word;
253 word = ( (unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b * 2 ) / 3;
254 colors[ 3 ].b = (unsigned char) word;
255 colors[ 3 ].a = 0xff;
259 /* three-color block: derive the other color.
260 00 = color 0, 01 = color 1, 10 = color 2,
262 These two bit codes correspond to the 2-bit fields
263 stored in the 64-bit block */
265 word = ( (unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r ) / 2;
266 colors[ 2 ].r = (unsigned char) word;
267 word = ( (unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g ) / 2;
268 colors[ 2 ].g = (unsigned char) word;
269 word = ( (unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b ) / 2;
270 colors[ 2 ].b = (unsigned char) word;
271 colors[ 2 ].a = 0xff;
273 /* random color to indicate alpha */
274 colors[ 3 ].r = 0x00;
275 colors[ 3 ].g = 0xff;
276 colors[ 3 ].b = 0xff;
277 colors[ 3 ].a = 0x00;
284 DDSDecodeColorBlock()
285 decodes a dds color block
286 fixme: make endian-safe
289 static void DDSDecodeColorBlock( unsigned int *pixel, ddsColorBlock_t *block, int width, unsigned int colors[ 4 ] ){
292 unsigned int masks[] = { 3, 12, 3 << 4, 3 << 6 }; /* bit masks = 00000011, 00001100, 00110000, 11000000 */
293 int shift[] = { 0, 2, 4, 6 };
296 /* r steps through lines in y */
297 for ( r = 0; r < 4; r++, pixel += ( width - 4 ) ) /* no width * 4 as unsigned int ptr inc will * 4 */
299 /* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
301 /* n steps through pixels */
302 for ( n = 0; n < 4; n++ )
304 bits = block->row[ r ] & masks[ n ];
310 *pixel = colors[ 0 ];
315 *pixel = colors[ 1 ];
320 *pixel = colors[ 2 ];
325 *pixel = colors[ 3 ];
341 DDSDecodeAlphaExplicit()
342 decodes a dds explicit alpha block
345 static void DDSDecodeAlphaExplicit( unsigned int *pixel, ddsAlphaBlockExplicit_t *alphaBlock, int width, unsigned int alphaZero ){
357 for ( row = 0; row < 4; row++, pixel += ( width - 4 ) )
359 word = DDSLittleShort( alphaBlock->row[ row ] );
362 for ( pix = 0; pix < 4; pix++ )
364 /* zero the alpha bits of image pixel */
366 color.a = word & 0x000F;
367 color.a = color.a | ( color.a << 4 );
368 *pixel |= *( (unsigned int*) &color );
369 word >>= 4; /* move next bits to lowest 4 */
370 pixel++; /* move to next pixel in the row */
379 DDSDecodeAlpha3BitLinear()
380 decodes interpolated alpha block
383 static void DDSDecodeAlpha3BitLinear( unsigned int *pixel, ddsAlphaBlock3BitLinear_t *alphaBlock, int width, unsigned int alphaZero ){
387 unsigned char bits[ 4 ][ 4 ];
388 unsigned short alphas[ 8 ];
389 ddsColor_t aColors[ 4 ][ 4 ];
392 /* get initial alphas */
393 alphas[ 0 ] = alphaBlock->alpha0;
394 alphas[ 1 ] = alphaBlock->alpha1;
397 if ( alphas[ 0 ] > alphas[ 1 ] ) {
398 /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
399 alphas[ 2 ] = ( 6 * alphas[ 0 ] + alphas[ 1 ] ) / 7; /* bit code 010 */
400 alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ] ) / 7; /* bit code 011 */
401 alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ] ) / 7; /* bit code 100 */
402 alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ] ) / 7; /* bit code 101 */
403 alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ] ) / 7; /* bit code 110 */
404 alphas[ 7 ] = ( alphas[ 0 ] + 6 * alphas[ 1 ] ) / 7; /* bit code 111 */
410 /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
411 alphas[ 2 ] = ( 4 * alphas[ 0 ] + alphas[ 1 ] ) / 5; /* bit code 010 */
412 alphas[ 3 ] = ( 3 * alphas[ 0 ] + 2 * alphas[ 1 ] ) / 5; /* bit code 011 */
413 alphas[ 4 ] = ( 2 * alphas[ 0 ] + 3 * alphas[ 1 ] ) / 5; /* bit code 100 */
414 alphas[ 5 ] = ( alphas[ 0 ] + 4 * alphas[ 1 ] ) / 5; /* bit code 101 */
415 alphas[ 6 ] = 0; /* bit code 110 */
416 alphas[ 7 ] = 255; /* bit code 111 */
419 /* decode 3-bit fields into array of 16 bytes with same value */
421 /* first two rows of 4 pixels each */
422 stuff = *( (unsigned int*) &( alphaBlock->stuff[ 0 ] ) );
424 bits[ 0 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
426 bits[ 0 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
428 bits[ 0 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
430 bits[ 0 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
432 bits[ 1 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
434 bits[ 1 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
436 bits[ 1 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
438 bits[ 1 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
441 stuff = *( (unsigned int*) &( alphaBlock->stuff[ 3 ] ) ); /* last 3 bytes */
443 bits[ 2 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
445 bits[ 2 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
447 bits[ 2 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
449 bits[ 2 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
451 bits[ 3 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
453 bits[ 3 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
455 bits[ 3 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
457 bits[ 3 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
459 /* decode the codes into alpha values */
460 for ( row = 0; row < 4; row++ )
462 for ( pix = 0; pix < 4; pix++ )
464 aColors[ row ][ pix ].r = 0;
465 aColors[ row ][ pix ].g = 0;
466 aColors[ row ][ pix ].b = 0;
467 aColors[ row ][ pix ].a = (unsigned char) alphas[ bits[ row ][ pix ] ];
471 /* write out alpha values to the image bits */
472 for ( row = 0; row < 4; row++, pixel += width - 4 )
474 for ( pix = 0; pix < 4; pix++ )
476 /* zero the alpha bits of image pixel */
479 /* or the bits into the prev. nulled alpha */
480 *pixel |= *( (unsigned int*) &( aColors[ row ][ pix ] ) );
490 decompresses a dxt1 format texture
493 static int DDSDecompressDXT1( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
494 int x, y, xBlocks, yBlocks;
496 ddsColorBlock_t *block;
497 ddsColor_t colors[ 4 ];
502 yBlocks = height / 4;
505 for ( y = 0; y < yBlocks; y++ )
507 /* 8 bytes per block */
508 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 8 );
511 for ( x = 0; x < xBlocks; x++, block++ )
513 DDSGetColorBlockColors( block, colors );
514 pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
515 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
527 decompresses a dxt3 format texture
530 static int DDSDecompressDXT3( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
531 int x, y, xBlocks, yBlocks;
532 unsigned int *pixel, alphaZero;
533 ddsColorBlock_t *block;
534 ddsAlphaBlockExplicit_t *alphaBlock;
535 ddsColor_t colors[ 4 ];
540 yBlocks = height / 4;
542 /* create zero alpha */
544 colors[ 0 ].r = 0xFF;
545 colors[ 0 ].g = 0xFF;
546 colors[ 0 ].b = 0xFF;
547 alphaZero = *( (unsigned int*) &colors[ 0 ] );
550 for ( y = 0; y < yBlocks; y++ )
552 /* 8 bytes per block, 1 block for alpha, 1 block for color */
553 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 16 );
556 for ( x = 0; x < xBlocks; x++, block++ )
558 /* get alpha block */
559 alphaBlock = (ddsAlphaBlockExplicit_t*) block;
561 /* get color block */
563 DDSGetColorBlockColors( block, colors );
565 /* decode color block */
566 pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
567 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
569 /* overwrite alpha bits with alpha block */
570 DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
582 decompresses a dxt5 format texture
585 static int DDSDecompressDXT5( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
586 int x, y, xBlocks, yBlocks;
587 unsigned int *pixel, alphaZero;
588 ddsColorBlock_t *block;
589 ddsAlphaBlock3BitLinear_t *alphaBlock;
590 ddsColor_t colors[ 4 ];
595 yBlocks = height / 4;
597 /* create zero alpha */
599 colors[ 0 ].r = 0xFF;
600 colors[ 0 ].g = 0xFF;
601 colors[ 0 ].b = 0xFF;
602 alphaZero = *( (unsigned int*) &colors[ 0 ] );
605 for ( y = 0; y < yBlocks; y++ )
607 /* 8 bytes per block, 1 block for alpha, 1 block for color */
608 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 16 );
611 for ( x = 0; x < xBlocks; x++, block++ )
613 /* get alpha block */
614 alphaBlock = (ddsAlphaBlock3BitLinear_t*) block;
616 /* get color block */
618 DDSGetColorBlockColors( block, colors );
620 /* decode color block */
621 pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
622 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
624 /* overwrite alpha bits with alpha block */
625 DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
637 decompresses a dxt2 format texture (fixme: un-premultiply alpha)
640 static int DDSDecompressDXT2( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
644 /* decompress dxt3 first */
645 r = DDSDecompressDXT3( dds, width, height, pixels );
647 /* return to sender */
655 decompresses a dxt4 format texture (fixme: un-premultiply alpha)
658 static int DDSDecompressDXT4( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
662 /* decompress dxt5 first */
663 r = DDSDecompressDXT5( dds, width, height, pixels );
665 /* return to sender */
672 DDSDecompressARGB8888()
673 decompresses an argb 8888 format texture
676 static int DDSDecompressARGB8888( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
678 unsigned char *in, *out;
686 for ( y = 0; y < height; y++ )
689 for ( x = 0; x < width; x++ )
706 decompresses a dds texture into an rgba image buffer, returns 0 on success
709 int DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels ){
710 int width, height, r;
715 r = DDSGetInfo( dds, &width, &height, &pf );
723 case DDS_PF_ARGB8888:
724 /* fixme: support other [a]rgb formats */
725 r = DDSDecompressARGB8888( dds, width, height, pixels );
729 r = DDSDecompressDXT1( dds, width, height, pixels );
733 r = DDSDecompressDXT2( dds, width, height, pixels );
737 r = DDSDecompressDXT3( dds, width, height, pixels );
741 r = DDSDecompressDXT4( dds, width, height, pixels );
745 r = DDSDecompressDXT5( dds, width, height, pixels );
750 memset( pixels, 0xFF, width * height * 4 );
755 /* return to sender */