1
- // DDS loader
2
- // http://lonesock.net/soil.html
1
+ /* DDS file support
2
+ License: Public Domain, http://lonesock.net/soil.html
3
+ Modified fork that adds basic DDS_HEADER_DXT10 and volume support
4
+ */
3
5
4
6
#ifndef HEADER_STB_IMAGE_DDS_AUGMENTATION
5
7
#define HEADER_STB_IMAGE_DDS_AUGMENTATION
8
10
extern "C" {
9
11
#endif
10
12
11
- extern int stbi_dds_test_memory (stbi_uc const * buffer , int len );
12
- extern stbi_uc * stbi_dds_load (const char * filename , int * x , int * y , int * z , int * comp , int req_comp );
13
- extern stbi_uc * stbi_dds_load_from_memory (stbi_uc const * buffer , int len , int * x , int * y , int * z , int * comp , int req_comp );
14
13
#ifndef STBI_NO_STDIO
15
14
extern int stbi_dds_test_file (FILE * f );
15
+ #endif
16
+
17
+ extern int stbi_dds_test_memory (stbi_uc const * buffer , int len );
18
+
19
+ #ifndef STBI_NO_STDIO
20
+ extern stbi_uc * stbi_dds_load (const char * filename , int * x , int * y , int * z , int * comp , int req_comp );
16
21
extern stbi_uc * stbi_dds_load_from_file (FILE * f , int * x , int * y , int * z , int * comp , int req_comp );
17
22
#endif
18
23
24
+ extern stbi_uc * stbi_dds_load_from_memory (stbi_uc const * buffer , int len , int * x , int * y , int * z , int * comp , int req_comp );
25
+
26
+ #ifdef __cplusplus
27
+ }
28
+ #endif
29
+
19
30
#ifdef STB_IMAGE_DDS_IMPLEMENTATION
20
31
21
32
typedef struct DDS_HEADER
@@ -92,18 +103,29 @@ typedef struct DDS_HEADER_DXT10
92
103
93
104
#define MAKEFOURCC (ch0 , ch1 , ch2 , ch3 ) ((stbi__uint32)(stbi_uc)(ch0) | ((stbi__uint32)(stbi_uc)(ch1) << 8) | ((stbi__uint32)(stbi_uc)(ch2) << 16) | ((stbi__uint32)(stbi_uc)(ch3) << 24 ))
94
105
106
+ static int stbi__dds_test (stbi__context * s )
107
+ {
108
+ // check the magic number
109
+ if (stbi__get8 (s ) != 'D' ) return 0 ;
110
+ if (stbi__get8 (s ) != 'D' ) return 0 ;
111
+ if (stbi__get8 (s ) != 'S' ) return 0 ;
112
+ if (stbi__get8 (s ) != ' ' ) return 0 ;
113
+ return 1 ;
114
+ }
115
+
95
116
stbi_inline static int stbi__convert_bit_range (int c , int from_bits , int to_bits )
96
117
{
97
118
int b = (1 << (from_bits - 1 )) + c * ((1 << to_bits ) - 1 );
98
-
99
119
return (b + (b >> from_bits )) >> from_bits ;
100
120
}
121
+
101
122
stbi_inline static void stbi__rgb_888_from_565 (unsigned int c , int * r , int * g , int * b )
102
123
{
103
124
* r = stbi__convert_bit_range ((c >> 11 ) & 31 , 5 , 8 );
104
125
* g = stbi__convert_bit_range ((c >> 05 ) & 63 , 6 , 8 );
105
126
* b = stbi__convert_bit_range ((c >> 00 ) & 31 , 5 , 8 );
106
127
}
128
+
107
129
void stbi__dxt_decode_DXT1_block (unsigned char uncompressed [16 * 4 ], unsigned char compressed [8 ])
108
130
{
109
131
int next_bit = 4 * 8 ;
@@ -162,7 +184,7 @@ void stbi__dxt_decode_DXT1_block(unsigned char uncompressed[16 * 4], unsigned ch
162
184
void stbi__dxt_decode_DXT23_alpha_block (unsigned char uncompressed [16 * 4 ], unsigned char compressed [8 ])
163
185
{
164
186
int i , next_bit = 0 ;
165
-
187
+ // each alpha value gets 4 bits
166
188
for (i = 3 ; i < 16 * 4 ; i += 4 )
167
189
{
168
190
uncompressed [i ] = stbi__convert_bit_range ((compressed [next_bit >> 3 ] >> (next_bit & 7 )) & 15 , 4 , 8 );
@@ -249,141 +271,115 @@ void stbi__dxt_decode_DXT_color_block(unsigned char uncompressed[16 * 4], unsign
249
271
// done
250
272
}
251
273
252
- static int stbi__dds_test (stbi__context * s )
253
- {
254
- // Check the magic number
255
- if (stbi__get8 (s ) != 'D' )
256
- {
257
- return 0 ;
258
- }
259
- if (stbi__get8 (s ) != 'D' )
260
- {
261
- return 0 ;
262
- }
263
- if (stbi__get8 (s ) != 'S' )
264
- {
265
- return 0 ;
266
- }
267
- if (stbi__get8 (s ) != ' ' )
268
- {
269
- return 0 ;
270
- }
271
-
272
- return 1 ;
273
- }
274
-
275
274
static stbi_uc * stbi__dds_load (stbi__context * s , int * x , int * y , int * z , int * comp , int req_comp )
276
275
{
277
- // All variables go up front
276
+ // all variables go up front
278
277
stbi_uc * dds_data = NULL ;
279
278
stbi_uc block [16 * 4 ];
280
279
stbi_uc compressed [8 ];
281
- int flags , DXT_family ;
280
+ int DXT_family = 0 ;
282
281
int has_alpha , has_mipmap ;
283
- int is_compressed , cubemap_faces ;
282
+ int cubemap_faces ;
284
283
int block_pitch , num_blocks ;
285
- int i , sz , cf ;
286
284
DDS_HEADER header ;
287
285
DDS_HEADER_DXT10 header2 ;
286
+ int i , sz , cf ;
288
287
289
- // Check the magic number
290
288
if (!stbi__dds_test (s ))
291
- {
292
289
return NULL ;
293
- }
294
290
295
- // Load the header
296
- stbi__getn (s , (stbi_uc * )( & header ) , sizeof (DDS_HEADER ));
291
+ // load the header
292
+ stbi__getn (s , (stbi_uc * )& header , sizeof (header ));
297
293
298
- if ( header . dwSize != 124 )
299
- {
294
+ // and do some checking
295
+ if ( header . dwSize != sizeof ( header ))
300
296
return NULL ;
301
- }
302
-
303
- // Checks
304
- flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT ;
305
-
306
- if ((header .dwFlags & flags ) != flags )
307
- {
297
+ if ((header .dwFlags & (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT )) != (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT ))
308
298
return NULL ;
309
- }
310
-
311
- if (header .sPixelFormat .dwSize != 32 )
312
- {
299
+ if ( header .sPixelFormat .dwSize != sizeof (header .sPixelFormat ))
313
300
return NULL ;
314
- }
315
-
316
- flags = DDPF_FOURCC | DDPF_RGB | DDPF_LUMINANCE | DDPF_YUV ;
317
-
318
- if ((header .sPixelFormat .dwFlags & flags ) == 0 )
319
- {
301
+ if ((header .sPixelFormat .dwFlags & (DDPF_FOURCC | DDPF_RGB | DDPF_LUMINANCE | DDPF_YUV )) == 0 )
320
302
return NULL ;
321
- }
322
-
323
303
if ((header .sCaps .dwCaps1 & DDSCAPS_TEXTURE ) == 0 )
324
- {
325
304
return NULL ;
305
+
306
+ if ((header .sPixelFormat .dwFlags & DDPF_FOURCC ) != 0 )
307
+ {
308
+ if (header .sPixelFormat .dwFourCC == MAKEFOURCC ('D' , 'X' , '1' , '0' ))
309
+ {
310
+ stbi__getn (s , (stbi_uc * )& header2 , sizeof (header2 ));
311
+
312
+ if (header2 .arraySize > 1 )
313
+ return NULL ;
314
+
315
+ switch (header2 .dxgiFormat )
316
+ {
317
+ case 28 : // DXGI_FORMAT_R8G8B8A8_UNORM
318
+ case 49 : // DXGI_FORMAT_R8G8_UNORM
319
+ case 61 : // DXGI_FORMAT_R8_UNORM
320
+ break ;
321
+ case 71 : // DXGI_FORMAT_BC1_UNORM
322
+ DXT_family = 1 ;
323
+ break ;
324
+ case 74 : // DXGI_FORMAT_BC2_UNORM
325
+ DXT_family = 3 ;
326
+ break ;
327
+ case 77 : // DXGI_FORMAT_BC3_UNORM
328
+ DXT_family = 5 ;
329
+ break ;
330
+ default :
331
+ return NULL ;
332
+ }
333
+ }
334
+ else
335
+ {
336
+ // dwFourCC is something like (('D' << 0) | ('X' << 8) | ('T' << 16) | ('1' << 24))
337
+ DXT_family = 1 + (header .sPixelFormat .dwFourCC >> 24 ) - '1' ;
338
+ if ((DXT_family < 1 ) || (DXT_family > 5 ))
339
+ return NULL ;
340
+ }
326
341
}
327
342
328
- // Get the image information
343
+ // get the image data
329
344
* x = s -> img_x = header .dwWidth ;
330
345
* y = s -> img_y = header .dwHeight ;
331
346
* z = (header .dwDepth > 1 ) ? header .dwDepth : 1 ;
332
347
* comp = s -> img_n = 4 ;
333
348
334
- is_compressed = (header .sPixelFormat .dwFlags & DDPF_FOURCC ) / DDPF_FOURCC ;
335
349
has_alpha = (header .sPixelFormat .dwFlags & DDPF_ALPHAPIXELS ) / DDPF_ALPHAPIXELS ;
336
350
has_mipmap = (header .sCaps .dwCaps1 & DDSCAPS_MIPMAP ) && (header .dwMipMapCount > 1 );
337
351
cubemap_faces = (header .sCaps .dwCaps2 & DDSCAPS2_CUBEMAP ) / DDSCAPS2_CUBEMAP ;
338
352
339
- // Cubemaps need to have square faces
353
+ // cubemaps need to have square faces
340
354
cubemap_faces &= (s -> img_x == s -> img_y );
341
355
cubemap_faces *= 5 ;
342
356
cubemap_faces += 1 ;
343
357
344
358
if ((header .dwDepth > 1 ) && cubemap_faces != 1 )
345
- {
346
359
return NULL ;
347
- }
348
360
349
361
cubemap_faces *= (* z );
350
362
* z = cubemap_faces ;
351
363
352
- block_pitch = (s -> img_x + 3 ) >> 2 ;
353
- num_blocks = block_pitch * ((s -> img_y + 3 ) >> 2 );
354
-
355
- if (is_compressed )
364
+ if (DXT_family != 0 )
356
365
{
357
- #pragma region Compressed
358
- if (header .sPixelFormat .dwFourCC & MAKEFOURCC ('D' , 'X' , '1' , '0' ))
359
- {
360
- stbi__getn (s , (stbi_uc * )(& header2 ), sizeof (DDS_HEADER_DXT10 ));
361
- }
366
+ block_pitch = (s -> img_x + 3 ) >> 2 ;
367
+ num_blocks = block_pitch * ((s -> img_y + 3 ) >> 2 );
362
368
363
- /* compressed */
364
- // note: header.sPixelFormat.dwFourCC is something like (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24))
365
- DXT_family = 1 + (header .sPixelFormat .dwFourCC >> 24 ) - '1' ;
366
- if ((DXT_family < 1 ) || (DXT_family > 5 ))
367
- {
368
- return NULL ;
369
- }
370
-
371
- /* check the expected size...oops, nevermind...
372
- those non-compliant writers leave
373
- dwPitchOrLinearSize == 0 */
374
369
// passed all the tests, get the RAM for decoding
375
370
sz = (s -> img_x ) * (s -> img_y ) * 4 * cubemap_faces ;
376
- dds_data = (stbi_uc * )malloc (sz );
377
- /* do this once for each face */
371
+ dds_data = (stbi_uc * )stbi__malloc (sz );
372
+
373
+ // do this once for each face
378
374
for (cf = 0 ; cf < cubemap_faces ; ++ cf )
379
375
{
380
- // now read and decode all the blocks
376
+ // read and decode all the blocks
381
377
for (i = 0 ; i < num_blocks ; ++ i )
382
378
{
383
- // where are we?
384
379
int bx , by , bw = 4 , bh = 4 ;
385
380
int ref_x = 4 * (i % block_pitch );
386
381
int ref_y = 4 * (i / block_pitch );
382
+
387
383
// get the next block's worth of compressed data, and decompress it
388
384
if (DXT_family == 1 )
389
385
{
@@ -407,6 +403,7 @@ static stbi_uc *stbi__dds_load(stbi__context *s, int *x, int *y, int *z, int *co
407
403
stbi__getn (s , compressed , 8 );
408
404
stbi__dxt_decode_DXT_color_block (block , compressed );
409
405
}
406
+
410
407
// is this a partial block?
411
408
if (ref_x + 4 > (int )s -> img_x )
412
409
{
@@ -416,6 +413,7 @@ static stbi_uc *stbi__dds_load(stbi__context *s, int *x, int *y, int *z, int *co
416
413
{
417
414
bh = s -> img_y - ref_y ;
418
415
}
416
+
419
417
// now drop our decompressed data into the buffer
420
418
for (by = 0 ; by < bh ; ++ by )
421
419
{
@@ -427,14 +425,15 @@ static stbi_uc *stbi__dds_load(stbi__context *s, int *x, int *y, int *z, int *co
427
425
}
428
426
}
429
427
430
- /* done reading and decoding the main image... skip MIPmaps if present */
428
+ // done reading and decoding the main image... skip MIPmaps if present
431
429
if (has_mipmap )
432
430
{
433
431
int block_size = 16 ;
434
432
if (DXT_family == 1 )
435
433
{
436
434
block_size = 8 ;
437
435
}
436
+
438
437
for (i = 1 ; i < (int )header .dwMipMapCount ; ++ i )
439
438
{
440
439
int mx = s -> img_x >> (i + 2 );
@@ -451,13 +450,9 @@ static stbi_uc *stbi__dds_load(stbi__context *s, int *x, int *y, int *z, int *co
451
450
}
452
451
}
453
452
}
454
- #pragma endregion
455
453
}
456
454
else
457
455
{
458
- #pragma region Uncompressed
459
- DXT_family = 0 ;
460
-
461
456
if (header .sPixelFormat .dwRGBBitCount != 0 )
462
457
{
463
458
s -> img_n = header .sPixelFormat .dwRGBBitCount / 8 ;
@@ -473,15 +468,15 @@ static stbi_uc *stbi__dds_load(stbi__context *s, int *x, int *y, int *z, int *co
473
468
* comp = s -> img_n ;
474
469
475
470
sz = (s -> img_x ) * (s -> img_y ) * s -> img_n * cubemap_faces ;
476
- dds_data = (stbi_uc * )malloc (sz );
471
+ dds_data = (stbi_uc * )stbi__malloc (sz );
477
472
478
- /* do this once for each face */
473
+ // do this once for each face
479
474
for (cf = 0 ; cf < cubemap_faces ; ++ cf )
480
475
{
481
- /* read the main image for this face */
476
+ // read the main image for this face
482
477
stbi__getn (s , & dds_data [cf * s -> img_x * s -> img_y * s -> img_n ], s -> img_x * s -> img_y * s -> img_n );
483
478
484
- /* done reading and decoding the main image... skip MIPmaps if present */
479
+ // done reading and decoding the main image... skip MIPmaps if present
485
480
if (has_mipmap )
486
481
{
487
482
for (i = 1 ; i < (int )header .dwMipMapCount ; ++ i )
@@ -503,20 +498,18 @@ static stbi_uc *stbi__dds_load(stbi__context *s, int *x, int *y, int *z, int *co
503
498
504
499
if (s -> img_n >= 3 )
505
500
{
506
- /* data was BGR, I need it RGB */
501
+ // data was BGR, convert it to RGB
507
502
for (i = 0 ; i < sz ; i += s -> img_n )
508
503
{
509
504
stbi_uc temp = dds_data [i ];
510
505
dds_data [i ] = dds_data [i + 2 ];
511
506
dds_data [i + 2 ] = temp ;
512
507
}
513
508
}
514
- #pragma endregion
515
509
}
516
510
517
- // Test if all alpha values are 255 (i.e. no transparency)
511
+ // see if all the alpha values are 255 (i.e. no transparency)
518
512
has_alpha = 0 ;
519
-
520
513
if (s -> img_n == 4 )
521
514
{
522
515
for (i = 3 ; (i < sz ) && (has_alpha == 0 ); i += 4 )
@@ -556,6 +549,7 @@ int stbi_dds_test_file(FILE *f)
556
549
return r ;
557
550
}
558
551
#endif
552
+
559
553
int stbi_dds_test_memory (stbi_uc const * buffer , int len )
560
554
{
561
555
stbi__context s ;
@@ -590,8 +584,4 @@ stbi_uc *stbi_dds_load_from_memory(stbi_uc const *buffer, int len, int *x, int *
590
584
591
585
#endif
592
586
593
- #ifdef __cplusplus
594
- }
595
- #endif
596
-
597
587
#endif // HEADER_STB_IMAGE_DDS_AUGMENTATION
0 commit comments