ActivePerl+Anhttpd環境下でadiaryのサムネイル機能を使う(Imager編)

先のエントリでImager改造云々と書いておきながらソース上げないのはどうかと思うので書きかけながら上げてみる。

序論

adiaryといえば言わずと知れた純Perl+SQL-Freeな超軽量blogwareですが*1、画像周り、特にサムネイル作成機能はImageMagickを用いているためにプラットホームを選ぶという難点があります。

そこで今回、adiary v1.44 において、ImageMagickを捨て、windowsでも動作可能なImagerを用いて編集できるようにソースの改造を試みました。

下準備

サーバー

Apacheでもよかったのですが、Windowsローカルで使うには如何せん大きすぎるので、お手軽なAnhttpdで行くことに。Anhttpdでadiaryを動かす方法については本家マニュアルを参照のこと

Perl

Windowsで動くPerl実装といえばActivePerlでしょ、ということでActivePerl5.8系最新版、5.8.8.822を取得Cygwinでもいいけど*2ちなみにActivePerl5.10系ではImagerが動かなかった。

Imager

ActivePerl本家のPPMにはbmpしか読み込めないImagerしかなく、使い物にならないので、ここはImager Project本家が用意しているwin32向けパッケージをインストールしてやります。現時点でのバージョンは0.60。

ppm install http://ppd.develop-help.com/ppd/Imager.ppd

ソース改変

概要

adiaryはSatsuki-systemというフレームワークの上で動いていますが、このSatsuki-systemについては現在リファレンスが整備されていません。ですので、挙動を探るにはどうしてもソースを追いかけながらデバッグするようにしなければならず、今回の修正で完全にカバーできているかどうかは必ずしも明らかではありません。
ソースコードの改変を行う場合は必ず自己責任でお願いします。

改変場所は adiary.cgi がある場所がルートとすると

  • /lib/Satsuki/Upload.pm
  • /info/textparser_tags.txt

の二カ所。

Uploader.pm

ファイルアップロードのコアモジュールです。コメントも書かれているのでわかりやすいかと。Imagerの書き方についてはRedirecting…を参考にしました。

これの250行目付近、

#----------------------------------------------------------------------
# ImageMagic があるとき、サムネイルを作る
#----------------------------------------------------------------------

というコメント以下を次のように書き換え。

#----------------------------------------------------------------------
# ImageMagic があるとき、サムネイルを作る
#----------------------------------------------------------------------
if (!$self->{make_thumbnail} || !$ROBJ->check_lib("Imager")) { return 0; }

require 'Imager.pm';

# サムネイルdirの作成
$dir .= $self->{upload_thumbnail_dir};
$ROBJ->mkdir($dir);

my $thumbnail_file = $ROBJ->get_filepath( $dir . $file_name );

my $image = Imager->new;

$image -> read( file => $save_file_real ) or die $image->errstr;

# リサイズ
my $width = $image->getwidth();
my $height = $image->getheight();
my $size = $self->{thumbnail_size};
if ($size < 16) { $size=120; }
if ($width<$size && $height<$size) {
 $size = 0;  # resize しない
} elsif ($width > $height) {
 $height = int($height*($size/$width));
 $width  = $size;
} else {
 $width  = int($width*($size/$height));
 $height = $size;
}
if ($size) {# リサイズ
 $image = $image -> scale(
  xpixels => $width,
  ypixels => $height,
 );
}

# ファイルに書き出し
$image->write( file => $thumbnail_file) or die $image->errstr;
if ($ROBJ->{File_mode}) { chmod($ROBJ->{File_mode}, $thumbnail_file); }

#----------------------------------------------------------------------
# タグの再生成
#----------------------------------------------------------------------
$tag = $self->{upload_tag_thumbnail};
# 元サイズで表示 または サムネイル生成失敗
if ($form->{org_size} || !-r $thumbnail_file) {
 $tag = $self->{upload_tag}; # 標準画像の参照
}
	$tag =~ s/%(\w)/$h{$1}/g;
	$self->{tag} = $tag;
	return 0;# 成功
}

1;  # おまじない
  1. 元のアルゴリズムからほとんど変化させてません。Image::MagickのAPIにアクセスしている部分をImagerに対応できるよう書き換えただけです。
  2. 気が向いたらdiff上げます。
  3. 元は blur がかかってますが、このソースではかけてないです。フィルタはImagerリファレンス@CPANを見つつお好きな感じでどうぞ。
  4. サムネイルのサイズが小さい場合は uploader.conf.cgi の <$v.thumbnail_size = 120> を適当に書き換えれば幸せになれるかもしれない。
textparser_tag.txt

230行目付近、
# 標準アップローダ
以下の

image#small = 画像アルバム, image, 3,  ${public}image/$1/$2thumbnail/$3.jpg

から、末尾の .jpg を消去。

(余談だけど、この箇所を探すのに半日かかった。Namazu入れたら一発で見つかった。手動じゃ無理だ。それまでは

/lib/Satsuki/TextParser/TagPlugin/Tag_image.pm

の最後、

return "<a href=\"$link\"$tag->{class}$target><img alt=\"$name\" title=\"$name\"$size src=\"$url\"></a>";

の直前に

$url = substr($url, 0, length($url)-4);

を入れてトリムしようと考えてた。)

蛇足

先の日記

先に書いた文と前後してしまってちょっとややこしいんですが、時系列的にはこちらの記事が先。 textparser_tag.txt の修正については前の日記を参照

ImageMagickとかGDとか

ImageMagickPerlとの橋渡し部分(旧PerlMagick)がImageMagick本体にマージされちゃったらしく、普通にImageMagickを入れればPerlから Image::Magick を呼び出せるはずなのに何をやっても動かない。ここは本当に訳がわからなかった。
一方、GDも厄介でActivePerlのppmに存在せず、野良ppdを拾ってきたら GD/Image.al がありませんとのこと。これも使い物にならない。Imlib2はwindowsで動くのが見あたらなかった。

Acknowledgement

この素晴らしいソフトの作者である、nabe氏に心より感謝を。

*1:正直なぜ未だに他のblogwareに隠れてるのか謎。Wordpressよりも圧倒的に使いやすいと思う。

*2:というか、Cygwinだと自分でソースからimagerのコンパイルが可能なので、Cygwin-Apache/Lighttpdで実行可能だと思う。