hogehoge foobar Blog Style Beta

Web,Mac,Linux,JavaScript,Perl,PHP,RegExp,Git,Vim,Redmineなど技術的なことのメモや、ちょっと便利そうなものの紹介をしています。

Perlでディレクトリ内の画像ファイルのピクセル数を調べる

特定のディレクトリの中から特定のピクセル数以上の画像ファイルを抽出&リストアップするperlスクリプトです。
WEBサイト等でドキュメントルート以下の画像サイズを知りたいときや、○○ピクセル以上のサイズの画像を抜き出して画像サイズを変更する場合等に使えるかと思います。

Image::Sizeのインストール

今回、画像のピクセル数を取得するのに「Image::Size」を使用しました。
「Image::Size」はCPANからインストールできます。
※今回のスクリプトは「Image::Size」をインストールしないと動作しません。

$ perl -MCPAN -e shell

cpan shell -- CPAN exploration and modules installation (v1.9402)
Enter 'h' for help.

cpan[1]> install Image::Size

Image::Sizeの使い方

「Image::Size」で画像のピクセル数を取得するには、「imgsize」を使用します。
「imgsize」の書式は以下のような形になります。

@ピクセル数 = imgsize("画像ファイル名");

「imgsize("画像ファイル名")」とすると、1番目に横ピクセル数、2番目に縦ピクセル数をセットした配列を戻してくれます。
具体的には以下のようなコードで画像ファイル名のピクセル数を取得できます。

# imgsizeで縦横のピクセル数を取得(Image::Size)
# $widthに横ピクセル数(幅)をセット
# $heightに縦ピクセル数(高さ)をセット
(my $width, my $height) = imgsize($filename);

File::Find::Ruleでファイルを検索

画像ファイルの検索について「`find`」みたいなコマンド直接実行や、「File::Find」を使用しようと思いましたが、
「File::Find::Rule」が便利そう&分かりやすそうだったので使ってみました。

# File::Find::Ruleオブジェクト生成
my $rule =  File::Find::Rule->new;

# 検索対象をファイルのみに指定
$rule->file;

# 検索するファイル拡張子を指定(正規表現)
$rule->name(qr/\.(gif|jpg|png)$/);

# 指定した条件で検索
# 検索結果を配列に格納
my @files = $rule->in($directory);

特定ピクセル数以上の画像ファイルを抽出&リストアップするスクリプト(全体)

今回作成したPerlスクリプトの全体は以下に記載します。
ファイル名を「image_pixel.pl」として作成しています。
※忘れっぽいので備忘録としてコメントをウダウダと書いています。

image_pixel.pl
#!/usr/bin/perl

use strict;
use warnings;

use Image::Size;
use File::Find::Rule;
use File::Basename;
use File::Path;
use File::Copy;

# 該当するファイルのコピー先ディレクトリ名
my $copy = 'copy';

my $directory = shift @ARGV;   # 検索対象のディレクトリ
my $max_width = shift @ARGV;   # コピー対象ファイルの横ピクセル数
my $max_height = shift @ARGV;  # コピー対象ファイルの縦ピクセル数

# File::Find::Ruleオブジェクト生成
my $rule =  File::Find::Rule->new;

# 検索対象をファイルのみに指定
$rule->file;

# 検索するファイル拡張子を指定(正規表現)
$rule->name(qr/\.(gif|jpg|png)$/);

# 指定した条件で検索
# 検索結果を配列に格納
my @files = $rule->in($directory);

foreach (@files)
{
    # imgsizeで縦横のピクセル数を取得(Image::Size)
    (my $width, my $height) = imgsize($_);

    # 指定したピクセル数以上のサイズか?
    if ($width >= $max_width or $height >= $max_height){

        # ファイルコピー用のディレクトリを作成
        # (File::Basename,File::Path)
        my $dirname = $copy . '/' . dirname($_);
        &make_directory($dirname);

        # ファイルをコピー(File::Copy)
        copy $_, $dirname;

        # ファイル名,横ピクセル数,縦ピクセル数を出力
        print "$_\t$width\t$height\n";
    }
}

##################################################
# [sub] Create File Copy Directory.
##################################################
sub make_directory
{
    (my $dirname) = @_;

    # 既にディレクトリが存在しているか?
    if (! -d $dirname ){

        # 「mkpath」が失敗した場合、例外が発生するので「eval」で囲む
        eval{
            # ディレクトリの作成(File::Path)
            mkpath($dirname);
        };
        # 「mkpath」の例外の内容は「$@」にセットされる
        if( $@ ){
            die "$dirname creace err -> $@";
        }
    }
}

image_pixel.plの使い方

上記のPerlスクリプト(image_pixel.pl)は以下のような形でコマンドラインから使用できます。

$ perl ./image_pixel.pl ディレクトリ 対象の横ピクセル数 対象の縦ピクセル数 > 対象の画像リスト.tsv

例えば、htdocsディレクトリ以下の画像で横200px以上または縦150px以上の画像を抽出&リストアップしたい場合は、以下のような形になります。
※対象の画像リストは「image_list.tsv」に出力されます。

$ perl ./image_pixel.pl htdocs 200 160 > image_list.tsv

今回参考にしたページ

perlで、画像ファイルのサイズ(ピクセル)を取得する - undiscoの日記
http://d.hatena.ne.jp/undiscokidd/20080212/p1

File Find Rule File Findの使いやすいインターフェィス - あじゃぱー
http://d.hatena.ne.jp/minesouta/20070908/p1

複数階層のディレクトリを作成する File Path mkpath() - サンプルコードによるPerl入門
http://d.hatena.ne.jp/perlcodesample/20080524/1211608231

CPAN経由でLinuxにモジュールを組み込む
http://y-kit.jp/saba/xp/cpan.htm