Last active
August 31, 2015 14:23
-
-
Save gyakoo/acda1b149137e1888506 to your computer and use it in GitHub Desktop.
Inspects header of the image file and returns the width, height, depth and size in bytes Suppoted formats: dds, sgi rgb, jpg, png, tga, bmp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Inspects header of the image file and returns the width, height, depth and size in bytes | |
Suppoted formats: dds, sgi rgb, jpg, png, tga, bmp | |
You have to provide the implementation for: | |
* _swap16/32: Is a byte order swap for little endian platforms, because most of the formats are in network order (big endian). | |
* ExtensionIs: Returns true if the filename has the passed extension | |
Note: For the DDS format, if the depth is negative, then it specifies the compression format. -1 for DXT1, -2 for DXT2 and so on. | |
Note: ImgAttr might be removed and passing width/height/depth/size as out parameters of the function. | |
*/ | |
struct ImgAttr | |
{ | |
int width; | |
int height; | |
int depth; | |
int size; | |
}; | |
// (Hamming weight) returns number of bits that are set in an 32 bits int | |
int32_t CountBits(int32_t i); | |
// Inspects header of the image file and returns the width, height, depth and size in bytes | |
bool ReadImageAttr(const char* filename, ImgAttr* attr) | |
{ | |
attr->width=attr->height=0; | |
attr->depth=attr->size=0; | |
char c; | |
unsigned short u16; | |
FILE* f = fopen(filename,"rb"); | |
if ( !f ) return false; | |
if ( ExtensionIs(filename,".rgb") || ExtensionIs(filename,".rgba") || ExtensionIs(filename,".sgi") ) | |
{ | |
fseek(f,6,SEEK_SET); | |
fread(&u16, 1, 2, f); _swap16(&u16); attr->width=u16; | |
fread(&u16, 1, 2, f); _swap16(&u16); attr->height=u16; | |
fread(&u16, 1, 2, f); _swap16(&u16); attr->depth=u16<<3; | |
} | |
else if ( ExtensionIs(filename, ".dds") ) | |
{ | |
fseek(f,12,SEEK_SET); | |
fread(&attr->height, 1, 4, f); | |
fread(&attr->width, 1, 4, f); | |
fseek(f,12+44+4,SEEK_CUR); | |
unsigned int flags, fourcc, rgbbc, masks[4]; | |
fread(&flags,1,4,f); | |
fread(&fourcc,1,4,f); | |
fread(&rgbbc,1,4,f); | |
fread(masks,4,4,f); | |
if (flags & 0x4 ) | |
{ | |
const char* fcc=(const char*)&fourcc; | |
attr->depth = -(fcc[3]-'1'+1); | |
} | |
else if ( (flags & 0x1) || (flags & 0x40) ) | |
{ | |
unsigned int allm=masks[0]|masks[1]|masks[2]|masks[3]; | |
attr->depth = CountBits(allm); | |
} | |
} | |
else if ( ExtensionIs(filename, ".jpeg") || ExtensionIs(filename,".jpg") ) | |
{ | |
unsigned char tmp[2048]; | |
int r = fread(tmp,1,2048,f); | |
int i = 0; | |
while ((i++)<r) | |
{ | |
if ( tmp[i]!=0xff ) continue; | |
++i; if ( i>=r ) break; | |
switch(tmp[i]) | |
{ | |
case 0xc0: | |
case 0xc1: | |
case 0xc2: | |
i+=4; if ( i>=r ) break; | |
u16 = *(unsigned short*)(tmp+i);_swap16(&u16); attr->width=u16;i+=2; | |
u16= *(unsigned short*)(tmp+i);_swap16(&u16); attr->height=u16;i+=2; | |
attr->depth= ( *(unsigned char*)(tmp+i) ) << 3; | |
i=r; | |
break; | |
} | |
} | |
} | |
else if (ExtensionIs(filename, ".png") ) | |
{ | |
fseek(f, 16, SEEK_SET); | |
fread(&attr->width, 1, 4, f); _swap32(&attr->width); | |
fread(&attr->height, 1, 4, f); _swap32(&attr->height); | |
fread(&c,1,1,f); attr->depth = c<<3; | |
} | |
else if (ExtensionIs(filename, ".tga")) | |
{ | |
fseek(f,12,SEEK_SET); | |
fread(&u16, 1, 2, f); attr->width=u16; | |
fread(&u16, 1, 2, f); attr->height=u16; | |
fread(&c,1,1,f); attr->depth = c; | |
} | |
else if (ExtensionIs(filename,".bmp")) | |
{ | |
fseek(f,14,SEEK_SET); | |
fread(&u16, 1, 2, f); attr->width=u16; | |
fread(&u16, 1, 2, f); attr->height=u16; | |
fseek(f,2,SEEK_CUR); | |
fread(&u16, 1, 2, f); attr->depth=u16; | |
} | |
fseek(f,0,SEEK_END); | |
attr->size = ftell(f); | |
fclose(f); | |
return true; | |
} | |
// Hamming weight | |
int32_t CountBits(int32_t i) | |
{ | |
i = i - ((i >> 1) & 0x55555555); | |
i = (i & 0x33333333) + ((i >> 2) & 0x33333333); | |
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment