にっきダイアリー

はてなダイアリーからはてなblogに移動してみました。

Imager を使ってサムネール作成

突然ですが、500枚以上のJpegファイルのサムネールを作成しなければならなくなりました。

そこで、複数の画像ファイルを一括で変換してくれるツールをいろいろ探してみました。ベクターWindows用画像変換ツールページを見ると、そらもーサムネール作成に特化したツールが山のようにあり、中でも「縮小専用」というものがわりかしメジャーで設定が少なく急ぎの用途にぱっと使うには適してるようです。

ですが、その縮小専用も含め自分が試してみたフリーソフトの全部が元画像の縦横比を維持したまま、四角いサムネールを作ることが出来ないのですね。

図で表現するとこんなかんじ↓

数時間、いろんなそふとをあーでもないこーでもないと試した挙句、出来ないなら自作してやれ。とまで思いつめて、ActivePerl + Imager でサムネール作成用のスクリプト作りました。

以下ソース。


3分クッキングレベルなスクリプトなので、背景色が黒に決め打ちされておりますが、元画像の縦横比を保持したまま四角いサムネールがほしい人がいたら参考にしてください。

use strict;
use warnings;
use Imager;

&main;

#----------------------------------------------------------
# 指定のフォルダにあるjpg画像を全部サムネール化
#----------------------------------------------------------
sub main{
	my $dir = './';
	my $thumbs = './thumbs/';
	opendir(DIR, $dir) || die "Can't open $dir($!)\n";
	while(my $file = readdir(DIR)){
		next if($file =~ /^\./ or !($file =~ /jpg$/i));
		&mkthumb($dir.$file, $thumbs.$file,64,1);
	}
	closedir(DIR);

}

#----------------------------------------------------------
# サムネール作成
# file = 元ファイルのパス
# thumb = サムネールのパス
# size = 最大サイズ
# fill = 余白をうめて正方形にするかどうか
#----------------------------------------------------------
sub mkthumb {
	my($file,$thumb,$size,$fill) = @_;
	my $img = Imager->new;
	if($img->read(file=>$file)){
#		$img->filter( type => 'unsharpmask', stddev => 1 );
		$img = $img->scale(xpixels => $size,ypixels => $size,type => 'min');
		my $ix = $img->getwidth;
		my $iy = $img->getheight;
		if($fill and ($ix != $iy) ){ # 余白を埋める
			my $x = ($ix != $size) ? int(($size-$ix) / 2) : 0;
			my $y = ($iy != $size) ? int(($size-$iy) / 2) : 0;
			my $img2 = Imager->new(xsize => $size, ysize => $size);
			$img2->box(filled=>1, color=>'#000000');
			$img2->paste(left=>$x,top=>$y,img=>$img);
			$img = $img2;
		}
		$img->write(file=>$thumb)  or warn $img->errstr;
	}
	else{
		warn $img->errstr;
	}
}


#一箇所コメントアウトしてあるのはアンシャープマスクフィルタをかけるかかけないかで悩んでたときの名残です。