にっきダイアリー

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

サムネール一括生成スクリプト

どうせ一回しか使わない&複数のサイズ同時に生成したい&サムネのファイル名はWordpressのそれっぽく設定したい&ベクターのライブラリには大量に類似のツールが登録されている&希望通りの動作をするツールを検証してる時間がもったいない&サムネールの画質にさほどこだわってない&perlImageMagickもある=だから作っちまえ。

いや、最初は以前日記に書いておいた(d:id:Nikki_A:20080805)Imager使ったサムネール作成スクリプト流用しようと思ったの。そしたら、あれを公開した当時使ってたActivePerlとImagerはjpegの読み書きができてたのに、バージョンアップしたらImagerがjpeg読み書きできなくなってるんだよ。調べてみたら、Imagerはデフォルトのまま構築するとbmpとiconしか読み書きしないようになってるぽい。対応フォーマットを追加するためには、必要なライブラリをインストールしてから構築しないとダメ? ……面倒くさい。

なので、Imager使ってた部分をImageMagickに書き直したのを使って、数日後自宅での作業中にまた使いたくなったけど、作ったスクリプトは会社のマシンに保存されてましたよと。

ちくしょう……くやしいな……。by アッシュ・カナン

もうたぶん使わないだろうけど、いつかまた使うかもしれないからこのImageMagick版も記録に残す。

  • 20091020 : 細部訂正
#!/usr/bin/perl
# Image::Magick を使って、Wordpress のサムネール命名法に
# あわせたファイル名でサムネールを一括作成。
# ファイルは引数で指定
use strict;
use warnings;
use Carp;
use File::Basename;
use Image::Magick;
my $MK = new MK_THUMB;

foreach my $file (@ARGV){
	my($base,$dir,$ext) = main::fileparse($file,qr/\.[^.]*/);
	my $thumb = $dir.$base.'-'.$x.'x'.$y.$ext;
	$MK->mkthumb($file,150,1,0); # thumbは四角
	$MK->mkthumb($file,320,0,0); # medium <デフォルトは300だけどね
	$MK->mkthumb($file,800,0,0); # large
}

package MK_THUMB;
#----------------------------------------------------------
# コンストラクタ
#----------------------------------------------------------
sub new {
	my $proto = shift;
	my $bgcolor = shift || '#000'; # サムネールのバックカラー
	my $class = ref($proto) || $proto;
	my $self = {
		'bgcolor' => $bgcolor,
	};
	bless $self, $class;
}

#----------------------------------------------------------
# サムネール作成
#----------------------------------------------------------
sub mkthumb {
	my $self = shift;
	my($file,$size,$square,$fill) = @_;
	my $img = new Image::Magick;
	my $warn = $img->Read($file);
	unless("$warn"){
		my($ix,$iy) = $img->Get('width','height');
		return if($ix <= $size && $iy <= $size);
		my($x,$y) = (0,0);
		if( $square and !($fill) ){ # 四角いサムネール(長辺切り落とし)
			if($ix < $iy){ # 短いほうを基準にする
				$x = $size;
				$y = int($size / $ix * $iy);
			}
			else{
				$x = int($size / $iy * $ix);
				$y = $size;
			}
			$img->Resize(width=>$x,height=>$y);
			$img->Crop(geometry=>$size.'x'.$size.'+0+0', gravity=>'center');
			$x = $y = $size;
		}
		else{
			if($ix > $iy){ # 長いほうを基準にする
				$x = $size;
				$y = int($size / $ix * $iy);
			}
			else{
				$x = int($size / $iy * $ix);
				$y = $size;
			}
			$img->Resize(width=>$x,height=>$y);
			if($fill){ # 余白を埋めて四角いサムネールにする
				$img->Extent(geometry=>$size.'x'.$size.'+0+0',gravity=>'center', background=>$self->{bgcolor});
				$x = $y = $size;
			}
		}
		my($base,$dir,$ext) = main::fileparse($file,qr/\.[^.]*/);
		my $thumb = $dir.$base.'-'.$x.'x'.$y.$ext;
		$warn = $img->Write(filename=>$thumb); # 書き込み
	}
	main::carp( $warn ) if $warn;
}

後から調べたところ、ImageMagick の Resize はフィルタ指定しないとLanczos が使われるらしいフィルタを色々設定した時のサンプル一覧を参考にいろいろ設定するのもいいかもしれないなあ。まあ、次に使う時に考えよう。