角度は通常 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
座標 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
座標 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画像ファイルは、先頭の 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 は、Boutell.Com 社が開発した無償のグラフィックライブラリです。線、文字、画像を組み合わせた JPEG 画像や PNG 画像を生成することができます。昔は GIF もサポートしていましたが、Unisys 社の特許問題により GIF 画像のサポートが中止になりました。しかし、現在では多くのブラウザが PNG にも対応しているので問題は少ないでしょう。収集したデータをグラフ化するなどの用途に有用です。
GD.pm は、GD ライブラリを Perl から読み出せるようにした Perl モジュールです。CPAN や ppm に登録されています。
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 に関するマニュアルは、perldoc を用いて下記のように参照してください。
C:\>perldoc GD
GD.pm を用いて簡単な PNG 画像を書き出すサンプルを下記に示します。
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);
print OUT $img->png; の箇所を下記のようにすると、JPEG ファイルへの書き出しを行います。
print OUT $img->jpeg();
JPEG の画像品質を 0~100 で指定することもできます。
print OUT $img->jpeg(70);
座標 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);
座標 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);
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);
座標 50, 50 の場所に小フォントで "Hello" を描画します。
$img->string(gdSmallFont, 50, 50, "Hello", $black);
文字を 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());