図形描画

■ 角度とラジアンの変換

◆ ラジアン単位とは

角度は通常 0~360°で表しますが、SI 単位系では ラジアン単位系 を用います。ラジアン単位系では、180°が π、360°が 2π に相当します。Perl でも sin() や cos() など多くの関数がラジアン単位系を用います。

◆ 角度とラジアン単位の変換

通常の角度(°)からラジアン単位系への変換、また、その逆変換は下記のようにします。

# π を定義しておく
sub PI() { 3.141592653589793; }

# 角度からラジアンへの変換
sub DegToRad { return $_[0] * PI / 180; }

# ラジアンから角度への変換
sub RadToDeg { return $_[0] * 180 / PI; }

次のように使用します。

$kakudo = 45;     # 角度45°

$rad = DegToRad($kakudo);
print "ラジアン:$rad\n";

$deg = RadToDeg($rad);
print "角度(°):$deg\n";

結果は次のようになります。

ラジアン:0.785398163397448
角度(°):45

■ 角度と距離からXY座標への変換

◆ 角度と距離からXY座標への変換

座標 0, 0 から、角度30度、距離 100ドットの場所の X, Y 座標を求めます。

sub PI() { 3.141592653589793; }            # 円周率 π
sub DegToRad { return $_[0] * PI / 180; }  # 度→ラジアン単位への変換

$d = 100;                                  # 距離 100ドット
$a = 30;                                   # 角度 30°

$x = $d * cos(DegToRad($a));               # X座標を求める
$y = $d * sin(DegToRad($a));               # Y座標を求める

printf("x=%5.2f, y=%5.2f\n", $x, $y);

結果は次のようになります。

x=86.60, y=50.00

■ XY座標から角度への変換

◆ XY座標から角度への変換

座標 0, 0 から見て、座標 X, Y の角度は、atan2(y, x) により求まります。返される値はラジアン単位なので、これを角度°の単位に変換しています。

sub PI () { 3.141592653589793; }           # 円周率
sub RadToDeg { return $_[0] * 180 / PI; }  # ラジアン→度への変換

$x = 86.60;                                # X座標
$y = 50.00;                                # Y座標

$a = RadToDeg(atan2($y, $x));              # 角度を求める

printf("a=%5.2f°\n", $a);

結果は次のようになります。

a=30.00°

■ GIF画像の大きさを求める

◆ GIF画像の大きさを求める

GIF画像ファイルは、先頭の 3バイトが "G"、"I"、"F"、次の 3バイトが "8"、"9"、"a" などのバージョン番号、次の 2バイトに幅、次の 2バイトに高さの情報が格納されています。幅と高さは、最初の 1バイトが下位 8ビット、次の 1バイトが上位 8ビットを示します。下記のサブルーチンでは、指定したファイルからこの情報を読み取り、返しています。

sub GetGifSize {
    local($gif, *height, *width) = @_;
    local(*IN, $buf);

    open(IN, $gif) || return 0;
    binmode(IN);
    read(IN, $buf, 10);
    close(IN);

    $width = ord(substr($buf, 7, 1)) * 256 + ord(substr($buf, 6, 1));
    $height = ord(substr($buf, 9, 1)) * 256 + ord(substr($buf, 8, 1));

    return 1;
}

使用例を下記に示します。

GetGifSize("image.gif", *height, *width);
print "height=$height, width=$width\n";

実行結果は例えば次のようになります。

height=31, width=88

■ GDをインストールする

◆ GDとは

GD は、Boutell.Com 社が開発した無償のグラフィックライブラリです。線、文字、画像を組み合わせた JPEG 画像や PNG 画像を生成することができます。昔は GIF もサポートしていましたが、Unisys 社の特許問題により GIF 画像のサポートが中止になりました。しかし、現在では多くのブラウザが PNG にも対応しているので問題は少ないでしょう。収集したデータをグラフ化するなどの用途に有用です。

◆ GD.pm とは

GD.pm は、GD ライブラリを Perl から読み出せるようにした Perl モジュールです。CPANppm に登録されています。

◆ インストール方法

Windows 環境に GD.pm をインストールする方法を紹介します。通常であれば、ppm コマンドを用いて下記のようにインストールできます。

C:\> ppm install GD

上記でうまくいかない場合は、http://www.activestate.com/PPMPackages/zips/ から GD.zip をダウンロードし、解凍した後、GD.ppd が存在するフォルダで下記のコマンドを実行してください。

C:\Temp\GD> ppm install GD.ppd

それでもうまくいかない場合は、正式なインストール方法ではありませんが、GD.zip の中に含まれる MSWin32-x86-multi-thread\GD.tar.gz ファイルを「解凍レンジ」などの解凍ソフトで解凍し、最低限下記のファイルを ActivePerl がインストールされているフォルダにコピーしてください。

◆ GD に関するマニュアル

GD に関するマニュアルは、perldoc を用いて下記のように参照してください。

C:\>perldoc GD

■ GDで画像を書き出す(gd)

◆ gdモジュール

GD.pm を用いて簡単な PNG 画像を書き出すサンプルを下記に示します。

gd-test.pl
use GD;

# 画像を作る
$img = new GD::Image(100, 100);

# 色を定義する
$white = $img->colorAllocate(255, 255, 255);
$black = $img->colorAllocate(0, 0, 0);
$green = $img->colorAllocate(0, 128, 0);

# 白を透明色にし、インタレース化する
$img->transparent($white);
$img->interlaced('true');

# 枠線、円を描き、塗りつぶし、文字を描く
$img->rectangle(0, 0, 99, 99, $black);
$img->arc(50, 50, 50, 50, 0, 360, $green);
$img->fill(50, 50, $green);
$img->string(gdMediumBoldFont, 10, 10, "Hello!!", $black);

# 結果を PNG 形式でファイルに書き出す
open(OUT, "> gd-test.png");
binmode(OUT);
print OUT $img->png;
close(OUT);
◆ JPEGファイルへの書き出し

print OUT $img->png; の箇所を下記のようにすると、JPEG ファイルへの書き出しを行います。

print OUT $img->jpeg();

JPEG の画像品質を 0~100 で指定することもできます。

print OUT $img->jpeg(70);

■ GDの各種描画ルーチン(描画)

◆ 点を描画する

座標 50, 50 に黒い点を描画します。$black の部分には colorAllocate() で作成したカラーインデックスを指定します。

$img->setPixel(50, 50, $black);
◆ 線を描画する

座標 0, 0 から 座標 99, 99 に黒い線を描画します。

$img->line(0, 0, 99, 99, $black);
◆ 点線を描画する

座標 0, 0 から 座標 99, 99 に黒い点線を描画します。

$img->dashedLine(0, 0, 99, 99, $black);
◆ 円を描画する

座標 50, 50 を中心に、幅 100、高さ 100、開始角度 0度、終了角度 360度の黒い孤を描画します。

$img->arc(50, 50, 100, 100, 0, 360, $black);
◆ 矩形を描画する

座標 0, 0 と 座標 99, 99 を頂点とする黒い矩形を描画します。

$img->rectangle(0, 0, 99, 99, $black);
◆ 多角形を描画する

座標 50, 0、座標 0, 99、座標 99, 99 を頂点とする多角形を描画します。

$poly = new GD::Polygon;
$poly->addPt(50,0);
$poly->addPt(0,99);
$poly->addPt(99,99);
$img->polygon($poly, $black);

■ GDの使い方(塗りつぶし)

◆ 塗りつぶし矩形を描画する

座標 0, 0 と 座標 99, 99 を頂点とする黒い矩形を描画し、中を塗りつぶします。

$img->filledRectangle(0, 0, 99, 99, $black);
◆ 塗りつぶし多角形を描画する

座標 50, 0、座標 0, 99、座標 99, 99 を頂点とする多角形を描画し、中を塗りつぶします。

$poly = new GD::Polygon;
$poly->addPt(50,0);
$poly->addPt(0,99);
$poly->addPt(99,99);
$img->filledPolygon($poly, $black);
◆ 塗りつぶし円弧(扇形)を描画する

残念ながら、GD.pm(Ver1.27)では塗りつぶしの円弧(扇形)はまだサポートされていないようです。

◆ 閉領域を塗りつぶす

座標 50, 50 を含む閉領域を黒く塗りつぶします。

$img->fill(50, 50, $black);
◆ 指定色の閉領域を塗りつぶす

座標 50, 50 を含む、青い線で囲まれた閉領域を黒く塗りつぶします。

$img->fillToBorder(50, 50, $blue, $black);
◆ 塗りつぶしパターン

塗りつぶしパターンを画像で指定します。

$tile = newFromPng GD::Image('pattern.png');
$img->setTile($tile); 
$img->filledRectangle(0, 0, 99, 99, gdTiled);

■ GDの使い方(色関連)

◆ 色を生成する

line() や rectangle() などで使用する色を作成し、そのカラーインデックスを返します。引数には RGB(赤、緑、青)の色を 0~255 の範囲で指定します。

$white = $img->colorAllocate(255, 255, 255);
◆ 指定座標のカラーインデックスを得る

指定した座標に描画されているカラーインデックスを取得します。

$color1 = $img->getPixel(50, 50);
◆ カラーインデックスから色情報を得る

カラーインデックスから、赤、緑、青の色情報を得ます。各色情報は 0~255 となります。

($red, $green, $blue) = $img->rgb($color1);
◆ 透過色を指定する

透過形式の PNG 画像を作成する際の、透過色にするカラーインデックスを指定します。引数無しで呼び出すと、現在の透過カラーインデックスを返します。透過色が指定されていない場合は -1 を返します。

$img->transparent($white);
◆ 近似色を得る

現在、画像に関連付けられているカラーテーブルの中から、指定した色に一番近い色のカラーインデックスを返します。見つからない場合は -1 を返します。

$blue = $img->getClosest(0, 0, 255);

■ GDの使い方(文字)

◆ 文字を描画する

座標 50, 50 の場所に小フォントで "Hello" を描画します。

$img->string(gdSmallFont, 50, 50, "Hello", $black);
◆ 90°傾けた文字を描画する

文字を 90°傾けたフォントで描画します。

$img->stringUp(gdSmallFont, 50, 50, "Hello", $black);
◆ 日本語を描画する

日本語を描画するには stringTTF() を用います。下記の例では、黒色で、"MS ゴシック" の 18ポイントフォントで、角度 0°の方向に、座標 20, 20 から、"あいうえお" を描画しています。フォントは *.TTF や *.TTC を指定してください。日本語は Unicode(UTF-8) で指定する必要があるので、Jcode.pm を用いて変換しています。

use Jcode;
$img->stringTTF($black, "c:\\windows\\fonts\\msgothic.ttc",
    18, 0, 20, 20, Jcode->new("あいうえお", "sjis")->utf8());

Copyright (C) 2002 杜甫々