PerlのImagerライブラリで「キャラクターなんとか機」のマネをしてみる(2)

前回の課題の解決に挑戦。

Cent OS 6サーバ上でCGIとして動作させる

画像生成の部品として使用しているキャラクターなんとか機のパーツは、ファイル名がそのまま表示名になる仕様であり、日本語になっている。
FTPソフトで転送した際に文字化けを起こしていたので、Cent OS 6のファイルシステムに合わせてUTF-8に変更して転送する設定にした。
また、スクリプトから日本語でファイル名を直接指定しているので、スクリプト自体も文字コードをUTF-8にして保存する。
これであっさりとサーバ上で動作した。
せっかくなので、実行するとHTTPヘッダと画像データのバイナリを標準出力に書き込む動作に変更し、昔のアクセスカウンターのようにimgタグで呼び出す仕様にしてみた。

色をランダムに選択

これに関してはこれができることを意識してもともとスクリプトを書いていたので、簡単に終了。

スクリプト全文


#!/usr/bin/perl
use Imager;
local $basedir = './data/default';
local @layers = (
'accessory_back',
'hair_back',
'hair_back_accessory',
'body_back',
'accessory_underwear',
'body_front',
'body_front_color',
'accessory_middle_back',
'head',
'accessory_middle_front',
'face_back',
'hair_front',
'hair_front_accessory',
'face_front',
'eye',
'accessory_front'
);
local %colorgloup = (
'head'				=> 'body',
'face_back'			=> '',
'face_front'			=> '',
'eye'				=> 'eye',
'hair_back'			=> 'hair',
'hair_front'			=> 'hair',
'hair_back_accessory'		=> '',
'hair_front_accessory'		=> '',
'body_back'			=> 'body',
'body_front'			=> '',
'body_front_color'		=> 'cloth',
'accessory_underwear'		=> '',
'accessory_middle_back'		=> '',
'accessory_middle_front'	=> '',
'accessory_back'		=> '',
'accessory_front'		=> ''
);
my %charaparts = (
'head'				=> '普通な顔1.png',
'face_back'			=> '素.png',
'face_front'			=> '素.png',
'eye'				=> '普通な目1.png',
'hair_back'			=> 'ロング.png',
'hair_front'			=> 'ナチュラル.png',
'hair_back_accessory'		=> 'ツインテール(長).png',
'hair_front_accessory'		=> '',
'body_back'			=> 'サマードレス1.png',
'body_front'			=> '',
'body_front_color'		=> 'サマードレス1.png',
'accessory_underwear'		=> '',
'accessory_middle_back'		=> '',
'accessory_middle_front'	=> '',
'accessory_back'		=> '',
'accessory_front'		=> ''
);
local %colormatrixorigin = (
'blue' =>   [	[ 1	, 0	, 0	, 0	],
		[ 1	, 0	, 0	, 0	],
		[ 0	, 0	, 1	, 0	],
		[ 0	, 0	, 0	, 1	], ],
'purple' => [	[ 0	, 0	, 1	, 0	],
		[ 1	, 0	, 0	, 0	],
		[ 0	, 0	, 1	, 0	],
		[ 0	, 0	, 0	, 1	], ],
'red' =>   [	[ 0	, 0	, 1	, 0	],
		[ 1	, 0	, 0	, 0	],
		[ 1	, 0	, 0	, 0	],
		[ 0	, 0	, 0	, 1	], ],
'yellow' => [	[ 0	, 0	, 1	, 0	],
		[ 0	, 0	, 1	, 0	],
		[ 1	, 0	, 0	, 0	],
		[ 0	, 0	, 0	, 1	], ],
'green' => [	[ 1	, 0	, 0	, 0	],
		[ 0	, 0	, 1	, 0	],
		[ 1	, 0	, 0	, 0	],
		[ 0	, 0	, 0	, 1	], ],
'water' => [	[ 1	, 0	, 0	, 0	],
		[ 0	, 0	, 1	, 0	],
		[ 0	, 0	, 1	, 0	],
		[ 0	, 0	, 0	, 1	], ],
'black' => [	[ 1	, 0	, 0	, 0	],
		[ 1	, 0	, 0	, 0	],
		[ 1	, 0	, 0	, 0	],
		[ 0	, 0	, 0	, 1	], ],
'white' => [	[ 0	, 0	, 1	, 0	],
		[ 0	, 0	, 1	, 0	],
		[ 0	, 0	, 1	, 0	],
		[ 0	, 0	, 0	, 1	], ],
'dummy' => [	[ 1	, 0	, 0	, 0	],
		[ 0	, 1	, 0	, 0	],
		[ 0	, 0	, 1	, 0	],
		[ 0	, 0	, 0	, 1	], ]
);
my @colorlist =  keys(%colormatrixorigin);
my %colormatrix = (
'eye'	=> $colormatrixorigin{$colorlist[int(rand(@colorlist))]},
'hair'	=> $colormatrixorigin{$colorlist[int(rand(@colorlist))]},
'cloth'	=> $colormatrixorigin{$colorlist[int(rand(@colorlist))]},
'body'	=> $colormatrixorigin{'dummy'},
);
my $imager = Imager->new(xsize => 300,ysize => 400, channels => 4);
$imager = &makechara($imager,\%charaparts,\%colormatrix);
my $data;
$imager->write(data => \$data, type => 'png') or die $imager->errstr;
binmode STDOUT;
print "Content-type: image/png\n";
print "Pragma: no-cache\n\n";
print $data;
sub makechara{
	(my $imager,my $charapartsref,my $colormatrixref) = @_;
	my $imagertmp = Imager->new(xsize => 300,ysize => 400, channels => 4);
	foreach(@layers){
		unless($charapartsref->{$_}){next;}
		$imagertmp->read( file => "$basedir/$_/$charapartsref->{$_}" ) or die $imagertmp->errstr;
		if($colormatrix{$colorgloup{$_}}){
			$imagertmp = $imagertmp->convert(matrix => $colormatrixref->{$colorgloup{$_}});
		}
		$imager->rubthrough( src => $imagertmp, tx => 0, ty =>0);
	}
	return $imager;
}

結果

↓リロードしたら色が変わるはず
imagertest

今後の課題

  • 本当はローカル(windows)とサーバ(linux)を同一スクリプトで動かしたい。スクリプト・ファイルシステム・テキストファイル内の文字コードを自動で判別して変換してくれるライブラリだかモジュールだかがあるんじゃないかと思ったが、ちょっと探したところ見つけられなかった。ローカルではShift-JISで動かして、サーバにFTPで転送する際にUTF-8に変換されるように設定するという方法もある…のか?
  • パーツのランダム選択機能はどうしようか。ディレクトリ内のファイルリストを作ってランダムで選ぶ or 別途パーツリストを作ってそこから選択で検討。後者を選ぶなら、ついでにパーツの名称とファイル名の変換テーブルも作ってファイルをリネームすればもう一つの問題も解決できるが、パーツフォルダはそのままで本家キャラクターなんとか機と互換する状態にしたいとも思う。
  • ところでこれって、ユーザがブラウザ上でパーツを選びべるようにして、Ajaxとかでプレビュー画像を随時更新すればWeb版キャラクターなんとか機になるんじゃないかと思ったら、すでにJavaScript版が公開されていた。当然この用途ならJavaScriptの方が効率的だよなぁ…あとFlashもアリか。