HOME備忘帳

画像の縦横のピクセル数を求める

保存されている画像ファイルの、縦と横のピクセル数を求めるサブルーチンです。 PerlでHTMLを出力するために使用したものなので、画像フォーマットはJPEG、GIF、PNGにのみ対応しています。

ソースコード

Download (テキストファイル)

# 画像の縦横ピクセル数取得

sub get_imagesize {
    # エラー報告にCarp.pm
    use Carp qw(croak);

    my $filename = shift;   # 画像ファイル名
    my $rise_error = shift; # エラー処理

    my ( $width, $height ); # 戻り値

    # ファイルが存在しないとき
    if ( ! -e $filename ) {
        if ( $rise_error ) {
            croak("Cannot find file [$filename].");
        } else {
            return (0,0);
        }
    }

    # オープンできないとき
    unless ( open( IMG, $filename ) ) {
        if ( $rise_error ) {
            croak("Cannot open file [$filename].");
        } else {
            return (0,0);
        }
    }
    binmode(IMG);

    my $buf;

    # GIF
    if( $filename =~ /\.gif$/i ){
        read( IMG, $buf, 6 );
        if ( $buf =~ /^GIF/ ) {
            read( IMG, $buf, 2 );
            $width  = unpack("v*", $buf);
            read( IMG, $buf, 2);
            $height = unpack("v*", $buf);
        } else {
            croak("GIF Format error") if ( $rise_error );
        }
    }

    # PNG
    elsif( $filename =~ /\.png$/i ){
        read( IMG, $buf, 8 );
        if ( $buf =~ /^\x89PNG/ ) {
            read ( IMG, $buf, 8 );
            my ( $size, $type ) = unpack( "NA4", $buf );
            if ( $type ne 'IHDR' ) {
                read( IMG, $buf, 8 );
                ($width, $height) = unpack("NN", $buf);
            } else {
                croak("PNG Format error") if ( $rise_error );
            }
        } else {
            croak("PNG Format error") if ( $rise_error );
        }
    }

    # JPEG
    elsif ( $filename =~ /\.jpe?g?$/i ) {
        seek( IMG, 0, 0 );
        read( IMG, $buf, 2 );
        # FFD8 = JPEGファイルの先頭
        if ( $buf =~ /^\xFF\xD8$/ ) {
            my $skip_size;
            # マーカーごとに読む
            while ( read( IMG, $buf, 2 ) ) {
                # 画像サイズはFFC0マーカーで記述
                if ( $buf =~ /^\xFF\xC0$/ ) {
                    seek( IMG, 3, 1 );
                    read( IMG, $height, 2 );
                    $height = unpack("n*", $height);
                    read( IMG, $width, 2 );
                    $width  = unpack("n*", $width);
                    last;
                }
                # FFD9 = ファイル終端
                # FFDA = イメージデータそのもの
                elsif ( $buf =~ /\xFF(?:\xD9|\xDA)/ ) {
                    last;
                }
                # FFC0にたどり着くまでは読み飛ばす
                elsif ( $buf =~ /\xFF(?:[\xE0-\xED]|\xFE|\xDB|\xDD|\xC4)/ ) {
                    read( IMG, $buf, 2 );
                    $skip_size = unpack("n*", $buf) - 2;
                    seek( IMG, $skip_size, 1 );
                }
            }
        } else {
            croak("JPEG Format error") if ( $rise_error );
        }
    }

    # その他
    else {
        croak("Bad filename [$filename]") if ( $rise_error );
    }

    close( IMG );
    return( $width, $height );
}

[ ページ先頭へ ]

書式

my ( $width, $height ) = get_imagesize($filename, $rise_err);

引数

$filename
画像ファイル名。
受け取った値でそのままOPENを試みるので、実行ディレクトリからの相対パスか、絶対パスで指定してください。
$rize_error

読取エラーの時に、例外を発生させるかどうかを指定。
1 = 例外発生、0 = 発生させない(デフォルト)。

省略した場合、エラー処理は自分で行ってください。
例外を発生させた場合、能動的にそれを拾っていなければ、おそらくプログラムは中断するでしょう。

戻り値

$width, $height
画像の横、縦のピクセル数(数値)。読取に失敗した場合など、正しく読めなかった時は、それぞれ0を返す。

[ ページ先頭へ ]

CGIで利用するなら、多分こんな感じ

# 画像ファイル名はパスつきで指定
my $filename = "../img/someimage.jpg";

# 縦横の画像サイズを取得
my($width, $height) = get_imagesize($filename);

# 画像タグを生成
my $image_tag;
if ( $width == 0 && $height == 0 ) {
    $image_tag = qq|(画像の読込に失敗しました)|;
}
else {
    $image_tag = qq|<img src="$filename" width="$width" height="$height">|;
}

[ ページ先頭へ ]

利用方法、備考

ソースコードを、自分のプログラムにコピーするなどして、ご利用ください。グローバル変数は使っていないので、use strictしていても動作OKなはずです。

サブルーチン内では、画像フォーマットの仕様で定められている(らしい)画像ピクセル数のデータを読み出しています。

画像フォーマットは、ファイル名の拡張子で判断しています。対応している拡張子は「.gif」「.png」「.jpg」「.jpeg」(それぞれ大文字・小文字どちらでも可)です。その後、画像フォーマットが正しいかどうかチェックしています。

正規表現で手を抜いているので、「.jpe」と「.jp」でもJPEGと判断するのはご愛嬌ということで。

 

最終更新日:2008/09/02

[ ページ先頭へ ]