2009年11月10日火曜日

Thumbnailを作る

バイクに乗った時に,いろいろな写真を撮ってくる。折角撮ってきたらそれを整理したくなる。これまではwindows上のフリーソフトでサムネイルとwebページを作ってくれるソフトを使っていた。名前はすなねいる。何故すなねいるかというと,最初に見つけたから。でもこれが結構いけてた。コメントを入れる時には画像を見ながらコメント書けるし,コメントを保存しておいて後からやり直すこともできるし。しかし,気に入らない点もあった。例えば,写真の一覧の時に横にサムネイルを5個並べるのだが,もうちょっと多くしてwebページの幅を広げたい,とか,コメントと写真の配置が私好みじゃないとか,などである。人の作ってくれたフリーソフトを使っていて文句は言えないが…。そこで,ふと,自分でやってみようか?と思い立った。ではどうするか?まさかwindows上で動くソフトを自分で作ろうとは思わない。だってきっと有料のソフトを使わないといけなさそうだから。そこで,FreeBSD上でやってしまおうと思った。今回はその顛末。

まずは作戦を考えた。欲しいのは画像のサムネイルを作る,という作業とwebページを作るという作業。webページを作る作業としては,コメントを入れたい,というのが希望。これがちょっと厄介。写真にコメントをつけようと思っても,ファイル名だけ見ててもどんな写真かがわからない。やっぱり写真と見ながらじゃないとねぇ。すなねいるはその点はよかったのよねぇ。でもあまり凝った作戦にすると大変だから,できるだけ楽にしたいし…。そこで,複数のターミナルを開けて,横に写真を表示させながらコメントを入れる作戦にすることにした。しかしファイル名が一致する写真を探すのが大変。そこで考えた作戦は,
 (1) 画像ファイルをまとめて一つのディレクトリに入れる。
 (2) 一括してファイルネーム順に並べてサムネイルを作る。
   (できれば今後時間順に並べるようにしたい,と画策中)
 (3) サムネイルと同時に,
    (a) 写真情報の一覧のファイル(テキストファイルで,タブ区切りのファイル)と,
    (b) 一覧表示できる作業用webページ,
   を作る。作業用webページは1行に写真を5枚ずつにしておいて,
   一覧ファイルは5行ごとに(1写真につき1行)区切りを入れる。
 (4) 作業用webページを見ながら,一覧ファイルにコメントを追加して行く。
 (5) コメントが追加された一覧ファイルから,最終的なwebページを作る。
という感じ。さっそく下調べを始めた。

 まず,問題なのはサムネイルを作る部分。FreeBSD上なので,Perlのスクリプトでいいのがあるに違いないと思っていろいろ検索してみた。いろいろ見ていると,どうやら ImageMagick がよさそうだった。ImageMagick はコマンドラインから命令をいれて画像を加工するためのソフト。それにはいろいろなソフトから使えるようになっていて,PerlからならPerlMagickというのを使えばいいみたい。FreeBSDならImageMagickを入れればPerlMagickも入るみたい。そこで,さっそくportsからImageMagickをインストールした。これが時間かかった。なんであんなに時間かかるのかねぇ?ImageMagickが入ったらさっそくテストしてみた。まずは他の人がやってるのを真似してみるのが楽チン。そこでdrk7.jpさんの記事を参考にさせてもらった。ただ,そこで使われてるFile::Findを使うと,ディレクトリに入っているファイルを変な順に処理された困ってしまった。アルファベットと数字の順にしてくれればいいのに,よくわからない順序で作業をされてしまった。そこで,opendirとreaddirを使ってファイルリストを配列にいれて,ソートして処理をさせることにした。今後はここを撮影された時刻で並べなおしたいと目論んでいる。
opendir(DIR, $target_dir);
while ($file = readdir(DIR)) {
    if (($file ne '.') and ($file ne '..')) {
        if (($file =~ /(.*)¥.jpg/) or ($file =~ /(.*)¥.JPG/)) {
            push(@filelist,$file);
        }
    }
} # while $file = readdir(DIR);

foreach $xx (sort(@filelist)) {
    &make_thumb($xx,$target_dir);
}
追記)これってglob関数@file = glob('*.JPG');みたいに使えばいいみたい…

ここで &make_thumb($xx,$target_dir)は実際の処理をしているサブルーチン。
ImageMagickでは,Resizeメソッドを使う方法を採用した。
use Image::Magick;
と最初の方に書いておき,
our $RESIZE_X = 100;
our $RESIZE_Y = 75;

my $img = Image::Magick->new;
$img->Read($dir.$name);
my ($x, $y) = $img->Get('width', 'height');

if ( $x > $y) {
# landscape
    $img->Resize(width => $RESIZE_X, height => $y*$RESIZE_X/$x, blur=>0.5);
} else {
# portrait
    $img->Resize( width => $x * $RESIZE_X / $y, height => $RESIZE_X, blur=>0.5);
}
binmode(STDOUT);
if ($name =~ /(.+)¥..+$/) {
    $filehead = $1;
}
$newname=$filehead.'_thumb';
print qq{$name -> $dir$newname.png¥n};
$img->Write("png:$dir$newname.png");
と処理した。最初にインスタンスの作成,画像ファイルの読み込み,画像ファイルのサイズの読み取り,それから縦長か横長かで変数の取り方を変えて,Resizeしている。また元の画像は*.jpgか*.JPGのみとしておいて,サムネイルはpngで作っている。最初は
$img->Thumbnail( width => $x * $RESIZE_X/$y, height => $RESIZE_X);
とThumbnailメソッドを使う作戦や,他のメソッドを使うという作戦も考えたが,どうやらResize以外は補間をしないらしいので,Resizeを使うことにした。また,Resizeというメソッドではぼかし(Blur)や補間のフィルタを選べるらしい。そういえば,今回サムネイルを作成してみると,以前すなねいるで作った時よりもなんとなくぼやけた感じがしていた。そこで今回はblur=>0.5としてシャープになるようにしてみた。blurが1より大きいとぼやけ,blurが1より小さいとシャープになるらしい。blurを0.5としたのは適当。サンプルだと0.8とかになってたりするけど,まぁいいや。filterとblurの効果についてはhttp://www.dylanbeattie.net/magick/filters/result.htmlを参照してみてほしい。

 さて,これでいいかというともう一個欲しい情報があった。それは画像に貼付けてある撮影の日時などの情報。これはImageMagickならidentifyというコマンドで取り出せるみたいだが,PerlMagickにはないらしい。そこでImage::ExifTool;を使うことにした。これもFreeBSDならportsからインストールできる。これを使えばいろいろな情報を取り出せる。方法は
use Image::ExifTool;
my($exifTool) = new Image::ExifTool;
my($exifInfo) = $exifTool->ImageInfo($dir.$name);

my($key);
print '-------------------'."¥n";
for $key (sort keys %$exifInfo){
    print("$key : $exifInfo->{$key}¥n");
}
print '-------------------'."¥n";
とすればよい。かなり多くの情報が表示されるはず。もし特定の項目だけ取り出したければ
use Image::ExifTool;
my($exifTool) = new Image::ExifTool;
my($exifInfo) = $exifTool->ImageInfo($dir.$name);

$create_date = $exifInfo->{'CreateDate'};
のようにすればよい。
さて,ImageMagickとExifToolを使うと簡単に写真の整理ができることがわかった。以前作ったページも新しいのに置き換えようかと思っているところである。

(追記):ExifInfoを使っていろんな写真の写真情報を見ていると Rotationなる単語を発見した。これは写真を撮る時にカメラをどう傾けていたか,という項目。ただし,その項目名はOrientationという。この項目があるのはデジカメの中でもまあまあの値段の物。一番安いものにはどうも角度を検出するセンサーをつけてないみたい。なので新しくても安いデジカメにはこの項目はなかった。
$orientation = $exifInfo->{'Orientation'};
としてやると,結果は「Rotation 90 CW」などとなる。このCWはClockwise(時計回り)を意味している。写真と比べると,時計回りに90°回すと元に戻る,という意味っぽい。ちなみにRotation 270 CWというのもあったが,上下逆の場合はPanasonicだけがRotation 180と出た。他社は何もでなかった。さすがに逆さにして撮影する人はあまりいないからねぇ。さて,Orientationがわかれば,撮ってきた写真を処理する時に,Orientationの値を見て,Rotation 90 CWなら
$angle = 90;
$img->Rotate(degrees => $angle);
のようにして回してから処理してやりましょう。
ちなみに元の画像は,
system("/bin/cp -p $dir$name $org_dir$filehead"."_org.JPG");
のように別名でコピーしておいて,新しく保存し直しておきましょう。後は上述のようにサムネイルを作ってできあがり〜

(追記):PerlMagickの使い方を5回に分けてブログに載せておいた。PerlMagickの使い方を知りたい方は,PerlMagickの使い方を見てください。

0 件のコメント: