2011-07-17

[perl] Imager で背景用タイル画像を動的に生成する

このブログをご覧の数少ない読者さんはもうご存知かもしれませんが、hidekiy.com の背景画像と配色その他を夏用にリニューアルしてみました。

ひとつ前のバージョンでは、Image::Imlib2 を使っていたのですが、HSV色空間への対応や、変数への書き出しのあたりがイマイチだと思っていたので、今回は新しく Imager を使ってみました。
$ cpanm Imager
で簡単にインストール出来る点と、丁寧なドキュメントを考慮すると、ImageMagickより良さそうな気がしました。

ソースコードは以下の通りです。

use strict;
use warnings;
use Imager;
use Plack::Request;

my $app = sub {
    my ($env) = @_;
    my $req = Plack::Request->new($env);

    my ($xsize, $ysize) = (60, 60);

    my $img = Imager->new(
        xsize => $xsize,
        ysize => $ysize,
    );

    $img->box(filled => 1, color => 'white');

    my $hue1 = rand(360);
    my $hue2 = $hue1 + 60;

    for my $i (0 .. 9) {
        my $color =  Imager::Color->new(
            hue => ($i % 2 ? $hue1 : $hue2),
            saturation => rand(0.1),
            value => 1,
        );

        $img->box(
            xmin => rand($xsize),
            ymin => rand($ysize),
            filled => 1,
            color => $color,
        );
    }

    my $data;
    $img->write(type => 'png', data => \$data);

    my $res = $req->new_response;
    $res->status(200);
    $res->content_type('image/png');
    $res->body([$data]);

    return $res->finalize;
};

出力例(60x60pxの画像を25個くっつけたもの)

動かし方: app.plで保存して、$ plackup app.pl

まず、$hue1, $hue2は、色相環で考えたときに60度離れた色相を2つ用意しています。
10回のループ中で、画像内のランダムな任意の一点から右下隅までを塗りつぶします。
塗りつぶすときの色は、用意した色相を交互に用いながら、彩度をランダムに変更することで、ちょっと色のくすみ方が変わります。

これをRGBで選ぶ方法でいい感じにするのは難しいので、HSV色空間を理解されると色指定が簡単になると思います。