GEL  2
GEL is a library for Geometry and Linear Algebra
/Users/jab/Documents/Teaching/02585/GEL2_and_demos/GEL/src/GLGraphics/stbi_DDS_aug_c.h
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations