Search code examples
regeximageperlpng

Getting image width and height from PNG without library


Based on specification of PNG (Portable Network Graphics) file, a very first chunk has to be IHDR (4 bytes), contains the image's width, height, and bit depth. So right behind IHDR are 4 bytes representing width and then next 4 bytes representing height of the image.

Is it safe to use regex /IHDR(.{4})(.{4})/s and convert $1 and $2 into width and height? If so, how can I do such conversion? Should I use unpack("N", $x) or unpack("V", $x) ..?


My current code (not sure if it works for large images):

if ($png =~ m/^\x89PNG\x0D\x0A\x1A\x0A....IHDR(.{4})(.{4})/s) {
  ($width, $height) = (unpack("N", $1) , unpack("N", $2));  
}

Solution

  • I just looked up the png specification; there's more stuff in front of the IHDR. So this should work:

    open(IN, "<xx.png");
    binmode(IN);
    read(IN, $header, 24);
    if (substr($header, 12, 4) ne "IHDR") {
        die "this is not a PNG file";
    }
    ($width, $height)=unpack("NN", substr($header, 16));
    print "width: $width height: $height\n";
    close IN;