# ImageSize.pl # # This code is Copyright 2003,2007 Tony Lewis . # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see http://www.gnu.org/licenses/. # ################################################################################ # Return the size of an image (width, height) # # my ($width, $height, $format) = ImageSize($filePath) # # If the return values are negative, an error occurred. Each combination of # values indicates a specific error. # # The first number indicates an open error or which image type failed: # -1 open or read header of image file failed # -2 GIF failure # -3 JPG failure # -4 BMP failure # -5 PNG failure # # The second number indicates the specific error that occurred. (See the code # for the meanings of the various combinations. # ################################################################################ sub ImageSize { my ($path) = @_; my ($w, $h, $w1, $w2, $w3, $w4, $h1, $h2, $h3, $h4, $header, $marker, $skip, $len, $len1, $len2); # Guess the format from the file extension my ($format) = $path =~ m/\.(...)$/; $format = lc($format); open IMGSIZEF, "$path" or return (-1,-1,$format); # Override the guessed format if header indicates the type of file return ImageSizeCloseF(-1,-2,$format) if read(IMGSIZEF, $header, 8) < 8; $format = "gif" if substr($header,0,6) eq "GIF87a" || substr($header,0,6) eq "GIF89a"; $format = "jpg" if substr($header,0,2) eq "\xff\xd8"; $format = "bmp" if substr($header,0,2) eq "BM"; $format = "png" if substr($header,0,8) eq "\x89PNG\r\n\x1A\n"; seek(IMGSIZEF,0,0); ############ GIF if ($format eq "gif") { return ImageSizeCloseF(-2,-1,$format) if read(IMGSIZEF, $header, 6) < 6; return ImageSizeCloseF(-2,-2,$format) if $header ne "GIF87a" && $header ne "GIF89a"; return ImageSizeCloseF(-2,-3,$format) if read(IMGSIZEF, $w1, 1) < 1; return ImageSizeCloseF(-2,-4,$format) if read(IMGSIZEF, $w2, 1) < 1; return ImageSizeCloseF(-2,-5,$format) if read(IMGSIZEF, $h1, 1) < 1; return ImageSizeCloseF(-2,-6,$format) if read(IMGSIZEF, $h2, 1) < 1; return ImageSizeCloseF(ord($w2) * 256 + ord($w1), ord($h2) * 256 + ord($h1),$format); ############ JPG } elsif ($format eq "jpg") { return ImageSizeCloseF(-3,-1,$format) if read(IMGSIZEF, $header, 2) < 2; return ImageSizeCloseF(-3,-2,$format) if $header ne "\xff\xd8"; # SOI marker while (1) { return ImageSizeCloseF(-3,-3,$format) if read(IMGSIZEF, $header, 1) < 1 || ord($header) != 0xFF; return ImageSizeCloseF(-3,-4,$format) if read(IMGSIZEF, $marker, 1) < 1; return ImageSizeCloseF(-3,-5,$format) if read(IMGSIZEF, $len1, 1) < 1; return ImageSizeCloseF(-3,-6,$format) if read(IMGSIZEF, $len2, 1) < 1; $len = ord($len1) * 256 + ord($len2) - 2; if (ord($marker) < 0xC0 || ord($marker) > 0xCA || ord($marker) == 0xC4 || ord($marker) == 0xC8 || ord($marker) == 0xCC) { return ImageSizeCloseF(-3,-7,$format) if read(IMGSIZEF, $skip, $len) < $len; } else { return ImageSizeCloseF(-3,-8,$format) if read(IMGSIZEF, $skip, 1) < 1; # precision return ImageSizeCloseF(-3,-9,$format) if read(IMGSIZEF, $h1, 1) < 1; return ImageSizeCloseF(-3,-10,$format) if read(IMGSIZEF, $h2, 1) < 1; return ImageSizeCloseF(-3,-11,$format) if read(IMGSIZEF, $w1, 1) < 1; return ImageSizeCloseF(-3,-12,$format) if read(IMGSIZEF, $w2, 1) < 1; return ImageSizeCloseF(ord($w1) * 256 + ord($w2), ord($h1) * 256 + ord($h2),$format); } } ############ BMP } elsif ($format eq "bmp") { return ImageSizeCloseF(-4,-1,$format) if read(IMGSIZEF, $header, 2) < 2; return ImageSizeCloseF(-4,-2,$format) if $header ne "BM"; return ImageSizeCloseF(-4,-3,$format) if read(IMGSIZEF, $skip, 12) < 12; # rest of the BMP file header return ImageSizeCloseF(-4,-4,$format) if read(IMGSIZEF, $skip, 4) < 4; # Bitmap Header: length return ImageSizeCloseF(-4,-5,$format) if read(IMGSIZEF, $w1, 1) < 1; return ImageSizeCloseF(-4,-6,$format) if read(IMGSIZEF, $w2, 1) < 1; return ImageSizeCloseF(-4,-7,$format) if read(IMGSIZEF, $w3, 1) < 1; return ImageSizeCloseF(-4,-8,$format) if read(IMGSIZEF, $w4, 1) < 1; return ImageSizeCloseF(-4,-9,$format) if read(IMGSIZEF, $h1, 1) < 1; return ImageSizeCloseF(-4,-10,$format) if read(IMGSIZEF, $h2, 1) < 1; return ImageSizeCloseF(-4,-11,$format) if read(IMGSIZEF, $h3, 1) < 1; return ImageSizeCloseF(-4,-12,$format) if read(IMGSIZEF, $h4, 1) < 1; return ImageSizeCloseF(ord($w4) * (256**3) + ord($w3) * (256**2) + ord($w2) * 256 + ord($w1), ord($h4) * (256**3) + ord($h3) * (256**2) + ord($h2) * 256 + ord($h1),$format); ############ PNG } elsif ($format eq "png") { return ImageSizeCloseF(-5,-1,$format) if read(IMGSIZEF, $header, 8) < 8; return ImageSizeCloseF(-5,-2,$format) if $header ne "\x89PNG\r\n\x1A\n"; return ImageSizeCloseF(-5,-3,$format) if read(IMGSIZEF, $skip, 4) < 4; # length of the IHDR chunk return ImageSizeCloseF(-5,-4,$format) if read(IMGSIZEF, $skip, 4) < 4; # chunk type return ImageSizeCloseF(-5,-5,$format) if $skip ne "IHDR"; return ImageSizeCloseF(-5,-6,$format) if read(IMGSIZEF, $w1, 1) < 1; return ImageSizeCloseF(-5,-7,$format) if read(IMGSIZEF, $w2, 1) < 1; return ImageSizeCloseF(-5,-8,$format) if read(IMGSIZEF, $w3, 1) < 1; return ImageSizeCloseF(-5,-9,$format) if read(IMGSIZEF, $w4, 1) < 1; return ImageSizeCloseF(-5,-10,$format) if read(IMGSIZEF, $h1, 1) < 1; return ImageSizeCloseF(-5,-11,$format) if read(IMGSIZEF, $h2, 1) < 1; return ImageSizeCloseF(-5,-12,$format) if read(IMGSIZEF, $h3, 1) < 1; return ImageSizeCloseF(-5,-13,$format) if read(IMGSIZEF, $h4, 1) < 1; return ImageSizeCloseF(ord($w1) * (256**3) + ord($w2) * (256**2) + ord($w3) * 256 + ord($w4), ord($h1) * (256**3) + ord($h2) * (256**2) + ord($h3) * 256 + ord($h4),$format); } return ImageSizeCloseF(-1, -3,$format); } sub ImageSizeCloseF { close IMGSIZEF; return @_; } 1;