Image::Magick で画像に透かしを付ける方法


Perl モジュール Image::Magick を使って CGI プログラムでアップロードした画像に透かし(ウォーターマーク)を付ける方法のご紹介です。
むやみな転用を防ぐための「サンプル」などの表示を画像の上に表示します。

これはシリーズ記事「Image::Magick の使い方」の 8/8 番目です。 目次を表示

Image::Magick で画像に透かしを付ける

Image::Magickの使い方サンプルコード元画像

元画像

Image::Magickで透かしを追加した画像

透かしを追加した画像

Image::Magick で画像に透かしを付ける手順

文字なども透かしにできます。手順は少し複雑で、以下の通りです。

  1. 透かしにする内容(文字やマーク)を白黒画像として描く
  2. 透かし部分だけを薄く有効にするマスクを作成
  3. マークファイルとマスクと元画像を結合

もし透かしにアイコンなどの画像を使用したい場合はマークファイルとマスクファイルは手動で作成しサーバにアップロードしておき、Image::Magick で読み込みと結合を行います。

Image::Magick サンプルコード:Image::Magick で画像に透かしを付ける

my $watermark;
my $watermarked;
eval{
#元画像と同じサイズの画像を作る
$watermark=$img->Clone();
$ret = $watermark->Set(
colorspace => ‘RGB’,
);
#一旦黒で塗りつぶし
$ret = $watermark->Colorize(fill=>’Black’);
#マスク画像用に複製しておく
my $mask = $watermark->Clone();

#白字で透かしの内容を書く
$ret = $watermark->Annotate(
font=>’/path/to/font/sazanami-gothic.ttf’,
pointsize=>45, fill=>’white’,
text=> ‘SAMPLE’,
rotate=>-30,
gravity => ‘NorthWest’,
geometry => ‘+30+100’, #gravity指定した位置からのパッディング
);

この時、$watermark->Write で書き出すと以下のような状態です。黒字に白で字を書いたところです。

透かしファイル 中途の状態 (1) 表示する文字を書いた所

透かしファイル 中途の状態 (1) 表示する文字を書いた所

#立体的にするための加工。この辺りはお好みで。
$ret = $watermark->Shade(geometry=>’135×45′);
#Shadeのパラメータ:(光源の位置)x(光源と地面の角度)
#光源の位置は0が真東(右)、90は北(上)。135は北西(左上)から光が当たっている状態

この時、$watermark->Write で書き出すと以下のような状態です。Shade の効果で文字が立体的になっています。

透かしファイル 中途の状態 (2) 立体的に加工

透かしファイル 中途の状態 (2) 立体的に加工

#文字を書いた位置だけが見えるようにマスクを設定。
#この例では文字の部分だけ透過させたいので、
#上で描いた文字と同じ位置に縁を付け加えて薄いグレーで色を付けている。
$ret = $mask->Annotate(
font=>’/path/to/font/sazanami-gothic.ttf’,
pointsize=>45, fill=>’gray20′,
strokewidth=>1, stroke=>’gray20′,
text=> ‘SAMPLE’,
rotate=>-30,
gravity => ‘NorthWest’,
geometry => ‘+30+100’, #gravity指定した位置からのパッディング
);

このマスクだけを、$mask->Write で書き出すと以下のような状態です。黒い所は後で写真を透過し、白い所は透かしとなる文字模様を反映させます。この状態だと、この文字の薄さで、先ほどの影付きの「SAMPLE」を透過する、という事になります。

透かしファイル 中途の状態 (3) マスクとなるファイル

透かしファイル 中途の状態 (3) マスクとなるファイル

#マークとマスクを元画像と合体
$watermarked=$img->Clone();
$ret = $watermarked->Composite(
image=>$watermark, #マークを指定
gravity=>’NorthWest’,
geometry=>’+0-30′,
mask=>$mask, #マスクを指定
);
};
if ($ret||$@) {
print “マスク画像の作成に失敗しました。: $ret $@”;
exit;
}
$saved{wartermark} = “$dir/watermark.png”;
$saved{wartermarked} = “$dir/watermarked.png”;
my $ret;
eval{$ret=$watermark->Write(filename=>$saved{wartermark})};
if ($ret||$@){
print “透かしファイルの保存に失敗しました。: $ret $@\n”;
exit;
}
eval{$ret=$watermarked->Write(filename=>$saved{wartermarked})};
if ($ret||$@){
print “透かし付きファイルの保存に失敗しました。: $ret $@\n”;
exit;
}

これで透かし付きファイルの保存ができました。

そして最後にこれがちょっと不思議なのですが、メッソッド Composite は $watermarked->Composite と、写真に適用したのに、$watermark (マークファイル)の方も、このメソッド実行の後 $watermark->Write で書き出してみると、こちらにもマスクが適用されています。そういうもののようです。

Image::Magickで作成した透かしマーク画像

透かしマーク画像