Programmer » GetImageSize

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.


C++ version

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;
}

PHP version

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.'"');
  }
}
In the PHP version, the line:
> if (isset($x,$y,$type)) return false;
should be:
> if (!isset($x,$y,$type)) return false;
as far as I can tell. Then it works for me.
 
great, thanks!
searched the whole web for this thanks :-)
thx! very useful!
I wrote a couple of stream wrappers and getimagesize() was sometimes returning false for no obvious reason. thanks to your post I am now able to at least debug and see that I seem to have made a mistake at implementing stream_ftell() or stream_fseek(). Thanks a lot!
Fantastic,,,,,Thank You very much
 
You are really great
This doesnt work for jpegs that were saved in photoshop :(
Hi, thanks for the code, do you have any examples of use with the c++ code?
Thanks
Thanks You!
jr
modifed code http://stackoverflow.com/questions/10111784/get-image-resolution-from-image-file#comment12969712_10111784
add comment  edit commentPlease add comments here