「Ruby でグラフィックス」— 作品を作ってみよう


プログラムのしくみ

どうしてプログラムが必要なの?

ここではもういちどプログラムの働きを見ておくことにしよう.

画像ファイルはものすごい数のピクセルデータの集まりだ。手でひとつずつ打ち込むなんてとても無理。

コンピュータのパワーを使って大量のデータを一気に書き出させる:そのためのプログラムを作って 仕事をさせる。

プログラムの概要

最初に走らせたプログラムを見てみよう

# ex-001.rb
nx = 600                                # 横のサイズを設定
ny = 480                                # 縦のサイズを設定
puts "P6"                               # ファイルの種類を指定
puts "# Let's try Graphics with Ruby"   # コメント(なんでもいい)を出力
puts "#{nx} #{ny}"                      # 600 480 が出力される
puts "255"                              # 255 が最も明るいという指定
for i in 0 .. ny - 1   ## これ以降が実際にピクセルを出力する部分
  for j in 0 .. nx - 1      
    r = 255                 #    
    g = 0                   # RGB に 255, 0 255 を与えている→マゼンタの色を指定
    b = 255                 #
    print r.chr + g.chr + b.chr  # 3色からなるピクセルを出力
  end
end

for ループの役割

上のソースには for で始まる行がある。これはその後にある end と対になって,for ループという仕掛けを 実現する。たとえば次のプログラムは, 3,6,9,12,18 と出力して行く。つまり i という変数が 1,2,3,4,5,6 と変化しながら繰り返し実行される。

for i in 1 to 6
  puts i * 3
end

二重のforループ!

このプログラムでは,2つのループが組み合わされている。

for i in 0 .. ny - 1
  for j in 0 .. nx - 1 
    .....
    .....
  end
end

これは,ピクセルの配置が横と縦の2次元になっているために,横にピクセルを並べるための繰り返しを, 縦に並べる繰り返しの中に入れなければならないからだ。次の図にそのことを示した。

ijloop

いくつかのテクニック

縦横に塗り分けてみよう

一面同じ色の画像なんてほとんど使いものにはならない。 画面全体を4分割して色分けした例を紹介しよう。

# ex-002.rb
nx = 600
ny = 480
puts "P6"
puts "# Love Kyojo!"
puts "#{nx} #{ny}"
puts 255
for i in 0 .. ny - 1
  for j in 0 .. nx - 1
    if i < ny / 2 then     # i が ny の半分より小さかったら
      b = 127              # b を 127 にする		  
    else                   # そうでなかったら		  
      b = 255              # b を 255 にする              
    end
    if j < nx / 2 then     # j が nx の半分より小さかったら
      r = 255		   # r を 255 にする		  
    else		   # そうでなかったら		  
      r = 0		   # r を 0 にする              
    end
    g = 0                  # g は常に 0 のまま
    print r.chr + g.chr + b.chr
  end
end

作られる画像は次のようになる(説明の文字が後から書き込まれている)。 これはプログラムの中の if の働きによるものだ。プログラムのコメントと 画像を見比べると,この絵が作られる理屈がわかる。

ijloop

グラデーションをつける

グラデーション(グラジェントともいう) は色の濃さが滑らかに移り変わるようなパターンだ。次のサンプルプログラムを 走らせてみよう。

# ex-003.rb
nx = 600
ny = 480
puts "P6"
puts "# Gradation "
puts "#{nx} #{ny}"
puts 255
for i in 0 .. ny - 1
  for j in 0 .. nx - 1
    r = j % 200
    g = i % 240
    b = 0
    print r.chr + g.chr + b.chr
  end
end

プログラムの中にある j % 200 というのは, j を 200 で割った余りを計算するものだ。 for ループの中で j は 0, 1, 2, ... と増えていき ..., 200, 201 と 200 を超えた ところで(余りだから) 0, 1, ... とまた戻る。結局, 横に 1 ピクセル進むごとに 赤みを増して 200 進むとまた 0 に戻ることになる。 i についても同様で,下に向かって 緑のグラデーションがかかる。

gradation

iとjの関数で描画してみる

# ex-004.rb
nx = 600
ny = 480
puts "P6"
puts "# Let's try Graphics with Ruby"
puts "#{nx} #{ny}"
puts "255"
for i in 0 .. ny - 1
  for j in 0 .. nx - 1
    r = (i * j / 100) % 250 
    g = 0
    b = 0
    print r.chr + g.chr + b.chr
  end
end

このプログラムは,i と j の積を100で割った値(こうすることであまりにも大きくなりすぎないようにしている)を計算し,それが 250 を超えないように 余りをとって r の値にしている。

i*j

もどる