Skip to content

Instantly share code, notes, and snippets.

@sebbu2
Created June 19, 2012 19:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebbu2/2955990 to your computer and use it in GitHub Desktop.
Save sebbu2/2955990 to your computer and use it in GitHub Desktop.
Fast Image Size Reader
#include <vector>
#include <cerrno>
#include <climits>
#include "fast_image_size_reader.hpp"
#include "crc32.hpp"
enum file_type get_file_type(const char* filename) {
assert(strcmp(filename,"")!=0);
enum file_type res=UNKNOWN;
FILE* fp=fopen(filename, "rb");
if (fp==NULL) {
return UNKNOWN;
}
//uint8_t f2[2];
uint8_t f8[9];
//int res=fread(f2, 2, 1, fp);
size_t result=fread(f8, 8, 1, fp);
//fprintf(stderr, "%02X %02X\n", f2[0], f2[1]);
//fprintf(stderr, "%02X %02X %02X %02X %02X %02X %02X %02X\n", f8[0], f8[1], f8[2], f8[3], f8[4], f8[5], f8[6], f8[7]);
assert(result==1);
uint8_t f26[27];//new TGA only
result=fread(f26, 26, 1, fp);
assert(result==1);
size_t len=strlen(filename);
if (strncmp((char*)f8, "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8)==0) { //PNG
//printf("File = '%s' Type = PNG\n", filename);
res=PNG;
}
else if (strncmp((char*)f8, "\xFF\xD8\xFF\xE0", 4)==0) { //JPG
//printf("File = '%s' Type = JPG\n", filename);
res=JPG;
}
else if (strncmp((char*)f8, "BM", 2)==0) { //BMP
//printf("File = '%s' Type = BMP\n", filename);
res=BMP;
}
else if (strncmp((char*)f8, "GIF", 3)==0) { //GIF
assert(strncmp((char*)f8+3,"87a", 3)==0 || strncmp((char*)f8+3,"89a", 3)==0); //can be either of the 2 version
//printf("File = '%s' Type = GIF\n", filename);
res=GIF;
}
else if (memcmp((char*)f8, "II\x2A\0", 4)==0) { //TIF
//printf("File = '%s' Type = TIF\n", filename);
res=TIF;
}
else if (memcmp((char*)f8, "MM\0\x2A", 4)==0) { //TIF
//printf("File = '%s' Type = TIF\n", filename);
res=TIF;
//printf("Type = UNKNOWN\n");
//res=UNKNOWN;
}
//VDA,ICB,TGA,VST
else if (memcmp((char*)f26+8, "TRUEVISION-XFILE.\0", 18)==0) { //new TGA
//printf("File = '%s' Type = TGA\n", filename);
res=TGA;
}
else if (f8[2]=='\x00' || f8[2]=='\x01' || f8[2]=='\x02' || f8[2]=='\x03' || f8[2]=='\x09' || f8[2]=='\x0A' || f8[2]=='\x0B' || f8[2]=='\x20' || f8[2]=='\x21') {
//not enough to be sure, extension check
if (strncmp(filename+len-4, ".tga", 4)==0 || strncmp(filename+len-4, ".vda", 4)==0 || strncmp(filename+len-4, ".icb", 4)==0 || strncmp(filename+len-4, ".vst", 4)==0 || strncmp(filename+len-5, ".tpic", 5)==0) {
//printf("File = '%s' Type = TGA OLD\n", filename);
res=TGA_OLD;
}
else {
printf("File = '%s' Type = UNKNOWN\n", filename);
}
}
//fprintf(stderr, "[DEBUG] filename+len-4 = %s\n", filename+len-4);
fclose(fp);
return res;
}
uint64_t get_file_dim(const char* filename) {
assert(strcmp(filename,"")!=0);
//uint64_t res=0;
enum file_type ft=get_file_type(filename);
return get_file_dim2(filename, ft);
//return res;//depreciated in my case
}
uint64_t get_file_dim2(const char* filename, enum file_type ft) {
uint64_t res=0;
FILE* fp=NULL;
switch (ft) { //print the file type
case PNG:
fp=fopen(filename, "rb");
if (fp==NULL) {
return res;
}
fseek(fp, 8, SEEK_SET);//header already checked by get_file_type
res=get_file_dim_png(fp);
fclose(fp);
break;
case JPG:
fp=fopen(filename, "rb");
if (fp==NULL) {
return res;
}
fseek(fp, 4, SEEK_SET);//header already checked by get_file_type
res=get_file_dim_jpg(fp);
fclose(fp);
break;
case BMP:
fp=fopen(filename, "rb");
if (fp==NULL) {
return res;
}
fseek(fp, 2, SEEK_SET);//header already checked by get_file_type
res=get_file_dim_bmp(fp);
fclose(fp);
break;
case GIF:
fp=fopen(filename, "rb");
if (fp==NULL) {
return res;
}
fseek(fp, 6, SEEK_SET);//header already checked by get_file_type
res=get_file_dim_gif(fp);
fclose(fp);
break;
case TIF:
fp=fopen(filename, "rb");
if (fp==NULL) {
return res;
}
fseek(fp, 4, SEEK_SET);//header already checked by get_file_type
res=get_file_dim_tif(fp);
fclose(fp);
break;
case TGA:
fp=fopen(filename, "rb");
if (fp==NULL) {
return res;
}
//ext start
fseek(fp, -26, SEEK_END);//extension area offset + developer directory offset//8 bytes only, rest is signature (already treated)
res=get_file_dim_tga(fp);
//ext end
//old start
//res=get_file_dim_tga_old(fp);//read new as well
//old end
fclose(fp);
break;
case TGA_OLD:
fp=fopen(filename, "rb");
if (fp==NULL) {
return res;
}
//seek to 0 == N/A
res=get_file_dim_tga_old(fp);//read new as well
fclose(fp);
break;
case UNKNOWN:
printf("UNKNOWN\n");
break;
default:
printf("UNKNOWN and untreated : %d\n", get_file_type(filename)); //second call
break;
}
return res;
}
typedef unsigned char uchar;
uint64_t get_file_dim_png(FILE* fp) {
uchar chunk_size[5];
size_t read=fread(chunk_size, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int chunk_s= ((unsigned)chunk_size[0]<<24) | ((unsigned)chunk_size[1]<<16) | ((unsigned)chunk_size[2]<<8) | chunk_size[3];
assert(chunk_s == 13); //first chunk should be IHDR, which is 13 bytes long
//read chunk type
uchar chunk_type[5];
read=fread(chunk_type, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
assert(strncmp((char*)chunk_type, "IHDR", 4)==0); //is IHDR
//read data part 1 (width)
uchar width_s[5];
read=fread(width_s, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int width=((unsigned)width_s[0]<<24)|((unsigned)width_s[1]<<16)|((unsigned)width_s[2]<<8)|width_s[3];
//read data part 2 (height)
uchar height_s[5];
read=fread(height_s, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int height=((unsigned)height_s[0]<<24)|((unsigned)height_s[1]<<16)|((unsigned)height_s[2]<<8)|height_s[3];
//read data part 3 (bit depth, colour type, compression method, filter method, interlace method
uchar data_p3[6];
read=fread(data_p3, 5, 1, fp);
assert(read==1); //read 1 * 5 bytes
uchar bit_depth=data_p3[0];
uchar colour_type=data_p3[1];
assert(
(colour_type==0 && (bit_depth==1||bit_depth==2||bit_depth==4||bit_depth==8||bit_depth==16)) ||
(colour_type==2 && (bit_depth==8||bit_depth==16)) ||
(colour_type==3 && (bit_depth==1||bit_depth==2||bit_depth==4||bit_depth==8)) ||
(colour_type==4 && (bit_depth==8||bit_depth==16)) ||
(colour_type==6 && (bit_depth==8||bit_depth==16))
);//allowed combinaison
uchar compression_method=data_p3[2];
assert(compression_method==0); //deflate/inflate compression with a sliding window of at most 32768 bytes
uchar filter_method=data_p3[3];
assert(filter_method==0); //adaptive filtering with five basic filter types
uchar interlace_method=data_p3[4];
assert(interlace_method==0 || interlace_method==1); //no interlace || Adam7 interlace
//read CRC
uchar crc_s[5];
read=fread(crc_s, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int crc_f=(unsigned)crc_s[0]<<24|(unsigned)crc_s[1]<<16|(unsigned)crc_s[2]<<8|(unsigned)crc_s[3];
//printf("crc_f = %X\n", crc_f);
//calculate CRC
unsigned long crc2=update_crc(0xffffffffL, chunk_type, 4);
crc2=update_crc(crc2, width_s, 4);
crc2=update_crc(crc2, height_s, 4);
crc2=update_crc(crc2, data_p3, 5);
crc2^=0xffffffffL;
//printf("crc2 = %lX\n", crc2);
assert(crc_f==crc2); //should be egal
return (uint64_t)(((uint64_t)width<<32)|(uint64_t)height);
}
#define M_SOF0 0xC0 /* Start Of Frame N */
#define M_SOF1 0xC1 /* N indicates which compression process */
#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
#define M_SOF3 0xC3
#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
#define M_SOF6 0xC6
#define M_SOF7 0xC7
#define M_SOF9 0xC9
#define M_SOF10 0xCA
#define M_SOF11 0xCB
#define M_SOF13 0xCD
#define M_SOF14 0xCE
#define M_SOF15 0xCF
#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
#define M_EOI 0xD9 /* End Of Image (end of datastream) */
#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
#define M_APP0 0xE0 /* Application-specific marker, type N */
#define M_APP1 0xE1
#define M_APP2 0xE2
#define M_APP3 0xE3
#define M_APP4 0xE4
#define M_APP5 0xE5
#define M_APP6 0xE6
#define M_APP7 0xE7
#define M_APP8 0xE8
#define M_APP9 0xE9
#define M_APP10 0xEA
#define M_APP11 0xEB
#define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */
#define M_COM 0xFE /* COMment */
uint64_t get_file_dim_jpg(FILE* fp) {
uchar app0_ls[2];
size_t read=fread(app0_ls, 2, 1, fp);
assert(read == 1);
short app0_l=(short)((short)app0_ls[0]<<8|(short)app0_ls[1]);
//later assert
uchar ident_s[6];
read=fread(ident_s, 5, 1, fp);
assert(read==1);
assert(strncmp((char*)ident_s, "JFIF\0", 5)==0);
uchar rev_s[3];
read=fread(rev_s, 2, 1, fp);
assert(read==1);
uchar unit=(unsigned char)'\xFF';
read=fread(&unit, 1, 1, fp);
assert(read==1);
uchar xdens_s[3];
read=fread(xdens_s, 2, 1, fp);
assert(read==1);
uchar ydens_s[3];
read=fread(ydens_s, 2, 1, fp);
assert(read==1);
uchar xth='\x00';
read=fread(&xth, 1, 1, fp);
assert(read==1);
uchar yth='\x00';
read=fread(&yth, 1, 1, fp);
assert(read==1);
//app0 assert
assert(app0_l == (16+3*xth*yth));
//finished reading header
unsigned int marker=0;
unsigned int length=0;
int data_precision=-1;
unsigned int image_height=0;
unsigned int image_width=0;
int num_components=-1;
int loop=1;
//for(;;) {//infinite loop with breaks
while (loop==1) {
uchar tmp[3];
read=fread(tmp, 2, 1, fp);
assert(read==1);
assert((uchar)tmp[0] == 0xFF);
marker=tmp[1];
switch (marker) {
case M_EOI:
case M_SOI:
case M_SOS:
loop=0;
break;
case M_SOF0: /* Baseline */
case M_SOF1: /* Extended sequential, Huffman */
case M_SOF2: /* Progressive, Huffman */
case M_SOF3: /* Lossless, Huffman */
case M_SOF5: /* Differential sequential, Huffman */
case M_SOF6: /* Differential progressive, Huffman */
case M_SOF7: /* Differential lossless, Huffman */
case M_SOF9: /* Extended sequential, arithmetic */
case M_SOF10: /* Progressive, arithmetic */
case M_SOF11: /* Lossless, arithmetic */
case M_SOF13: /* Differential sequential, arithmetic */
case M_SOF14: /* Differential progressive, arithmetic */
case M_SOF15: /* Differential lossless, arithmetic */
//do_process_SOFn(fp, marker);
read=fread(tmp, 2, 1, fp);
assert(read==1);
//printf("length: %02X%02X\n", tmp[0], tmp[1]);
length=(unsigned)tmp[0]<<8|tmp[1];
//length = read_2_bytes(); /* usual parameter length count */
read=fread(tmp, 1, 1, fp);
assert(read==1);
//printf("data_precision: %02X\n", tmp[0]);
data_precision=tmp[0];
//data_precision = read_1_byte();
assert(data_precision>=0);
read=fread(tmp, 2, 1, fp);
assert(read==1);
//printf("image_height: %02X%02X\n", tmp[0], tmp[1]);
image_height = (unsigned)tmp[0]<<8|tmp[1];
//image_height = read_2_bytes();
read=fread(tmp, 2, 1, fp);
assert(read==1);
//printf("image_width: %02X%02X\n", tmp[0], tmp[1]);
image_width = (unsigned)tmp[0]<<8|tmp[1];
//image_width = read_2_bytes();
read=fread(tmp, 1, 1, fp);
assert(read==1);
//printf("num_components: %02X\n", tmp[0]);
num_components=tmp[0];
if (length != (unsigned int)(8 + num_components * 3)) {
fprintf(stderr,"Bogus SOF marker length\n");
//exit(1);
}
fseek(fp, 3*num_components, SEEK_CUR);
break;
case M_APP0:
case M_APP1:
case M_APP2:
case M_APP3:
case M_APP4:
case M_APP5:
case M_APP6:
case M_APP7:
case M_APP8:
case M_APP9:
case M_APP10:
case M_APP11:
case M_APP12:
case M_COM:
default:
/* Get the marker parameter length count */
read=fread(tmp, 2, 1, fp);
assert(read==1);
length = (unsigned)tmp[0]<<8|tmp[1];
//length = read_2_bytes();
/* Length includes itself, so must be at least 2 */
if (length < 2) {
fprintf(stderr, "Erroneous JPEG marker length\n");
break;//don't exit, return 0 width & height
}
length -= 2;
/* Skip over the remaining bytes */
fseek(fp, (long)length, SEEK_CUR);
break;
}
}
return ((uint64_t)image_width<<32|(uint64_t)image_height);
}
uint64_t get_file_dim_bmp(FILE* fp) {
uchar tmp[5];
size_t read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int file_s=((unsigned)tmp[0]<<24)|((unsigned)tmp[1]<<16)|((unsigned)tmp[2]<<8)|tmp[3];
assert(file_s > 0);
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 bytes
assert(tmp[0]=='\0' && tmp[1]=='\0'); //reserved
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 bytes
assert(tmp[0]=='\0' && tmp[1]=='\0'); //reserved
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
//int bfOffBits=tmp[0]<<24|tmp[1]<<16|tmp[2]<<8|tmp[3];//later use
unsigned int bfOffBits=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);//later use
//fprintf(stderr, "[DEBUG] bfOffBits = %d\n", bfOffBits);
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int biSize=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);//40
assert(biSize==40);
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int biWidth=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int biHeight=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 bytes
unsigned short biPlanes=(unsigned short)(tmp[0]|((unsigned short)tmp[1]<<8));
assert(biPlanes==0 || biPlanes==1); //reserved
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 bytes
unsigned short biBitCount=(unsigned short)(tmp[0]|((unsigned short)tmp[1]<<8));
//fprintf(stderr, "[DEBUG] biBitCount= %d\n", biBitCount);
assert(biBitCount==1 || biBitCount==4 || biBitCount==8 || biBitCount==24); //possible values
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int biCompression=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);
assert(biCompression==0); //compression not treated
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int biSizeImage=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);//can be zero
//assert( biSizeImage>=0 );
assert(biSizeImage <= UINT_MAX);
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int biXPelsPerMeter=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);//can be zero
//assert( biXPelsPerMeter>=0 );
assert(biXPelsPerMeter <= UINT_MAX);
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int biYPelsPerMeter=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);//can be zero
//assert( biYPelsPerMeter>=0 );
assert(biYPelsPerMeter <= UINT_MAX);
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int biClrUsed=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);//can be zero
//assert( biClrUsed>=0 );
assert(biClrUsed <= UINT_MAX);
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int biClrImportant=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);//can be zero
//assert( biClrImportant>=0 );
assert(biClrImportant <= UINT_MAX);
//later test
assert(
(biBitCount==1 && bfOffBits==14+40+4*2) ||
(biBitCount==4 && bfOffBits==14+40+4*16) ||
(biBitCount==8 && bfOffBits==14+40+4*256) ||
(biBitCount==24 && bfOffBits==14+40)
);
return ((uint64_t)biWidth<<32|(uint64_t)biHeight);
}
uint64_t get_file_dim_gif(FILE* fp) {
uchar tmp[5];
size_t read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 bytes
unsigned short biWidth=(unsigned short)(tmp[0]|((unsigned short)tmp[1]<<8));
//fprintf(stderr, "[DEBUG] biWidth = %d\n", biWidth);
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 bytes
unsigned short biHeight=(unsigned short)(tmp[0]|((unsigned short)tmp[1]<<8));
//fprintf(stderr, "[DEBUG] biHeight = %d\n", biHeight);
read=fread(tmp, 1, 1, fp);
assert(read==1);
uchar ct=(uchar)(tmp[0]>>7); //color table
assert(ct==0 || ct==1); //used !
uchar cr=(tmp[0]>>4)&0x07;//bit of color resolution PER primary color
++cr;
assert(cr>0);
//fprintf(stderr, "[DEBUG] bit of color resolution %d\n", cr);
uchar st=(tmp[0]>>3&0x01);//sort flag
assert(st==0 || st==1); //used !
uchar bp=(tmp[0]&0x07);//bit per pixel
++bp;
assert(bp>0);
//fprintf(stderr, "[DEBUG] bit per pixel %d\n", bp);
//background color index (not done)
//pixel aspect ratio (not done)
return ((uint64_t)biWidth<<32|(uint64_t)biHeight);
}
uint64_t get_file_dim_tif(FILE* fp) {
uchar tmp[5];
size_t read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int offset=tmp[0]|(unsigned)tmp[1]<<8|(unsigned)tmp[2]<<16|(unsigned)tmp[3]<<24;
//assert( offset==8 );//standard TIFF//test
unsigned int width=0;
unsigned int height=0;
unsigned int bitsPerSample=0;
std::vector<unsigned int> field_tag_v;
std::vector<unsigned int> field_type_v;
std::vector<unsigned int> length_v;
std::vector<unsigned int> data_offset_v;
//offset=8;//don't care of the initialized variable == //standard TIFF in my exemples
do {
fseek(fp, (long)offset, SEEK_SET);
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 byte
int num=tmp[0]|tmp[1]<<8;
for (int i=0; i<num; ++i) {
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 bytes
unsigned int field_tag=tmp[0]|(unsigned)tmp[1]<<8;
/**/
field_tag_v.push_back(field_tag);
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 bytes
unsigned int field_type=tmp[0]|(unsigned)tmp[1]<<8;
/**/
field_type_v.push_back(field_type);
assert(field_type>=1 && field_type<=5); //allowed types
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int length=tmp[0]|(unsigned)tmp[1]<<8|(unsigned)tmp[2]<<16|(unsigned)tmp[3]<<24;
/**/
length_v.push_back(length);
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int data_offset=tmp[0]|(unsigned)tmp[1]<<8|(unsigned)tmp[2]<<16|(unsigned)tmp[3]<<24;
/**/
data_offset_v.push_back(data_offset);
}
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
offset=tmp[0]|(unsigned)tmp[1]<<8|(unsigned)tmp[2]<<16|(unsigned)tmp[3]<<24;
}
while (offset!=0);
//fprintf(stderr, "[INFO] vector.size = %d\n", field_tag_v.size());
//search of width, height & BitsPerSample
std::vector<unsigned int>::iterator it1, it2;
it1=field_tag_v.begin();
it2=field_tag_v.end();
unsigned int i=0;
/* field type
1 - byte
2 - ASCII string, counted in length.
Most often an ASCIIZ string, the
trailing zero is counted with the
data length.
3 - word
4 - dword / uword
5 - rational (2 dwords, numerator and denominator)
*/
//offset used only if length > 4
for (; it1!=it2; ++it1,++i) {
if (*it1==256) {
//width//word or dword
assert(field_type_v.at(i)==3 || field_type_v.at(i)==4);
assert(data_offset_v.at(i)!=0); //error
assert(length_v.at(i)==1); //error
width = data_offset_v.at(i);
}
else if (*it1==257) {
//height//word or dword
assert(field_type_v.at(i)==3 || field_type_v.at(i)==4);
assert(data_offset_v.at(i)!=0); //error
assert(length_v.at(i)==1); //error
height = data_offset_v.at(i);
}
else if (*it1==258) {
//BitsPerSample//word
assert(field_type_v.at(i)==3); //word
assert(data_offset_v.at(i)!=0); //error
assert(length_v.at(i)==1); //error
bitsPerSample = data_offset_v.at(i);
assert((/*bitsPerSample>=0 &&*/ bitsPerSample<=4) || bitsPerSample%2==0);
}
}
//fprintf(stderr, "[INFO] bitsPerSample = %d\n", bitsPerSample);
return ((uint64_t)width<<32|(uint64_t)height);
}
uint64_t get_file_dim_tga(FILE* fp) {
uchar tmp[5];
size_t read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int ext_area_offset=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);
//assert( ext_area_offset >= 0 );//used !
assert(ext_area_offset <= UINT_MAX);
read=fread(tmp, 4, 1, fp);
assert(read==1); //read 1 * 4 bytes
unsigned int dev_area_offset=tmp[0]|((unsigned)tmp[1]<<8)|((unsigned)tmp[2]<<16)|((unsigned)tmp[3]<<24);
//assert( dev_area_offset >= 0 );//used !
assert(dev_area_offset <= UINT_MAX);
fseek(fp, 0, SEEK_SET);
//return to beginning of file
return get_file_dim_tga_old(fp);
}
uint64_t get_file_dim_tga_old(FILE* fp) {
uchar tmp[5];
char image_id_length=(char)fgetc(fp);//read 1 byte
assert(errno==0);
char color_map_type=(char)fgetc(fp);//read 1 byte
assert(errno==0);
char data_type=(char)fgetc(fp);//read 1 byte (value already checked)
assert(errno==0);
//3
size_t read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 byte
short color_map_origin=(short)(tmp[0]|(unsigned short)tmp[1]<<8);
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 byte
short color_map_length=(short)(tmp[0]|tmp[1]<<8);
char color_map_depth=(char)fgetc(fp);//read 1 byte
assert(errno==0);
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 byte
//3+5=8
short x_origin=(short)(tmp[0]|tmp[1]<<8);
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 byte
short y_origin=(short)(tmp[0]|tmp[1]<<8);
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 byte
unsigned short width=(unsigned short)(tmp[0]|(unsigned short)tmp[1]<<8);
read=fread(tmp, 2, 1, fp);
assert(read==1); //read 1 * 2 byte
unsigned short height=(unsigned short)(tmp[0]|(unsigned short)tmp[1]<<8);
char bitPerPixel=(char)fgetc(fp);//read 1 byte
assert(errno==0);
//fprintf(stderr, "[INFO] Bit Per Pixel = %d\n", bitPerPixel);
char imageDescriptor=(char)fgetc(fp);//read 1 byte
assert(errno==0);
//3+5+10=18
//fprintf(stderr, "[INFO] ftell = %ld\n", ftell(fp));
assert(ftell(fp)==18); //reading size check
//unused bypass start
assert(image_id_length+color_map_type+data_type +
color_map_origin+color_map_length+color_map_depth +
x_origin+y_origin+width+height+bitPerPixel+imageDescriptor >= 0);
//you must be VERY unlucky if this happens, go talk to Murphy.
//unused bypass end
return ((uint64_t)width<<32|(uint64_t)height);
}
//
#ifndef FAST_IMAGE_SIZE_READER_HPP
#define FAST_IMAGE_SIZE_READER_HPP
#include <cstdio>
#include <cstring>
#include <cassert>
#include <inttypes.h>
#include "crc32.hpp"
enum file_type {
UNKNOWN=0,
PNG=1,
JPG=2,
BMP=4,
GIF=8,
TIF=16,
TGA=32,
TGA_OLD=64
};
enum file_type get_file_type(const char* filename);
uint64_t get_file_dim(const char* filename);
uint64_t get_file_dim2(const char* filename, enum file_type ft);
uint64_t get_file_dim_png(FILE* fp);
uint64_t get_file_dim_jpg(FILE* fp);
uint64_t get_file_dim_bmp(FILE* fp);
uint64_t get_file_dim_gif(FILE* fp);
uint64_t get_file_dim_tif(FILE* fp);
uint64_t get_file_dim_tga(FILE* fp);
uint64_t get_file_dim_tga_old(FILE* fp);
#endif /*FAST_IMAGE_SIZE_READER_HPP*/
//
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment