GD でグラデーション@山王ココ商店街

 山王ココ商店街のホームページリニューアルにあたり、二十四節気を利用したデザインにしようと考えた。
 とはいえ二十四の画像を一個一個作るのは面倒なので、GD/Perl でまとめて作ってみる。

グラデーションをプログラムする

 今回は左から右へ白くなるグラデーションを作成する。
 画像の横幅は400px。
 CSS で縦に連続するので、縦幅は 1px 。
 各RGB を10進数として、右に1px ずつ 255に近づけていく。
 つまりベースの色の数値から (255-$base)/400 ずつ数値を増やしていく。
 描画は 1x1 の塗りつぶしブロックを400個連結。

	my ($color1, $color2, $color3) = @rgb;
	my $color1_diff = 255-$color1;
	my $color2_diff = 255-$color2;
	my $color3_diff = 255-$color3;
	my $gradation_width = 400;
	for (my $i=0; $i<$gradation_width; $i++) {
		my $color = $image->colorAllocate($color1, $color2, $color3);
		$image->filledRectangle($i, 0, $i+1, 1, $color);
		$color1 += $color1_diff/$gradation_width;
		$color2 += $color2_diff/$gradation_width;
		$color3 += $color3_diff/$gradation_width;
	}

注意点

 単純な256色で作るときれいにグラデーションしないので、True Color で生成。

my $image = new GD::Image(
	400, # 横幅
	1,   # 縦幅
	1    # True Color フラグ
);

実際のコード

use strict;
use utf8;
use Encode;
use Text::CSV_XS;
use GD;

my $file_24sekki_csv = "24sekki.csv";
my $csv = new Text::CSV_XS({binary=>1});
my @list24sekki = ();
open my $IN, '<', $file_24sekki_csv;
while (my $line = $csv->getline($IN)) {
	push @list24sekki, $line;
}
close $IN;

foreach my $sekki (@list24sekki) {
	my @sekki = @$sekki;
	my $title = $sekki[0];
	my @title = split //, decode_utf8($sekki[0]);
	my @color = @sekki[1,2,3];
	my ($color1, $color2, $color3) = @color;
	my $color1_diff = 255-$color1;
	my $color2_diff = 255-$color2;
	my $color3_diff = 255-$color3;
	my $image = new GD::Image(400, 1, 1);
	$image->interlaced('true');
	$image->filledRectangle(0, 0, 400, 1, $image->colorAllocate(255, 255, 255));
	my $gradation_width = 400;
	for (my $i=0; $i<$gradation_width; $i++) {
		my $color = $image->colorAllocate($color1, $color2, $color3);
		$image->filledRectangle($i, 0, $i+1, 1, $color);
		$color1 += $color1_diff/$gradation_width;
		$color2 += $color2_diff/$gradation_width;
		$color3 += $color3_diff/$gradation_width;
	}
	open (OUT, "> background/${title}.jpg");
	binmode OUT;
	print OUT $image->jpeg;
	close OUT;
}