Here are some routines to get the size of a GIF/JPEG/PNG image. There's a version in C++ which might be useful to some people. And there's a version in PHP which is completely useless because you can just use the built-in getimagesize() function.
bool GetImageSize(const char *fn, int *x,int *y) { FILE *f=fopen(fn,"rb"); if (f==0) return false; fseek(f,0,SEEK_END); long len=ftell(f); fseek(f,0,SEEK_SET); if (len<24) {fclose(f); return false;} // Strategy: // reading GIF dimensions requires the first 10 bytes of the file // reading PNG dimensions requires the first 24 bytes of the file // reading JPEG dimensions requires scanning through jpeg chunks // In all formats, the file is at least 24 bytes big, so we'll read that always unsigned char buf[24]; fread(buf,1,24,f); // For JPEGs, we need to read the first 12 bytes of each chunk. // We'll read those 12 bytes at buf+2...buf+14, i.e. overwriting the existing buf. if (buf[0]==0xFF && buf[1]==0xD8 && buf[2]==0xFF && buf[3]==0xE0 && buf[6]=='J' && buf[7]=='F' && buf[8]=='I' && buf[9]=='F') { long pos=2; while (buf[2]==0xFF) { if (buf[3]==0xC0 || buf[3]==0xC1 || buf[3]==0xC2 || buf[3]==0xC3 || buf[3]==0xC9 || buf[3]==0xCA || buf[3]==0xCB) break; pos += 2+(buf[4]<<8)+buf[5]; if (pos+12>len) break; fseek(f,pos,SEEK_SET); fread(buf+2,1,12,f); } } fclose(f); // JPEG: (first two bytes of buf are first two bytes of the jpeg file; rest of buf is the DCT frame if (buf[0]==0xFF && buf[1]==0xD8 && buf[2]==0xFF) { *y = (buf[7]<<8) + buf[8]; *x = (buf[9]<<8) + buf[10]; return true; } // GIF: first three bytes say "GIF", next three give version number. Then dimensions if (buf[0]=='G' && buf[1]=='I' && buf[2]=='F') { *x = buf[6] + (buf[7]<<8); *y = buf[8] + (buf[9]<<8); return true; } // PNG: the first frame is by definition an IHDR frame, which gives dimensions if ( buf[0]==0x89 && buf[1]=='P' && buf[2]=='N' && buf[3]=='G' && buf[4]==0x0D && buf[5]==0x0A && buf[6]==0x1A && buf[7]==0x0A && buf[12]=='I' && buf[13]=='H' && buf[14]=='D' && buf[15]=='R') { *x = (buf[16]<<24) + (buf[17]<<16) + (buf[18]<<8) + (buf[19]<<0); *y = (buf[20]<<24) + (buf[21]<<16) + (buf[22]<<8) + (buf[23]<<0); return true; } return false; }
if (!function_exists('getimagesize')) { function getimagesize0($fn) { $f = @fopen($fn,'rb'); if ($f===false) return false; fseek($f,0,SEEK_END); $len=ftell($f); if ($len<24) {fclose($f); return false;} fseek($f,0); $buf=fread($f,24); if ($buf===false) {fclose($f); return false;} if (ord($buf[0])==255 && ord($buf[1])==216 && ord($buf[2])==255 && ord($buf[3])==224 && $buf[6]=='J' && $buf[7]=='F' && $buf[8]=='I' && $buf[9]=='F') { $pos=2; while (ord($buf[2])==255) { if (ord($buf[3])==192 || ord($buf[3])==193 || ord($buf[3])==194 || ord($buf[3])==195 || ord($buf[3])==201 || ord($buf[3])==202 || ord($buf[3])==203) break; // we've found the image frame $pos += 2+(ord($buf[4])<<8)+ord($buf[5]); if ($pos+12>$len) break; // too far fseek($f,$pos); $buf = $buf[0].$buf[1].fread($f,12); } } fclose($f); // GIF: if ($buf[0]=='G' && $buf[1]=='I' && $buf[2]=='F') { $x = ord($buf[6]) + (ord($buf[7])<<8); $y = ord($buf[8]) + (ord($buf[9])<<8); $type = 1; } // JPEG: if (ord($buf[0])==255 && ord($buf[1])==216 && ord($buf[2])==255) { $y = (ord($buf[7])<<8) + ord($buf[8]); $x = (ord($buf[9])<<8) + ord($buf[10]); $type = 2; } // PNG: if (ord($buf[0])==0x89 && $buf[1]=='P' && $buf[2]=='N' && $buf[3]=='G' && ord($buf[4])==0x0D && ord($buf[5])==0x0A && ord($buf[6])==0x1A && ord($buf[7])==0x0A && $buf[12]=='I' && $buf[13]=='H' && $buf[14]=='D' && $buf[15]=='R') { $x = (ord($buf[16])<<24) + (ord($buf[17])<<16) + (ord($buf[18])<<8) + (ord($buf[19])<<0); $y = (ord($buf[20])<<24) + (ord($buf[21])<<16) + (ord($buf[22])<<8) + (ord($buf[23])<<0); $type = 3; } if (isset($x,$y,$type)) return false; return array($x,$y,$type,'height="'.$x.'" width="'.$y.'"'); } }