暑いけど、色々動いてますた。盆休みはないけど、普段そんなに忙しくなかったり。
さて、ここじゃ評判の悪いプログラムの話。備忘録的なこともあるけど、普段からサンプルスクリプトを公開している多くの人たちにヒントをもらっている(パクリとも言う)ので恩返し的な意味もあるからやりますよ。ギブ&テイクってやつ?
今回はGDとImageMagick(PerlMagick)のPerlモジュールを使ったサムネイル生成について。単純にGIF/PNG/JPEG画像を指定の大きさに縮小してJPEGで別名保存するスクリプトである。透過GIF/PNGはJPEGに変換すると何故か透過部分が真っ黒になってしまうので、それを回避するために背景色を指定して塗りつぶせるようにした。いろいろ検索してもそういうのがありそうでなかったので自力で組んだ。ひいふう。
大体私は人から「こうなんだよ」と言われても頭ン中じゃ納得せず、自分で動かして失敗してから納得する人。たとえ目的のスクリプトがあったとしても、自分がそれを理解できていないとそのまま使うことができない。そんな、損な性格。
#!/usr/bin/perl
$usemodule = 1; # GDを使う場合1、ImageMagickを使う場合2
$image = 'original.png'; # 元の画像、GIF/PNG/JPEG
$thumbimg = 'thumbnail.jpg'; # サムネイル画像名
$w_maxlimt = 250; # 縮小サイズ横
$h_maxlimt = 250; # 縮小サイズ縦(縦横どちらかがこの数値を超えていたらリサイズ)
$bgcolor = '#f4efdc'; # 元画像が透過GIF/PNGのときに塗りつぶす背景色、16進数指定
# GD
if ($usemodule == 1) {
use GD;
my $thumb = $image;
$thumb =~ /\.jpe?g$/i and $thumb = GD::Image->newFromJpeg("$image");
$thumb =~ /\.gif$/i and $thumb = GD::Image->newFromGif("$image");
$thumb =~ /\.png$/i and $thumb = GD::Image->newFromPng("$image");
my ($width, $height) = $thumb->getBounds(); # 画像サイズ取得
my ($thumbW, $thumbH) = ($width, $height); # リサイズ前処理
if ($thumbW > $w_maxlimt) {
$thumbH = int ($thumbH * ($w_maxlimt / $thumbW));
$thumbW = $w_maxlimt;
}
if ($thumbH > $h_maxlimt) {
$thumbW = int ($thumbW * ($h_maxlimt / $thumbH));
$thumbH = $h_maxlimt;
}
my $thumbnail = GD::Image->new($thumbW, $thumbH);
if ($image !~ /\.jpe?g$/i) { # 背景色塗りつぶし処理(元画像がGIF/PNG)
my (@clr,@clr2);
my $bcolor = $bgcolor;
$bcolor =~ tr/a-f/A-F/;
$bcolor =~ s/#(..)(..)(..)/$1,$2,$3/;
@clr = split /,/,$bcolor;
for (my $i = 0; $i < 3; $i++){ $clr2[$i] = hex ("$clr[$i]"); }
my $bgclr = $thumbnail->colorAllocate($clr2[0],$clr2[1],$clr2[2]);
$thumbnail->transparent($bgclr);
}
$thumbnail->copyResized($thumb, 0, 0, 0, 0, $thumbW, $thumbH, $width, $height); # リサイズ
open (OUT, ">$thumbimg"); # サムネイルの保存
binmode (OUT);
print OUT $thumbnail->jpeg;
close (OUT);
# ImageMagick
} elsif ($usemodule == 2) {
use Image::Magick;
my $thumb = Image::Magick->new();
$thumb->Read("$image");
$thumb->Profile(name=>"*",profile=>""); # Exif情報削除
$thumb->AdaptiveResize(geometry=>"$w_maxlimt x $h_maxlimt"); # リサイズ
if ($image !~ /\.jpe?g$/i) {# 背景色塗りつぶし処理(元画像がGIF/PNG)
my ($thumbW, $thumbH) = $thumb->Get('width', 'height');
my $bgclr = Image::Magick->new(); # 背景画像生成
$bgclr->Set(size =>"$thumbW x $thumbH");
$bgclr->ReadImage("xc:$bgcolor");
$bgclr->Composite(image=>$thumb, compose=>'Over'); # 背景色と元画像を合成
$bgclr->[0]->Write(filename=>$thumbimg); # サムネイルの保存(元画像がGIF/PNG)
undef $bgclr; # ImageMagickの場合、メモリに溜まった画像をクリアする
} else {
$thumb->[0]->Write(filename=>$thumbimg); # サムネイルの保存(元画像がJPEG)
}
undef $thumb; # ImageMagickの場合、メモリに溜まった画像をクリアする
}
exit;
GDは元々ベクター系の画像生成モジュールなので機能はあまりない。その分ImageMagickより処理が長めになる。ImageMagickは画像生成に特化して何でも処理できるスグレモノだけど、かなりクセがあって動かなくて四苦八苦。ちなみにExif情報ってのは、デジカメや画像編集ソフトによってつけられる画像情報。ImageMagickだとそのまま元画像の情報を保持してその分画像が重くなるのでクリアにしておく。
私の知識じゃあんまりスマートに打てなかったけど、動かしていて問題ないので多分大丈夫かと。使いたい人は適当にコピペして動かしてみたり改変してみてください。て、言ってもサムネイルに特化したPerlモジュールもいっぱいあるみたいだけどね。そっちを利用した方が早いかも。しかし私も掲示板運営でもしない限りGDやImageMagickに手を出すことはなかったと思うので、いい勉強になりますた。
テスト環境(Perl 5.10.0/GD 2.44/PerlMagick6.5.3)を使って透過PNGのサムネイル生成結果を見ると、GDの方がサーバ負荷が少ないけど色が悪いしJPEGノイズが目立つしと画質は若干悪い。ImageMagickはシャープに出るけどファイルサイズが大きく、サーバのメモリも倍以上食うみたい。
元画像 (ブラウザのリサイズ/53.7KB |
GD (8.57KB) |
ImageMagick (12.4KB) |
そのうちこの日記にも導入しようと思ってはいるのだが、Nicky!ってかなり改造が難しいんだよね…(すでに色々いじってるけど)。