Skip to content

Commit e4f7ac1

Browse files
committed
Fix loading of DDS files which contain "DDS_HEADER_DXT10"
1 parent 80fd1be commit e4f7ac1

File tree

1 file changed

+97
-107
lines changed

1 file changed

+97
-107
lines changed

deps/stb_image_dds/stb_image_dds.h

+97-107
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
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+
*/
35

46
#ifndef HEADER_STB_IMAGE_DDS_AUGMENTATION
57
#define HEADER_STB_IMAGE_DDS_AUGMENTATION
@@ -8,14 +10,23 @@
810
extern "C" {
911
#endif
1012

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);
1413
#ifndef STBI_NO_STDIO
1514
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);
1621
extern stbi_uc *stbi_dds_load_from_file(FILE *f, int *x, int *y, int *z, int *comp, int req_comp);
1722
#endif
1823

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+
1930
#ifdef STB_IMAGE_DDS_IMPLEMENTATION
2031

2132
typedef struct DDS_HEADER
@@ -92,18 +103,29 @@ typedef struct DDS_HEADER_DXT10
92103

93104
#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 ))
94105

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+
95116
stbi_inline static int stbi__convert_bit_range(int c, int from_bits, int to_bits)
96117
{
97118
int b = (1 << (from_bits - 1)) + c * ((1 << to_bits) - 1);
98-
99119
return (b + (b >> from_bits)) >> from_bits;
100120
}
121+
101122
stbi_inline static void stbi__rgb_888_from_565(unsigned int c, int *r, int *g, int *b)
102123
{
103124
*r = stbi__convert_bit_range((c >> 11) & 31, 5, 8);
104125
*g = stbi__convert_bit_range((c >> 05) & 63, 6, 8);
105126
*b = stbi__convert_bit_range((c >> 00) & 31, 5, 8);
106127
}
128+
107129
void stbi__dxt_decode_DXT1_block(unsigned char uncompressed[16 * 4], unsigned char compressed[8])
108130
{
109131
int next_bit = 4 * 8;
@@ -162,7 +184,7 @@ void stbi__dxt_decode_DXT1_block(unsigned char uncompressed[16 * 4], unsigned ch
162184
void stbi__dxt_decode_DXT23_alpha_block(unsigned char uncompressed[16 * 4], unsigned char compressed[8])
163185
{
164186
int i, next_bit = 0;
165-
187+
// each alpha value gets 4 bits
166188
for (i = 3; i < 16 * 4; i += 4)
167189
{
168190
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
249271
// done
250272
}
251273

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-
275274
static stbi_uc *stbi__dds_load(stbi__context *s, int *x, int *y, int *z, int *comp, int req_comp)
276275
{
277-
// All variables go up front
276+
// all variables go up front
278277
stbi_uc *dds_data = NULL;
279278
stbi_uc block[16 * 4];
280279
stbi_uc compressed[8];
281-
int flags, DXT_family;
280+
int DXT_family = 0;
282281
int has_alpha, has_mipmap;
283-
int is_compressed, cubemap_faces;
282+
int cubemap_faces;
284283
int block_pitch, num_blocks;
285-
int i, sz, cf;
286284
DDS_HEADER header;
287285
DDS_HEADER_DXT10 header2;
286+
int i, sz, cf;
288287

289-
// Check the magic number
290288
if (!stbi__dds_test(s))
291-
{
292289
return NULL;
293-
}
294290

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));
297293

298-
if (header.dwSize != 124)
299-
{
294+
// and do some checking
295+
if ( header.dwSize != sizeof(header))
300296
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))
308298
return NULL;
309-
}
310-
311-
if (header.sPixelFormat.dwSize != 32)
312-
{
299+
if ( header.sPixelFormat.dwSize != sizeof(header.sPixelFormat))
313300
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)
320302
return NULL;
321-
}
322-
323303
if ((header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0)
324-
{
325304
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+
}
326341
}
327342

328-
// Get the image information
343+
// get the image data
329344
*x = s->img_x = header.dwWidth;
330345
*y = s->img_y = header.dwHeight;
331346
*z = (header.dwDepth > 1) ? header.dwDepth : 1;
332347
*comp = s->img_n = 4;
333348

334-
is_compressed = (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC;
335349
has_alpha = (header.sPixelFormat.dwFlags & DDPF_ALPHAPIXELS) / DDPF_ALPHAPIXELS;
336350
has_mipmap = (header.sCaps.dwCaps1 & DDSCAPS_MIPMAP) && (header.dwMipMapCount > 1);
337351
cubemap_faces = (header.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) / DDSCAPS2_CUBEMAP;
338352

339-
// Cubemaps need to have square faces
353+
// cubemaps need to have square faces
340354
cubemap_faces &= (s->img_x == s->img_y);
341355
cubemap_faces *= 5;
342356
cubemap_faces += 1;
343357

344358
if ((header.dwDepth > 1) && cubemap_faces != 1)
345-
{
346359
return NULL;
347-
}
348360

349361
cubemap_faces *= (*z);
350362
*z = cubemap_faces;
351363

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)
356365
{
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);
362368

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 */
374369
// passed all the tests, get the RAM for decoding
375370
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
378374
for (cf = 0; cf < cubemap_faces; ++cf)
379375
{
380-
// now read and decode all the blocks
376+
// read and decode all the blocks
381377
for (i = 0; i < num_blocks; ++i)
382378
{
383-
// where are we?
384379
int bx, by, bw = 4, bh = 4;
385380
int ref_x = 4 * (i % block_pitch);
386381
int ref_y = 4 * (i / block_pitch);
382+
387383
// get the next block's worth of compressed data, and decompress it
388384
if (DXT_family == 1)
389385
{
@@ -407,6 +403,7 @@ static stbi_uc *stbi__dds_load(stbi__context *s, int *x, int *y, int *z, int *co
407403
stbi__getn(s, compressed, 8);
408404
stbi__dxt_decode_DXT_color_block(block, compressed);
409405
}
406+
410407
// is this a partial block?
411408
if (ref_x + 4 > (int)s->img_x)
412409
{
@@ -416,6 +413,7 @@ static stbi_uc *stbi__dds_load(stbi__context *s, int *x, int *y, int *z, int *co
416413
{
417414
bh = s->img_y - ref_y;
418415
}
416+
419417
// now drop our decompressed data into the buffer
420418
for (by = 0; by < bh; ++by)
421419
{
@@ -427,14 +425,15 @@ static stbi_uc *stbi__dds_load(stbi__context *s, int *x, int *y, int *z, int *co
427425
}
428426
}
429427

430-
/* done reading and decoding the main image... skip MIPmaps if present */
428+
// done reading and decoding the main image... skip MIPmaps if present
431429
if (has_mipmap)
432430
{
433431
int block_size = 16;
434432
if (DXT_family == 1)
435433
{
436434
block_size = 8;
437435
}
436+
438437
for (i = 1; i < (int)header.dwMipMapCount; ++i)
439438
{
440439
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
451450
}
452451
}
453452
}
454-
#pragma endregion
455453
}
456454
else
457455
{
458-
#pragma region Uncompressed
459-
DXT_family = 0;
460-
461456
if (header.sPixelFormat.dwRGBBitCount != 0)
462457
{
463458
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
473468
*comp = s->img_n;
474469

475470
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);
477472

478-
/* do this once for each face */
473+
// do this once for each face
479474
for (cf = 0; cf < cubemap_faces; ++cf)
480475
{
481-
/* read the main image for this face */
476+
// read the main image for this face
482477
stbi__getn(s, &dds_data[cf * s->img_x * s->img_y * s->img_n], s->img_x * s->img_y * s->img_n);
483478

484-
/* done reading and decoding the main image... skip MIPmaps if present */
479+
// done reading and decoding the main image... skip MIPmaps if present
485480
if (has_mipmap)
486481
{
487482
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
503498

504499
if (s->img_n >= 3)
505500
{
506-
/* data was BGR, I need it RGB */
501+
// data was BGR, convert it to RGB
507502
for (i = 0; i < sz; i += s->img_n)
508503
{
509504
stbi_uc temp = dds_data[i];
510505
dds_data[i] = dds_data[i + 2];
511506
dds_data[i + 2] = temp;
512507
}
513508
}
514-
#pragma endregion
515509
}
516510

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)
518512
has_alpha = 0;
519-
520513
if (s->img_n == 4)
521514
{
522515
for (i = 3; (i < sz) && (has_alpha == 0); i += 4)
@@ -556,6 +549,7 @@ int stbi_dds_test_file(FILE *f)
556549
return r;
557550
}
558551
#endif
552+
559553
int stbi_dds_test_memory(stbi_uc const *buffer, int len)
560554
{
561555
stbi__context s;
@@ -590,8 +584,4 @@ stbi_uc *stbi_dds_load_from_memory(stbi_uc const *buffer, int len, int *x, int *
590584

591585
#endif
592586

593-
#ifdef __cplusplus
594-
}
595-
#endif
596-
597587
#endif // HEADER_STB_IMAGE_DDS_AUGMENTATION

0 commit comments

Comments
 (0)