~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CImageLoaderDDS.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2002-2011 Thomas Alten
 
2
// This file is part of the "Irrlicht Engine".
 
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
4
 
 
5
/*
 
6
        Based on Code from Copyright (c) 2003 Randy Reddig
 
7
        Based on code from Nvidia's DDS example:
 
8
        http://www.nvidia.com/object/dxtc_decompression_code.html
 
9
 
 
10
        mainly c to cpp
 
11
*/
 
12
 
 
13
 
 
14
#include "CImageLoaderDDS.h"
 
15
 
 
16
#ifdef _IRR_COMPILE_WITH_DDS_LOADER_
 
17
 
 
18
#include "IReadFile.h"
 
19
#include "os.h"
 
20
#include "CColorConverter.h"
 
21
#include "CImage.h"
 
22
#include "irrString.h"
 
23
 
 
24
 
 
25
namespace irr
 
26
{
 
27
 
 
28
namespace video
 
29
{
 
30
 
 
31
namespace
 
32
{
 
33
 
 
34
/*!
 
35
        DDSDecodePixelFormat()
 
36
        determines which pixel format the dds texture is in
 
37
*/
 
38
void DDSDecodePixelFormat( ddsBuffer *dds, eDDSPixelFormat *pf )
 
39
{
 
40
        /* dummy check */
 
41
        if(     dds == NULL || pf == NULL )
 
42
                return;
 
43
 
 
44
        /* extract fourCC */
 
45
        const u32 fourCC = dds->pixelFormat.fourCC;
 
46
 
 
47
        /* test it */
 
48
        if( fourCC == 0 )
 
49
                *pf = DDS_PF_ARGB8888;
 
50
        else if( fourCC == *((u32*) "DXT1") )
 
51
                *pf = DDS_PF_DXT1;
 
52
        else if( fourCC == *((u32*) "DXT2") )
 
53
                *pf = DDS_PF_DXT2;
 
54
        else if( fourCC == *((u32*) "DXT3") )
 
55
                *pf = DDS_PF_DXT3;
 
56
        else if( fourCC == *((u32*) "DXT4") )
 
57
                *pf = DDS_PF_DXT4;
 
58
        else if( fourCC == *((u32*) "DXT5") )
 
59
                *pf = DDS_PF_DXT5;
 
60
        else
 
61
                *pf = DDS_PF_UNKNOWN;
 
62
}
 
63
 
 
64
 
 
65
/*!
 
66
DDSGetInfo()
 
67
extracts relevant info from a dds texture, returns 0 on success
 
68
*/
 
69
s32 DDSGetInfo( ddsBuffer *dds, s32 *width, s32 *height, eDDSPixelFormat *pf )
 
70
{
 
71
        /* dummy test */
 
72
        if( dds == NULL )
 
73
                return -1;
 
74
 
 
75
        /* test dds header */
 
76
        if( *((s32*) dds->magic) != *((s32*) "DDS ") )
 
77
                return -1;
 
78
        if( DDSLittleLong( dds->size ) != 124 )
 
79
                return -1;
 
80
 
 
81
        /* extract width and height */
 
82
        if( width != NULL )
 
83
                *width = DDSLittleLong( dds->width );
 
84
        if( height != NULL )
 
85
                *height = DDSLittleLong( dds->height );
 
86
 
 
87
        /* get pixel format */
 
88
        DDSDecodePixelFormat( dds, pf );
 
89
 
 
90
        /* return ok */
 
91
        return 0;
 
92
}
 
93
 
 
94
 
 
95
/*!
 
96
        DDSGetColorBlockColors()
 
97
        extracts colors from a dds color block
 
98
*/
 
99
void DDSGetColorBlockColors( ddsColorBlock *block, ddsColor colors[ 4 ] )
 
100
{
 
101
        u16             word;
 
102
 
 
103
 
 
104
        /* color 0 */
 
105
        word = DDSLittleShort( block->colors[ 0 ] );
 
106
        colors[ 0 ].a = 0xff;
 
107
 
 
108
        /* extract rgb bits */
 
109
        colors[ 0 ].b = (u8) word;
 
110
        colors[ 0 ].b <<= 3;
 
111
        colors[ 0 ].b |= (colors[ 0 ].b >> 5);
 
112
        word >>= 5;
 
113
        colors[ 0 ].g = (u8) word;
 
114
        colors[ 0 ].g <<= 2;
 
115
        colors[ 0 ].g |= (colors[ 0 ].g >> 5);
 
116
        word >>= 6;
 
117
        colors[ 0 ].r = (u8) word;
 
118
        colors[ 0 ].r <<= 3;
 
119
        colors[ 0 ].r |= (colors[ 0 ].r >> 5);
 
120
 
 
121
        /* same for color 1 */
 
122
        word = DDSLittleShort( block->colors[ 1 ] );
 
123
        colors[ 1 ].a = 0xff;
 
124
 
 
125
        /* extract rgb bits */
 
126
        colors[ 1 ].b = (u8) word;
 
127
        colors[ 1 ].b <<= 3;
 
128
        colors[ 1 ].b |= (colors[ 1 ].b >> 5);
 
129
        word >>= 5;
 
130
        colors[ 1 ].g = (u8) word;
 
131
        colors[ 1 ].g <<= 2;
 
132
        colors[ 1 ].g |= (colors[ 1 ].g >> 5);
 
133
        word >>= 6;
 
134
        colors[ 1 ].r = (u8) word;
 
135
        colors[ 1 ].r <<= 3;
 
136
        colors[ 1 ].r |= (colors[ 1 ].r >> 5);
 
137
 
 
138
        /* use this for all but the super-freak math method */
 
139
        if( block->colors[ 0 ] > block->colors[ 1 ] )
 
140
        {
 
141
                /* four-color block: derive the other two colors.
 
142
                00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3
 
143
                these two bit codes correspond to the 2-bit fields
 
144
                stored in the 64-bit block. */
 
145
 
 
146
                word = ((u16) colors[ 0 ].r * 2 + (u16) colors[ 1 ].r ) / 3;
 
147
                /* no +1 for rounding */
 
148
                /* as bits have been shifted to 888 */
 
149
                colors[ 2 ].r = (u8) word;
 
150
                word = ((u16) colors[ 0 ].g * 2 + (u16) colors[ 1 ].g) / 3;
 
151
                colors[ 2 ].g = (u8) word;
 
152
                word = ((u16) colors[ 0 ].b * 2 + (u16) colors[ 1 ].b) / 3;
 
153
                colors[ 2 ].b = (u8) word;
 
154
                colors[ 2 ].a = 0xff;
 
155
 
 
156
                word = ((u16) colors[ 0 ].r + (u16) colors[ 1 ].r * 2) / 3;
 
157
                colors[ 3 ].r = (u8) word;
 
158
                word = ((u16) colors[ 0 ].g + (u16) colors[ 1 ].g * 2) / 3;
 
159
                colors[ 3 ].g = (u8) word;
 
160
                word = ((u16) colors[ 0 ].b + (u16) colors[ 1 ].b * 2) / 3;
 
161
                colors[ 3 ].b = (u8) word;
 
162
                colors[ 3 ].a = 0xff;
 
163
        }
 
164
        else
 
165
        {
 
166
                /* three-color block: derive the other color.
 
167
                00 = color 0, 01 = color 1, 10 = color 2,
 
168
                11 = transparent.
 
169
                These two bit codes correspond to the 2-bit fields
 
170
                stored in the 64-bit block */
 
171
 
 
172
                word = ((u16) colors[ 0 ].r + (u16) colors[ 1 ].r) / 2;
 
173
                colors[ 2 ].r = (u8) word;
 
174
                word = ((u16) colors[ 0 ].g + (u16) colors[ 1 ].g) / 2;
 
175
                colors[ 2 ].g = (u8) word;
 
176
                word = ((u16) colors[ 0 ].b + (u16) colors[ 1 ].b) / 2;
 
177
                colors[ 2 ].b = (u8) word;
 
178
                colors[ 2 ].a = 0xff;
 
179
 
 
180
                /* random color to indicate alpha */
 
181
                colors[ 3 ].r = 0x00;
 
182
                colors[ 3 ].g = 0xff;
 
183
                colors[ 3 ].b = 0xff;
 
184
                colors[ 3 ].a = 0x00;
 
185
        }
 
186
}
 
187
 
 
188
 
 
189
/*
 
190
DDSDecodeColorBlock()
 
191
decodes a dds color block
 
192
fixme: make endian-safe
 
193
*/
 
194
 
 
195
void DDSDecodeColorBlock( u32 *pixel, ddsColorBlock *block, s32 width, u32 colors[ 4 ] )
 
196
{
 
197
        s32                             r, n;
 
198
        u32     bits;
 
199
        u32     masks[] = { 3, 12, 3 << 4, 3 << 6 };    /* bit masks = 00000011, 00001100, 00110000, 11000000 */
 
200
        s32                             shift[] = { 0, 2, 4, 6 };
 
201
 
 
202
 
 
203
        /* r steps through lines in y */
 
204
        for( r = 0; r < 4; r++, pixel += (width - 4) )  /* no width * 4 as u32 ptr inc will * 4 */
 
205
        {
 
206
                /* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
 
207
 
 
208
                /* n steps through pixels */
 
209
                for( n = 0; n < 4; n++ )
 
210
                {
 
211
                        bits = block->row[ r ] & masks[ n ];
 
212
                        bits >>= shift[ n ];
 
213
 
 
214
                        switch( bits )
 
215
                        {
 
216
                        case 0:
 
217
                                *pixel = colors[ 0 ];
 
218
                                pixel++;
 
219
                                break;
 
220
 
 
221
                        case 1:
 
222
                                *pixel = colors[ 1 ];
 
223
                                pixel++;
 
224
                                break;
 
225
 
 
226
                        case 2:
 
227
                                *pixel = colors[ 2 ];
 
228
                                pixel++;
 
229
                                break;
 
230
 
 
231
                        case 3:
 
232
                                *pixel = colors[ 3 ];
 
233
                                pixel++;
 
234
                                break;
 
235
 
 
236
                        default:
 
237
                                /* invalid */
 
238
                                pixel++;
 
239
                                break;
 
240
                        }
 
241
                }
 
242
        }
 
243
}
 
244
 
 
245
 
 
246
/*
 
247
DDSDecodeAlphaExplicit()
 
248
decodes a dds explicit alpha block
 
249
*/
 
250
void DDSDecodeAlphaExplicit( u32 *pixel, ddsAlphaBlockExplicit *alphaBlock, s32 width, u32 alphaZero )
 
251
{
 
252
        s32                             row, pix;
 
253
        u16     word;
 
254
        ddsColor                color;
 
255
 
 
256
 
 
257
        /* clear color */
 
258
        color.r = 0;
 
259
        color.g = 0;
 
260
        color.b = 0;
 
261
 
 
262
        /* walk rows */
 
263
        for( row = 0; row < 4; row++, pixel += (width - 4) )
 
264
        {
 
265
                word = DDSLittleShort( alphaBlock->row[ row ] );
 
266
 
 
267
                /* walk pixels */
 
268
                for( pix = 0; pix < 4; pix++ )
 
269
                {
 
270
                        /* zero the alpha bits of image pixel */
 
271
                        *pixel &= alphaZero;
 
272
                        color.a = word & 0x000F;
 
273
                        color.a = color.a | (color.a << 4);
 
274
                        *pixel |= *((u32*) &color);
 
275
                        word >>= 4;             /* move next bits to lowest 4 */
 
276
                        pixel++;                /* move to next pixel in the row */
 
277
                }
 
278
        }
 
279
}
 
280
 
 
281
 
 
282
 
 
283
/*
 
284
DDSDecodeAlpha3BitLinear()
 
285
decodes interpolated alpha block
 
286
*/
 
287
void DDSDecodeAlpha3BitLinear( u32 *pixel, ddsAlphaBlock3BitLinear *alphaBlock, s32 width, u32 alphaZero )
 
288
{
 
289
 
 
290
        s32 row, pix;
 
291
        u32 stuff;
 
292
        u8 bits[ 4 ][ 4 ];
 
293
        u16 alphas[ 8 ];
 
294
        ddsColor aColors[ 4 ][ 4 ];
 
295
 
 
296
        /* get initial alphas */
 
297
        alphas[ 0 ] = alphaBlock->alpha0;
 
298
        alphas[ 1 ] = alphaBlock->alpha1;
 
299
 
 
300
        /* 8-alpha block */
 
301
        if( alphas[ 0 ] > alphas[ 1 ] )
 
302
        {
 
303
                /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
 
304
                alphas[ 2 ] = ( 6 * alphas[ 0 ] +     alphas[ 1 ]) / 7; /* bit code 010 */
 
305
                alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 7; /* bit code 011 */
 
306
                alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 7; /* bit code 100 */
 
307
                alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ]) / 7; /* bit code 101 */
 
308
                alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ]) / 7; /* bit code 110 */
 
309
                alphas[ 7 ] = (     alphas[ 0 ] + 6 * alphas[ 1 ]) / 7; /* bit code 111 */
 
310
        }
 
311
 
 
312
        /* 6-alpha block */
 
313
        else
 
314
        {
 
315
                /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
 
316
                alphas[ 2 ] = (4 * alphas[ 0 ] +     alphas[ 1 ]) / 5;  /* bit code 010 */
 
317
                alphas[ 3 ] = (3 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 5;  /* bit code 011 */
 
318
                alphas[ 4 ] = (2 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 5;  /* bit code 100 */
 
319
                alphas[ 5 ] = (    alphas[ 0 ] + 4 * alphas[ 1 ]) / 5;  /* bit code 101 */
 
320
                alphas[ 6 ] = 0;                                                                                /* bit code 110 */
 
321
                alphas[ 7 ] = 255;                                                                              /* bit code 111 */
 
322
        }
 
323
 
 
324
        /* decode 3-bit fields into array of 16 bytes with same value */
 
325
 
 
326
        /* first two rows of 4 pixels each */
 
327
        stuff = *((u32*) &(alphaBlock->stuff[ 0 ]));
 
328
 
 
329
        bits[ 0 ][ 0 ] = (u8) (stuff & 0x00000007);
 
330
        stuff >>= 3;
 
331
        bits[ 0 ][ 1 ] = (u8) (stuff & 0x00000007);
 
332
        stuff >>= 3;
 
333
        bits[ 0 ][ 2 ] = (u8) (stuff & 0x00000007);
 
334
        stuff >>= 3;
 
335
        bits[ 0 ][ 3 ] = (u8) (stuff & 0x00000007);
 
336
        stuff >>= 3;
 
337
        bits[ 1 ][ 0 ] = (u8) (stuff & 0x00000007);
 
338
        stuff >>= 3;
 
339
        bits[ 1 ][ 1 ] = (u8) (stuff & 0x00000007);
 
340
        stuff >>= 3;
 
341
        bits[ 1 ][ 2 ] = (u8) (stuff & 0x00000007);
 
342
        stuff >>= 3;
 
343
        bits[ 1 ][ 3 ] = (u8) (stuff & 0x00000007);
 
344
 
 
345
        /* last two rows */
 
346
        stuff = *((u32*) &(alphaBlock->stuff[ 3 ])); /* last 3 bytes */
 
347
 
 
348
        bits[ 2 ][ 0 ] = (u8) (stuff & 0x00000007);
 
349
        stuff >>= 3;
 
350
        bits[ 2 ][ 1 ] = (u8) (stuff & 0x00000007);
 
351
        stuff >>= 3;
 
352
        bits[ 2 ][ 2 ] = (u8) (stuff & 0x00000007);
 
353
        stuff >>= 3;
 
354
        bits[ 2 ][ 3 ] = (u8) (stuff & 0x00000007);
 
355
        stuff >>= 3;
 
356
        bits[ 3 ][ 0 ] = (u8) (stuff & 0x00000007);
 
357
        stuff >>= 3;
 
358
        bits[ 3 ][ 1 ] = (u8) (stuff & 0x00000007);
 
359
        stuff >>= 3;
 
360
        bits[ 3 ][ 2 ] = (u8) (stuff & 0x00000007);
 
361
        stuff >>= 3;
 
362
        bits[ 3 ][ 3 ] = (u8) (stuff & 0x00000007);
 
363
 
 
364
        /* decode the codes into alpha values */
 
365
        for( row = 0; row < 4; row++ )
 
366
        {
 
367
                for( pix=0; pix < 4; pix++ )
 
368
                {
 
369
                        aColors[ row ][ pix ].r = 0;
 
370
                        aColors[ row ][ pix ].g = 0;
 
371
                        aColors[ row ][ pix ].b = 0;
 
372
                        aColors[ row ][ pix ].a = (u8) alphas[ bits[ row ][ pix ] ];
 
373
                }
 
374
        }
 
375
 
 
376
        /* write out alpha values to the image bits */
 
377
        for( row = 0; row < 4; row++, pixel += width-4 )
 
378
        {
 
379
                for( pix = 0; pix < 4; pix++ )
 
380
                {
 
381
                        /* zero the alpha bits of image pixel */
 
382
                        *pixel &= alphaZero;
 
383
 
 
384
                        /* or the bits into the prev. nulled alpha */
 
385
                        *pixel |= *((u32*) &(aColors[ row ][ pix ]));
 
386
                        pixel++;
 
387
                }
 
388
        }
 
389
}
 
390
 
 
391
 
 
392
/*
 
393
DDSDecompressDXT1()
 
394
decompresses a dxt1 format texture
 
395
*/
 
396
s32 DDSDecompressDXT1( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
 
397
{
 
398
        s32 x, y, xBlocks, yBlocks;
 
399
        u32 *pixel;
 
400
        ddsColorBlock *block;
 
401
        ddsColor colors[ 4 ];
 
402
 
 
403
        /* setup */
 
404
        xBlocks = width / 4;
 
405
        yBlocks = height / 4;
 
406
 
 
407
        /* walk y */
 
408
        for( y = 0; y < yBlocks; y++ )
 
409
        {
 
410
                /* 8 bytes per block */
 
411
                block = (ddsColorBlock*) (dds->data + y * xBlocks * 8);
 
412
 
 
413
                /* walk x */
 
414
                for( x = 0; x < xBlocks; x++, block++ )
 
415
                {
 
416
                        DDSGetColorBlockColors( block, colors );
 
417
                        pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4);
 
418
                        DDSDecodeColorBlock( pixel, block, width, (u32*) colors );
 
419
                }
 
420
        }
 
421
 
 
422
        /* return ok */
 
423
        return 0;
 
424
}
 
425
 
 
426
 
 
427
/*
 
428
DDSDecompressDXT3()
 
429
decompresses a dxt3 format texture
 
430
*/
 
431
 
 
432
s32 DDSDecompressDXT3( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
 
433
{
 
434
        s32 x, y, xBlocks, yBlocks;
 
435
        u32 *pixel, alphaZero;
 
436
        ddsColorBlock *block;
 
437
        ddsAlphaBlockExplicit *alphaBlock;
 
438
        ddsColor colors[ 4 ];
 
439
 
 
440
        /* setup */
 
441
        xBlocks = width / 4;
 
442
        yBlocks = height / 4;
 
443
 
 
444
        /* create zero alpha */
 
445
        colors[ 0 ].a = 0;
 
446
        colors[ 0 ].r = 0xFF;
 
447
        colors[ 0 ].g = 0xFF;
 
448
        colors[ 0 ].b = 0xFF;
 
449
        alphaZero = *((u32*) &colors[ 0 ]);
 
450
 
 
451
        /* walk y */
 
452
        for( y = 0; y < yBlocks; y++ )
 
453
        {
 
454
                /* 8 bytes per block, 1 block for alpha, 1 block for color */
 
455
                block = (ddsColorBlock*) (dds->data + y * xBlocks * 16);
 
456
 
 
457
                /* walk x */
 
458
                for( x = 0; x < xBlocks; x++, block++ )
 
459
                {
 
460
                        /* get alpha block */
 
461
                        alphaBlock = (ddsAlphaBlockExplicit*) block;
 
462
 
 
463
                        /* get color block */
 
464
                        block++;
 
465
                        DDSGetColorBlockColors( block, colors );
 
466
 
 
467
                        /* decode color block */
 
468
                        pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4);
 
469
                        DDSDecodeColorBlock( pixel, block, width, (u32*) colors );
 
470
 
 
471
                        /* overwrite alpha bits with alpha block */
 
472
                        DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
 
473
                }
 
474
        }
 
475
 
 
476
        /* return ok */
 
477
        return 0;
 
478
}
 
479
 
 
480
 
 
481
/*
 
482
DDSDecompressDXT5()
 
483
decompresses a dxt5 format texture
 
484
*/
 
485
s32 DDSDecompressDXT5( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
 
486
{
 
487
        s32 x, y, xBlocks, yBlocks;
 
488
        u32 *pixel, alphaZero;
 
489
        ddsColorBlock *block;
 
490
        ddsAlphaBlock3BitLinear *alphaBlock;
 
491
        ddsColor colors[ 4 ];
 
492
 
 
493
        /* setup */
 
494
        xBlocks = width / 4;
 
495
        yBlocks = height / 4;
 
496
 
 
497
        /* create zero alpha */
 
498
        colors[ 0 ].a = 0;
 
499
        colors[ 0 ].r = 0xFF;
 
500
        colors[ 0 ].g = 0xFF;
 
501
        colors[ 0 ].b = 0xFF;
 
502
        alphaZero = *((u32*) &colors[ 0 ]);
 
503
 
 
504
        /* walk y */
 
505
        for( y = 0; y < yBlocks; y++ )
 
506
        {
 
507
                /* 8 bytes per block, 1 block for alpha, 1 block for color */
 
508
                block = (ddsColorBlock*) (dds->data + y * xBlocks * 16);
 
509
 
 
510
                /* walk x */
 
511
                for( x = 0; x < xBlocks; x++, block++ )
 
512
                {
 
513
                        /* get alpha block */
 
514
                        alphaBlock = (ddsAlphaBlock3BitLinear*) block;
 
515
 
 
516
                        /* get color block */
 
517
                        block++;
 
518
                        DDSGetColorBlockColors( block, colors );
 
519
 
 
520
                        /* decode color block */
 
521
                        pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4);
 
522
                        DDSDecodeColorBlock( pixel, block, width, (u32*) colors );
 
523
 
 
524
                        /* overwrite alpha bits with alpha block */
 
525
                        DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
 
526
                }
 
527
        }
 
528
 
 
529
        /* return ok */
 
530
        return 0;
 
531
}
 
532
 
 
533
 
 
534
/*
 
535
DDSDecompressDXT2()
 
536
decompresses a dxt2 format texture (fixme: un-premultiply alpha)
 
537
*/
 
538
s32 DDSDecompressDXT2( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
 
539
{
 
540
        /* decompress dxt3 first */
 
541
        const s32 r = DDSDecompressDXT3( dds, width, height, pixels );
 
542
 
 
543
        /* return to sender */
 
544
        return r;
 
545
}
 
546
 
 
547
 
 
548
/*
 
549
DDSDecompressDXT4()
 
550
decompresses a dxt4 format texture (fixme: un-premultiply alpha)
 
551
*/
 
552
s32 DDSDecompressDXT4( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
 
553
{
 
554
        /* decompress dxt5 first */
 
555
        const s32 r = DDSDecompressDXT5( dds, width, height, pixels );
 
556
 
 
557
        /* return to sender */
 
558
        return r;
 
559
}
 
560
 
 
561
 
 
562
/*
 
563
DDSDecompressARGB8888()
 
564
decompresses an argb 8888 format texture
 
565
*/
 
566
s32 DDSDecompressARGB8888( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
 
567
{
 
568
        /* setup */
 
569
        u8* in = dds->data;
 
570
        u8* out = pixels;
 
571
 
 
572
        /* walk y */
 
573
        for(s32 y = 0; y < height; y++)
 
574
        {
 
575
                /* walk x */
 
576
                for(s32 x = 0; x < width; x++)
 
577
                {
 
578
                        *out++ = *in++;
 
579
                        *out++ = *in++;
 
580
                        *out++ = *in++;
 
581
                        *out++ = *in++;
 
582
                }
 
583
        }
 
584
 
 
585
        /* return ok */
 
586
        return 0;
 
587
}
 
588
 
 
589
 
 
590
/*
 
591
DDSDecompress()
 
592
decompresses a dds texture into an rgba image buffer, returns 0 on success
 
593
*/
 
594
s32 DDSDecompress( ddsBuffer *dds, u8 *pixels )
 
595
{
 
596
        s32 width, height;
 
597
        eDDSPixelFormat pf;
 
598
 
 
599
        /* get dds info */
 
600
        s32 r = DDSGetInfo( dds, &width, &height, &pf );
 
601
        if ( r )
 
602
                return r;
 
603
 
 
604
        /* decompress */
 
605
        switch( pf )
 
606
        {
 
607
        case DDS_PF_ARGB8888:
 
608
                /* fixme: support other [a]rgb formats */
 
609
                r = DDSDecompressARGB8888( dds, width, height, pixels );
 
610
                break;
 
611
 
 
612
        case DDS_PF_DXT1:
 
613
                r = DDSDecompressDXT1( dds, width, height, pixels );
 
614
                break;
 
615
 
 
616
        case DDS_PF_DXT2:
 
617
                r = DDSDecompressDXT2( dds, width, height, pixels );
 
618
                break;
 
619
 
 
620
        case DDS_PF_DXT3:
 
621
                r = DDSDecompressDXT3( dds, width, height, pixels );
 
622
                break;
 
623
 
 
624
        case DDS_PF_DXT4:
 
625
                r = DDSDecompressDXT4( dds, width, height, pixels );
 
626
                break;
 
627
 
 
628
        case DDS_PF_DXT5:
 
629
                r = DDSDecompressDXT5( dds, width, height, pixels );
 
630
                break;
 
631
 
 
632
        default:
 
633
        case DDS_PF_UNKNOWN:
 
634
                memset( pixels, 0xFF, width * height * 4 );
 
635
                r = -1;
 
636
                break;
 
637
        }
 
638
 
 
639
        /* return to sender */
 
640
        return r;
 
641
}
 
642
 
 
643
} // end anonymous namespace
 
644
 
 
645
 
 
646
//! returns true if the file maybe is able to be loaded by this class
 
647
//! based on the file extension (e.g. ".tga")
 
648
bool CImageLoaderDDS::isALoadableFileExtension(const io::path& filename) const
 
649
{
 
650
        return core::hasFileExtension ( filename, "dds" );
 
651
}
 
652
 
 
653
 
 
654
//! returns true if the file maybe is able to be loaded by this class
 
655
bool CImageLoaderDDS::isALoadableFileFormat(io::IReadFile* file) const
 
656
{
 
657
        if (!file)
 
658
                return false;
 
659
 
 
660
        ddsBuffer header;
 
661
        file->read(&header, sizeof(header));
 
662
 
 
663
        s32 width, height;
 
664
        eDDSPixelFormat pixelFormat;
 
665
 
 
666
        return (0 == DDSGetInfo( &header, &width, &height, &pixelFormat));
 
667
}
 
668
 
 
669
 
 
670
//! creates a surface from the file
 
671
IImage* CImageLoaderDDS::loadImage(io::IReadFile* file) const
 
672
{
 
673
        u8 *memFile = new u8 [ file->getSize() ];
 
674
        file->read ( memFile, file->getSize() );
 
675
 
 
676
        ddsBuffer *header = (ddsBuffer*) memFile;
 
677
        IImage* image = 0;
 
678
        s32 width, height;
 
679
        eDDSPixelFormat pixelFormat;
 
680
 
 
681
        if ( 0 == DDSGetInfo( header, &width, &height, &pixelFormat) )
 
682
        {
 
683
                image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
 
684
 
 
685
                if ( DDSDecompress( header, (u8*) image->lock() ) == -1)
 
686
                {
 
687
                        image->unlock();
 
688
                        image->drop();
 
689
                        image = 0;
 
690
                }
 
691
        }
 
692
 
 
693
        delete [] memFile;
 
694
        if ( image )
 
695
                image->unlock();
 
696
 
 
697
        return image;
 
698
}
 
699
 
 
700
 
 
701
//! creates a loader which is able to load dds images
 
702
IImageLoader* createImageLoaderDDS()
 
703
{
 
704
        return new CImageLoaderDDS();
 
705
}
 
706
 
 
707
 
 
708
} // end namespace video
 
709
} // end namespace irr
 
710
 
 
711
#endif