Ruby/GD の主な使用方法について紹介します.Ruby/GD で提供されているメソッ ドの完全なリストについては同梱されているmanual.htmlを参照して下さい. また,このドキュメントの最新版は常にここ に置いてあります.
GD -+ | +- GD::Image | +- GD::Polygon | +- GD::Font
GD::Image#polygon
によってポリゴンが実際
に描画される.
GD::Fontオブジェクトは文字(列)描画メソッドの引数に用
いられる.
以下では次のような記法を採用します.
- クラスメソッドはクラス名とメソッド名をピリオドで連結したもので表
現する.
例:GD::Image.new
- メソッド(インスタンスメソッド)はクラス名とメソッド名をシャープ記
号で連結したもので表現する.
例:GD::Image#line
- Boutell の gd library のことを gd と表記する.
はじめに
Ruby/GD ライブラリを用いる場合,スクリプトの始めに
require 'GD'
の1行を書いて下さい.
目次
- 1. イメージを生成する
- 1.1 新規にイメージを生成する
- 1.2 画像ファイルから新規にイメージを生成する
- 2. イメージの操作
- 2.1 線分を描く
- 2.2 カスタマイズした線分を描く
- 2.3 図形を描く
- 2.4 多角形を描く
- 2.5 イメージのコピー
- 3. 文字(列)を描く
- 3.1
GD::Font
クラスで提供されるフォント
を使う
- 3.2 TrueTypeフォントを使う
- 4. イメージの出力
- 5. 補足
- 5.1 オブジェクトの削除
- 5.2 インタレース
- 5.3 色の割り当てについてもっと
1. イメージを生成する
GD::Image
インタンス生成のための一連のクラスメソッドが用意
されています.
1.1 新規にイメージを生成する
イメージを新規に生成するために,次のクラスメソッドが提供されています.
GD::Image.new(w, h)
- 幅w, 高さhのGD::Imageオブジェクトを生成する(w,hの単位はピクセル).
戻り値は生成されたGD::Imageオブジェクト.
新規にイメージを生成した場合,描画などの操作を行う前に必ず背
景色を設定するようにしましょう.そのためにGD::Image#colorAllocateメソッ
ドを使用します.
GD::Image#colorAllocate(r, g, b)
GD::Image#colorAllocate(str)
- オブジェクトに対して r, g, bで指定したRGB要素,または文字列
"#xxxxxx"(xは16進数)で色を設定する.
r, g, bは0から255までの整数.戻り値は指定された色のテーブルのイ
ンデックス.
オブジェクトに対して最初にこのメソッドを適用した場合,
そのときに指定した色が背景色となる.
1.2 画像ファイルから新規にイメージを生成する
以下のフォーマットの画像ファイルを読みこんで,GD::Imageオブジェクトを
生成することができます.
- PNG(Portable Network Graphic)形式
- Xpm(Xピクセルマップ)形式
- Xbm(Xビットマップ)形式
- (gd-1.8.3から)JPEG形式
さらにあまり一般的ではありませんが,gd固有の画像フォーマットとしてGd,
Gd2形式があり,これらで保存したイメージからもGD::Imageオブジェクトを作
成することができます.
典型的な例を挙げると,PNGイメージファイルからイメージを読み込んで,
GD::Imageオブジェクトを生成するためのクラスメソッドは次の通りです.
GD::Image.newFromPng(file)
- fileからイメージを読み込んでGD::Imageオブジェクトを生成する.
file はFile.openによって読み取り用にオープンされたFileインス
タンスか,標準入力.戻り値は生成されたGD::Imageオブジェクト.
例
- 幅100ピクセル,高さ100ピクセルのインスタンスを新規に生成し,背景色
を白に設定する.
im = GD::Image.new(100, 100)
white = im.colorAllocate(255, 255, 255)
# 変数whiteの値は白(red:255, green:255, blue:255)に
# 対応するカラーテーブルのインデックス
# 次のように書いてもO.Kです.
# white = im.colorAllocate("#FFFFFF")
- カレントディレクトリにあるPNG画像ファイル"image.png"からインタン
スを生成する.
in_file = File.open("image.png", "r")
im = GD::Image.newFromPng(in_file)
in_file.close
2. イメージの操作
線分や図形を描画する際に点などの位置,または角度の情報を与えることが必
要になります.その際使用される座標軸はイメージの左上角を原点として下図
のように表されます.
(イメージの左上角) X
+-------------->
|
| .
| (x,y)
|
|
Y v
2.1 線分を描く
イメージに単色の線分を描くには,次のメソッドを用います.
GD::Image#line(x1, y1, x2, y2, color)
- (x1, y1) から (x2, y2) まで color で指定された色で
線分を描く.color は GD::Image#colorAllocateで指定
された色.
例
im = GD::Image.new(100,100)
# 背景色は黒.im.colorAllocate("#000000") と書いてもいいです.以下同様.
black = im.colorAllocate(0, 0, 0)
red = im.colorAllocate(255, 0, 0)
# (0,0) から (50, 50) まで赤で線分を描く
im.line(0,0,50,50,red)
出力例:
2.2 カスタマイズした線分を描く
(1) 描画色のパターンを指定する
上のようにcolorとしてGD::Image#colorAllocateで割り当てられた色を用いる
と単色の線分が描かれますが,GD::Image#setStyleを用いると,この線分の色
をカスタマイズすることができます.これを利用して好みでカラフルな線分,
破線や点線などを生成することもできます.
GD::Image#setStyle(color1, color2...)
- 描画色パターンを指定する.引数は1つ以上のGD::Image#colorAllocate
で割り当てられた色,もしくはGD::Transparentによって指定された透
明色.
GD::Styled
- 描画メソッドの色の引数にこの定数を与えると,上の
GD::Image#setStyle で指定された色パターンを用いて描画が行われる.
例 ("カラフル"な線分を描く)
black = im.colorAllocate(0,0,0) # 背景は黒.
red = im.colorAllocate(255, 0, 0) # im.colorAllocate("#FF0000") でも
blue = im.colorAllocate(0, 0, 255) # だいじょうぶです.以下同様.
green = im.colorAllocate(0, 255, 0)
# 赤,緑,青の順に2ピクセルづつ色が異なる線分のスタイルを指定する.
im.setStyle(red, red, green, green, blue, blue)
im.line(0,0,100,100, GD::Styled)
出力例:
破線や点線を描くときには,線分が切れて描かれないところは背景の画像の色
がそのままであった方がよいでしょう.この目的のためにスタイルの指定時に
定数GD::Transparent
を使うことができます.
例 (赤地に白色の破線を描く)
red = im.colorAllocate(255, 0, 0)
white = im.colorAllocate(255, 255, 255)
im.setStyle(white, white, white,
GD::Transparent, GD::Transparent, GD::Transparent)
im.line(0,0,100,100, GD::Styled)
出力例:
もちろん,線を描画するイメージが複雑でもちゃんと透過してくれます.
出力例:
(2) ブラシを指定する
幅があり何らかの形状を持つイメージを繰り返しを用いて線や図形を描くこと
があります.そのようなイメージは特にブラシ(brush) といいます.Ruby/GD
では任意のGD::Image
オブジェクトをブラシとすることができま
す.このブラシを用いて線分を描くことができます.そのためには,ブラシイ
メージを指定しなければなりません.
GD::Image#setBrush(image)
- ブラシとしてimageを指定する.
GD::Image::Brushed
- 描画メソッドの色の引数にこの定数を与えると,
上のGD::Image#setBrushで指定したブラシで描画される.
例 (ブラシを使って線分を描く:その1)
例えば,
("xpy.png
")
をブラシとして指定したいとします(こ
のイメージに描かれている絵を以降「プヨの絵」と称することにします).
im = GD::Image.new(100,100)
white = im.colorAllocate(255,255,255) # 背景色は白
black = im.colorAllocate(0,0,0)
br_file = open("xpy.png", "r")
brush = GD::Image.newFromPng(br_file)
im.setBrush (brush)
# (0,0) から (100,100) までsetBrushで指定したブラシイメージで線分を描く
im.line(0,0,100,100,GD::Brushed)
出力例:
これはまさに期待される出力結果なのですが,指定したブラシイメージが悪かっ
たんでしょうね.もう少し見映えよく線分が描画されたいものです.
まず,元のブラシ画像でプヨの絵の境界から外は背景の色を透過させたい.そ
してプヨの絵がもうすこし分かるように描画されたい.前者の目的のために次
のメソッドが提供されています.
GD::Image#transparent(color)
- 透過色をcolorで指定された色にする.colorは
GD::Image#colorAllocateなどによってわりあてられた色.
次の定数を利用すると,後者の目的を果たすことができます.
GD::StyledBrushed
- 描画メソッドの色の引数にこの定数を与えると,GD::Image#setStyleで
指定されたパターンで,GD::Image#setBrushで指定したブラシによって
描画される.
例 (ブラシを使って線分を描く:その2)
im = GD::Image.new(100,100)
white = im.colorAllocate(255,255,255) # 背景色は白
dummy_color = im.colorAllocate(0,0,0)
file = open("xpy.png", "r")
brush = GD::Image.newFromPng file
brush.transparent white # 透過色を白(背景色)に設定する.
# 10個のGD::Transparentからなる配列を生成.
tr_ary = Array.new(10, GD::Transparent)
im.setBrush(brush)
# 描画パターンの指定.*を付けて配列を展開していることに注意.
im.setStyle(black, *tr_ary)
im.line(0,0,100,100,GD::StyledBrushed)
出力例:
ほとんど「線分の描画」というテーマから離れてきているな...
上のスクリプト例では,描画パターンの指定は「黒1ピクセルに10ピクセル分
の背景イメージ色を変化させない」ですが,GD::StyledBrushed
を描画メソッドの色の引数に与えると,描画メソッドはこのsetStyleメソッド
で指定されたパターンを見て,「GD::Transparent
や
0と指定されていないところ」(上の例では
"black
")にブラシイメージを配置します.ですから
"black"
でなくても任意の色であればよいのです.
まとめると,上の例では,「10ピクセルの間隔でプヨの絵を並べる」というパ
ターンで線分を描画していることになります.プヨの絵は縦横ともに32ピクセ
ルなので一部重なっているのです.
2.3 図形を描く
以下に示すメソッドで描画色を指定する際,上でとりあげた
GD::Styled
,GD::Brushed
,
GD::StyledBrushed
を指定することができます.
長方形を描く
長方形を描くためには次のメソッドを用います.
GD::Image#rectangle(x1, y1, x2, y2, color)
- (x1,y1)から(x2,y2)までの線分を対角線とする長方形を color 色で描く.
例 (長方形および破線の長方形)
im = GD::Image.new(100, 100)
white = im.colorAllocate(255, 255, 255) # 背景は白
black = im.colorAllocate(0, 0, 0)
im.setStyle(black, black, GD::Transparent, GD::Transparent)
im.rectangle(10, 10, 50, 50, black)
im.rectangle(50, 50, 90, 90, GD::Styled)
出力例:
弧を描く
次のメソッドを用います.
GD::Image#arc(cx, cy, w, h, s, e, color)
- (cx,cy) を中心にもつ幅w高さhの楕円のうち,角度s から角度eまでの範囲を
色colorにて描画する.
例 (楕円,およびブラシで描かれた円弧
im = GD::Image.new(100, 100)
brush = GD::Image.new(5,5)
green = brush.colorAllocate(0,255,0) # ブラシの背景は緑
white = im.colorAllocate(255, 255, 255) # 背景は白
black = im.colorAllocate(0, 0, 0)
im.setBrush br # 5x5ピクセルの緑色の正方形をブラシに設定
im.arc(25, 50, 40, 90, 0, 360, black)
im.arc(75, 50, 40, 90, 0, 160, GD::Brushed)
出力例:
2.4 多角形 (ポリゴン) を描く
ポリゴンを描画するためには,次のような手順にしたがいます.
- クラスメソッドGD::Polygon.newによって新しいポリゴンオブジェクトを生成する
- ポリゴンオブジェクトに提供されているメソッドを用いて,頂点の追加等の操作を行なう(下記参照).
- GD::Image#polygonによってポリゴンをイメージ上に描く.
頂点の追加
ポリゴンを生成するには,ポリゴンを形成する(頂)点を指定する必要がありま
す.そのためのメソッドは次のようなものです.
GD::Polygon#addPt(x, y)
- ポリゴンオブジェクトに,(x, y)に位置する点を追加する.
頂点は追加された順にインデックスが振られ,n角形ならばそれぞれ追加した
順に0番目,1番目,... ,(n-1)番目の頂点になります.
例 (三角形を描画する)
im = GD::Image.new(100,100)
black = im.colorAllocate(0,255,0) # 背景色は緑
red = im.colorAllocate(255, 0, 0) # ポリゴンの色は赤にしよう.
poly = GD::Polygon.new # この時点では多角形の頂点は存在していない.
poly.addPt(25, 25) # 以下,頂点の追加
poly.addPt(75, 25)
poly.addPt(25, 75)
im.polygon(poly, red) # イメージ im 上にこのポリゴンを描画
出力例:
色の指定に,2.1で扱ったGD::Styled,GD::Brushed,
GD::StyledBrushed
を用いることもできます.
頂点の追加を次のように書いても,上のスクリプトと同様の出力結果を得ること
ができます.
poly = GD::Polygon.new # この時点では多角形の頂点は存在していない.
poly.toPt(25, 25) # 以下,頂点の追加
poly.toPt(50, 0)
poly.toPt(-50, 50)
GD::Polygon#toPt(dx, dy)
- ポリゴンオブジェクトの頂点から(dx, dy)だけ増減させた座標に
新しい点を追加する.頂点が存在しないとき,(dx, dy)が最初の
頂点となる.
GD::Polygon.newによって新規にオブジェクトを生成した時点ではまだ頂点が
存在しないので,上のpoly.toPt(25,25)
によって最初の新しい
頂点(25,25)が生成されます.その次のpoly.toPt(50,0)
によっ
て,新規に頂点(25+50, 25+0)が追加されます.以下同様です.
頂点の変更
ある頂点の座標の値を変更したいときもあります.そのためのメソッドが
GD::Image#setPtです.
GD::Polygon#setPt(idx, new_x, new_y)
- idx番目の頂点の座標を(new_x, new_y)に設定する.
例 (最初の頂点を変更する)
im = GD::Image.new(100,100)
black = im.colorAllocate(0,255,0) # 背景色は緑.
red = im.colorAllocate(255, 0, 0) # ポリゴンの色は赤.
poly = GD::Polygon.new
poly.addPt(25, 25)
poly.addPt(75, 25)
poly.addPt(25, 75)
poly.setPt(0, 100, 100) # 最初の(0番目の)頂点座標を(100,100)に変更した.
im.polygon(poly, red) # イメージ im 上にこのポリゴンを赤で描画.
出力例:
頂点の削除
ある頂点を削除したい場合には次のメソッドを用います.
GD::Polygon#deletePt(idx)
- idx番目の頂点を削除する.
ポリゴンの情報を得る (頂点座標の把握)
ポリゴンオブジェクトが現在どのような頂点を持っているか知りたいことがあ
ります.そのために,次のようなメソッドが用意されています.
GD::Polygon#vertices
- ポリゴンの頂点座標をArrayに格納して返す.
GD::Polygon#length
- ポリゴンの頂点の個数を返す.
例
...
poly = GD::Polygon.new
poly.addPt(25, 25)
poly.addPt(75, 25)
poly.addPt(25, 75)
p poly.vertices # => [[25, 25], [75, 25], [25, 75]]
p poly.length # => 3
poly.setPt(0, 100, 100)
p poly.vertices # => [[100, 100], [75, 25], [25, 75]]
...
2.5 イメージのコピー
あるイメージを別のイメージ上にコピーしたいときのために,コピー方法に応
じて次の4つのメソッドが提供されています.
そのうち2つは,イメージの一部をコピーして別のイメージの指定した箇所に
貼りつけるものです.
GD::Image#copy(Image, to_x, to_y, from_x, from_y, w, h)
- コピー先のImageの(to_x, to_y)に,コピー元(self)の(from_x, from_y)
を左上角とした幅w高さhの領域をコピーする.
GD::Image#copyResized(Image, to_x, to_y, from_x, from_y, to_w, to_h, from_w, from_h)
- コピー先のImageの(to_x, to_y)を左角上とする幅to_w高さto_hの領域
に,コピー元(self)の(from_x, from_y) を左上角とした幅from_w
高さfrom_hの領域をコピーする.領域の大きさが異なる場合拡大または
縮小される.
例 (画像ファイルからイメージを読んで,新規イメージへコピー)
高さが同一の2つのPNGイメージ(0.png
と1.png
)からイメージオブジェクトをそれぞれ生成し,新規イメー
ジにコピーします.新規イメージの幅は2つのコピー元のイメージがちょうど
おさまるようにします.
f0 = open("0.png", "r")
f1 = open("1.png", "r")
im0 = GD::Image.newFromPng(f0)
im1 = GD::Image.newFromPng(f1)
f0.close
f1.close
# GD::Image#width,GD::Image#height はそれぞれイメージの
# 幅と高さを返すメソッド.
im = GD::Image.new(im0.width+im1.width, im0.height)
# 何はともかく背景色は必ず設定する.重要!
im.colorAllocate(0,0,0)
im0.copy(im, 0, 0, 0, 0, im0.width, im0.height)
im1.copy(im, im0.width+1, 0, 0, 0, im1.width, im1.height)
出力例:
[注意]
悲しいことに,PNG形式の利点の1つであるアルファ
チャネルは現段階のgdではサポートされていないようです.よって,上の
0.png,1.pngをそのままGD経由で読み込むとアルファチャネルが無視され,出
力されたPNG画像は上のように見映えが悪くなってしまいます.
あとの2つは,イメージの一部をコピー先のイメージの指定した箇所に"重ねあ
わせるように"(コピーした部分の元画像が見えるように)コピーするものです.
この機能を用いると,単一色画像を用いて,コピー先の指定した部分をハイラ
イト(強調)するような効果をもたせることができます.
GD::Image#copyMerge(Image, to_x, to_y, from_x, from_y, w, h, percent)
- コピー先のImageの(to_x, to_y)に,コピー元(self)の(from_x,
from_y) を左上角とした幅w高さhの領域を重ねあわせる.混ざり具合は
percentで指定する.
GD::Image#copyMergeGray(Image, to_x, to_y, from_x, from_y, w, h, percent)
- コピー先のImageの(to_x, to_y)に,コピー元(self)の(from_x,
from_y) を左上角とした幅w高さhの領域を,グレースケールで重ねあわ
せる.混ざり具合はpercentで指定する.
例 (イメージの一部の領域を"強調"する)
f0 = open("demoin.png", "r")
im = GD::Image.newFromPng(f0)
f0.close
# 緑の背景色をもつイメージの生成
hilightt_im = GD::Image.new(50, 50)
green = hilight_im.colorAllocate(0, 255, 0)
# im の(25,25)のところからhilight_imを透過度50%で重ね合わせる.
hilit_im.copyMerge(im, 25, 25, 0, 0, 50, 50, 50)
出力例:
GD::Image#copyMergeGrayはどうも上手く機能し
ないようです..gd に添付されているサンプル画像(copy_merge.png)でも,
グレースケールにはならず,copyMerge された画像と同一になっています.
3. 文字(列)を描く
文字(列)の描画には,gd であらかじめ容易されたフォントをGD::Fontクラス
を用いて利用する方法と,TrueTypeフォントを用いる方法の2種類があります.
後者の利用には,gd-1.6.1 以上が必要です.
3.1 GD::Font
クラスで提供されるフォント
を使う
gdでは"Giant","Large","Medium","Small","Tiny"という5種類のサイズの
異なるフォントが用意されています.Ruby/GD でそれらを利用するために
GD::Font
クラスが提供されており,このクラスのオブジェクト
を用いて文字列の描画を行なうことができます.
GD::Font.new(Font_size)
- GD::Fontオブジェクトの生成を行うクラスメソッド.上記の5つの
フォントのどれを使うかは,Font_sizeに文字列
"Giant","Large","Medium","Small","Tiny"
を指定することによって決定する.
GD::Fontオブジェクトには,指定したフォントのポイントサイズなどを調べる
メソッドが提供されています.そのようなメソッドが必要ないとき,フォント
の指定にはGD::Fontクラスで定義されている定数GD::Font::GiantFont
,GD::Font::LargeFont
,GD::Font::MediumFont
,GD::Font::SmallFont
,GD::Font::TinyFont
を使用することもできます.
実際に文字列を描画するメソッドは次の通りです.
GD::Image#sting(Font, x, y, str, color)
- 位置(x, y)に,フォント Font を用いて文字列 str をcolor色で描画する.
Font には上で生成されたGD::Fontオブジェクトか,またはGD::Fontクラスで
定義された定数を用いる.
例 (文字列の描画: フォントをGD::Fontインタンスで指定する)
# GD::Fontオブジェクトの生成
giant = GD::Font.new("Giant")
large = GD::Font.new("Large")
medium = GD::Font.new("Medium")
small = GD::Font.new("Small")
tiny = GD::Font.new("Tiny")
string = "Hello, Ruby/GD World!!"
str_size = string.size
# GD::Font#width はフォントに含まれる文字の幅を返すメソッド
im_width = giant.width*str_size
# GD::Font#height はフォントに含まれる文字の高さを返すメソッド
im_height = giant.height + large.height + medium.height + small.height + tiny.height
# 描画するべきイメージの生成
im = GD::Image.new(im_width, im_height)
white = im.colorAllocate(255, 255, 255) # 背景は白色
black = im.colorAllocate(0, 0, 0)
im.string(giant, 0, 0, string, black)
im.string(large, 0, giant.height, string, black)
im.string(medium, 0, giant.height + large.height, string, black)
im.string(small, 0, giant.height + large.height + medium.height, string, black)
im.string(tiny, 0, giant.height + large.height + medium.height + small.height, string, black)
出力例:
例 (文字列の描画: フォントを定数で指定する)
im = GD::Image.new(200, 30)
white = im.colorAllocate(0, 0, 0) # 背景は黒色
green = im.colorAllocate(0, 255, 0)
im.string(GD::Font::GiantFont, 0, 0, "This is the Giant font", green)
出力例:
3.2 TrueType フォントを使う
gd-1.6.1 からはTrueTypeフォントで描画することが可能になりました.
TrueTypeフォントを用いて文字列を描画するメソッドは次の通りです.
GD::Image#stingTTF(color, font_path, pt, angle, x, y, str)
- 位置(x, y)に,font_pathで指定されたTrueTypeフォントを用いて,
ポイントサイズpt, 回転角angle(ラジアン),色colorで文字列strを描画する.
戻り値は次のような配列である.
["エラーメッセージ", [文字列のBounding boxの8つの頂点からなる配列]]
文字列が正しく描画された場合,エラーメッセージはnil
となる.
例 (TrueTypeフォントを用いた描画)
im = GD::Image.new(100, 100)
white = im.colorAllocate(255, 255, 255)
blue = im.colorAllocate(0, 0, 255)
# フォントパスは文字列にて指定する
ttfont = "/usr/share/fonts/TrueType/wadalab-gothic.ttf"
str = "日本語文字列もオッケー!"
angle = 45*(Math::PI/180.0) # degree -> radian
im.stringTTF(blue, ttfont, 14, angle, 0, 50, str)
出力例:
上の例では,14ポイントフォントで文字列をイメージ左上角(0, 0)のところか
ら-45度傾けて描画しているのですが,イメージサイズは100x100ピクセルで決
め打ちしているので,出力例のように文字列がはみ出て一部表示できていませ
ん.そこで,メソッドの戻り値を調べてみると,
[nil, [1, 4, 147, 151, 160, 138, 13, -7]]
となっています.2番目の要素の配列の意味は下の通りです.
(13, -7) (160, 138)
+------------------+
|日本語文字列もオッケー!| # 実際には-45度傾いてます.
+------------------+
(1,4) (147, 151)
よって,指定された文字列をちゃんと表示するには100x100のイメージ
では不十分で,もう少し大きなイメージが必要です.その情報は上の配列から
得ることができますが,これを得るためには実際に1回文字列を描画するとい
う,不要な(しかもコストが高い)操作を伴ないます.
要は,実際に描画するに先立って上の頂点の配列の情報が分かればそれなりに
対処もできるということです.そこでこの目的のために,次のクラスメソッド
が提供されています.
GD::Image.stingTTF(color, font_path, pt, angle, x, y, str)
- GD::Image#stringTTFと同じであるが,実際に描画は行わない.描画し
た場合に得られるエラーメッセージと,Bouding Boxの配列からなる配
列を返す:
["エラーメッセージ", [文字列のBounding boxの8つの頂点からなる配列]]
正しく描画できる場合,エラーメッセージはnil
である.
例 (TrueType フォントを用いた描画:改訂版)
ttfont = "/usr/share/fonts/TrueType/wadalab-gothic.ttf"
str = "日本語文字列もオッケー!"
angle = -45*(Math::PI/180.0)
# Bounding box の頂点を先ずは把握する.
msg, brect = GD::Image.stringTTF(0, ttfont, 14, angle, 0, 0, str)
unless msg == nil
puts msg
exit 1
end
# イメージサイズは,文字列がちょうど描ける大きさに...
im_height = [brect[3], brect[5]].max - [brect[1], brect[7]].min
im_width = [brect[2], brect[4]].max - [brect[0], brect[6]].min
im = GD::Image.new(im_width, im_height)
white = im.colorAllocate(255, 255, 255)
blue = im.colorAllocate(0, 0, 255)
msg, brect = im.stringTTF(blue, ttfont, 14, angle, 0, 7, str)
出力例:
上のスクリプトは行き当たりばったりなので(^^;;,より一般的な例については,
配布物に同梱されているgdtestttf.rbを参照して下さい.
4. イメージの出力
Ruby/GD が対応している出力イメージフォーマットのうち,よく使う2つのメ
ソッドだけ示します.
GD::Image#png(file)
- 完成したイメージをPNG形式のイメージとしてfileに出力する.file は
File.openで指定された書きこみ可能なファイルか,$stdout(標準出力)
などである.
GD::Image#jpeg(file, quality)
- 完成したイメージをJPEG形式のイメージとしてfileに出力する.file
はFile.openで指定された書きこみ可能なファイルか,$stdout(標準出
力)などである.また,quality は0-100までの数値を指定した場合には
対応する品質で出力される.-1を指定した場合にはgdで提供されたデフォ
ルトの品質で出力される.
5. 補足
今までのところで言及できなかった幾つかの重要と思われる事項を最後にまと
めておきます.
5.1 オブジェクトの削除
イメージを出力した後や,設定したブラシで描画が終わった後など,不要となっ
たイメージオブジェクトはgdの流儀にしたがうならば,GD::Image#delete
にて即座に削除するのがよい
のかも知れません.
5.2 インタレース
イメージ全体を全部読みこんでから一度に表示させるのではなく,読み込んだ
順から徐々に表示させていくプログレッシブ効果を実現するためにはインタレー
ス機能を用います.
Ruby/GD ではGD::Image#interlace=
というメソッドが用意されていて,これにtrue
を設定すると,
イメージがインタレースされます.
またイメージがインタレースされているかどうか知りたいときのために
GD::Image#interlaceというメソッ
ドが用意されており,インタレースされているならばtrue
を返
します.
インタレース機能の使用例については,'sample/webpng.rb' を御覧ください.
5.3 色の割り当てについてもっと
GD::Image
オブジェクトは内部に(r,g,b)の組を256個保持し(こ
れをカラーテーブルと呼びます),それぞれに0番目から255番目までインデッ
クスが振られています.すなわち,GD::Image#colorAllocate
によって,ひとつのイ
メージに高々256種類の色しか割り当てることができません.しかも,このメ
ソッドは機械的に引数(r,g,b)(または"#xxxxxx")を登録して新しいインデック
スを作成してしまうため,既製のイメージにさらに色を割り当てる際,既に登
録されている(r,g,b)の組の存在を知らずに重複して割り当ててしまうことが
あります.比較的多数の色が使われているイメージを扱う場合,このような無
駄は最大256 色という制限には好ましくないです.
そこで,いま割り当てようとする色が既にイメージの中で使われているのなら
ば,それのインデックスを使えるようにすれば効率よいというものです.その
ために次のメソッドが提供されています.
GD::Image#colorExact(r, g, b)
GD::Image#colorExact(str)
- 色(r, g, b)(または"#xxxxxx")の組が既に用いられているのならば,そ
のカラーテーブルのインデックスを返す.用いられていない場合には,-
1を返す.
次に,色がこれ以上追加できないような状況を考えてみましょう.この場合,
GD::Image#colorAllocate
を使うこ
とは勿論できません.そこで,上のGD::Image#colorExact(r, g, b)の利用が考えられます.
ところが,これの戻り値が-1であり,割り当てようとした色は未だ登録されて
いないとします.このような場合,既存のイメージに使われている色のうち,
割り当てようとしている色に最も「近い」色のインデックスを返してくれる便
利なメソッドが提供されているので,それを使用することができます.
GD::Image#colorClosest(r, g, b)
GD::Image#colorClosest(str)
- 色(r, g, b)(または"#xxxxxx")の組に最も「近い」カラーテーブルのイ
ンデックスを返す.
すると,色の割り当ての方法の中で一番効率的な方法というのは次のようにな
ります(よほど多数の色を使っている状況ではない限りここまですることは必
要ないのかも知れませんが).
-
GD::Image#colorExact
を用い
てイメージオブジェクト内のカラーテーブルを調べ,既にその色が使われてい
ることが判明すれば,そのインデックスを用いる.
- この色が未だ使われていない場合には,
GD::Image#colorAllocate
によって新規にカラー
テーブルに色を割り当てる.
- 既に256色使ってしまっている場合,これ以上色は割り当てられないので,
やむを得ず
GD::Image#colorClosest
を用いてイメージオブ
ジェクトのカラーテーブルの中で一番近い色を「代用色」として使用する.
これをRubyのコードで書くと次のようになります.
# RGB要素が(r0, g0, b0)である色color0を割り当てようとする.
if (color0 = im.colorExact(r0, g0, b0)) == -1
if (color0 = im.colorAllocate(r0, g0, b0)) == -1
color0 = im.colorClosest(r0, g0, b0)
end
end
色を割り当てる際,毎回このようなコードを書くのは面倒です.Ruby/GD では
上のコードと等価なことを次のメソッドで実現することができます.
GD::Image#colorResolve(r, g, b)
GD::Image#colorResolve(str)
- 割り当てようとする色(r, g, b)(または"#xxxxxx")が既にカラーテーブ
ルに登録されていたらそれに対応するインデックスを返す.そうでない
場合は新たに登録し,対応するインデックスを返す.さらに登録できな
い場合には,イメージのカラーテーブルの中から,(r, g, b)(または
"#xxxxxx")に最も近い色のインデックスを返す.
GD::Image#colorAllocateに対するこの
メソッドの利点は,イメージで既に何色使われていようが,どんな色を指定し
ようが,必ず対応するインデックスが返ってくるということです.
例 (GD::Image#colorResolveで,多いときも安心)
では,このメソッドの使用例を下の人為的なイメージを用いて例示してみましょ
う./usr/X11R6/lib/X11/rgb.txtの最初の256行に記載されている色を,GD::Image#colorAllocateを用いて全て使用したイメー
ジです.
:既に256色使ってしまったイメージ
実は,rgb.txtの最初の256行には重複しているエントリが幾つか存在し,上の
イメージも厳密に256色使っているわけではありません.ところが,GD::Image#colorAllocateは重複のチェックはせずに単
にカラーテーブルに指定した色のRGB要素を追加していくだけなので,イメー
ジオブジェクトの内部ではカラーテーブルの全てが使われて,これ以上色の追
加は不可能な状態になっています.
このイメージの上に,
- blue(このイメージのカラーテーブルに既に登録されている色)
- purple1(このイメージのカラーテーブルに既に登録されていない色)
で描画します.色blueを使って線分を描き,色purple1を使って塗り潰し四角
形を描いてみます.
blue = im.colorResolve(0, 0, 255)
# (155,48,255) はrgb.txtで定義されているpurple1のRGB要素.
purple1 = im.colorResolve(155, 48, 255)
# これの戻り値は220,すなわちこの色に最も近い色がイメージの
# インデックス220に発見された.
im.line(0,0,im.width, im.height, blue)
im.filledRectangle(0,im.height-30, 30, im.height, purple1)
出力例:
blue はイメージオブジェクトのカラーテーブル内に対応するインデックスが
あるので,それを用いて線分が描かれています.また,左下隅に,イメージに
既に登録されている色のなかで purple1 に最も近い色(RGB要素は
(160,32,240))で四角形が描画されています.
このように,それ以上色が割り当てられない状況で何らかの色で描画しなけれ
ばならないとき,GD::Image#colorResolve を用
いれば最悪でも指定した色にできるだけ近い色で描画することが可能となるの
です.
御意見,御要望はこちらまで :田村 龍一(tam@kais.kyoto-u.ac.jp)