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 ----------------------------------------------------------------------------- */
50 /* endian tomfoolery */
59 #ifndef __BIG_ENDIAN__
61 #define __BIG_ENDIAN__
68 int DDSBigLong( int src ) { return src; }
69 short DDSBigShort( short src ) { return src; }
70 float DDSBigFloat( float src ) { return src; }
72 int DDSLittleLong( int src ){
73 return ( ( src & 0xFF000000 ) >> 24 ) |
74 ( ( src & 0x00FF0000 ) >> 8 ) |
75 ( ( src & 0x0000FF00 ) << 8 ) |
76 ( ( src & 0x000000FF ) << 24 );
79 short DDSLittleShort( short src ){
80 return ( ( src & 0xFF00 ) >> 8 ) |
81 ( ( src & 0x00FF ) << 8 );
84 float DDSLittleFloat( float src ){
85 floatSwapUnion in,out;
87 out.c[ 0 ] = in.c[ 3 ];
88 out.c[ 1 ] = in.c[ 2 ];
89 out.c[ 2 ] = in.c[ 1 ];
90 out.c[ 3 ] = in.c[ 0 ];
94 #else /*__BIG_ENDIAN__*/
96 int DDSLittleLong( int src ) { return src; }
97 short DDSLittleShort( short src ) { return src; }
98 float DDSLittleFloat( float src ) { return src; }
100 int DDSBigLong( int src ){
101 return ( ( src & 0xFF000000 ) >> 24 ) |
102 ( ( src & 0x00FF0000 ) >> 8 ) |
103 ( ( src & 0x0000FF00 ) << 8 ) |
104 ( ( src & 0x000000FF ) << 24 );
107 short DDSBigShort( short src ){
108 return ( ( src & 0xFF00 ) >> 8 ) |
109 ( ( src & 0x00FF ) << 8 );
112 float DDSBigFloat( float src ){
113 floatSwapUnion in,out;
115 out.c[ 0 ] = in.c[ 3 ];
116 out.c[ 1 ] = in.c[ 2 ];
117 out.c[ 2 ] = in.c[ 1 ];
118 out.c[ 3 ] = in.c[ 0 ];
122 #endif /*__BIG_ENDIAN__*/
127 DDSDecodePixelFormat()
128 determines which pixel format the dds texture is in
131 static void DDSDecodePixelFormat( ddsBuffer_t *dds, ddsPF_t *pf ){
136 if ( dds == NULL || pf == NULL ) {
141 fourCC = dds->pixelFormat.fourCC;
145 *pf = DDS_PF_ARGB8888;
147 else if ( fourCC == *( (unsigned int*) "DXT1" ) ) {
150 else if ( fourCC == *( (unsigned int*) "DXT2" ) ) {
153 else if ( fourCC == *( (unsigned int*) "DXT3" ) ) {
156 else if ( fourCC == *( (unsigned int*) "DXT4" ) ) {
159 else if ( fourCC == *( (unsigned int*) "DXT5" ) ) {
163 *pf = DDS_PF_UNKNOWN;
171 extracts relevant info from a dds texture, returns 0 on success
174 int DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf ){
180 /* test dds header */
181 if ( *( (int*) dds->magic ) != *( (int*) "DDS " ) ) {
184 if ( DDSLittleLong( dds->size ) != 124 ) {
188 /* extract width and height */
189 if ( width != NULL ) {
190 *width = DDSLittleLong( dds->width );
192 if ( height != NULL ) {
193 *height = DDSLittleLong( dds->height );
196 /* get pixel format */
197 DDSDecodePixelFormat( dds, pf );
206 DDSGetColorBlockColors()
207 extracts colors from a dds color block
210 static void DDSGetColorBlockColors( ddsColorBlock_t *block, ddsColor_t colors[ 4 ] ){
215 word = DDSLittleShort( block->colors[ 0 ] );
216 colors[ 0 ].a = 0xff;
218 /* extract rgb bits */
219 colors[ 0 ].b = (unsigned char) word;
221 colors[ 0 ].b |= ( colors[ 0 ].b >> 5 );
223 colors[ 0 ].g = (unsigned char) word;
225 colors[ 0 ].g |= ( colors[ 0 ].g >> 5 );
227 colors[ 0 ].r = (unsigned char) word;
229 colors[ 0 ].r |= ( colors[ 0 ].r >> 5 );
231 /* same for color 1 */
232 word = DDSLittleShort( block->colors[ 1 ] );
233 colors[ 1 ].a = 0xff;
235 /* extract rgb bits */
236 colors[ 1 ].b = (unsigned char) word;
238 colors[ 1 ].b |= ( colors[ 1 ].b >> 5 );
240 colors[ 1 ].g = (unsigned char) word;
242 colors[ 1 ].g |= ( colors[ 1 ].g >> 5 );
244 colors[ 1 ].r = (unsigned char) word;
246 colors[ 1 ].r |= ( colors[ 1 ].r >> 5 );
248 /* use this for all but the super-freak math method */
249 if ( block->colors[ 0 ] > block->colors[ 1 ] ) {
250 /* four-color block: derive the other two colors.
251 00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3
252 these two bit codes correspond to the 2-bit fields
253 stored in the 64-bit block. */
255 word = ( (unsigned short) colors[ 0 ].r * 2 + (unsigned short) colors[ 1 ].r ) / 3;
256 /* no +1 for rounding */
257 /* as bits have been shifted to 888 */
258 colors[ 2 ].r = (unsigned char) word;
259 word = ( (unsigned short) colors[ 0 ].g * 2 + (unsigned short) colors[ 1 ].g ) / 3;
260 colors[ 2 ].g = (unsigned char) word;
261 word = ( (unsigned short) colors[ 0 ].b * 2 + (unsigned short) colors[ 1 ].b ) / 3;
262 colors[ 2 ].b = (unsigned char) word;
263 colors[ 2 ].a = 0xff;
265 word = ( (unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r * 2 ) / 3;
266 colors[ 3 ].r = (unsigned char) word;
267 word = ( (unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g * 2 ) / 3;
268 colors[ 3 ].g = (unsigned char) word;
269 word = ( (unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b * 2 ) / 3;
270 colors[ 3 ].b = (unsigned char) word;
271 colors[ 3 ].a = 0xff;
275 /* three-color block: derive the other color.
276 00 = color 0, 01 = color 1, 10 = color 2,
278 These two bit codes correspond to the 2-bit fields
279 stored in the 64-bit block */
281 word = ( (unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r ) / 2;
282 colors[ 2 ].r = (unsigned char) word;
283 word = ( (unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g ) / 2;
284 colors[ 2 ].g = (unsigned char) word;
285 word = ( (unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b ) / 2;
286 colors[ 2 ].b = (unsigned char) word;
287 colors[ 2 ].a = 0xff;
289 /* random color to indicate alpha */
290 colors[ 3 ].r = 0x00;
291 colors[ 3 ].g = 0xff;
292 colors[ 3 ].b = 0xff;
293 colors[ 3 ].a = 0x00;
300 DDSDecodeColorBlock()
301 decodes a dds color block
302 fixme: make endian-safe
305 static void DDSDecodeColorBlock( unsigned int *pixel, ddsColorBlock_t *block, int width, unsigned int colors[ 4 ] ){
308 unsigned int masks[] = { 3, 12, 3 << 4, 3 << 6 }; /* bit masks = 00000011, 00001100, 00110000, 11000000 */
309 int shift[] = { 0, 2, 4, 6 };
312 /* r steps through lines in y */
313 for ( r = 0; r < 4; r++, pixel += ( width - 4 ) ) /* no width * 4 as unsigned int ptr inc will * 4 */
315 /* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
317 /* n steps through pixels */
318 for ( n = 0; n < 4; n++ )
320 bits = block->row[ r ] & masks[ n ];
326 *pixel = colors[ 0 ];
331 *pixel = colors[ 1 ];
336 *pixel = colors[ 2 ];
341 *pixel = colors[ 3 ];
357 DDSDecodeAlphaExplicit()
358 decodes a dds explicit alpha block
361 static void DDSDecodeAlphaExplicit( unsigned int *pixel, ddsAlphaBlockExplicit_t *alphaBlock, int width, unsigned int alphaZero ){
373 for ( row = 0; row < 4; row++, pixel += ( width - 4 ) )
375 word = DDSLittleShort( alphaBlock->row[ row ] );
378 for ( pix = 0; pix < 4; pix++ )
380 /* zero the alpha bits of image pixel */
382 color.a = word & 0x000F;
383 color.a = color.a | ( color.a << 4 );
384 *pixel |= *( (unsigned int*) &color );
385 word >>= 4; /* move next bits to lowest 4 */
386 pixel++; /* move to next pixel in the row */
395 DDSDecodeAlpha3BitLinear()
396 decodes interpolated alpha block
399 static void DDSDecodeAlpha3BitLinear( unsigned int *pixel, ddsAlphaBlock3BitLinear_t *alphaBlock, int width, unsigned int alphaZero ){
403 unsigned char bits[ 4 ][ 4 ];
404 unsigned short alphas[ 8 ];
405 ddsColor_t aColors[ 4 ][ 4 ];
408 /* get initial alphas */
409 alphas[ 0 ] = alphaBlock->alpha0;
410 alphas[ 1 ] = alphaBlock->alpha1;
413 if ( alphas[ 0 ] > alphas[ 1 ] ) {
414 /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
415 alphas[ 2 ] = ( 6 * alphas[ 0 ] + alphas[ 1 ] ) / 7; /* bit code 010 */
416 alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ] ) / 7; /* bit code 011 */
417 alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ] ) / 7; /* bit code 100 */
418 alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ] ) / 7; /* bit code 101 */
419 alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ] ) / 7; /* bit code 110 */
420 alphas[ 7 ] = ( alphas[ 0 ] + 6 * alphas[ 1 ] ) / 7; /* bit code 111 */
426 /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
427 alphas[ 2 ] = ( 4 * alphas[ 0 ] + alphas[ 1 ] ) / 5; /* bit code 010 */
428 alphas[ 3 ] = ( 3 * alphas[ 0 ] + 2 * alphas[ 1 ] ) / 5; /* bit code 011 */
429 alphas[ 4 ] = ( 2 * alphas[ 0 ] + 3 * alphas[ 1 ] ) / 5; /* bit code 100 */
430 alphas[ 5 ] = ( alphas[ 0 ] + 4 * alphas[ 1 ] ) / 5; /* bit code 101 */
431 alphas[ 6 ] = 0; /* bit code 110 */
432 alphas[ 7 ] = 255; /* bit code 111 */
435 /* decode 3-bit fields into array of 16 bytes with same value */
437 /* first two rows of 4 pixels each */
438 stuff = *( (unsigned int*) &( alphaBlock->stuff[ 0 ] ) );
440 bits[ 0 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
442 bits[ 0 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
444 bits[ 0 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
446 bits[ 0 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
448 bits[ 1 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
450 bits[ 1 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
452 bits[ 1 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
454 bits[ 1 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
457 stuff = *( (unsigned int*) &( alphaBlock->stuff[ 3 ] ) ); /* last 3 bytes */
459 bits[ 2 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
461 bits[ 2 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
463 bits[ 2 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
465 bits[ 2 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
467 bits[ 3 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
469 bits[ 3 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
471 bits[ 3 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
473 bits[ 3 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
475 /* decode the codes into alpha values */
476 for ( row = 0; row < 4; row++ )
478 for ( pix = 0; pix < 4; pix++ )
480 aColors[ row ][ pix ].r = 0;
481 aColors[ row ][ pix ].g = 0;
482 aColors[ row ][ pix ].b = 0;
483 aColors[ row ][ pix ].a = (unsigned char) alphas[ bits[ row ][ pix ] ];
487 /* write out alpha values to the image bits */
488 for ( row = 0; row < 4; row++, pixel += width - 4 )
490 for ( pix = 0; pix < 4; pix++ )
492 /* zero the alpha bits of image pixel */
495 /* or the bits into the prev. nulled alpha */
496 *pixel |= *( (unsigned int*) &( aColors[ row ][ pix ] ) );
506 decompresses a dxt1 format texture
509 static int DDSDecompressDXT1( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
510 int x, y, xBlocks, yBlocks;
512 ddsColorBlock_t *block;
513 ddsColor_t colors[ 4 ];
518 yBlocks = height / 4;
521 for ( y = 0; y < yBlocks; y++ )
523 /* 8 bytes per block */
524 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 8 );
527 for ( x = 0; x < xBlocks; x++, block++ )
529 DDSGetColorBlockColors( block, colors );
530 pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
531 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
543 decompresses a dxt3 format texture
546 static int DDSDecompressDXT3( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
547 int x, y, xBlocks, yBlocks;
548 unsigned int *pixel, alphaZero;
549 ddsColorBlock_t *block;
550 ddsAlphaBlockExplicit_t *alphaBlock;
551 ddsColor_t colors[ 4 ];
556 yBlocks = height / 4;
558 /* create zero alpha */
560 colors[ 0 ].r = 0xFF;
561 colors[ 0 ].g = 0xFF;
562 colors[ 0 ].b = 0xFF;
563 alphaZero = *( (unsigned int*) &colors[ 0 ] );
566 for ( y = 0; y < yBlocks; y++ )
568 /* 8 bytes per block, 1 block for alpha, 1 block for color */
569 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 16 );
572 for ( x = 0; x < xBlocks; x++, block++ )
574 /* get alpha block */
575 alphaBlock = (ddsAlphaBlockExplicit_t*) block;
577 /* get color block */
579 DDSGetColorBlockColors( block, colors );
581 /* decode color block */
582 pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
583 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
585 /* overwrite alpha bits with alpha block */
586 DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
598 decompresses a dxt5 format texture
601 static int DDSDecompressDXT5( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
602 int x, y, xBlocks, yBlocks;
603 unsigned int *pixel, alphaZero;
604 ddsColorBlock_t *block;
605 ddsAlphaBlock3BitLinear_t *alphaBlock;
606 ddsColor_t colors[ 4 ];
611 yBlocks = height / 4;
613 /* create zero alpha */
615 colors[ 0 ].r = 0xFF;
616 colors[ 0 ].g = 0xFF;
617 colors[ 0 ].b = 0xFF;
618 alphaZero = *( (unsigned int*) &colors[ 0 ] );
621 for ( y = 0; y < yBlocks; y++ )
623 /* 8 bytes per block, 1 block for alpha, 1 block for color */
624 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 16 );
627 for ( x = 0; x < xBlocks; x++, block++ )
629 /* get alpha block */
630 alphaBlock = (ddsAlphaBlock3BitLinear_t*) block;
632 /* get color block */
634 DDSGetColorBlockColors( block, colors );
636 /* decode color block */
637 pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
638 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
640 /* overwrite alpha bits with alpha block */
641 DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
653 decompresses a dxt2 format texture (fixme: un-premultiply alpha)
656 static int DDSDecompressDXT2( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
660 /* decompress dxt3 first */
661 r = DDSDecompressDXT3( dds, width, height, pixels );
663 /* return to sender */
671 decompresses a dxt4 format texture (fixme: un-premultiply alpha)
674 static int DDSDecompressDXT4( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
678 /* decompress dxt5 first */
679 r = DDSDecompressDXT5( dds, width, height, pixels );
681 /* return to sender */
688 DDSDecompressARGB8888()
689 decompresses an argb 8888 format texture
692 static int DDSDecompressARGB8888( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
694 unsigned char *in, *out;
702 for ( y = 0; y < height; y++ )
705 for ( x = 0; x < width; x++ )
722 decompresses a dds texture into an rgba image buffer, returns 0 on success
725 int DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels ){
726 int width, height, r;
731 r = DDSGetInfo( dds, &width, &height, &pf );
739 case DDS_PF_ARGB8888:
740 /* fixme: support other [a]rgb formats */
741 r = DDSDecompressARGB8888( dds, width, height, pixels );
745 r = DDSDecompressDXT1( dds, width, height, pixels );
749 r = DDSDecompressDXT2( dds, width, height, pixels );
753 r = DDSDecompressDXT3( dds, width, height, pixels );
757 r = DDSDecompressDXT4( dds, width, height, pixels );
761 r = DDSDecompressDXT5( dds, width, height, pixels );
766 memset( pixels, 0xFF, width * height * 4 );
771 /* return to sender */