594 |
jab |
1 |
/**
|
|
|
2 |
* @file stbi_DDS_aug_c.h
|
|
|
3 |
* @brief DDS file support
|
|
|
4 |
*/
|
369 |
jab |
5 |
|
|
|
6 |
/// DDS file support, does decoding, _not_ direct uploading
|
|
|
7 |
/// (use SOIL for that ;-)
|
|
|
8 |
|
|
|
9 |
/// A bunch of DirectDraw Surface structures and flags
|
|
|
10 |
typedef struct {
|
|
|
11 |
unsigned int dwMagic;
|
|
|
12 |
unsigned int dwSize;
|
|
|
13 |
unsigned int dwFlags;
|
|
|
14 |
unsigned int dwHeight;
|
|
|
15 |
unsigned int dwWidth;
|
|
|
16 |
unsigned int dwPitchOrLinearSize;
|
|
|
17 |
unsigned int dwDepth;
|
|
|
18 |
unsigned int dwMipMapCount;
|
|
|
19 |
unsigned int dwReserved1[ 11 ];
|
|
|
20 |
|
|
|
21 |
// DDPIXELFORMAT
|
|
|
22 |
struct {
|
|
|
23 |
unsigned int dwSize;
|
|
|
24 |
unsigned int dwFlags;
|
|
|
25 |
unsigned int dwFourCC;
|
|
|
26 |
unsigned int dwRGBBitCount;
|
|
|
27 |
unsigned int dwRBitMask;
|
|
|
28 |
unsigned int dwGBitMask;
|
|
|
29 |
unsigned int dwBBitMask;
|
|
|
30 |
unsigned int dwAlphaBitMask;
|
|
|
31 |
} sPixelFormat;
|
|
|
32 |
|
|
|
33 |
// DDCAPS2
|
|
|
34 |
struct {
|
|
|
35 |
unsigned int dwCaps1;
|
|
|
36 |
unsigned int dwCaps2;
|
|
|
37 |
unsigned int dwDDSX;
|
|
|
38 |
unsigned int dwReserved;
|
|
|
39 |
} sCaps;
|
|
|
40 |
unsigned int dwReserved2;
|
|
|
41 |
} DDS_header ;
|
|
|
42 |
|
|
|
43 |
// the following constants were copied directly off the MSDN website
|
|
|
44 |
|
|
|
45 |
// The dwFlags member of the original DDSURFACEDESC2 structure
|
|
|
46 |
// can be set to one or more of the following values.
|
|
|
47 |
#define DDSD_CAPS 0x00000001
|
|
|
48 |
#define DDSD_HEIGHT 0x00000002
|
|
|
49 |
#define DDSD_WIDTH 0x00000004
|
|
|
50 |
#define DDSD_PITCH 0x00000008
|
|
|
51 |
#define DDSD_PIXELFORMAT 0x00001000
|
|
|
52 |
#define DDSD_MIPMAPCOUNT 0x00020000
|
|
|
53 |
#define DDSD_LINEARSIZE 0x00080000
|
|
|
54 |
#define DDSD_DEPTH 0x00800000
|
|
|
55 |
|
|
|
56 |
// DirectDraw Pixel Format
|
|
|
57 |
#define DDPF_ALPHAPIXELS 0x00000001
|
|
|
58 |
#define DDPF_FOURCC 0x00000004
|
|
|
59 |
#define DDPF_RGB 0x00000040
|
|
|
60 |
|
|
|
61 |
// The dwCaps1 member of the DDSCAPS2 structure can be
|
|
|
62 |
// set to one or more of the following values.
|
|
|
63 |
#define DDSCAPS_COMPLEX 0x00000008
|
|
|
64 |
#define DDSCAPS_TEXTURE 0x00001000
|
|
|
65 |
#define DDSCAPS_MIPMAP 0x00400000
|
|
|
66 |
|
|
|
67 |
// The dwCaps2 member of the DDSCAPS2 structure can be
|
|
|
68 |
// set to one or more of the following values.
|
|
|
69 |
#define DDSCAPS2_CUBEMAP 0x00000200
|
|
|
70 |
#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
|
|
|
71 |
#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
|
|
|
72 |
#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
|
|
|
73 |
#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
|
|
|
74 |
#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
|
|
|
75 |
#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
|
|
|
76 |
#define DDSCAPS2_VOLUME 0x00200000
|
|
|
77 |
|
|
|
78 |
static int dds_test(stbi *s)
|
|
|
79 |
{
|
|
|
80 |
// check the magic number
|
|
|
81 |
if (get8(s) != 'D') return 0;
|
|
|
82 |
if (get8(s) != 'D') return 0;
|
|
|
83 |
if (get8(s) != 'S') return 0;
|
|
|
84 |
if (get8(s) != ' ') return 0;
|
|
|
85 |
// check header size
|
|
|
86 |
if (get32le(s) != 124) return 0;
|
|
|
87 |
return 1;
|
|
|
88 |
}
|
|
|
89 |
#ifndef STBI_NO_STDIO
|
|
|
90 |
int stbi_dds_test_file (FILE *f)
|
|
|
91 |
{
|
|
|
92 |
stbi s;
|
|
|
93 |
int r,n = ftell(f);
|
|
|
94 |
start_file(&s,f);
|
|
|
95 |
r = dds_test(&s);
|
|
|
96 |
fseek(f,n,SEEK_SET);
|
|
|
97 |
return r;
|
|
|
98 |
}
|
|
|
99 |
#endif
|
|
|
100 |
|
|
|
101 |
int stbi_dds_test_memory (stbi_uc const *buffer, int len)
|
|
|
102 |
{
|
|
|
103 |
stbi s;
|
|
|
104 |
start_mem(&s,buffer, len);
|
|
|
105 |
return dds_test(&s);
|
|
|
106 |
}
|
|
|
107 |
|
|
|
108 |
// helper functions
|
|
|
109 |
int stbi_convert_bit_range( int c, int from_bits, int to_bits )
|
|
|
110 |
{
|
|
|
111 |
int b = (1 << (from_bits - 1)) + c * ((1 << to_bits) - 1);
|
|
|
112 |
return (b + (b >> from_bits)) >> from_bits;
|
|
|
113 |
}
|
|
|
114 |
void stbi_rgb_888_from_565( unsigned int c, int *r, int *g, int *b )
|
|
|
115 |
{
|
|
|
116 |
*r = stbi_convert_bit_range( (c >> 11) & 31, 5, 8 );
|
|
|
117 |
*g = stbi_convert_bit_range( (c >> 05) & 63, 6, 8 );
|
|
|
118 |
*b = stbi_convert_bit_range( (c >> 00) & 31, 5, 8 );
|
|
|
119 |
}
|
|
|
120 |
void stbi_decode_DXT1_block(
|
|
|
121 |
unsigned char uncompressed[16*4],
|
|
|
122 |
unsigned char compressed[8] )
|
|
|
123 |
{
|
|
|
124 |
int next_bit = 4*8;
|
|
|
125 |
int i, r, g, b;
|
|
|
126 |
int c0, c1;
|
|
|
127 |
unsigned char decode_colors[4*4];
|
|
|
128 |
// find the 2 primary colors
|
|
|
129 |
c0 = compressed[0] + (compressed[1] << 8);
|
|
|
130 |
c1 = compressed[2] + (compressed[3] << 8);
|
|
|
131 |
stbi_rgb_888_from_565( c0, &r, &g, &b );
|
|
|
132 |
decode_colors[0] = r;
|
|
|
133 |
decode_colors[1] = g;
|
|
|
134 |
decode_colors[2] = b;
|
|
|
135 |
decode_colors[3] = 255;
|
|
|
136 |
stbi_rgb_888_from_565( c1, &r, &g, &b );
|
|
|
137 |
decode_colors[4] = r;
|
|
|
138 |
decode_colors[5] = g;
|
|
|
139 |
decode_colors[6] = b;
|
|
|
140 |
decode_colors[7] = 255;
|
|
|
141 |
if( c0 > c1 )
|
|
|
142 |
{
|
|
|
143 |
// no alpha, 2 interpolated colors
|
|
|
144 |
decode_colors[8] = (2*decode_colors[0] + decode_colors[4]) / 3;
|
|
|
145 |
decode_colors[9] = (2*decode_colors[1] + decode_colors[5]) / 3;
|
|
|
146 |
decode_colors[10] = (2*decode_colors[2] + decode_colors[6]) / 3;
|
|
|
147 |
decode_colors[11] = 255;
|
|
|
148 |
decode_colors[12] = (decode_colors[0] + 2*decode_colors[4]) / 3;
|
|
|
149 |
decode_colors[13] = (decode_colors[1] + 2*decode_colors[5]) / 3;
|
|
|
150 |
decode_colors[14] = (decode_colors[2] + 2*decode_colors[6]) / 3;
|
|
|
151 |
decode_colors[15] = 255;
|
|
|
152 |
} else
|
|
|
153 |
{
|
|
|
154 |
// 1 interpolated color, alpha
|
|
|
155 |
decode_colors[8] = (decode_colors[0] + decode_colors[4]) / 2;
|
|
|
156 |
decode_colors[9] = (decode_colors[1] + decode_colors[5]) / 2;
|
|
|
157 |
decode_colors[10] = (decode_colors[2] + decode_colors[6]) / 2;
|
|
|
158 |
decode_colors[11] = 255;
|
|
|
159 |
decode_colors[12] = 0;
|
|
|
160 |
decode_colors[13] = 0;
|
|
|
161 |
decode_colors[14] = 0;
|
|
|
162 |
decode_colors[15] = 0;
|
|
|
163 |
}
|
|
|
164 |
// decode the block
|
|
|
165 |
for( i = 0; i < 16*4; i += 4 )
|
|
|
166 |
{
|
|
|
167 |
int idx = ((compressed[next_bit>>3] >> (next_bit & 7)) & 3) * 4;
|
|
|
168 |
next_bit += 2;
|
|
|
169 |
uncompressed[i+0] = decode_colors[idx+0];
|
|
|
170 |
uncompressed[i+1] = decode_colors[idx+1];
|
|
|
171 |
uncompressed[i+2] = decode_colors[idx+2];
|
|
|
172 |
uncompressed[i+3] = decode_colors[idx+3];
|
|
|
173 |
}
|
|
|
174 |
// done
|
|
|
175 |
}
|
|
|
176 |
void stbi_decode_DXT23_alpha_block(
|
|
|
177 |
unsigned char uncompressed[16*4],
|
|
|
178 |
unsigned char compressed[8] )
|
|
|
179 |
{
|
|
|
180 |
int i, next_bit = 0;
|
|
|
181 |
// each alpha value gets 4 bits
|
|
|
182 |
for( i = 3; i < 16*4; i += 4 )
|
|
|
183 |
{
|
|
|
184 |
uncompressed[i] = stbi_convert_bit_range(
|
|
|
185 |
(compressed[next_bit>>3] >> (next_bit&7)) & 15,
|
|
|
186 |
4, 8 );
|
|
|
187 |
next_bit += 4;
|
|
|
188 |
}
|
|
|
189 |
}
|
|
|
190 |
void stbi_decode_DXT45_alpha_block(
|
|
|
191 |
unsigned char uncompressed[16*4],
|
|
|
192 |
unsigned char compressed[8] )
|
|
|
193 |
{
|
|
|
194 |
int i, next_bit = 8*2;
|
|
|
195 |
unsigned char decode_alpha[8];
|
|
|
196 |
// each alpha value gets 3 bits, and the 1st 2 bytes are the range
|
|
|
197 |
decode_alpha[0] = compressed[0];
|
|
|
198 |
decode_alpha[1] = compressed[1];
|
|
|
199 |
if( decode_alpha[0] > decode_alpha[1] )
|
|
|
200 |
{
|
|
|
201 |
// 6 step intermediate
|
|
|
202 |
decode_alpha[2] = (6*decode_alpha[0] + 1*decode_alpha[1]) / 7;
|
|
|
203 |
decode_alpha[3] = (5*decode_alpha[0] + 2*decode_alpha[1]) / 7;
|
|
|
204 |
decode_alpha[4] = (4*decode_alpha[0] + 3*decode_alpha[1]) / 7;
|
|
|
205 |
decode_alpha[5] = (3*decode_alpha[0] + 4*decode_alpha[1]) / 7;
|
|
|
206 |
decode_alpha[6] = (2*decode_alpha[0] + 5*decode_alpha[1]) / 7;
|
|
|
207 |
decode_alpha[7] = (1*decode_alpha[0] + 6*decode_alpha[1]) / 7;
|
|
|
208 |
} else
|
|
|
209 |
{
|
|
|
210 |
// 4 step intermediate, pluss full and none
|
|
|
211 |
decode_alpha[2] = (4*decode_alpha[0] + 1*decode_alpha[1]) / 5;
|
|
|
212 |
decode_alpha[3] = (3*decode_alpha[0] + 2*decode_alpha[1]) / 5;
|
|
|
213 |
decode_alpha[4] = (2*decode_alpha[0] + 3*decode_alpha[1]) / 5;
|
|
|
214 |
decode_alpha[5] = (1*decode_alpha[0] + 4*decode_alpha[1]) / 5;
|
|
|
215 |
decode_alpha[6] = 0;
|
|
|
216 |
decode_alpha[7] = 255;
|
|
|
217 |
}
|
|
|
218 |
for( i = 3; i < 16*4; i += 4 )
|
|
|
219 |
{
|
|
|
220 |
int idx = 0, bit;
|
|
|
221 |
bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1;
|
|
|
222 |
idx += bit << 0;
|
|
|
223 |
++next_bit;
|
|
|
224 |
bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1;
|
|
|
225 |
idx += bit << 1;
|
|
|
226 |
++next_bit;
|
|
|
227 |
bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1;
|
|
|
228 |
idx += bit << 2;
|
|
|
229 |
++next_bit;
|
|
|
230 |
uncompressed[i] = decode_alpha[idx & 7];
|
|
|
231 |
}
|
|
|
232 |
// done
|
|
|
233 |
}
|
|
|
234 |
void stbi_decode_DXT_color_block(
|
|
|
235 |
unsigned char uncompressed[16*4],
|
|
|
236 |
unsigned char compressed[8] )
|
|
|
237 |
{
|
|
|
238 |
int next_bit = 4*8;
|
|
|
239 |
int i, r, g, b;
|
|
|
240 |
int c0, c1;
|
|
|
241 |
unsigned char decode_colors[4*3];
|
|
|
242 |
// find the 2 primary colors
|
|
|
243 |
c0 = compressed[0] + (compressed[1] << 8);
|
|
|
244 |
c1 = compressed[2] + (compressed[3] << 8);
|
|
|
245 |
stbi_rgb_888_from_565( c0, &r, &g, &b );
|
|
|
246 |
decode_colors[0] = r;
|
|
|
247 |
decode_colors[1] = g;
|
|
|
248 |
decode_colors[2] = b;
|
|
|
249 |
stbi_rgb_888_from_565( c1, &r, &g, &b );
|
|
|
250 |
decode_colors[3] = r;
|
|
|
251 |
decode_colors[4] = g;
|
|
|
252 |
decode_colors[5] = b;
|
|
|
253 |
// Like DXT1, but no choicees:
|
|
|
254 |
// no alpha, 2 interpolated colors
|
|
|
255 |
decode_colors[6] = (2*decode_colors[0] + decode_colors[3]) / 3;
|
|
|
256 |
decode_colors[7] = (2*decode_colors[1] + decode_colors[4]) / 3;
|
|
|
257 |
decode_colors[8] = (2*decode_colors[2] + decode_colors[5]) / 3;
|
|
|
258 |
decode_colors[9] = (decode_colors[0] + 2*decode_colors[3]) / 3;
|
|
|
259 |
decode_colors[10] = (decode_colors[1] + 2*decode_colors[4]) / 3;
|
|
|
260 |
decode_colors[11] = (decode_colors[2] + 2*decode_colors[5]) / 3;
|
|
|
261 |
// decode the block
|
|
|
262 |
for( i = 0; i < 16*4; i += 4 )
|
|
|
263 |
{
|
|
|
264 |
int idx = ((compressed[next_bit>>3] >> (next_bit & 7)) & 3) * 3;
|
|
|
265 |
next_bit += 2;
|
|
|
266 |
uncompressed[i+0] = decode_colors[idx+0];
|
|
|
267 |
uncompressed[i+1] = decode_colors[idx+1];
|
|
|
268 |
uncompressed[i+2] = decode_colors[idx+2];
|
|
|
269 |
}
|
|
|
270 |
// done
|
|
|
271 |
}
|
|
|
272 |
static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
|
|
273 |
{
|
|
|
274 |
// all variables go up front
|
|
|
275 |
stbi_uc *dds_data = NULL;
|
|
|
276 |
stbi_uc block[16*4];
|
|
|
277 |
stbi_uc compressed[8];
|
|
|
278 |
int flags, DXT_family;
|
|
|
279 |
int has_alpha, has_mipmap;
|
|
|
280 |
int is_compressed, cubemap_faces;
|
|
|
281 |
int block_pitch, num_blocks;
|
|
|
282 |
DDS_header header;
|
|
|
283 |
int i, sz, cf;
|
|
|
284 |
// load the header
|
|
|
285 |
if( sizeof( DDS_header ) != 128 )
|
|
|
286 |
{
|
|
|
287 |
return NULL;
|
|
|
288 |
}
|
|
|
289 |
getn( s, (stbi_uc*)(&header), 128 );
|
|
|
290 |
// and do some checking
|
|
|
291 |
if( header.dwMagic != (('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24)) ) return NULL;
|
|
|
292 |
if( header.dwSize != 124 ) return NULL;
|
|
|
293 |
flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
|
|
|
294 |
if( (header.dwFlags & flags) != flags ) return NULL;
|
|
|
295 |
/* According to the MSDN spec, the dwFlags should contain
|
|
|
296 |
DDSD_LINEARSIZE if it's compressed, or DDSD_PITCH if
|
|
|
297 |
uncompressed. Some DDS writers do not conform to the
|
|
|
298 |
spec, so I need to make my reader more tolerant */
|
|
|
299 |
if( header.sPixelFormat.dwSize != 32 ) return NULL;
|
|
|
300 |
flags = DDPF_FOURCC | DDPF_RGB;
|
|
|
301 |
if( (header.sPixelFormat.dwFlags & flags) == 0 ) return NULL;
|
|
|
302 |
if( (header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0 ) return NULL;
|
|
|
303 |
// get the image data
|
|
|
304 |
s->img_x = header.dwWidth;
|
|
|
305 |
s->img_y = header.dwHeight;
|
|
|
306 |
s->img_n = 4;
|
|
|
307 |
is_compressed = (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC;
|
|
|
308 |
has_alpha = (header.sPixelFormat.dwFlags & DDPF_ALPHAPIXELS) / DDPF_ALPHAPIXELS;
|
|
|
309 |
has_mipmap = (header.sCaps.dwCaps1 & DDSCAPS_MIPMAP) && (header.dwMipMapCount > 1);
|
|
|
310 |
cubemap_faces = (header.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) / DDSCAPS2_CUBEMAP;
|
|
|
311 |
/* I need cubemaps to have square faces */
|
|
|
312 |
cubemap_faces &= (s->img_x == s->img_y);
|
|
|
313 |
cubemap_faces *= 5;
|
|
|
314 |
cubemap_faces += 1;
|
|
|
315 |
block_pitch = (s->img_x+3) >> 2;
|
|
|
316 |
num_blocks = block_pitch * ((s->img_y+3) >> 2);
|
|
|
317 |
/* let the user know what's going on */
|
|
|
318 |
*x = s->img_x;
|
|
|
319 |
*y = s->img_y;
|
|
|
320 |
*comp = s->img_n;
|
|
|
321 |
/* is this uncompressed? */
|
|
|
322 |
if( is_compressed )
|
|
|
323 |
{
|
|
|
324 |
/* compressed */
|
|
|
325 |
// note: header.sPixelFormat.dwFourCC is something like (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24))
|
|
|
326 |
DXT_family = 1 + (header.sPixelFormat.dwFourCC >> 24) - '1';
|
|
|
327 |
if( (DXT_family < 1) || (DXT_family > 5) ) return NULL;
|
|
|
328 |
/* check the expected size...oops, nevermind...
|
|
|
329 |
those non-compliant writers leave
|
|
|
330 |
dwPitchOrLinearSize == 0 */
|
|
|
331 |
// passed all the tests, get the RAM for decoding
|
|
|
332 |
sz = (s->img_x)*(s->img_y)*4*cubemap_faces;
|
|
|
333 |
dds_data = (unsigned char*)malloc( sz );
|
|
|
334 |
/* do this once for each face */
|
|
|
335 |
for( cf = 0; cf < cubemap_faces; ++ cf )
|
|
|
336 |
{
|
|
|
337 |
// now read and decode all the blocks
|
|
|
338 |
for( i = 0; i < num_blocks; ++i )
|
|
|
339 |
{
|
|
|
340 |
// where are we?
|
|
|
341 |
int bx, by, bw=4, bh=4;
|
|
|
342 |
int ref_x = 4 * (i % block_pitch);
|
|
|
343 |
int ref_y = 4 * (i / block_pitch);
|
|
|
344 |
// get the next block's worth of compressed data, and decompress it
|
|
|
345 |
if( DXT_family == 1 )
|
|
|
346 |
{
|
|
|
347 |
// DXT1
|
|
|
348 |
getn( s, compressed, 8 );
|
|
|
349 |
stbi_decode_DXT1_block( block, compressed );
|
|
|
350 |
} else if( DXT_family < 4 )
|
|
|
351 |
{
|
|
|
352 |
// DXT2/3
|
|
|
353 |
getn( s, compressed, 8 );
|
|
|
354 |
stbi_decode_DXT23_alpha_block ( block, compressed );
|
|
|
355 |
getn( s, compressed, 8 );
|
|
|
356 |
stbi_decode_DXT_color_block ( block, compressed );
|
|
|
357 |
} else
|
|
|
358 |
{
|
|
|
359 |
// DXT4/5
|
|
|
360 |
getn( s, compressed, 8 );
|
|
|
361 |
stbi_decode_DXT45_alpha_block ( block, compressed );
|
|
|
362 |
getn( s, compressed, 8 );
|
|
|
363 |
stbi_decode_DXT_color_block ( block, compressed );
|
|
|
364 |
}
|
|
|
365 |
// is this a partial block?
|
373 |
jrf |
366 |
if( ref_x + 4 > (int)s->img_x )
|
369 |
jab |
367 |
{
|
|
|
368 |
bw = s->img_x - ref_x;
|
|
|
369 |
}
|
373 |
jrf |
370 |
if( ref_y + 4 > (int)s->img_y )
|
369 |
jab |
371 |
{
|
|
|
372 |
bh = s->img_y - ref_y;
|
|
|
373 |
}
|
|
|
374 |
// now drop our decompressed data into the buffer
|
|
|
375 |
for( by = 0; by < bh; ++by )
|
|
|
376 |
{
|
|
|
377 |
int idx = 4*((ref_y+by+cf*s->img_x)*s->img_x + ref_x);
|
|
|
378 |
for( bx = 0; bx < bw*4; ++bx )
|
|
|
379 |
{
|
|
|
380 |
|
|
|
381 |
dds_data[idx+bx] = block[by*16+bx];
|
|
|
382 |
}
|
|
|
383 |
}
|
|
|
384 |
}
|
|
|
385 |
/* done reading and decoding the main image...
|
|
|
386 |
skip MIPmaps if present */
|
|
|
387 |
if( has_mipmap )
|
|
|
388 |
{
|
|
|
389 |
int block_size = 16;
|
|
|
390 |
if( DXT_family == 1 )
|
|
|
391 |
{
|
|
|
392 |
block_size = 8;
|
|
|
393 |
}
|
373 |
jrf |
394 |
for( i = 1; i < (int)header.dwMipMapCount; ++i )
|
369 |
jab |
395 |
{
|
|
|
396 |
int mx = s->img_x >> (i + 2);
|
|
|
397 |
int my = s->img_y >> (i + 2);
|
|
|
398 |
if( mx < 1 )
|
|
|
399 |
{
|
|
|
400 |
mx = 1;
|
|
|
401 |
}
|
|
|
402 |
if( my < 1 )
|
|
|
403 |
{
|
|
|
404 |
my = 1;
|
|
|
405 |
}
|
|
|
406 |
skip( s, mx*my*block_size );
|
|
|
407 |
}
|
|
|
408 |
}
|
|
|
409 |
}/* per cubemap face */
|
|
|
410 |
} else
|
|
|
411 |
{
|
|
|
412 |
/* uncompressed */
|
|
|
413 |
DXT_family = 0;
|
|
|
414 |
s->img_n = 3;
|
|
|
415 |
if( has_alpha )
|
|
|
416 |
{
|
|
|
417 |
s->img_n = 4;
|
|
|
418 |
}
|
|
|
419 |
*comp = s->img_n;
|
|
|
420 |
sz = s->img_x*s->img_y*s->img_n*cubemap_faces;
|
|
|
421 |
dds_data = (unsigned char*)malloc( sz );
|
|
|
422 |
/* do this once for each face */
|
|
|
423 |
for( cf = 0; cf < cubemap_faces; ++ cf )
|
|
|
424 |
{
|
|
|
425 |
/* read the main image for this face */
|
|
|
426 |
getn( s, &dds_data[cf*s->img_x*s->img_y*s->img_n], s->img_x*s->img_y*s->img_n );
|
|
|
427 |
/* done reading and decoding the main image...
|
|
|
428 |
skip MIPmaps if present */
|
|
|
429 |
if( has_mipmap )
|
|
|
430 |
{
|
373 |
jrf |
431 |
for( i = 1; i < (int)header.dwMipMapCount; ++i )
|
369 |
jab |
432 |
{
|
|
|
433 |
int mx = s->img_x >> i;
|
|
|
434 |
int my = s->img_y >> i;
|
|
|
435 |
if( mx < 1 )
|
|
|
436 |
{
|
|
|
437 |
mx = 1;
|
|
|
438 |
}
|
|
|
439 |
if( my < 1 )
|
|
|
440 |
{
|
|
|
441 |
my = 1;
|
|
|
442 |
}
|
|
|
443 |
skip( s, mx*my*s->img_n );
|
|
|
444 |
}
|
|
|
445 |
}
|
|
|
446 |
}
|
|
|
447 |
/* data was BGR, I need it RGB */
|
|
|
448 |
for( i = 0; i < sz; i += s->img_n )
|
|
|
449 |
{
|
|
|
450 |
unsigned char temp = dds_data[i];
|
|
|
451 |
dds_data[i] = dds_data[i+2];
|
|
|
452 |
dds_data[i+2] = temp;
|
|
|
453 |
}
|
|
|
454 |
}
|
|
|
455 |
/* finished decompressing into RGBA,
|
|
|
456 |
adjust the y size if we have a cubemap
|
|
|
457 |
note: sz is already up to date */
|
|
|
458 |
s->img_y *= cubemap_faces;
|
|
|
459 |
*y = s->img_y;
|
|
|
460 |
// did the user want something else, or
|
|
|
461 |
// see if all the alpha values are 255 (i.e. no transparency)
|
|
|
462 |
has_alpha = 0;
|
|
|
463 |
if( s->img_n == 4)
|
|
|
464 |
{
|
|
|
465 |
for( i = 3; (i < sz) && (has_alpha == 0); i += 4 )
|
|
|
466 |
{
|
|
|
467 |
has_alpha |= (dds_data[i] < 255);
|
|
|
468 |
}
|
|
|
469 |
}
|
|
|
470 |
if( (req_comp <= 4) && (req_comp >= 1) )
|
|
|
471 |
{
|
|
|
472 |
// user has some requirements, meet them
|
|
|
473 |
if( req_comp != s->img_n )
|
|
|
474 |
{
|
|
|
475 |
dds_data = convert_format( dds_data, s->img_n, req_comp, s->img_x, s->img_y );
|
|
|
476 |
*comp = s->img_n;
|
|
|
477 |
}
|
|
|
478 |
} else
|
|
|
479 |
{
|
|
|
480 |
// user had no requirements, only drop to RGB is no alpha
|
|
|
481 |
if( (has_alpha == 0) && (s->img_n == 4) )
|
|
|
482 |
{
|
|
|
483 |
dds_data = convert_format( dds_data, 4, 3, s->img_x, s->img_y );
|
|
|
484 |
*comp = 3;
|
|
|
485 |
}
|
|
|
486 |
}
|
|
|
487 |
// OK, done
|
|
|
488 |
return dds_data;
|
|
|
489 |
}
|
|
|
490 |
|
|
|
491 |
#ifndef STBI_NO_STDIO
|
|
|
492 |
stbi_uc *stbi_dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
|
|
|
493 |
{
|
|
|
494 |
stbi s;
|
|
|
495 |
start_file(&s,f);
|
|
|
496 |
return dds_load(&s,x,y,comp,req_comp);
|
|
|
497 |
}
|
|
|
498 |
|
|
|
499 |
stbi_uc *stbi_dds_load (char *filename, int *x, int *y, int *comp, int req_comp)
|
|
|
500 |
{
|
|
|
501 |
stbi_uc *data;
|
|
|
502 |
FILE *f = fopen(filename, "rb");
|
|
|
503 |
if (!f) return NULL;
|
|
|
504 |
data = stbi_dds_load_from_file(f,x,y,comp,req_comp);
|
|
|
505 |
fclose(f);
|
|
|
506 |
return data;
|
|
|
507 |
}
|
|
|
508 |
#endif
|
|
|
509 |
|
|
|
510 |
stbi_uc *stbi_dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
|
|
|
511 |
{
|
|
|
512 |
stbi s;
|
|
|
513 |
start_mem(&s,buffer, len);
|
|
|
514 |
return dds_load(&s,x,y,comp,req_comp);
|
|
|
515 |
}
|