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 ----------------------------------------------------------------------------- */
43 /* endian tomfoolery */
52 #ifndef __BIG_ENDIAN__
54 #define __BIG_ENDIAN__
61 int DDSBigLong( int src ) { return src; }
62 short DDSBigShort( short src ) { return src; }
63 float DDSBigFloat( float src ) { return src; }
65 int DDSLittleLong( int src ){
66 return ( ( src & 0xFF000000 ) >> 24 ) |
67 ( ( src & 0x00FF0000 ) >> 8 ) |
68 ( ( src & 0x0000FF00 ) << 8 ) |
69 ( ( src & 0x000000FF ) << 24 );
72 short DDSLittleShort( short src ){
73 return ( ( src & 0xFF00 ) >> 8 ) |
74 ( ( src & 0x00FF ) << 8 );
77 float DDSLittleFloat( float src ){
78 floatSwapUnion in,out;
80 out.c[ 0 ] = in.c[ 3 ];
81 out.c[ 1 ] = in.c[ 2 ];
82 out.c[ 2 ] = in.c[ 1 ];
83 out.c[ 3 ] = in.c[ 0 ];
87 #else /*__BIG_ENDIAN__*/
89 int DDSLittleLong( int src ) { return src; }
90 short DDSLittleShort( short src ) { return src; }
91 float DDSLittleFloat( float src ) { return src; }
93 int DDSBigLong( int src ){
94 return ( ( src & 0xFF000000 ) >> 24 ) |
95 ( ( src & 0x00FF0000 ) >> 8 ) |
96 ( ( src & 0x0000FF00 ) << 8 ) |
97 ( ( src & 0x000000FF ) << 24 );
100 short DDSBigShort( short src ){
101 return ( ( src & 0xFF00 ) >> 8 ) |
102 ( ( src & 0x00FF ) << 8 );
105 float DDSBigFloat( float src ){
106 floatSwapUnion in,out;
108 out.c[ 0 ] = in.c[ 3 ];
109 out.c[ 1 ] = in.c[ 2 ];
110 out.c[ 2 ] = in.c[ 1 ];
111 out.c[ 3 ] = in.c[ 0 ];
115 #endif /*__BIG_ENDIAN__*/
120 DDSDecodePixelFormat()
121 determines which pixel format the dds texture is in
124 static void DDSDecodePixelFormat( ddsBuffer_t *dds, ddsPF_t *pf ){
129 if ( dds == NULL || pf == NULL ) {
134 fourCC = dds->pixelFormat.fourCC;
138 *pf = DDS_PF_ARGB8888;
140 else if ( fourCC == *( (unsigned int*) "DXT1" ) ) {
143 else if ( fourCC == *( (unsigned int*) "DXT2" ) ) {
146 else if ( fourCC == *( (unsigned int*) "DXT3" ) ) {
149 else if ( fourCC == *( (unsigned int*) "DXT4" ) ) {
152 else if ( fourCC == *( (unsigned int*) "DXT5" ) ) {
156 *pf = DDS_PF_UNKNOWN;
164 extracts relevant info from a dds texture, returns 0 on success
167 int DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf ){
173 /* test dds header */
174 if ( *( (int*) dds->magic ) != *( (int*) "DDS " ) ) {
177 if ( DDSLittleLong( dds->size ) != 124 ) {
181 /* extract width and height */
182 if ( width != NULL ) {
183 *width = DDSLittleLong( dds->width );
185 if ( height != NULL ) {
186 *height = DDSLittleLong( dds->height );
189 /* get pixel format */
190 DDSDecodePixelFormat( dds, pf );
199 DDSGetColorBlockColors()
200 extracts colors from a dds color block
203 static void DDSGetColorBlockColors( ddsColorBlock_t *block, ddsColor_t colors[ 4 ] ){
208 word = DDSLittleShort( block->colors[ 0 ] );
209 colors[ 0 ].a = 0xff;
211 /* extract rgb bits */
212 colors[ 0 ].b = (unsigned char) word;
214 colors[ 0 ].b |= ( colors[ 0 ].b >> 5 );
216 colors[ 0 ].g = (unsigned char) word;
218 colors[ 0 ].g |= ( colors[ 0 ].g >> 5 );
220 colors[ 0 ].r = (unsigned char) word;
222 colors[ 0 ].r |= ( colors[ 0 ].r >> 5 );
224 /* same for color 1 */
225 word = DDSLittleShort( block->colors[ 1 ] );
226 colors[ 1 ].a = 0xff;
228 /* extract rgb bits */
229 colors[ 1 ].b = (unsigned char) word;
231 colors[ 1 ].b |= ( colors[ 1 ].b >> 5 );
233 colors[ 1 ].g = (unsigned char) word;
235 colors[ 1 ].g |= ( colors[ 1 ].g >> 5 );
237 colors[ 1 ].r = (unsigned char) word;
239 colors[ 1 ].r |= ( colors[ 1 ].r >> 5 );
241 /* use this for all but the super-freak math method */
242 if ( block->colors[ 0 ] > block->colors[ 1 ] ) {
243 /* four-color block: derive the other two colors.
244 00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3
245 these two bit codes correspond to the 2-bit fields
246 stored in the 64-bit block. */
248 word = ( (unsigned short) colors[ 0 ].r * 2 + (unsigned short) colors[ 1 ].r ) / 3;
249 /* no +1 for rounding */
250 /* as bits have been shifted to 888 */
251 colors[ 2 ].r = (unsigned char) word;
252 word = ( (unsigned short) colors[ 0 ].g * 2 + (unsigned short) colors[ 1 ].g ) / 3;
253 colors[ 2 ].g = (unsigned char) word;
254 word = ( (unsigned short) colors[ 0 ].b * 2 + (unsigned short) colors[ 1 ].b ) / 3;
255 colors[ 2 ].b = (unsigned char) word;
256 colors[ 2 ].a = 0xff;
258 word = ( (unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r * 2 ) / 3;
259 colors[ 3 ].r = (unsigned char) word;
260 word = ( (unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g * 2 ) / 3;
261 colors[ 3 ].g = (unsigned char) word;
262 word = ( (unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b * 2 ) / 3;
263 colors[ 3 ].b = (unsigned char) word;
264 colors[ 3 ].a = 0xff;
268 /* three-color block: derive the other color.
269 00 = color 0, 01 = color 1, 10 = color 2,
271 These two bit codes correspond to the 2-bit fields
272 stored in the 64-bit block */
274 word = ( (unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r ) / 2;
275 colors[ 2 ].r = (unsigned char) word;
276 word = ( (unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g ) / 2;
277 colors[ 2 ].g = (unsigned char) word;
278 word = ( (unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b ) / 2;
279 colors[ 2 ].b = (unsigned char) word;
280 colors[ 2 ].a = 0xff;
282 /* random color to indicate alpha */
283 colors[ 3 ].r = 0x00;
284 colors[ 3 ].g = 0xff;
285 colors[ 3 ].b = 0xff;
286 colors[ 3 ].a = 0x00;
293 DDSDecodeColorBlock()
294 decodes a dds color block
295 fixme: make endian-safe
298 static void DDSDecodeColorBlock( unsigned int *pixel, ddsColorBlock_t *block, int width, unsigned int colors[ 4 ] ){
301 unsigned int masks[] = { 3, 12, 3 << 4, 3 << 6 }; /* bit masks = 00000011, 00001100, 00110000, 11000000 */
302 int shift[] = { 0, 2, 4, 6 };
305 /* r steps through lines in y */
306 for ( r = 0; r < 4; r++, pixel += ( width - 4 ) ) /* no width * 4 as unsigned int ptr inc will * 4 */
308 /* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
310 /* n steps through pixels */
311 for ( n = 0; n < 4; n++ )
313 bits = block->row[ r ] & masks[ n ];
319 *pixel = colors[ 0 ];
324 *pixel = colors[ 1 ];
329 *pixel = colors[ 2 ];
334 *pixel = colors[ 3 ];
350 DDSDecodeAlphaExplicit()
351 decodes a dds explicit alpha block
354 static void DDSDecodeAlphaExplicit( unsigned int *pixel, ddsAlphaBlockExplicit_t *alphaBlock, int width, unsigned int alphaZero ){
366 for ( row = 0; row < 4; row++, pixel += ( width - 4 ) )
368 word = DDSLittleShort( alphaBlock->row[ row ] );
371 for ( pix = 0; pix < 4; pix++ )
373 /* zero the alpha bits of image pixel */
375 color.a = word & 0x000F;
376 color.a = color.a | ( color.a << 4 );
377 *pixel |= *( (unsigned int*) &color );
378 word >>= 4; /* move next bits to lowest 4 */
379 pixel++; /* move to next pixel in the row */
388 DDSDecodeAlpha3BitLinear()
389 decodes interpolated alpha block
392 static void DDSDecodeAlpha3BitLinear( unsigned int *pixel, ddsAlphaBlock3BitLinear_t *alphaBlock, int width, unsigned int alphaZero ){
396 unsigned char bits[ 4 ][ 4 ];
397 unsigned short alphas[ 8 ];
398 ddsColor_t aColors[ 4 ][ 4 ];
401 /* get initial alphas */
402 alphas[ 0 ] = alphaBlock->alpha0;
403 alphas[ 1 ] = alphaBlock->alpha1;
406 if ( alphas[ 0 ] > alphas[ 1 ] ) {
407 /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
408 alphas[ 2 ] = ( 6 * alphas[ 0 ] + alphas[ 1 ] ) / 7; /* bit code 010 */
409 alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ] ) / 7; /* bit code 011 */
410 alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ] ) / 7; /* bit code 100 */
411 alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ] ) / 7; /* bit code 101 */
412 alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ] ) / 7; /* bit code 110 */
413 alphas[ 7 ] = ( alphas[ 0 ] + 6 * alphas[ 1 ] ) / 7; /* bit code 111 */
419 /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
420 alphas[ 2 ] = ( 4 * alphas[ 0 ] + alphas[ 1 ] ) / 5; /* bit code 010 */
421 alphas[ 3 ] = ( 3 * alphas[ 0 ] + 2 * alphas[ 1 ] ) / 5; /* bit code 011 */
422 alphas[ 4 ] = ( 2 * alphas[ 0 ] + 3 * alphas[ 1 ] ) / 5; /* bit code 100 */
423 alphas[ 5 ] = ( alphas[ 0 ] + 4 * alphas[ 1 ] ) / 5; /* bit code 101 */
424 alphas[ 6 ] = 0; /* bit code 110 */
425 alphas[ 7 ] = 255; /* bit code 111 */
428 /* decode 3-bit fields into array of 16 bytes with same value */
430 /* first two rows of 4 pixels each */
431 stuff = *( (unsigned int*) &( alphaBlock->stuff[ 0 ] ) );
433 bits[ 0 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
435 bits[ 0 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
437 bits[ 0 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
439 bits[ 0 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
441 bits[ 1 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
443 bits[ 1 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
445 bits[ 1 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
447 bits[ 1 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
450 stuff = *( (unsigned int*) &( alphaBlock->stuff[ 3 ] ) ); /* last 3 bytes */
452 bits[ 2 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
454 bits[ 2 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
456 bits[ 2 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
458 bits[ 2 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
460 bits[ 3 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
462 bits[ 3 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
464 bits[ 3 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
466 bits[ 3 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
468 /* decode the codes into alpha values */
469 for ( row = 0; row < 4; row++ )
471 for ( pix = 0; pix < 4; pix++ )
473 aColors[ row ][ pix ].r = 0;
474 aColors[ row ][ pix ].g = 0;
475 aColors[ row ][ pix ].b = 0;
476 aColors[ row ][ pix ].a = (unsigned char) alphas[ bits[ row ][ pix ] ];
480 /* write out alpha values to the image bits */
481 for ( row = 0; row < 4; row++, pixel += width - 4 )
483 for ( pix = 0; pix < 4; pix++ )
485 /* zero the alpha bits of image pixel */
488 /* or the bits into the prev. nulled alpha */
489 *pixel |= *( (unsigned int*) &( aColors[ row ][ pix ] ) );
499 decompresses a dxt1 format texture
502 static int DDSDecompressDXT1( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
503 int x, y, xBlocks, yBlocks;
505 ddsColorBlock_t *block;
506 ddsColor_t colors[ 4 ];
511 yBlocks = height / 4;
514 for ( y = 0; y < yBlocks; y++ )
516 /* 8 bytes per block */
517 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 8 );
520 for ( x = 0; x < xBlocks; x++, block++ )
522 DDSGetColorBlockColors( block, colors );
523 pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
524 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
536 decompresses a dxt3 format texture
539 static int DDSDecompressDXT3( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
540 int x, y, xBlocks, yBlocks;
541 unsigned int *pixel, alphaZero;
542 ddsColorBlock_t *block;
543 ddsAlphaBlockExplicit_t *alphaBlock;
544 ddsColor_t colors[ 4 ];
549 yBlocks = height / 4;
551 /* create zero alpha */
553 colors[ 0 ].r = 0xFF;
554 colors[ 0 ].g = 0xFF;
555 colors[ 0 ].b = 0xFF;
556 alphaZero = *( (unsigned int*) &colors[ 0 ] );
559 for ( y = 0; y < yBlocks; y++ )
561 /* 8 bytes per block, 1 block for alpha, 1 block for color */
562 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 16 );
565 for ( x = 0; x < xBlocks; x++, block++ )
567 /* get alpha block */
568 alphaBlock = (ddsAlphaBlockExplicit_t*) block;
570 /* get color block */
572 DDSGetColorBlockColors( block, colors );
574 /* decode color block */
575 pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
576 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
578 /* overwrite alpha bits with alpha block */
579 DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
591 decompresses a dxt5 format texture
594 static int DDSDecompressDXT5( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
595 int x, y, xBlocks, yBlocks;
596 unsigned int *pixel, alphaZero;
597 ddsColorBlock_t *block;
598 ddsAlphaBlock3BitLinear_t *alphaBlock;
599 ddsColor_t colors[ 4 ];
604 yBlocks = height / 4;
606 /* create zero alpha */
608 colors[ 0 ].r = 0xFF;
609 colors[ 0 ].g = 0xFF;
610 colors[ 0 ].b = 0xFF;
611 alphaZero = *( (unsigned int*) &colors[ 0 ] );
614 for ( y = 0; y < yBlocks; y++ )
616 /* 8 bytes per block, 1 block for alpha, 1 block for color */
617 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 16 );
620 for ( x = 0; x < xBlocks; x++, block++ )
622 /* get alpha block */
623 alphaBlock = (ddsAlphaBlock3BitLinear_t*) block;
625 /* get color block */
627 DDSGetColorBlockColors( block, colors );
629 /* decode color block */
630 pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
631 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
633 /* overwrite alpha bits with alpha block */
634 DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
646 decompresses a dxt2 format texture (fixme: un-premultiply alpha)
649 static int DDSDecompressDXT2( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
653 /* decompress dxt3 first */
654 r = DDSDecompressDXT3( dds, width, height, pixels );
656 /* return to sender */
664 decompresses a dxt4 format texture (fixme: un-premultiply alpha)
667 static int DDSDecompressDXT4( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
671 /* decompress dxt5 first */
672 r = DDSDecompressDXT5( dds, width, height, pixels );
674 /* return to sender */
681 DDSDecompressARGB8888()
682 decompresses an argb 8888 format texture
685 static int DDSDecompressARGB8888( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
687 unsigned char *in, *out;
695 for ( y = 0; y < height; y++ )
698 for ( x = 0; x < width; x++ )
715 decompresses a dds texture into an rgba image buffer, returns 0 on success
718 int DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels ){
719 int width, height, r;
724 r = DDSGetInfo( dds, &width, &height, &pf );
732 case DDS_PF_ARGB8888:
733 /* fixme: support other [a]rgb formats */
734 r = DDSDecompressARGB8888( dds, width, height, pixels );
738 r = DDSDecompressDXT1( dds, width, height, pixels );
742 r = DDSDecompressDXT2( dds, width, height, pixels );
746 r = DDSDecompressDXT3( dds, width, height, pixels );
750 r = DDSDecompressDXT4( dds, width, height, pixels );
754 r = DDSDecompressDXT5( dds, width, height, pixels );
759 memset( pixels, 0xFF, width * height * 4 );
764 /* return to sender */