Subversion Repositories gelsvn

Rev

Rev 373 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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