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 )
74 return ((src & 0xFF000000) >> 24) |
75 ((src & 0x00FF0000) >> 8) |
76 ((src & 0x0000FF00) << 8) |
77 ((src & 0x000000FF) << 24);
80 short DDSLittleShort( short src )
82 return ((src & 0xFF00) >> 8) |
83 ((src & 0x00FF) << 8);
86 float DDSLittleFloat( float src )
88 floatSwapUnion in,out;
90 out.c[ 0 ] = in.c[ 3 ];
91 out.c[ 1 ] = in.c[ 2 ];
92 out.c[ 2 ] = in.c[ 1 ];
93 out.c[ 3 ] = in.c[ 0 ];
97 #else /*__BIG_ENDIAN__*/
99 int DDSLittleLong( int src ) { return src; }
100 short DDSLittleShort( short src ) { return src; }
101 float DDSLittleFloat( float src ) { return src; }
103 int DDSBigLong( int src )
105 return ((src & 0xFF000000) >> 24) |
106 ((src & 0x00FF0000) >> 8) |
107 ((src & 0x0000FF00) << 8) |
108 ((src & 0x000000FF) << 24);
111 short DDSBigShort( short src )
113 return ((src & 0xFF00) >> 8) |
114 ((src & 0x00FF) << 8);
117 float DDSBigFloat( float src )
119 floatSwapUnion in,out;
121 out.c[ 0 ] = in.c[ 3 ];
122 out.c[ 1 ] = in.c[ 2 ];
123 out.c[ 2 ] = in.c[ 1 ];
124 out.c[ 3 ] = in.c[ 0 ];
128 #endif /*__BIG_ENDIAN__*/
133 DDSDecodePixelFormat()
134 determines which pixel format the dds texture is in
137 static void DDSDecodePixelFormat( ddsBuffer_t *dds, ddsPF_t *pf )
143 if( dds == NULL || pf == NULL )
147 fourCC = dds->pixelFormat.fourCC;
151 *pf = DDS_PF_ARGB8888;
152 else if( fourCC == *((unsigned int*) "DXT1") )
154 else if( fourCC == *((unsigned int*) "DXT2") )
156 else if( fourCC == *((unsigned int*) "DXT3") )
158 else if( fourCC == *((unsigned int*) "DXT4") )
160 else if( fourCC == *((unsigned int*) "DXT5") )
163 *pf = DDS_PF_UNKNOWN;
170 extracts relevant info from a dds texture, returns 0 on success
173 int DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf )
179 /* test dds header */
180 if( *((int*) dds->magic) != *((int*) "DDS ") )
182 if( DDSLittleLong( dds->size ) != 124 )
185 /* extract width and height */
187 *width = DDSLittleLong( dds->width );
189 *height = DDSLittleLong( dds->height );
191 /* get pixel format */
192 DDSDecodePixelFormat( dds, pf );
201 DDSGetColorBlockColors()
202 extracts colors from a dds color block
205 static void DDSGetColorBlockColors( ddsColorBlock_t *block, ddsColor_t colors[ 4 ] )
211 word = DDSLittleShort( block->colors[ 0 ] );
212 colors[ 0 ].a = 0xff;
214 /* extract rgb bits */
215 colors[ 0 ].b = (unsigned char) word;
217 colors[ 0 ].b |= (colors[ 0 ].b >> 5);
219 colors[ 0 ].g = (unsigned char) word;
221 colors[ 0 ].g |= (colors[ 0 ].g >> 5);
223 colors[ 0 ].r = (unsigned char) word;
225 colors[ 0 ].r |= (colors[ 0 ].r >> 5);
227 /* same for color 1 */
228 word = DDSLittleShort( block->colors[ 1 ] );
229 colors[ 1 ].a = 0xff;
231 /* extract rgb bits */
232 colors[ 1 ].b = (unsigned char) word;
234 colors[ 1 ].b |= (colors[ 1 ].b >> 5);
236 colors[ 1 ].g = (unsigned char) word;
238 colors[ 1 ].g |= (colors[ 1 ].g >> 5);
240 colors[ 1 ].r = (unsigned char) word;
242 colors[ 1 ].r |= (colors[ 1 ].r >> 5);
244 /* use this for all but the super-freak math method */
245 if( block->colors[ 0 ] > block->colors[ 1 ] )
247 /* four-color block: derive the other two colors.
248 00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3
249 these two bit codes correspond to the 2-bit fields
250 stored in the 64-bit block. */
252 word = ((unsigned short) colors[ 0 ].r * 2 + (unsigned short) colors[ 1 ].r ) / 3;
253 /* no +1 for rounding */
254 /* as bits have been shifted to 888 */
255 colors[ 2 ].r = (unsigned char) word;
256 word = ((unsigned short) colors[ 0 ].g * 2 + (unsigned short) colors[ 1 ].g) / 3;
257 colors[ 2 ].g = (unsigned char) word;
258 word = ((unsigned short) colors[ 0 ].b * 2 + (unsigned short) colors[ 1 ].b) / 3;
259 colors[ 2 ].b = (unsigned char) word;
260 colors[ 2 ].a = 0xff;
262 word = ((unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r * 2) / 3;
263 colors[ 3 ].r = (unsigned char) word;
264 word = ((unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g * 2) / 3;
265 colors[ 3 ].g = (unsigned char) word;
266 word = ((unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b * 2) / 3;
267 colors[ 3 ].b = (unsigned char) word;
268 colors[ 3 ].a = 0xff;
272 /* three-color block: derive the other color.
273 00 = color 0, 01 = color 1, 10 = color 2,
275 These two bit codes correspond to the 2-bit fields
276 stored in the 64-bit block */
278 word = ((unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r) / 2;
279 colors[ 2 ].r = (unsigned char) word;
280 word = ((unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g) / 2;
281 colors[ 2 ].g = (unsigned char) word;
282 word = ((unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b) / 2;
283 colors[ 2 ].b = (unsigned char) word;
284 colors[ 2 ].a = 0xff;
286 /* random color to indicate alpha */
287 colors[ 3 ].r = 0x00;
288 colors[ 3 ].g = 0xff;
289 colors[ 3 ].b = 0xff;
290 colors[ 3 ].a = 0x00;
297 DDSDecodeColorBlock()
298 decodes a dds color block
299 fixme: make endian-safe
302 static void DDSDecodeColorBlock( unsigned int *pixel, ddsColorBlock_t *block, int width, unsigned int colors[ 4 ] )
306 unsigned int masks[] = { 3, 12, 3 << 4, 3 << 6 }; /* bit masks = 00000011, 00001100, 00110000, 11000000 */
307 int shift[] = { 0, 2, 4, 6 };
310 /* r steps through lines in y */
311 for( r = 0; r < 4; r++, pixel += (width - 4) ) /* no width * 4 as unsigned int ptr inc will * 4 */
313 /* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
315 /* n steps through pixels */
316 for( n = 0; n < 4; n++ )
318 bits = block->row[ r ] & masks[ n ];
324 *pixel = colors[ 0 ];
329 *pixel = colors[ 1 ];
334 *pixel = colors[ 2 ];
339 *pixel = colors[ 3 ];
355 DDSDecodeAlphaExplicit()
356 decodes a dds explicit alpha block
359 static void DDSDecodeAlphaExplicit( unsigned int *pixel, ddsAlphaBlockExplicit_t *alphaBlock, int width, unsigned int alphaZero )
372 for( row = 0; row < 4; row++, pixel += (width - 4) )
374 word = DDSLittleShort( alphaBlock->row[ row ] );
377 for( pix = 0; pix < 4; pix++ )
379 /* zero the alpha bits of image pixel */
381 color.a = word & 0x000F;
382 color.a = color.a | (color.a << 4);
383 *pixel |= *((unsigned int*) &color);
384 word >>= 4; /* move next bits to lowest 4 */
385 pixel++; /* move to next pixel in the row */
394 DDSDecodeAlpha3BitLinear()
395 decodes interpolated alpha block
398 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 ] )
415 /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
416 alphas[ 2 ] = ( 6 * alphas[ 0 ] + alphas[ 1 ]) / 7; /* bit code 010 */
417 alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 7; /* bit code 011 */
418 alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 7; /* bit code 100 */
419 alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ]) / 7; /* bit code 101 */
420 alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ]) / 7; /* bit code 110 */
421 alphas[ 7 ] = ( alphas[ 0 ] + 6 * alphas[ 1 ]) / 7; /* bit code 111 */
427 /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
428 alphas[ 2 ] = (4 * alphas[ 0 ] + alphas[ 1 ]) / 5; /* bit code 010 */
429 alphas[ 3 ] = (3 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 5; /* bit code 011 */
430 alphas[ 4 ] = (2 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 5; /* bit code 100 */
431 alphas[ 5 ] = ( alphas[ 0 ] + 4 * alphas[ 1 ]) / 5; /* bit code 101 */
432 alphas[ 6 ] = 0; /* bit code 110 */
433 alphas[ 7 ] = 255; /* bit code 111 */
436 /* decode 3-bit fields into array of 16 bytes with same value */
438 /* first two rows of 4 pixels each */
439 stuff = *((unsigned int*) &(alphaBlock->stuff[ 0 ]));
441 bits[ 0 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
443 bits[ 0 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
445 bits[ 0 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
447 bits[ 0 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
449 bits[ 1 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
451 bits[ 1 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
453 bits[ 1 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
455 bits[ 1 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
458 stuff = *((unsigned int*) &(alphaBlock->stuff[ 3 ])); /* last 3 bytes */
460 bits[ 2 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
462 bits[ 2 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
464 bits[ 2 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
466 bits[ 2 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
468 bits[ 3 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
470 bits[ 3 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
472 bits[ 3 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
474 bits[ 3 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
476 /* decode the codes into alpha values */
477 for( row = 0; row < 4; row++ )
479 for( pix=0; pix < 4; pix++ )
481 aColors[ row ][ pix ].r = 0;
482 aColors[ row ][ pix ].g = 0;
483 aColors[ row ][ pix ].b = 0;
484 aColors[ row ][ pix ].a = (unsigned char) alphas[ bits[ row ][ pix ] ];
488 /* write out alpha values to the image bits */
489 for( row = 0; row < 4; row++, pixel += width-4 )
491 for( pix = 0; pix < 4; pix++ )
493 /* zero the alpha bits of image pixel */
496 /* or the bits into the prev. nulled alpha */
497 *pixel |= *((unsigned int*) &(aColors[ row ][ pix ]));
507 decompresses a dxt1 format texture
510 static int DDSDecompressDXT1( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
512 int x, y, xBlocks, yBlocks;
514 ddsColorBlock_t *block;
515 ddsColor_t colors[ 4 ];
520 yBlocks = height / 4;
523 for( y = 0; y < yBlocks; y++ )
525 /* 8 bytes per block */
526 block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 8);
529 for( x = 0; x < xBlocks; x++, block++ )
531 DDSGetColorBlockColors( block, colors );
532 pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
533 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
545 decompresses a dxt3 format texture
548 static int DDSDecompressDXT3( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
550 int x, y, xBlocks, yBlocks;
551 unsigned int *pixel, alphaZero;
552 ddsColorBlock_t *block;
553 ddsAlphaBlockExplicit_t *alphaBlock;
554 ddsColor_t colors[ 4 ];
559 yBlocks = height / 4;
561 /* create zero alpha */
563 colors[ 0 ].r = 0xFF;
564 colors[ 0 ].g = 0xFF;
565 colors[ 0 ].b = 0xFF;
566 alphaZero = *((unsigned int*) &colors[ 0 ]);
569 for( y = 0; y < yBlocks; y++ )
571 /* 8 bytes per block, 1 block for alpha, 1 block for color */
572 block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 16);
575 for( x = 0; x < xBlocks; x++, block++ )
577 /* get alpha block */
578 alphaBlock = (ddsAlphaBlockExplicit_t*) block;
580 /* get color block */
582 DDSGetColorBlockColors( block, colors );
584 /* decode color block */
585 pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
586 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
588 /* overwrite alpha bits with alpha block */
589 DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
601 decompresses a dxt5 format texture
604 static int DDSDecompressDXT5( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
606 int x, y, xBlocks, yBlocks;
607 unsigned int *pixel, alphaZero;
608 ddsColorBlock_t *block;
609 ddsAlphaBlock3BitLinear_t *alphaBlock;
610 ddsColor_t colors[ 4 ];
615 yBlocks = height / 4;
617 /* create zero alpha */
619 colors[ 0 ].r = 0xFF;
620 colors[ 0 ].g = 0xFF;
621 colors[ 0 ].b = 0xFF;
622 alphaZero = *((unsigned int*) &colors[ 0 ]);
625 for( y = 0; y < yBlocks; y++ )
627 /* 8 bytes per block, 1 block for alpha, 1 block for color */
628 block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 16);
631 for( x = 0; x < xBlocks; x++, block++ )
633 /* get alpha block */
634 alphaBlock = (ddsAlphaBlock3BitLinear_t*) block;
636 /* get color block */
638 DDSGetColorBlockColors( block, colors );
640 /* decode color block */
641 pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
642 DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
644 /* overwrite alpha bits with alpha block */
645 DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
657 decompresses a dxt2 format texture (fixme: un-premultiply alpha)
660 static int DDSDecompressDXT2( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
665 /* decompress dxt3 first */
666 r = DDSDecompressDXT3( dds, width, height, pixels );
668 /* return to sender */
676 decompresses a dxt4 format texture (fixme: un-premultiply alpha)
679 static int DDSDecompressDXT4( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
684 /* decompress dxt5 first */
685 r = DDSDecompressDXT5( dds, width, height, pixels );
687 /* return to sender */
694 DDSDecompressARGB8888()
695 decompresses an argb 8888 format texture
698 static int DDSDecompressARGB8888( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
701 unsigned char *in, *out;
709 for( y = 0; y < height; y++ )
712 for( x = 0; x < width; x++ )
729 decompresses a dds texture into an rgba image buffer, returns 0 on success
732 int DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels )
734 int width, height, r;
739 r = DDSGetInfo( dds, &width, &height, &pf );
746 case DDS_PF_ARGB8888:
747 /* fixme: support other [a]rgb formats */
748 r = DDSDecompressARGB8888( dds, width, height, pixels );
752 r = DDSDecompressDXT1( dds, width, height, pixels );
756 r = DDSDecompressDXT2( dds, width, height, pixels );
760 r = DDSDecompressDXT3( dds, width, height, pixels );
764 r = DDSDecompressDXT4( dds, width, height, pixels );
768 r = DDSDecompressDXT5( dds, width, height, pixels );
773 memset( pixels, 0xFF, width * height * 4 );
778 /* return to sender */