]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/ddslib/ddslib.c
Centralise compile checks
[xonotic/netradiant.git] / libs / ddslib / ddslib.c
1 /* -----------------------------------------------------------------------------
2
3    DDS Library
4
5    Based on code from Nvidia's DDS example:
6    http://www.nvidia.com/object/dxtc_decompression_code.html
7
8    Copyright (c) 2003 Randy Reddig
9    All rights reserved.
10
11    Redistribution and use in source and binary forms, with or without modification,
12    are permitted provided that the following conditions are met:
13
14    Redistributions of source code must retain the above copyright notice, this list
15    of conditions and the following disclaimer.
16
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.
20
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.
24
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.
35
36    ----------------------------------------------------------------------------- */
37
38 /* dependencies */
39 #include "ddslib.h"
40 #include "globaldefs.h"
41
42 /* endian tomfoolery */
43 typedef union
44 {
45         float f;
46         char c[ 4 ];
47 }
48 floatSwapUnion;
49
50 #if GDEF_ARCH_ENDIAN_BIG
51
52 int   DDSBigLong( int src ) { return src; }
53 short DDSBigShort( short src ) { return src; }
54 float DDSBigFloat( float src ) { return src; }
55
56 int DDSLittleLong( int src ){
57         return ( ( src & 0xFF000000 ) >> 24 ) |
58                    ( ( src & 0x00FF0000 ) >> 8 ) |
59                    ( ( src & 0x0000FF00 ) << 8 ) |
60                    ( ( src & 0x000000FF ) << 24 );
61 }
62
63 short DDSLittleShort( short src ){
64         return ( ( src & 0xFF00 ) >> 8 ) |
65                    ( ( src & 0x00FF ) << 8 );
66 }
67
68 float DDSLittleFloat( float src ){
69         floatSwapUnion in,out;
70         in.f = src;
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 ];
75         return out.f;
76 }
77
78 #else /*__BIG_ENDIAN__*/
79
80 int   DDSLittleLong( int src ) { return src; }
81 short DDSLittleShort( short src ) { return src; }
82 float DDSLittleFloat( float src ) { return src; }
83
84 int DDSBigLong( int src ){
85         return ( ( src & 0xFF000000 ) >> 24 ) |
86                    ( ( src & 0x00FF0000 ) >> 8 ) |
87                    ( ( src & 0x0000FF00 ) << 8 ) |
88                    ( ( src & 0x000000FF ) << 24 );
89 }
90
91 short DDSBigShort( short src ){
92         return ( ( src & 0xFF00 ) >> 8 ) |
93                    ( ( src & 0x00FF ) << 8 );
94 }
95
96 float DDSBigFloat( float src ){
97         floatSwapUnion in,out;
98         in.f = src;
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 ];
103         return out.f;
104 }
105
106 #endif /*__BIG_ENDIAN__*/
107
108
109
110 /*
111    DDSDecodePixelFormat()
112    determines which pixel format the dds texture is in
113  */
114
115 static void DDSDecodePixelFormat( ddsBuffer_t *dds, ddsPF_t *pf ){
116         unsigned int fourCC;
117
118
119         /* dummy check */
120         if ( dds == NULL || pf == NULL ) {
121                 return;
122         }
123
124         /* extract fourCC */
125         fourCC = dds->pixelFormat.fourCC;
126
127         /* test it */
128         if ( fourCC == 0 ) {
129                 *pf = DDS_PF_ARGB8888;
130         }
131         else if ( fourCC == *( (unsigned int*) "DXT1" ) ) {
132                 *pf = DDS_PF_DXT1;
133         }
134         else if ( fourCC == *( (unsigned int*) "DXT2" ) ) {
135                 *pf = DDS_PF_DXT2;
136         }
137         else if ( fourCC == *( (unsigned int*) "DXT3" ) ) {
138                 *pf = DDS_PF_DXT3;
139         }
140         else if ( fourCC == *( (unsigned int*) "DXT4" ) ) {
141                 *pf = DDS_PF_DXT4;
142         }
143         else if ( fourCC == *( (unsigned int*) "DXT5" ) ) {
144                 *pf = DDS_PF_DXT5;
145         }
146         else{
147                 *pf = DDS_PF_UNKNOWN;
148         }
149 }
150
151
152
153 /*
154    DDSGetInfo()
155    extracts relevant info from a dds texture, returns 0 on success
156  */
157
158 int DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf ){
159         /* dummy test */
160         if ( dds == NULL ) {
161                 return -1;
162         }
163
164         /* test dds header */
165         if ( *( (int*) dds->magic ) != *( (int*) "DDS " ) ) {
166                 return -1;
167         }
168         if ( DDSLittleLong( dds->size ) != 124 ) {
169                 return -1;
170         }
171
172         /* extract width and height */
173         if ( width != NULL ) {
174                 *width = DDSLittleLong( dds->width );
175         }
176         if ( height != NULL ) {
177                 *height = DDSLittleLong( dds->height );
178         }
179
180         /* get pixel format */
181         DDSDecodePixelFormat( dds, pf );
182
183         /* return ok */
184         return 0;
185 }
186
187
188
189 /*
190    DDSGetColorBlockColors()
191    extracts colors from a dds color block
192  */
193
194 static void DDSGetColorBlockColors( ddsColorBlock_t *block, ddsColor_t colors[ 4 ] ){
195         unsigned short word;
196
197
198         /* color 0 */
199         word = DDSLittleShort( block->colors[ 0 ] );
200         colors[ 0 ].a = 0xff;
201
202         /* extract rgb bits */
203         colors[ 0 ].b = (unsigned char) word;
204         colors[ 0 ].b <<= 3;
205         colors[ 0 ].b |= ( colors[ 0 ].b >> 5 );
206         word >>= 5;
207         colors[ 0 ].g = (unsigned char) word;
208         colors[ 0 ].g <<= 2;
209         colors[ 0 ].g |= ( colors[ 0 ].g >> 5 );
210         word >>= 6;
211         colors[ 0 ].r = (unsigned char) word;
212         colors[ 0 ].r <<= 3;
213         colors[ 0 ].r |= ( colors[ 0 ].r >> 5 );
214
215         /* same for color 1 */
216         word = DDSLittleShort( block->colors[ 1 ] );
217         colors[ 1 ].a = 0xff;
218
219         /* extract rgb bits */
220         colors[ 1 ].b = (unsigned char) word;
221         colors[ 1 ].b <<= 3;
222         colors[ 1 ].b |= ( colors[ 1 ].b >> 5 );
223         word >>= 5;
224         colors[ 1 ].g = (unsigned char) word;
225         colors[ 1 ].g <<= 2;
226         colors[ 1 ].g |= ( colors[ 1 ].g >> 5 );
227         word >>= 6;
228         colors[ 1 ].r = (unsigned char) word;
229         colors[ 1 ].r <<= 3;
230         colors[ 1 ].r |= ( colors[ 1 ].r >> 5 );
231
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. */
238
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;
248
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;
256         }
257         else
258         {
259                 /* three-color block: derive the other color.
260                    00 = color 0, 01 = color 1, 10 = color 2,
261                    11 = transparent.
262                    These two bit codes correspond to the 2-bit fields
263                    stored in the 64-bit block */
264
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;
272
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;
278         }
279 }
280
281
282
283 /*
284    DDSDecodeColorBlock()
285    decodes a dds color block
286    fixme: make endian-safe
287  */
288
289 static void DDSDecodeColorBlock( unsigned int *pixel, ddsColorBlock_t *block, int width, unsigned int colors[ 4 ] ){
290         int r, n;
291         unsigned int bits;
292         unsigned int masks[] = { 3, 12, 3 << 4, 3 << 6 };       /* bit masks = 00000011, 00001100, 00110000, 11000000 */
293         int shift[] = { 0, 2, 4, 6 };
294
295
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 */
298         {
299                 /* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
300
301                 /* n steps through pixels */
302                 for ( n = 0; n < 4; n++ )
303                 {
304                         bits = block->row[ r ] & masks[ n ];
305                         bits >>= shift[ n ];
306
307                         switch ( bits )
308                         {
309                         case 0:
310                                 *pixel = colors[ 0 ];
311                                 pixel++;
312                                 break;
313
314                         case 1:
315                                 *pixel = colors[ 1 ];
316                                 pixel++;
317                                 break;
318
319                         case 2:
320                                 *pixel = colors[ 2 ];
321                                 pixel++;
322                                 break;
323
324                         case 3:
325                                 *pixel = colors[ 3 ];
326                                 pixel++;
327                                 break;
328
329                         default:
330                                 /* invalid */
331                                 pixel++;
332                                 break;
333                         }
334                 }
335         }
336 }
337
338
339
340 /*
341    DDSDecodeAlphaExplicit()
342    decodes a dds explicit alpha block
343  */
344
345 static void DDSDecodeAlphaExplicit( unsigned int *pixel, ddsAlphaBlockExplicit_t *alphaBlock, int width, unsigned int alphaZero ){
346         int row, pix;
347         unsigned short word;
348         ddsColor_t color;
349
350
351         /* clear color */
352         color.r = 0;
353         color.g = 0;
354         color.b = 0;
355
356         /* walk rows */
357         for ( row = 0; row < 4; row++, pixel += ( width - 4 ) )
358         {
359                 word = DDSLittleShort( alphaBlock->row[ row ] );
360
361                 /* walk pixels */
362                 for ( pix = 0; pix < 4; pix++ )
363                 {
364                         /* zero the alpha bits of image pixel */
365                         *pixel &= alphaZero;
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 */
371
372                 }
373         }
374 }
375
376
377
378 /*
379    DDSDecodeAlpha3BitLinear()
380    decodes interpolated alpha block
381  */
382
383 static void DDSDecodeAlpha3BitLinear( unsigned int *pixel, ddsAlphaBlock3BitLinear_t *alphaBlock, int width, unsigned int alphaZero ){
384
385         int row, pix;
386         unsigned int stuff;
387         unsigned char bits[ 4 ][ 4 ];
388         unsigned short alphas[ 8 ];
389         ddsColor_t aColors[ 4 ][ 4 ];
390
391
392         /* get initial alphas */
393         alphas[ 0 ] = alphaBlock->alpha0;
394         alphas[ 1 ] = alphaBlock->alpha1;
395
396         /* 8-alpha block */
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 */
405         }
406
407         /* 6-alpha block */
408         else
409         {
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 */
417         }
418
419         /* decode 3-bit fields into array of 16 bytes with same value */
420
421         /* first two rows of 4 pixels each */
422         stuff = *( (unsigned int*) &( alphaBlock->stuff[ 0 ] ) );
423
424         bits[ 0 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
425         stuff >>= 3;
426         bits[ 0 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
427         stuff >>= 3;
428         bits[ 0 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
429         stuff >>= 3;
430         bits[ 0 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
431         stuff >>= 3;
432         bits[ 1 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
433         stuff >>= 3;
434         bits[ 1 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
435         stuff >>= 3;
436         bits[ 1 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
437         stuff >>= 3;
438         bits[ 1 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
439
440         /* last two rows */
441         stuff = *( (unsigned int*) &( alphaBlock->stuff[ 3 ] ) ); /* last 3 bytes */
442
443         bits[ 2 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
444         stuff >>= 3;
445         bits[ 2 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
446         stuff >>= 3;
447         bits[ 2 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
448         stuff >>= 3;
449         bits[ 2 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
450         stuff >>= 3;
451         bits[ 3 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
452         stuff >>= 3;
453         bits[ 3 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
454         stuff >>= 3;
455         bits[ 3 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
456         stuff >>= 3;
457         bits[ 3 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
458
459         /* decode the codes into alpha values */
460         for ( row = 0; row < 4; row++ )
461         {
462                 for ( pix = 0; pix < 4; pix++ )
463                 {
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 ] ];
468                 }
469         }
470
471         /* write out alpha values to the image bits */
472         for ( row = 0; row < 4; row++, pixel += width - 4 )
473         {
474                 for ( pix = 0; pix < 4; pix++ )
475                 {
476                         /* zero the alpha bits of image pixel */
477                         *pixel &= alphaZero;
478
479                         /* or the bits into the prev. nulled alpha */
480                         *pixel |= *( (unsigned int*) &( aColors[ row ][ pix ] ) );
481                         pixel++;
482                 }
483         }
484 }
485
486
487
488 /*
489    DDSDecompressDXT1()
490    decompresses a dxt1 format texture
491  */
492
493 static int DDSDecompressDXT1( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
494         int x, y, xBlocks, yBlocks;
495         unsigned int    *pixel;
496         ddsColorBlock_t *block;
497         ddsColor_t colors[ 4 ];
498
499
500         /* setup */
501         xBlocks = width / 4;
502         yBlocks = height / 4;
503
504         /* walk y */
505         for ( y = 0; y < yBlocks; y++ )
506         {
507                 /* 8 bytes per block */
508                 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 8 );
509
510                 /* walk x */
511                 for ( x = 0; x < xBlocks; x++, block++ )
512                 {
513                         DDSGetColorBlockColors( block, colors );
514                         pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
515                         DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
516                 }
517         }
518
519         /* return ok */
520         return 0;
521 }
522
523
524
525 /*
526    DDSDecompressDXT3()
527    decompresses a dxt3 format texture
528  */
529
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 ];
536
537
538         /* setup */
539         xBlocks = width / 4;
540         yBlocks = height / 4;
541
542         /* create zero alpha */
543         colors[ 0 ].a = 0;
544         colors[ 0 ].r = 0xFF;
545         colors[ 0 ].g = 0xFF;
546         colors[ 0 ].b = 0xFF;
547         alphaZero = *( (unsigned int*) &colors[ 0 ] );
548
549         /* walk y */
550         for ( y = 0; y < yBlocks; y++ )
551         {
552                 /* 8 bytes per block, 1 block for alpha, 1 block for color */
553                 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 16 );
554
555                 /* walk x */
556                 for ( x = 0; x < xBlocks; x++, block++ )
557                 {
558                         /* get alpha block */
559                         alphaBlock = (ddsAlphaBlockExplicit_t*) block;
560
561                         /* get color block */
562                         block++;
563                         DDSGetColorBlockColors( block, colors );
564
565                         /* decode color block */
566                         pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
567                         DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
568
569                         /* overwrite alpha bits with alpha block */
570                         DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
571                 }
572         }
573
574         /* return ok */
575         return 0;
576 }
577
578
579
580 /*
581    DDSDecompressDXT5()
582    decompresses a dxt5 format texture
583  */
584
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 ];
591
592
593         /* setup */
594         xBlocks = width / 4;
595         yBlocks = height / 4;
596
597         /* create zero alpha */
598         colors[ 0 ].a = 0;
599         colors[ 0 ].r = 0xFF;
600         colors[ 0 ].g = 0xFF;
601         colors[ 0 ].b = 0xFF;
602         alphaZero = *( (unsigned int*) &colors[ 0 ] );
603
604         /* walk y */
605         for ( y = 0; y < yBlocks; y++ )
606         {
607                 /* 8 bytes per block, 1 block for alpha, 1 block for color */
608                 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 16 );
609
610                 /* walk x */
611                 for ( x = 0; x < xBlocks; x++, block++ )
612                 {
613                         /* get alpha block */
614                         alphaBlock = (ddsAlphaBlock3BitLinear_t*) block;
615
616                         /* get color block */
617                         block++;
618                         DDSGetColorBlockColors( block, colors );
619
620                         /* decode color block */
621                         pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
622                         DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
623
624                         /* overwrite alpha bits with alpha block */
625                         DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
626                 }
627         }
628
629         /* return ok */
630         return 0;
631 }
632
633
634
635 /*
636    DDSDecompressDXT2()
637    decompresses a dxt2 format texture (fixme: un-premultiply alpha)
638  */
639
640 static int DDSDecompressDXT2( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
641         int r;
642
643
644         /* decompress dxt3 first */
645         r = DDSDecompressDXT3( dds, width, height, pixels );
646
647         /* return to sender */
648         return r;
649 }
650
651
652
653 /*
654    DDSDecompressDXT4()
655    decompresses a dxt4 format texture (fixme: un-premultiply alpha)
656  */
657
658 static int DDSDecompressDXT4( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
659         int r;
660
661
662         /* decompress dxt5 first */
663         r = DDSDecompressDXT5( dds, width, height, pixels );
664
665         /* return to sender */
666         return r;
667 }
668
669
670
671 /*
672    DDSDecompressARGB8888()
673    decompresses an argb 8888 format texture
674  */
675
676 static int DDSDecompressARGB8888( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
677         int x, y;
678         unsigned char               *in, *out;
679
680
681         /* setup */
682         in = dds->data;
683         out = pixels;
684
685         /* walk y */
686         for ( y = 0; y < height; y++ )
687         {
688                 /* walk x */
689                 for ( x = 0; x < width; x++ )
690                 {
691                         *out++ = *in++;
692                         *out++ = *in++;
693                         *out++ = *in++;
694                         *out++ = *in++;
695                 }
696         }
697
698         /* return ok */
699         return 0;
700 }
701
702
703
704 /*
705    DDSDecompress()
706    decompresses a dds texture into an rgba image buffer, returns 0 on success
707  */
708
709 int DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels ){
710         int width, height, r;
711         ddsPF_t pf;
712
713
714         /* get dds info */
715         r = DDSGetInfo( dds, &width, &height, &pf );
716         if ( r ) {
717                 return r;
718         }
719
720         /* decompress */
721         switch ( pf )
722         {
723         case DDS_PF_ARGB8888:
724                 /* fixme: support other [a]rgb formats */
725                 r = DDSDecompressARGB8888( dds, width, height, pixels );
726                 break;
727
728         case DDS_PF_DXT1:
729                 r = DDSDecompressDXT1( dds, width, height, pixels );
730                 break;
731
732         case DDS_PF_DXT2:
733                 r = DDSDecompressDXT2( dds, width, height, pixels );
734                 break;
735
736         case DDS_PF_DXT3:
737                 r = DDSDecompressDXT3( dds, width, height, pixels );
738                 break;
739
740         case DDS_PF_DXT4:
741                 r = DDSDecompressDXT4( dds, width, height, pixels );
742                 break;
743
744         case DDS_PF_DXT5:
745                 r = DDSDecompressDXT5( dds, width, height, pixels );
746                 break;
747
748         default:
749         case DDS_PF_UNKNOWN:
750                 memset( pixels, 0xFF, width * height * 4 );
751                 r = -1;
752                 break;
753         }
754
755         /* return to sender */
756         return r;
757 }