読者です 読者をやめる 読者になる 読者になる

valid,invalid

関心を持てる事柄について

画像を指定の枠に収まるようにリサイズ&余白を透明化

業務で必要になり、Perlでの画像加工処理を書いた。

実現したいこと

  1. 画像のアスペクト比を維持したまま、指定したサイズの枠に収まるようにリサイズ
  2. 指定したサイズの枠の中心に画像を貼り付け、余白は透明にする

今回は透明のキャンバスを作り、その上にリサイズした画像を貼り付けることで実現する。
そのコードが下記。

use Image::Magick;

my $src = "cat.png"; # 読み込むファイル名
my $dst = "dst.png"; # 出力する画像ファイル名
my $canvas_width = '600'; # 枠の幅
my $canvas_height = '400'; # 枠の高さ

# 透明のcanvasを作成
my $canvas = Image::Magick->new;
$canvas -> Set(size=>$canvas_width . 'x' . $canvas_height);
$canvas -> ReadImage('xc:white');
$canvas -> Transparent(color=>'White');

# 画像を読み込む
my $src_image = Image::Magick->new;
$src_image -> Read("$src");
my($src_width, $src_height) = $src_image -> Get('width', 'height');

# 画像とcanvasアスペクト比を比較
my $canvas_ratio = $canvas_width / $canvas_height;
my $src_ratio = $src_width / $src_height;
my $magnification = 0;

# 画像がcanvasに対して縦長の場合
if ($canvas_ratio > $src_ratio) {
# 高さの比を倍率にする
$magnification = $canvas_height / $src_height;

# 画像がcanvasに対して横長、もしくは完全一致の場合
} elsif ($canvas_ratio <= $src_ratio) {
# 幅の比を倍率にする
$magnification = $canvas_width / $src_width;
}

# 倍率を指定してリサイズ
$src_image -> Resize(width=>int($src_width * $magnification),
height=>int($src_height * $magnification));

# 画像を重ねる
$canvas->Composite(image=>$src_image, compose=>'over', gravity=>'Center');

# 画像を出力
$canvas->Write("$dst");


【実行結果】

この猫の画像(1600x1200)を


600x400の枠に収めようとすると、出力結果はこんな感じになる。
クリックするとリサイズの効果と、左右に透明の余白があることがわかる(はず)。

とはいえあまりにわかりにくいのでExcelに貼り付け、画像に枠線を付けてみたのが↓。


Perlは半年以上前にいくつか手探りでバッチ作ったけど、それを除けばほとんど書いたことなし。
今回は文法をおさらいしつつ書いたけど、いまいちPerlの文化というか作法みたいなのはわからず…。

そして、Image::Magick便利。

【環境】

ActivePerl 5.16.3
Image::Magick 6.8.9

【参考】

Matsup's blog: FreeBSDでPerlMagick(その4)図形の描画と画像の加工
PerlMagickで画像の大きさを変更する(Image::Magick) | ぺんラボ
Perl::ImageMagickでよく使うコマンドとサンプル | くろひつじのメモ帳


【追記(2014/05/11)】

そういえば拡張子によっては透過って対応してないような…と思い、pnggif/jpgと試していった。
そしたらjpgだと余白が透過になっておらず、調べるとjpgは透過できないぽい。

透過背景とか使いたい場合は対応している拡張子で保存するようにする。

また、Image::MagickのRead/Write処理では記述した拡張子で読み込み/保存を行ってくれるとのこと。