package Image::Size;
# $Id: Size.pm,v 1.9 2001/01/10 08:12:43 tom Exp $
################################################################

use strict qw(vars);
use Exporter;
use vars qw(@ISA @EXPORT);

@ISA = qw(Exporter);
@EXPORT = qw(imgsize);

sub imgsize ($;$$)
{
    my ($file, $fd, $width_maxsize) = @_;

    unless(defined $fd){
	$fd = "filehandle";
	open($fd, $file) || return undef;
    } else {
	$fd = caller() . "::$fd";
    }

    my ($width, $height);
    if ($file =~ /\.gif$/i){
	($width, $height) = gif_size($fd);
    } elsif ($file =~ /\.png$/i){
	($width, $height) = png_size($fd);
    } elsif (($file =~ /\.jpeg$/i) || ($file =~ /\.jpg$/i)) {
	($width, $height) = jpeg_size($fd);
    } else {
        return undef;
    }
    # check max width size
    if ($width_maxsize > 0 && $width_maxsize < $width) {
	($width, $height) = ($width_maxsize,
			     int($height*($width_maxsize/$width)));
    }
    return ($width, $height);
}
    

################################################################
sub gif_size (*)
{
    my $fd = shift;
    my $tmp;

    local(*H) = $fd;
    read(H, $tmp, 6);	# skip 6 bytes
    read(H, $tmp, 4);	# width, height
    close(H);

    my ($wl, $wh, $hl, $hh) = unpack("CCCC", $tmp);
    my $width = $wl + ($wh << 8);
    my $height = $hl + ($hh << 8);

    return ($width, $height);
}

sub png_size (*)
{
    my $fd = shift;
    my $tmp;
    
    local (*H) = $fd;
    
    read(H, $tmp, 16);        # skip 16byte
    read(H, $tmp, 8);         # bigaidian: width -> height
    close(H);
    
    # unpack
    my ($width3, $width2, $width1, $width0,
	$height3, $height2, $height1, $height0) = unpack("CCCCCCCC",$tmp);
    
    my $width = $width0+($width1 << 8)+($width2 << 16)+($width3 << 24);
    my $height = $height0+($height1 << 8)+($height2 << 16)+($height3 << 24);
    
    return ($width, $height);
}

sub jpeg_size ($) {
    my $fd = shift;
    my $tmp;
    local(*H) = $fd;
    
    binmode(H);
    read(H, $tmp, 2);			# skip 2byte
    
    my ($width, $height);

    while(1) {
	my $seg_header;
	read(H, $seg_header, 4);     # header: marker,code,length(big endian)
                        	        
	my ($marker, $code, $length) = unpack("a a n", $seg_header);
	if( ord($marker) ne 0xff){
	    # not JPEG
	    last;
	}
	if( (ord($code) >= 0xc0) && ( ord($code) <= 0xc3 ) ) {
	    read(H, $tmp, 5);	# size (dummy,x(big endian),y(big endian))
	    my $dummy;
	    ($dummy, $height, $width) = unpack("a n n", $tmp);
	    last;
	}
	read(H, $tmp, $length - 2);
    }
    close(H);
    
    return ($width, $height);
}

1;
