Skip to content

Instantly share code, notes, and snippets.

@gyakoo
Last active August 31, 2015 14:23
Show Gist options
  • Save gyakoo/acda1b149137e1888506 to your computer and use it in GitHub Desktop.
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
/*
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