Imagerで画像編集

Strawberry Perlに入ってた Imagerモジュールで画像を少し加工した。ドキュメントが読みにくいけど、Windows環境でもGDIフォントでUnicode文字列を普通に描画できて、いいねコレ。

  • フォント作成時のfaceの指定だけはcp932にエンコードして渡す必要がある。
  • aaフラグを指定しても小サイズのフォントではビットマップが優先して使われてしまう。大きめにレンダリングしてから縮小するといい。
  • 画像縮小の品質はImageMagickに負けてるね。わりとボケる。
#!perl --
use strict;
use warnings;
use Imager;
use utf8;
use Encode;
use YAML::Syck;
$YAML::Syck::ImplicitUnicode =1;

binmode $_,":encoding(cp932)" for \*STDOUT,\*STDERR;

print "Has truetype\n"      if $Imager::formats{tt};
print "Has t1 postscript\n" if $Imager::formats{t1};
print "Has Win32 fonts\n"   if $Imager::formats{w32};
print "Has Freetype2\n"     if $Imager::formats{ft2};

my $font_size = 12;
my $font_internal_scale = 16;

my $font = Imager::Font->new(
	# face=>Encode::encode('cp932',"Georgia"),
	face=>Encode::encode('cp932',"FG丸ゴシック体Ca-B"),
	,size=>$font_size*$font_internal_scale,
	,aa=>1
	,utf8=>1
) or die $!;

sub makeStringImage{
	my($bg,$fg,$str)=@_;
	my @box_value = $font->bounding_box(string => $str);
	my @box_key = qw( neg_width global_descent pos_width global_ascent descent ascent advance_width right_bearing);
	my $box = {};
	for(my $i=0;$i<@box_value;++$i){
		$box->{$box_key[$i]}=$box_value[$i];
	}
	my $img = Imager->new(
		xsize=>$font_internal_scale*2 + $box->{pos_width}-$box->{neg_width},
		ysize=>$font_internal_scale*2 + $box->{global_ascent}-$box->{global_descent}
	);
	$img->box(filled=>1, color=>$bg);
	$img->string(
		text  => $str,
		font  => $font,
		x     => $font_internal_scale + ($box->{neg_width} <0?-$box->{neg_width}:0),
		'y'   => $font_internal_scale + ($box->{global_ascent}>0?$box->{global_ascent}:0),
		aa    => 1,
		color => $fg,
	);
	my $newimg = $img->scale( scalefactor=>(1/$font_internal_scale),qtype=>'normal');
	return $newimg;
}

	my $fg = Imager::Color->new("#000000");
	my $bg = Imager::Color->new("#ffffff");