GEL
2
GEL is a library for Geometry and Linear Algebra
|
00001 00004 00006 typedef struct { 00007 unsigned int dwMagic; 00008 unsigned int dwSize; 00009 unsigned int dwFlags; 00010 unsigned int dwHeight; 00011 unsigned int dwWidth; 00012 unsigned int dwPitchOrLinearSize; 00013 unsigned int dwDepth; 00014 unsigned int dwMipMapCount; 00015 unsigned int dwReserved1[ 11 ]; 00016 00017 // DDPIXELFORMAT 00018 struct { 00019 unsigned int dwSize; 00020 unsigned int dwFlags; 00021 unsigned int dwFourCC; 00022 unsigned int dwRGBBitCount; 00023 unsigned int dwRBitMask; 00024 unsigned int dwGBitMask; 00025 unsigned int dwBBitMask; 00026 unsigned int dwAlphaBitMask; 00027 } sPixelFormat; 00028 00029 // DDCAPS2 00030 struct { 00031 unsigned int dwCaps1; 00032 unsigned int dwCaps2; 00033 unsigned int dwDDSX; 00034 unsigned int dwReserved; 00035 } sCaps; 00036 unsigned int dwReserved2; 00037 } DDS_header ; 00038 00039 // the following constants were copied directly off the MSDN website 00040 00041 // The dwFlags member of the original DDSURFACEDESC2 structure 00042 // can be set to one or more of the following values. 00043 #define DDSD_CAPS 0x00000001 00044 #define DDSD_HEIGHT 0x00000002 00045 #define DDSD_WIDTH 0x00000004 00046 #define DDSD_PITCH 0x00000008 00047 #define DDSD_PIXELFORMAT 0x00001000 00048 #define DDSD_MIPMAPCOUNT 0x00020000 00049 #define DDSD_LINEARSIZE 0x00080000 00050 #define DDSD_DEPTH 0x00800000 00051 00052 // DirectDraw Pixel Format 00053 #define DDPF_ALPHAPIXELS 0x00000001 00054 #define DDPF_FOURCC 0x00000004 00055 #define DDPF_RGB 0x00000040 00056 00057 // The dwCaps1 member of the DDSCAPS2 structure can be 00058 // set to one or more of the following values. 00059 #define DDSCAPS_COMPLEX 0x00000008 00060 #define DDSCAPS_TEXTURE 0x00001000 00061 #define DDSCAPS_MIPMAP 0x00400000 00062 00063 // The dwCaps2 member of the DDSCAPS2 structure can be 00064 // set to one or more of the following values. 00065 #define DDSCAPS2_CUBEMAP 0x00000200 00066 #define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400 00067 #define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800 00068 #define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000 00069 #define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000 00070 #define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000 00071 #define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000 00072 #define DDSCAPS2_VOLUME 0x00200000 00073 00074 static int dds_test(stbi *s) 00075 { 00076 // check the magic number 00077 if (get8(s) != 'D') return 0; 00078 if (get8(s) != 'D') return 0; 00079 if (get8(s) != 'S') return 0; 00080 if (get8(s) != ' ') return 0; 00081 // check header size 00082 if (get32le(s) != 124) return 0; 00083 return 1; 00084 } 00085 #ifndef STBI_NO_STDIO 00086 int stbi_dds_test_file (FILE *f) 00087 { 00088 stbi s; 00089 int r,n = ftell(f); 00090 start_file(&s,f); 00091 r = dds_test(&s); 00092 fseek(f,n,SEEK_SET); 00093 return r; 00094 } 00095 #endif 00096 00097 int stbi_dds_test_memory (stbi_uc const *buffer, int len) 00098 { 00099 stbi s; 00100 start_mem(&s,buffer, len); 00101 return dds_test(&s); 00102 } 00103 00104 // helper functions 00105 int stbi_convert_bit_range( int c, int from_bits, int to_bits ) 00106 { 00107 int b = (1 << (from_bits - 1)) + c * ((1 << to_bits) - 1); 00108 return (b + (b >> from_bits)) >> from_bits; 00109 } 00110 void stbi_rgb_888_from_565( unsigned int c, int *r, int *g, int *b ) 00111 { 00112 *r = stbi_convert_bit_range( (c >> 11) & 31, 5, 8 ); 00113 *g = stbi_convert_bit_range( (c >> 05) & 63, 6, 8 ); 00114 *b = stbi_convert_bit_range( (c >> 00) & 31, 5, 8 ); 00115 } 00116 void stbi_decode_DXT1_block( 00117 unsigned char uncompressed[16*4], 00118 unsigned char compressed[8] ) 00119 { 00120 int next_bit = 4*8; 00121 int i, r, g, b; 00122 int c0, c1; 00123 unsigned char decode_colors[4*4]; 00124 // find the 2 primary colors 00125 c0 = compressed[0] + (compressed[1] << 8); 00126 c1 = compressed[2] + (compressed[3] << 8); 00127 stbi_rgb_888_from_565( c0, &r, &g, &b ); 00128 decode_colors[0] = r; 00129 decode_colors[1] = g; 00130 decode_colors[2] = b; 00131 decode_colors[3] = 255; 00132 stbi_rgb_888_from_565( c1, &r, &g, &b ); 00133 decode_colors[4] = r; 00134 decode_colors[5] = g; 00135 decode_colors[6] = b; 00136 decode_colors[7] = 255; 00137 if( c0 > c1 ) 00138 { 00139 // no alpha, 2 interpolated colors 00140 decode_colors[8] = (2*decode_colors[0] + decode_colors[4]) / 3; 00141 decode_colors[9] = (2*decode_colors[1] + decode_colors[5]) / 3; 00142 decode_colors[10] = (2*decode_colors[2] + decode_colors[6]) / 3; 00143 decode_colors[11] = 255; 00144 decode_colors[12] = (decode_colors[0] + 2*decode_colors[4]) / 3; 00145 decode_colors[13] = (decode_colors[1] + 2*decode_colors[5]) / 3; 00146 decode_colors[14] = (decode_colors[2] + 2*decode_colors[6]) / 3; 00147 decode_colors[15] = 255; 00148 } else 00149 { 00150 // 1 interpolated color, alpha 00151 decode_colors[8] = (decode_colors[0] + decode_colors[4]) / 2; 00152 decode_colors[9] = (decode_colors[1] + decode_colors[5]) / 2; 00153 decode_colors[10] = (decode_colors[2] + decode_colors[6]) / 2; 00154 decode_colors[11] = 255; 00155 decode_colors[12] = 0; 00156 decode_colors[13] = 0; 00157 decode_colors[14] = 0; 00158 decode_colors[15] = 0; 00159 } 00160 // decode the block 00161 for( i = 0; i < 16*4; i += 4 ) 00162 { 00163 int idx = ((compressed[next_bit>>3] >> (next_bit & 7)) & 3) * 4; 00164 next_bit += 2; 00165 uncompressed[i+0] = decode_colors[idx+0]; 00166 uncompressed[i+1] = decode_colors[idx+1]; 00167 uncompressed[i+2] = decode_colors[idx+2]; 00168 uncompressed[i+3] = decode_colors[idx+3]; 00169 } 00170 // done 00171 } 00172 void stbi_decode_DXT23_alpha_block( 00173 unsigned char uncompressed[16*4], 00174 unsigned char compressed[8] ) 00175 { 00176 int i, next_bit = 0; 00177 // each alpha value gets 4 bits 00178 for( i = 3; i < 16*4; i += 4 ) 00179 { 00180 uncompressed[i] = stbi_convert_bit_range( 00181 (compressed[next_bit>>3] >> (next_bit&7)) & 15, 00182 4, 8 ); 00183 next_bit += 4; 00184 } 00185 } 00186 void stbi_decode_DXT45_alpha_block( 00187 unsigned char uncompressed[16*4], 00188 unsigned char compressed[8] ) 00189 { 00190 int i, next_bit = 8*2; 00191 unsigned char decode_alpha[8]; 00192 // each alpha value gets 3 bits, and the 1st 2 bytes are the range 00193 decode_alpha[0] = compressed[0]; 00194 decode_alpha[1] = compressed[1]; 00195 if( decode_alpha[0] > decode_alpha[1] ) 00196 { 00197 // 6 step intermediate 00198 decode_alpha[2] = (6*decode_alpha[0] + 1*decode_alpha[1]) / 7; 00199 decode_alpha[3] = (5*decode_alpha[0] + 2*decode_alpha[1]) / 7; 00200 decode_alpha[4] = (4*decode_alpha[0] + 3*decode_alpha[1]) / 7; 00201 decode_alpha[5] = (3*decode_alpha[0] + 4*decode_alpha[1]) / 7; 00202 decode_alpha[6] = (2*decode_alpha[0] + 5*decode_alpha[1]) / 7; 00203 decode_alpha[7] = (1*decode_alpha[0] + 6*decode_alpha[1]) / 7; 00204 } else 00205 { 00206 // 4 step intermediate, pluss full and none 00207 decode_alpha[2] = (4*decode_alpha[0] + 1*decode_alpha[1]) / 5; 00208 decode_alpha[3] = (3*decode_alpha[0] + 2*decode_alpha[1]) / 5; 00209 decode_alpha[4] = (2*decode_alpha[0] + 3*decode_alpha[1]) / 5; 00210 decode_alpha[5] = (1*decode_alpha[0] + 4*decode_alpha[1]) / 5; 00211 decode_alpha[6] = 0; 00212 decode_alpha[7] = 255; 00213 } 00214 for( i = 3; i < 16*4; i += 4 ) 00215 { 00216 int idx = 0, bit; 00217 bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1; 00218 idx += bit << 0; 00219 ++next_bit; 00220 bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1; 00221 idx += bit << 1; 00222 ++next_bit; 00223 bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1; 00224 idx += bit << 2; 00225 ++next_bit; 00226 uncompressed[i] = decode_alpha[idx & 7]; 00227 } 00228 // done 00229 } 00230 void stbi_decode_DXT_color_block( 00231 unsigned char uncompressed[16*4], 00232 unsigned char compressed[8] ) 00233 { 00234 int next_bit = 4*8; 00235 int i, r, g, b; 00236 int c0, c1; 00237 unsigned char decode_colors[4*3]; 00238 // find the 2 primary colors 00239 c0 = compressed[0] + (compressed[1] << 8); 00240 c1 = compressed[2] + (compressed[3] << 8); 00241 stbi_rgb_888_from_565( c0, &r, &g, &b ); 00242 decode_colors[0] = r; 00243 decode_colors[1] = g; 00244 decode_colors[2] = b; 00245 stbi_rgb_888_from_565( c1, &r, &g, &b ); 00246 decode_colors[3] = r; 00247 decode_colors[4] = g; 00248 decode_colors[5] = b; 00249 // Like DXT1, but no choicees: 00250 // no alpha, 2 interpolated colors 00251 decode_colors[6] = (2*decode_colors[0] + decode_colors[3]) / 3; 00252 decode_colors[7] = (2*decode_colors[1] + decode_colors[4]) / 3; 00253 decode_colors[8] = (2*decode_colors[2] + decode_colors[5]) / 3; 00254 decode_colors[9] = (decode_colors[0] + 2*decode_colors[3]) / 3; 00255 decode_colors[10] = (decode_colors[1] + 2*decode_colors[4]) / 3; 00256 decode_colors[11] = (decode_colors[2] + 2*decode_colors[5]) / 3; 00257 // decode the block 00258 for( i = 0; i < 16*4; i += 4 ) 00259 { 00260 int idx = ((compressed[next_bit>>3] >> (next_bit & 7)) & 3) * 3; 00261 next_bit += 2; 00262 uncompressed[i+0] = decode_colors[idx+0]; 00263 uncompressed[i+1] = decode_colors[idx+1]; 00264 uncompressed[i+2] = decode_colors[idx+2]; 00265 } 00266 // done 00267 } 00268 static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp) 00269 { 00270 // all variables go up front 00271 stbi_uc *dds_data = NULL; 00272 stbi_uc block[16*4]; 00273 stbi_uc compressed[8]; 00274 int flags, DXT_family; 00275 int has_alpha, has_mipmap; 00276 int is_compressed, cubemap_faces; 00277 int block_pitch, num_blocks; 00278 DDS_header header; 00279 int i, sz, cf; 00280 // load the header 00281 if( sizeof( DDS_header ) != 128 ) 00282 { 00283 return NULL; 00284 } 00285 getn( s, (stbi_uc*)(&header), 128 ); 00286 // and do some checking 00287 if( header.dwMagic != (('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24)) ) return NULL; 00288 if( header.dwSize != 124 ) return NULL; 00289 flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; 00290 if( (header.dwFlags & flags) != flags ) return NULL; 00291 /* According to the MSDN spec, the dwFlags should contain 00292 DDSD_LINEARSIZE if it's compressed, or DDSD_PITCH if 00293 uncompressed. Some DDS writers do not conform to the 00294 spec, so I need to make my reader more tolerant */ 00295 if( header.sPixelFormat.dwSize != 32 ) return NULL; 00296 flags = DDPF_FOURCC | DDPF_RGB; 00297 if( (header.sPixelFormat.dwFlags & flags) == 0 ) return NULL; 00298 if( (header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0 ) return NULL; 00299 // get the image data 00300 s->img_x = header.dwWidth; 00301 s->img_y = header.dwHeight; 00302 s->img_n = 4; 00303 is_compressed = (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC; 00304 has_alpha = (header.sPixelFormat.dwFlags & DDPF_ALPHAPIXELS) / DDPF_ALPHAPIXELS; 00305 has_mipmap = (header.sCaps.dwCaps1 & DDSCAPS_MIPMAP) && (header.dwMipMapCount > 1); 00306 cubemap_faces = (header.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) / DDSCAPS2_CUBEMAP; 00307 /* I need cubemaps to have square faces */ 00308 cubemap_faces &= (s->img_x == s->img_y); 00309 cubemap_faces *= 5; 00310 cubemap_faces += 1; 00311 block_pitch = (s->img_x+3) >> 2; 00312 num_blocks = block_pitch * ((s->img_y+3) >> 2); 00313 /* let the user know what's going on */ 00314 *x = s->img_x; 00315 *y = s->img_y; 00316 *comp = s->img_n; 00317 /* is this uncompressed? */ 00318 if( is_compressed ) 00319 { 00320 /* compressed */ 00321 // note: header.sPixelFormat.dwFourCC is something like (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24)) 00322 DXT_family = 1 + (header.sPixelFormat.dwFourCC >> 24) - '1'; 00323 if( (DXT_family < 1) || (DXT_family > 5) ) return NULL; 00324 /* check the expected size...oops, nevermind... 00325 those non-compliant writers leave 00326 dwPitchOrLinearSize == 0 */ 00327 // passed all the tests, get the RAM for decoding 00328 sz = (s->img_x)*(s->img_y)*4*cubemap_faces; 00329 dds_data = (unsigned char*)malloc( sz ); 00330 /* do this once for each face */ 00331 for( cf = 0; cf < cubemap_faces; ++ cf ) 00332 { 00333 // now read and decode all the blocks 00334 for( i = 0; i < num_blocks; ++i ) 00335 { 00336 // where are we? 00337 int bx, by, bw=4, bh=4; 00338 int ref_x = 4 * (i % block_pitch); 00339 int ref_y = 4 * (i / block_pitch); 00340 // get the next block's worth of compressed data, and decompress it 00341 if( DXT_family == 1 ) 00342 { 00343 // DXT1 00344 getn( s, compressed, 8 ); 00345 stbi_decode_DXT1_block( block, compressed ); 00346 } else if( DXT_family < 4 ) 00347 { 00348 // DXT2/3 00349 getn( s, compressed, 8 ); 00350 stbi_decode_DXT23_alpha_block ( block, compressed ); 00351 getn( s, compressed, 8 ); 00352 stbi_decode_DXT_color_block ( block, compressed ); 00353 } else 00354 { 00355 // DXT4/5 00356 getn( s, compressed, 8 ); 00357 stbi_decode_DXT45_alpha_block ( block, compressed ); 00358 getn( s, compressed, 8 ); 00359 stbi_decode_DXT_color_block ( block, compressed ); 00360 } 00361 // is this a partial block? 00362 if( ref_x + 4 > (int)s->img_x ) 00363 { 00364 bw = s->img_x - ref_x; 00365 } 00366 if( ref_y + 4 > (int)s->img_y ) 00367 { 00368 bh = s->img_y - ref_y; 00369 } 00370 // now drop our decompressed data into the buffer 00371 for( by = 0; by < bh; ++by ) 00372 { 00373 int idx = 4*((ref_y+by+cf*s->img_x)*s->img_x + ref_x); 00374 for( bx = 0; bx < bw*4; ++bx ) 00375 { 00376 00377 dds_data[idx+bx] = block[by*16+bx]; 00378 } 00379 } 00380 } 00381 /* done reading and decoding the main image... 00382 skip MIPmaps if present */ 00383 if( has_mipmap ) 00384 { 00385 int block_size = 16; 00386 if( DXT_family == 1 ) 00387 { 00388 block_size = 8; 00389 } 00390 for( i = 1; i < (int)header.dwMipMapCount; ++i ) 00391 { 00392 int mx = s->img_x >> (i + 2); 00393 int my = s->img_y >> (i + 2); 00394 if( mx < 1 ) 00395 { 00396 mx = 1; 00397 } 00398 if( my < 1 ) 00399 { 00400 my = 1; 00401 } 00402 skip( s, mx*my*block_size ); 00403 } 00404 } 00405 }/* per cubemap face */ 00406 } else 00407 { 00408 /* uncompressed */ 00409 DXT_family = 0; 00410 s->img_n = 3; 00411 if( has_alpha ) 00412 { 00413 s->img_n = 4; 00414 } 00415 *comp = s->img_n; 00416 sz = s->img_x*s->img_y*s->img_n*cubemap_faces; 00417 dds_data = (unsigned char*)malloc( sz ); 00418 /* do this once for each face */ 00419 for( cf = 0; cf < cubemap_faces; ++ cf ) 00420 { 00421 /* read the main image for this face */ 00422 getn( s, &dds_data[cf*s->img_x*s->img_y*s->img_n], s->img_x*s->img_y*s->img_n ); 00423 /* done reading and decoding the main image... 00424 skip MIPmaps if present */ 00425 if( has_mipmap ) 00426 { 00427 for( i = 1; i < (int)header.dwMipMapCount; ++i ) 00428 { 00429 int mx = s->img_x >> i; 00430 int my = s->img_y >> i; 00431 if( mx < 1 ) 00432 { 00433 mx = 1; 00434 } 00435 if( my < 1 ) 00436 { 00437 my = 1; 00438 } 00439 skip( s, mx*my*s->img_n ); 00440 } 00441 } 00442 } 00443 /* data was BGR, I need it RGB */ 00444 for( i = 0; i < sz; i += s->img_n ) 00445 { 00446 unsigned char temp = dds_data[i]; 00447 dds_data[i] = dds_data[i+2]; 00448 dds_data[i+2] = temp; 00449 } 00450 } 00451 /* finished decompressing into RGBA, 00452 adjust the y size if we have a cubemap 00453 note: sz is already up to date */ 00454 s->img_y *= cubemap_faces; 00455 *y = s->img_y; 00456 // did the user want something else, or 00457 // see if all the alpha values are 255 (i.e. no transparency) 00458 has_alpha = 0; 00459 if( s->img_n == 4) 00460 { 00461 for( i = 3; (i < sz) && (has_alpha == 0); i += 4 ) 00462 { 00463 has_alpha |= (dds_data[i] < 255); 00464 } 00465 } 00466 if( (req_comp <= 4) && (req_comp >= 1) ) 00467 { 00468 // user has some requirements, meet them 00469 if( req_comp != s->img_n ) 00470 { 00471 dds_data = convert_format( dds_data, s->img_n, req_comp, s->img_x, s->img_y ); 00472 *comp = s->img_n; 00473 } 00474 } else 00475 { 00476 // user had no requirements, only drop to RGB is no alpha 00477 if( (has_alpha == 0) && (s->img_n == 4) ) 00478 { 00479 dds_data = convert_format( dds_data, 4, 3, s->img_x, s->img_y ); 00480 *comp = 3; 00481 } 00482 } 00483 // OK, done 00484 return dds_data; 00485 } 00486 00487 #ifndef STBI_NO_STDIO 00488 stbi_uc *stbi_dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) 00489 { 00490 stbi s; 00491 start_file(&s,f); 00492 return dds_load(&s,x,y,comp,req_comp); 00493 } 00494 00495 stbi_uc *stbi_dds_load (char *filename, int *x, int *y, int *comp, int req_comp) 00496 { 00497 stbi_uc *data; 00498 FILE *f = fopen(filename, "rb"); 00499 if (!f) return NULL; 00500 data = stbi_dds_load_from_file(f,x,y,comp,req_comp); 00501 fclose(f); 00502 return data; 00503 } 00504 #endif 00505 00506 stbi_uc *stbi_dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) 00507 { 00508 stbi s; 00509 start_mem(&s,buffer, len); 00510 return dds_load(&s,x,y,comp,req_comp); 00511 }