remove RSA's md4.c, replace by DP's
[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
39
40 /* marker */
41 #define DDSLIB_C
42
43
44
45 /* dependencies */
46 #include "ddslib.h"
47
48
49
50 /* endian tomfoolery */
51 typedef union
52 {
53         float   f;
54         char    c[ 4 ];
55 }
56 floatSwapUnion;
57
58
59 #ifndef __BIG_ENDIAN__
60         #ifdef _SGI_SOURCE
61                 #define __BIG_ENDIAN__
62         #endif
63 #endif
64
65
66 #ifdef __BIG_ENDIAN__
67
68         int   DDSBigLong( int src ) { return src; }
69         short DDSBigShort( short src ) { return src; }
70         float DDSBigFloat( float src ) { return src; }
71
72         int DDSLittleLong( int src )
73         {
74                 return ((src & 0xFF000000) >> 24) |
75                            ((src & 0x00FF0000) >> 8) |
76                            ((src & 0x0000FF00) << 8) |
77                            ((src & 0x000000FF) << 24);
78         }
79
80         short DDSLittleShort( short src )
81         {
82                 return ((src & 0xFF00) >> 8) |
83                            ((src & 0x00FF) << 8);
84         }
85
86         float DDSLittleFloat( float src )
87         {
88                 floatSwapUnion in,out;
89                 in.f = src;
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 ];
94                 return out.f;
95         }
96
97 #else /*__BIG_ENDIAN__*/
98
99         int   DDSLittleLong( int src ) { return src; }
100         short DDSLittleShort( short src ) { return src; }
101         float DDSLittleFloat( float src ) { return src; }
102                 
103         int DDSBigLong( int src )
104         {
105                 return ((src & 0xFF000000) >> 24) |
106                            ((src & 0x00FF0000) >> 8) |
107                            ((src & 0x0000FF00) << 8) |
108                            ((src & 0x000000FF) << 24);
109         }
110                 
111         short DDSBigShort( short src )
112         {
113                 return ((src & 0xFF00) >> 8) |
114                            ((src & 0x00FF) << 8);
115         }
116                 
117         float DDSBigFloat( float src )
118         {
119                 floatSwapUnion in,out;
120                 in.f = src;
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 ];
125                 return out.f;
126         }
127
128 #endif /*__BIG_ENDIAN__*/
129
130
131
132 /*
133 DDSDecodePixelFormat()
134 determines which pixel format the dds texture is in
135 */
136
137 static void DDSDecodePixelFormat( ddsBuffer_t *dds, ddsPF_t *pf )
138 {
139         unsigned int    fourCC;
140         
141         
142         /* dummy check */
143         if(     dds == NULL || pf == NULL )
144                 return;
145         
146         /* extract fourCC */
147         fourCC = dds->pixelFormat.fourCC;
148         
149         /* test it */
150         if( fourCC == 0 )
151                 *pf = DDS_PF_ARGB8888;
152         else if( fourCC == *((unsigned int*) "DXT1") )
153                 *pf = DDS_PF_DXT1;
154         else if( fourCC == *((unsigned int*) "DXT2") )
155                 *pf = DDS_PF_DXT2;
156         else if( fourCC == *((unsigned int*) "DXT3") )
157                 *pf = DDS_PF_DXT3;
158         else if( fourCC == *((unsigned int*) "DXT4") )
159                 *pf = DDS_PF_DXT4;
160         else if( fourCC == *((unsigned int*) "DXT5") )
161                 *pf = DDS_PF_DXT5;
162         else
163                 *pf = DDS_PF_UNKNOWN;
164 }
165
166
167
168 /*
169 DDSGetInfo()
170 extracts relevant info from a dds texture, returns 0 on success
171 */
172
173 int DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf )
174 {
175         /* dummy test */
176         if( dds == NULL )
177                 return -1;
178         
179         /* test dds header */
180         if( *((int*) dds->magic) != *((int*) "DDS ") )
181                 return -1;
182         if( DDSLittleLong( dds->size ) != 124 )
183                 return -1;
184         
185         /* extract width and height */
186         if( width != NULL )
187                 *width = DDSLittleLong( dds->width );
188         if( height != NULL )
189                 *height = DDSLittleLong( dds->height );
190         
191         /* get pixel format */
192         DDSDecodePixelFormat( dds, pf );
193         
194         /* return ok */
195         return 0;
196 }
197
198
199
200 /*
201 DDSGetColorBlockColors()
202 extracts colors from a dds color block
203 */
204
205 static void DDSGetColorBlockColors( ddsColorBlock_t *block, ddsColor_t colors[ 4 ] )
206 {
207         unsigned short          word;
208
209         
210         /* color 0 */
211         word = DDSLittleShort( block->colors[ 0 ] );
212         colors[ 0 ].a = 0xff;
213         
214         /* extract rgb bits */
215         colors[ 0 ].b = (unsigned char) word;
216         colors[ 0 ].b <<= 3;
217         colors[ 0 ].b |= (colors[ 0 ].b >> 5);
218         word >>= 5;
219         colors[ 0 ].g = (unsigned char) word;
220         colors[ 0 ].g <<= 2;
221         colors[ 0 ].g |= (colors[ 0 ].g >> 5);
222         word >>= 6;
223         colors[ 0 ].r = (unsigned char) word;
224         colors[ 0 ].r <<= 3;
225         colors[ 0 ].r |= (colors[ 0 ].r >> 5);
226
227         /* same for color 1 */
228         word = DDSLittleShort( block->colors[ 1 ] );
229         colors[ 1 ].a = 0xff;
230         
231         /* extract rgb bits */
232         colors[ 1 ].b = (unsigned char) word;
233         colors[ 1 ].b <<= 3;
234         colors[ 1 ].b |= (colors[ 1 ].b >> 5);
235         word >>= 5;
236         colors[ 1 ].g = (unsigned char) word;
237         colors[ 1 ].g <<= 2;
238         colors[ 1 ].g |= (colors[ 1 ].g >> 5);
239         word >>= 6;
240         colors[ 1 ].r = (unsigned char) word;
241         colors[ 1 ].r <<= 3;
242         colors[ 1 ].r |= (colors[ 1 ].r >> 5);
243         
244         /* use this for all but the super-freak math method */
245         if( block->colors[ 0 ] > block->colors[ 1 ] )
246         {
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. */
251
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;
261
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;
269         }
270         else
271         {
272                 /* three-color block: derive the other color.
273                    00 = color 0, 01 = color 1, 10 = color 2,  
274                    11 = transparent.
275                    These two bit codes correspond to the 2-bit fields 
276                    stored in the 64-bit block */
277
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;
285                 
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;
291         }
292 }
293
294
295
296 /*
297 DDSDecodeColorBlock()
298 decodes a dds color block
299 fixme: make endian-safe
300 */
301
302 static void DDSDecodeColorBlock( unsigned int *pixel, ddsColorBlock_t *block, int width, unsigned int colors[ 4 ] )
303 {
304         int                             r, n;
305         unsigned int    bits;
306         unsigned int    masks[] = { 3, 12, 3 << 4, 3 << 6 };    /* bit masks = 00000011, 00001100, 00110000, 11000000 */
307         int                             shift[] = { 0, 2, 4, 6 };
308         
309         
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 */
312         {
313                 /* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
314
315                 /* n steps through pixels */
316                 for( n = 0; n < 4; n++ )
317                 {
318                         bits = block->row[ r ] & masks[ n ];
319                         bits >>= shift[ n ];
320
321                         switch( bits )
322                         {
323                                 case 0:
324                                         *pixel = colors[ 0 ];
325                                         pixel++;
326                                         break;
327
328                                 case 1:
329                                         *pixel = colors[ 1 ];
330                                         pixel++;
331                                         break;
332
333                                 case 2:
334                                         *pixel = colors[ 2 ];
335                                         pixel++;
336                                         break;
337
338                                 case 3:
339                                         *pixel = colors[ 3 ];
340                                         pixel++;
341                                         break;
342
343                                 default:
344                                         /* invalid */
345                                         pixel++;
346                                         break;
347                         }
348                 }
349         }
350 }
351
352
353
354 /*
355 DDSDecodeAlphaExplicit()
356 decodes a dds explicit alpha block
357 */
358
359 static void DDSDecodeAlphaExplicit( unsigned int *pixel, ddsAlphaBlockExplicit_t *alphaBlock, int width, unsigned int alphaZero )
360 {       
361         int                             row, pix;
362         unsigned short  word;
363         ddsColor_t              color;
364         
365         
366         /* clear color */
367         color.r = 0;
368         color.g = 0;
369         color.b = 0;
370         
371         /* walk rows */
372         for( row = 0; row < 4; row++, pixel += (width - 4) )
373         {
374                 word = DDSLittleShort( alphaBlock->row[ row ] );
375                 
376                 /* walk pixels */
377                 for( pix = 0; pix < 4; pix++ )
378                 {
379                         /* zero the alpha bits of image pixel */
380                         *pixel &= alphaZero;
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 */
386
387                 }
388         }
389 }
390
391
392
393 /*
394 DDSDecodeAlpha3BitLinear()
395 decodes interpolated alpha block
396 */
397
398 static void DDSDecodeAlpha3BitLinear( unsigned int *pixel, ddsAlphaBlock3BitLinear_t *alphaBlock, int width, unsigned int alphaZero )
399 {
400         
401         int                                     row, pix;
402         unsigned int            stuff;
403         unsigned char           bits[ 4 ][ 4 ];
404         unsigned short          alphas[ 8 ];
405         ddsColor_t                      aColors[ 4 ][ 4 ];
406         
407         
408         /* get initial alphas */
409         alphas[ 0 ] = alphaBlock->alpha0;
410         alphas[ 1 ] = alphaBlock->alpha1;
411         
412         /* 8-alpha block */
413         if( alphas[ 0 ] > alphas[ 1 ] )
414         {
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 */
422         }
423         
424         /* 6-alpha block */
425         else
426         { 
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 */
434         }
435         
436         /* decode 3-bit fields into array of 16 bytes with same value */
437         
438         /* first two rows of 4 pixels each */
439         stuff = *((unsigned int*) &(alphaBlock->stuff[ 0 ]));
440         
441         bits[ 0 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
442         stuff >>= 3;
443         bits[ 0 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
444         stuff >>= 3;
445         bits[ 0 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
446         stuff >>= 3;
447         bits[ 0 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
448         stuff >>= 3;
449         bits[ 1 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
450         stuff >>= 3;
451         bits[ 1 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
452         stuff >>= 3;
453         bits[ 1 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
454         stuff >>= 3;
455         bits[ 1 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
456         
457         /* last two rows */
458         stuff = *((unsigned int*) &(alphaBlock->stuff[ 3 ])); /* last 3 bytes */
459         
460         bits[ 2 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
461         stuff >>= 3;
462         bits[ 2 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
463         stuff >>= 3;
464         bits[ 2 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
465         stuff >>= 3;
466         bits[ 2 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
467         stuff >>= 3;
468         bits[ 3 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
469         stuff >>= 3;
470         bits[ 3 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
471         stuff >>= 3;
472         bits[ 3 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
473         stuff >>= 3;
474         bits[ 3 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
475         
476         /* decode the codes into alpha values */
477         for( row = 0; row < 4; row++ )
478         {
479                 for( pix=0; pix < 4; pix++ )
480                 {
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 ] ];
485                 }
486         }
487         
488         /* write out alpha values to the image bits */
489         for( row = 0; row < 4; row++, pixel += width-4 )
490         {
491                 for( pix = 0; pix < 4; pix++ )
492                 {
493                         /* zero the alpha bits of image pixel */
494                         *pixel &= alphaZero;
495                         
496                         /* or the bits into the prev. nulled alpha */
497                         *pixel |= *((unsigned int*) &(aColors[ row ][ pix ]));  
498                         pixel++;
499                 }
500         }
501 }
502
503
504
505 /*
506 DDSDecompressDXT1()
507 decompresses a dxt1 format texture
508 */
509
510 static int DDSDecompressDXT1( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
511 {
512         int                             x, y, xBlocks, yBlocks;
513         unsigned int    *pixel;
514         ddsColorBlock_t *block;
515         ddsColor_t              colors[ 4 ];
516         
517         
518         /* setup */
519         xBlocks = width / 4;
520         yBlocks = height / 4;
521         
522         /* walk y */
523         for( y = 0; y < yBlocks; y++ )
524         {
525                 /* 8 bytes per block */
526                 block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 8);
527
528                 /* walk x */
529                 for( x = 0; x < xBlocks; x++, block++ )
530                 {
531                         DDSGetColorBlockColors( block, colors );
532                         pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
533                         DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
534                 }
535         }
536         
537         /* return ok */
538         return 0;
539 }
540
541
542
543 /*
544 DDSDecompressDXT3()
545 decompresses a dxt3 format texture
546 */
547
548 static int DDSDecompressDXT3( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
549 {
550         int                                             x, y, xBlocks, yBlocks;
551         unsigned int                    *pixel, alphaZero;
552         ddsColorBlock_t                 *block;
553         ddsAlphaBlockExplicit_t *alphaBlock;
554         ddsColor_t                              colors[ 4 ];
555
556
557         /* setup */
558         xBlocks = width / 4;
559         yBlocks = height / 4;
560         
561         /* create zero alpha */
562         colors[ 0 ].a = 0;
563         colors[ 0 ].r = 0xFF;
564         colors[ 0 ].g = 0xFF;
565         colors[ 0 ].b = 0xFF;
566         alphaZero = *((unsigned int*) &colors[ 0 ]);
567         
568         /* walk y */
569         for( y = 0; y < yBlocks; y++ )
570         {
571                 /* 8 bytes per block, 1 block for alpha, 1 block for color */
572                 block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 16);
573
574                 /* walk x */
575                 for( x = 0; x < xBlocks; x++, block++ )
576                 {
577                         /* get alpha block */
578                         alphaBlock = (ddsAlphaBlockExplicit_t*) block;
579                         
580                         /* get color block */
581                         block++;
582                         DDSGetColorBlockColors( block, colors );
583                         
584                         /* decode color block */
585                         pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
586                         DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
587                         
588                         /* overwrite alpha bits with alpha block */
589                         DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
590                 }
591         }
592         
593         /* return ok */
594         return 0;
595 }
596
597
598
599 /*
600 DDSDecompressDXT5()
601 decompresses a dxt5 format texture
602 */
603
604 static int DDSDecompressDXT5( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
605 {
606         int                                                     x, y, xBlocks, yBlocks;
607         unsigned int                            *pixel, alphaZero;
608         ddsColorBlock_t                         *block;
609         ddsAlphaBlock3BitLinear_t       *alphaBlock;
610         ddsColor_t                                      colors[ 4 ];
611
612
613         /* setup */
614         xBlocks = width / 4;
615         yBlocks = height / 4;
616         
617         /* create zero alpha */
618         colors[ 0 ].a = 0;
619         colors[ 0 ].r = 0xFF;
620         colors[ 0 ].g = 0xFF;
621         colors[ 0 ].b = 0xFF;
622         alphaZero = *((unsigned int*) &colors[ 0 ]);
623         
624         /* walk y */
625         for( y = 0; y < yBlocks; y++ )
626         {
627                 /* 8 bytes per block, 1 block for alpha, 1 block for color */
628                 block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 16);
629
630                 /* walk x */
631                 for( x = 0; x < xBlocks; x++, block++ )
632                 {
633                         /* get alpha block */
634                         alphaBlock = (ddsAlphaBlock3BitLinear_t*) block;
635                         
636                         /* get color block */
637                         block++;
638                         DDSGetColorBlockColors( block, colors );
639                         
640                         /* decode color block */
641                         pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
642                         DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
643                         
644                         /* overwrite alpha bits with alpha block */
645                         DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
646                 }
647         }
648         
649         /* return ok */
650         return 0;
651 }
652
653
654
655 /*
656 DDSDecompressDXT2()
657 decompresses a dxt2 format texture (fixme: un-premultiply alpha)
658 */
659
660 static int DDSDecompressDXT2( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
661 {
662         int             r;
663         
664         
665         /* decompress dxt3 first */
666         r = DDSDecompressDXT3( dds, width, height, pixels );
667         
668         /* return to sender */
669         return r;
670 }
671
672
673
674 /*
675 DDSDecompressDXT4()
676 decompresses a dxt4 format texture (fixme: un-premultiply alpha)
677 */
678
679 static int DDSDecompressDXT4( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
680 {
681         int             r;
682         
683         
684         /* decompress dxt5 first */
685         r = DDSDecompressDXT5( dds, width, height, pixels );
686         
687         /* return to sender */
688         return r;
689 }
690
691
692
693 /*
694 DDSDecompressARGB8888()
695 decompresses an argb 8888 format texture
696 */
697
698 static int DDSDecompressARGB8888( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
699 {
700         int                                                     x, y;
701         unsigned char                           *in, *out;
702         
703         
704         /* setup */
705         in = dds->data;
706         out = pixels;
707         
708         /* walk y */
709         for( y = 0; y < height; y++ )
710         {
711                 /* walk x */
712                 for( x = 0; x < width; x++ )
713                 {
714                         *out++ = *in++;
715                         *out++ = *in++;
716                         *out++ = *in++;
717                         *out++ = *in++;
718                 }
719         }
720         
721         /* return ok */
722         return 0;
723 }
724
725
726
727 /*
728 DDSDecompress()
729 decompresses a dds texture into an rgba image buffer, returns 0 on success
730 */
731
732 int DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels )
733 {
734         int                     width, height, r;
735         ddsPF_t         pf;
736         
737         
738         /* get dds info */
739         r = DDSGetInfo( dds, &width, &height, &pf );
740         if( r )
741                 return r;
742         
743         /* decompress */
744         switch( pf )
745         {
746                 case DDS_PF_ARGB8888:
747                         /* fixme: support other [a]rgb formats */
748                         r = DDSDecompressARGB8888( dds, width, height, pixels );
749                         break;
750                 
751                 case DDS_PF_DXT1:
752                         r = DDSDecompressDXT1( dds, width, height, pixels );
753                         break;
754                 
755                 case DDS_PF_DXT2:
756                         r = DDSDecompressDXT2( dds, width, height, pixels );
757                         break;
758                 
759                 case DDS_PF_DXT3:
760                         r = DDSDecompressDXT3( dds, width, height, pixels );    
761                         break;
762                 
763                 case DDS_PF_DXT4:
764                         r = DDSDecompressDXT4( dds, width, height, pixels );
765                         break;
766                 
767                 case DDS_PF_DXT5:
768                         r = DDSDecompressDXT5( dds, width, height, pixels );            
769                         break;
770                 
771                 default:
772                 case DDS_PF_UNKNOWN:
773                         memset( pixels, 0xFF, width * height * 4 );
774                         r = -1;
775                         break;
776         }
777         
778         /* return to sender */
779         return r;
780 }
781