小学校教員のためのプログラミング入門

色を使う

今回は図形に色をつけることを学びます.今回の目標は次のような図を描くことです.

4-1.jpg

光と色

  光の仕組み

 光は可視光線とも呼ばれる電磁波の一種です.電磁波は,携帯電話やテレビで用いられる電波,レントゲン写真に用いられる X 線,そして電子レンジに使われるものなど,空間そのものが振動して伝わる波の総称です.このうち人間は,波長が 360nm〜400nm から 760nm〜830nm の電磁波を可視光線として,目で感じられる,つまり色を感じることができます.この波長より少し短い電磁波が紫外線,少し長い電磁波が赤外線で,これらは馴染みのある名前だと思います.

4-2.jpg

  色の仕組み

 太陽やその他の照明から発せられる光は様々な波長の可視光線が混ざっていて,白(にきわめて近い)色に見えます.これがガラスを通過したり,紙に反射したりするときに,限られた波長の可視光線だけになり,ガラスや紙が色に見えることになります.前者を透過色,後者を反射色と呼びます.もちろん,ある波長の光を発する物体があれば,その波長の色で見えることになり,これを光源色と呼びます.

 色は重さや長さなど絶対的な量ではなく,感覚的なものであるということが重要です.つまり,波長が800nm あたりの電磁波を赤い色と感じるのは人間だからなのです.人間は,網膜内にある 3 種類の錐体細胞が吸収する可視光線の割合によって色を認識します.したがって,人によって錐体細胞の吸収する光の分布が異なり,同じ波長の光でも違った色として感じている可能性があります.

 網膜上には,錐体細胞以外に,杆体細胞というものがあります.こちらは暗い光を感じるための細胞です.哺乳類が誕生したころ,哺乳類は他の強い動物から身を守るために主に夜行生活をしていました.そのため,色の識別よりも暗い中でも行動できることが重要で,杆体細胞が発達し,他の脊椎動物が 3 または 4 種類持っていた錐体細胞を 2 種類に減らしてしまいました.現在でも哺乳類の網膜上の 95 % は杆体細胞であり,他の脊椎動物に比べ暗いところでの活動に適した仕組みになっています.その後,哺乳類の一部である霊長類のそのまた一部である人間やチンパンジーなどの狭鼻猿類は 3 つ目の錐体細胞を再獲得して,現在に至っています.したがって,他の脊椎動物は人間よりも多彩な色世界を見ているのかもしれません.

 人によって色の感じ方が違う例として,たとえば,日本人の男性の 20 人に 1 人,女性の 500 人に 1 人が赤緑色覚異常という色覚特性を持っていて,この場合,下図の二段目,三段目のように色を感じています.これは,先の人間の進化の過程に由来しているものと言われています.哺乳類が持っていた 2 つの錐体細胞のうち 1 つの錐体細胞を特徴づける遺伝子は X 染色体にあるのですが,これがあるときちょっと異なった遺伝子を持つ X 染色体に変異し,X 染色体を 2 つ持つメスに錐体細胞を 3 つ持つ個体が現れました.そのうちに一つの X 染色体に両方の遺伝子が組み込まれるようにオスでも 3 つの錐体細胞を持てるようになりました.この遺伝子による錐体細胞の出現によって緑と赤が区別できるようになり,木の実を食べるサルにとっては好都合な変異であったため,大部分のサルがこの特性を継承していったというわけです.もともと 1 つであったものが変異してできたという過程を踏んだたため,この 2 つの錐体細胞の光を吸収する分布は非常に近いものとなっています.また,2 つの X 染色体を持つ女性の方が,遺伝子情報にエラーが発生した場合の影響が少なくなり,赤と緑を区別できない人が少ないということになっているようです.

4-3.jpg

色覚障害のメカニズム(http://poem1465.blog.ocn.ne.jp/)より引用

  光と色の三原色

 赤の光と緑の光を混ぜると,黄色に見えることは知っているでしょうか.その光に青色を混ぜると白になります.先の太陽からの光が白という話と同じです.実は,人間の目は,適当な 3 種類の色を選択し,それを同時に見ることで,様々な色に感じるという現象があります.これは,先に述べたように人間は 3 種類の錐体細胞が吸収する可視光線の割合で色を感じることに起因します.黄色の波長を持った電磁波を受けたときと,赤と緑の波長を持った電磁波を受けたときの,錐体細胞が吸収する可視光線の割合が同じようになり,どちらも黄色と感じるわけです.そして,この二つのどちらの光を見ているのかは,人間は区別することができません.一方,空気の振動波である音は,2 つの波長の音を同時に聞いても,別の波長の音として聞こえるのではなく(違った音色として聞こえる),絶対音感を持っている人であれば,どのような波長の音がまざっているかを区別することができます.これが,色というものはある波長の電磁波を特徴づける絶対的なものではないという意味です.

,その 3 種類の錐体細胞はそれぞれ,主に赤,緑,青を感じる仕組みになっているためです.たとえば,黄色の波長を持った電磁波を受けたときと,赤と緑の波長を持った電磁波を受けたときの,錐体細胞が吸収する可視光線の割合が同じようになり,どちらも黄色と感じるわけです.

 このように,赤,緑,青の光を合わせて色を作りだす方法を加色混合と呼び,先の三色を光の三原色と呼びます.

4-4.png

 一方,紙にインクを塗って色を作るときには,元の光の色を打ち消すようにして色を作りだします.絵の具の混ぜ合わせを考えてみてください.黄色のインクを塗ると,黄色の反対色である青の光が吸収され弱まります.そこにマゼンタ(青と赤の光を1:1で混ぜたときの光の色)を塗ると,マゼンタの反対色である緑の光が吸収され弱まります.結局,青と緑の光が弱まるので,赤色に見えるというわけです.さらに,ここにシアン(青と緑の光を1:1に混ぜたときの光の色)をまぜると,赤の光も弱まることになり,黒になります.

 このように,光を遮るようにして色を作りだす方法を減色混合と呼び,このときに基本となるマゼンタ,シアン,イエローの三色を色の三原色と呼びます.

4-5.png

色の表現

 色を表現するには,波長や色の名前などありますが,前者は直観的ではなく,後者は限られた色しか表現できません.そこで,色を数値の組み合わせ(座標)で表現する方法(色空間)が作られました.たとえば,先の光の三原色の度合い用いて表現するRGB色空間,色の三原色,および黒の度合を用いて表現するCMYK色空間,色の三属性と呼ばれる色相,彩度,明度で表現するHSB色空間などがあります.

  RGB色空間による指定

 加色混合において,赤(R),緑(G),青(B) をどのくらいの度合いで混ぜるかを指定する表現する方法です.色をコンピュータの内部で表現するときに用いられており,プログラミングにおいても標準ではこの方法で指定するものが多くなっています.

 色が使えるようになった初期のコンピュータでは,それぞれの色を混ぜるか混ぜないかだけが指定できるだけ,つまり,三原色の一色につき 0 か 1 の 1bit だけ,三色で 3 bit だけで表現していました.この場合,表現できるのは黒,赤,緑,青,シアン,マゼンタ,黄色,白の 8 色です.現在は,一色につき256段階(8 bit),三色で 256 の 3 乗(24 bit)である約1677万色を指定することができるものがほとんどです.

4-6.jpg

クリエイティブ・コモンズ 表示-継承 3.0(http://creativecommons.org/licenses/by-sa/3.0/deed.ja)で利用することができます.

Original uploader was SharkD at en.wikipedia Later version(s) were uploaded by Ilmari Karonen, Omegatron at en.wikipedia

  HSB色空間

 色の三属性である色相(Hue),彩度(Saturation・Chroma),明度(Brightness・Value)で色を指定する色空間で,HSV色空間とも呼ばれます.RGB 表現が色の科学的な現象を元に指定するものであることに比べ,色の種類(色相)と鮮やかさと明るさという人間の感覚的な指標で指定ができるため,デザイナには好まれて使われます.

 HSB 色空間における色相は,0°〜360° の値を持ち,0 は赤,120 が緑,240 が青と定められています.HSV 色空間に限らず,色相を円状に配置したものを色相環と呼びますが,HSB色空間における色相環は次のようになります.

4-8.jpg

 HSB色空間における明度は 0〜100% で色の明るさを表し,各色相においてもっとも明るい色で 100% の値をとります.彩度も 0〜100% の値をとり,この値が小さくなるほど色が褪せていきます.明度が小さい場合,彩度を変化させても色はあまり変わりません.色相が 0° のときの彩度と明度の組み合わせを表した図を下に示します.横軸が彩度で左端が 0% で右端が 100%,縦軸が明度で上端が 0% で下端が 100% です.

4-7.jpg

  HLS 色空間

 HSB 色空間に似たものに HLS 色空間があります.HLS 色空間における明度は Lightness で,0% で黒,100% で白になり,50% のときもっとも純色に近くなり,彩度が 100% であれば,このとき純色となります.そして,彩度の値が小さくなると色がくすみ,0% のときは,明度に応じて白〜灰色〜黒色になります.

 HSB(HSV) と HLS の違いを表す図を下に示しておきます.HSBでは純色から彩度を落としていくと白になるのに対して,HLS では純色から彩度を落としていくと灰色になります.HLS で純色から白色へ移動するには明度をあげてゆきます.HLS 色空間は,Microsoft のソフトウェアや Paintshop,CSS3 などで用いられていますので,HSB と間違えないようにしましょう.

4-10.jpg 

貧乏人のためのCG講座 CG知識編(http://tt.sakura.ne.jp/~hiropon/lecture/color.html)より引用

Processing における色の指定

 色の知識は十分についたと思いますので,さっそく Processing で色を指定して図形を描いてみましょう.

  色指定モードの設定

 Processing では,RGB 色空間と HSB 色空間を利用することができます.RGB 色空間を使いたい場合は RGB を,HSB 色空間を使いたい場合は HSB をパラメータとして colorMode メソッドを呼び出します.

colorMode( RGB );
colorMode( HSB );

また,RGB においては赤,緑,青の度合,HSB においては色相,彩度,明度を,どのような範囲の数値で指定するかを設定することもできます.

colorMode( RGB, 100 );

とすれば,赤,緑,青それぞれの度合を 0〜99 の値で設定できます.先にも説明したようにコンピュータ内部では三原色各色 256 段階で表現できますので,この値にも 256 とすると,最大限の表現が可能になります.

colorMode( HSB, 100, 10, 10 );

とすれば,実際は0〜359°の色相を 0〜99,0〜100%の彩度と明度を 0〜10 で設定できるようになります.RGB の各値と HSB の色相の値は 0 から設定した値-1 が指定できるようになるのですが,彩度と明度は 0 から設定した値を指定できるようです.HSB では色相は角度,彩度と明度はパーセンテージで指定するのが自然ですので,パラメータは 360 or 3600,100,100 とするとわかりやすいと思います.

 また,Processing では RGB,HSV 色空間の指定に加え,透明度の指定をすることができます.透明度の設定範囲を指定したいときは,先のメソッドの呼び出しの最後に付け加えます.たとえば,

colorMode( RGB, 100, 100 );

とすれば,0 から 100 の値で透明度合を設定できます.透明度も彩度と明度と同じように 0 から 設定した値までの値が指摘できるようになります.

  色の指定

 では,さっそく色を指定して図形を描いてみます.まずは,赤色で四角形を描いてみます.線の色を指定する場合は stroke メソッドを利用します.stroke メソッドのパラメータは colorMode で設定したモードにあったパラメータ列となります.

size( 300, 300 );
colorMode( RGB, 256, 256, 256 );
stroke( 255, 0, 0 );
rect( 50, 50, 200, 200 );

4-11.jpg

 また,HSB 色空間を使った場合は,二行目,三行目を次のように変えます.

colorMode( HSB, 360, 100, 100 );
stroke( 0, 100, 100 );

さらに,他のプログラミング言語では 16進カラーコード による色指定がよく使われています.16進カラーコードは,2 桁の 16 進数(10進数における0〜255)で三原色各色の度合を表現し,それを赤緑青の順番に並べた 6 桁の 16 進数で色を表現する記法です.たとえば,FF0000 は赤色,FF00FF はマゼンタになります.Processing の場合この先頭に #をつけて記述します.この表記を利用した場合,先の二行目,三行目は次のように置き換えられます.

stroke( #FF0000 );

 色の指定には color型 の値を用いることも可能です.たとえば,先のスケッチは次のように書くこともできます.

size( 300, 300 );
colorMode( RGB, 256, 256, 256 );

color c1;
c1 = color( 255, 0, 0 );
stroke( c1 );
rect( 50, 50, 200, 200 );

c1 は color 型の変数として宣言されています.color メソッドは colorMode メソッドで設定したモードに合ったパラメータ列を color 型の値に変換するメソッドです.

  その他の色指定

 次に四角形の中身を緑で塗りつぶしてみます.塗りつぶし色の指定は fill メソッドを利用します.

size( 300, 300 );
colorMode( RGB, 256, 256, 256 );
stroke( 255, 0, 0 );
fill( 0, 255, 0 );
rect( 50, 50, 200, 200 );

4-12.jpg

 さらに,背景を黒色にしてみます.背景の設定は background メソッドを利用します.

size( 300, 300 );
colorMode( RGB, 256, 256, 256 );
background( 0, 0, 0 );
stroke( 255, 0, 0 );
fill( 0, 255, 0 );
rect( 50, 50, 200, 200 );

4-13.jpg

 なお,線を描きたくない(透明にする)ときは noStroke メソッドを,塗りつぶしをしたくない(透明にする)ときは noFill メソッドを利用します.

4-14.jpg

色相帯を描いてみる

 色の付け方がわかったので,今回の目標を目指してみましょう.まずは,第一段階として目標の図の一番下の方,純色の帯を描いてみます.

4-15.jpg

  手順

 今回は x 軸方向に色相を変化させた帯を描けばよいということになります.X座標が x のところには,色相 x で描くということです.具体的には,

stroke( x, 100, 100 );

の x の値を 0 から 360 に変化させながら(359は0と同じです),縦線分を横方向に並べればよいはずです.縦線分を描くのは縦幅を持った帯を描くためです.線分を描くには line メソッドを利用します.line メソッドは

line( 始点X座標,始点Y座標,終点X座標,終点Y座標 );

と記述します.ちょうど x の値を 0 から 360 までに変化させるので,これを X 座標に使うことにすれば,縦線分が横に並ぶはずです.つまり,

stroke( 0, 100, 100 );
line( 0, 0, 0, 10 );
stroke( 1, 100, 100 );
line( 1, 0, 1, 10 );
stroke( 2, 100, 100 );
line( 2, 0, 2, 10 );
   :

とすればよいはずです.

  繰り返し制御文

 前回と同じように,こんな同じような文を並べるのは面倒です.これを解決するために前回と同様,繰り返し構文を使ってみます.前回は while 文を利用しましたが,今回は for 文を利用します.for 文は次のように記述します.

for( 初期処理 ; 繰り返し条件 ; 繰り返し後処理 ) 繰り返し文;
または
for( 初期処理 ; 繰り返し条件 ; 繰り返し後処理 )
{
   繰り返し文;
   繰り返し文;
   :
}

初期処理は for 文を実行するときに一番最初に実行される処理です.そして,繰り返し条件が満たされるとき,繰り返し文を実行します.次に繰り返し後処理を実行し,再度繰り返し条件の判定に戻ります.繰り返し条件が満たされない場合は,for 文の実行を終了します.

 この for 文を利用すると目的のプログラムは次のようになります.

size(360,300);
colorMode(HSB,360,100,100);
background(#FFFFFF);

int x;
for( x = 0 ; x < 360 ; x++ )
{
  stroke( x, 100, 100 );
  line( x, 150, x, 160 );
}

 for 文で x を 0 に初期化した後,x が 360 未満であれば,色相が x の線分を,X 座標が x の縦線分を描きます.そして,x++ を実行した後,再び条件判定を行い,x が 360 以上になったとき,繰り返しが抜けだし,スケッチの実行を終了します.なお,x++ は x=x+1 と同じ処理を行います.演算子 ++ は,左側の変数の値に 1 を加えこむというインクリメンタル演算子と呼ばれるものです.

 もちろん,while 文を使っても書くことはできます.

int x = 0;
while( x < 360 )
{
  stroke( x, 100, 100 );
  line( x, 150, x, 160 );
  x++;
}

 どちらを使うかは好みの問題だと思います.

目標の図を描いてみる

 なんとなく,目標の図の描き方がわかったのではないでしょうか.目標の図は縦方向で彩度が変化しています.つまり,Y 座標が y のところは彩度を y にすればよさそうです.

 ある色相の線を描く部分は

stroke( x, 100, 100 );
line( x, 150, x, 160 );

です.この色相に対して,彩度を 0〜100 まで変化させるには,for 文を使えば,

int y;
for( y = 0 ; y < 100 ; y++ )
{
  stroke( x, y, 100 );
  line( x, y, x, y );     // 点を描く pset( x, y ) と同じ
}

のようになります.

 ある色相に対する,彩度を変化させた縦線を描くことができるようになったので,これを先の変数 x を使って色相と X 座標を変化させる仕組みと合わせてみます.

size(360,300);
colorMode(HSB,360,100,100);
background(#FFFFFF);

int x,y;
for( x = 0 ; x < 360 ; x++ )
{
  for( y = 0 ; y < 100 ; y++ )
  {
    stroke( x, y, 100 );
    line( x, y, x, y );
  }
}

ただし,これですと,目的の図を縦方向につぶした感じになっていますので,縦方向に三倍に引き延ばしてみます.このためには,彩度 y で描くのは Y 座標が y*3 から y*3+2 の間とすればよいはずですので,線分(点)を描いていた部分を

  line( x, y*3, x, y*3+2 );

とすれば,目的の図を描くスケッチになります.まず,色相が 0 の線を X 座標が 0 の軸に描きます.この線は,Y 座標が 0 から 2 までの線分を彩度 0 で,Y 座標が 3 から 5 までの線分を彩度 1 で...という風に彩度がだんだんあがってゆく線となっています.次に,色相が 1 の線を Y 座標 1 の軸に,色相が 2 の線を Y 座標が 2 の軸に...という風に描いていき,目標の図を描いています.

課題

 X 軸方向で明度,Y軸方向で彩度を変化させた図を描いてみましょう.下の図は左から色相を 0, 100, 200 にしたときの図です.

4-16.jpg4-17.jpg4-18.jpg

  ヒント

 まずは,画面サイズを 100×100 として,座標が (x,y) のところには,明度が x,彩度が y の点を描くようにするとよいでしょう.この際は line( x,y,x,y ) とするか pset( x,y ) とすると点が描けます.

 最終的にはこれでは小さいので,縦方向,横方向に3倍に引き延ばしてください.この場合,描くのは点ではなく正方形となるのは想像できると思います.正方形を描くメソッドは rect です.

参考文献

  • 岡部正隆,伊藤啓:色覚の多様性と色覚バリアフリーなプレゼンテーション細胞工学,Vol.21 No.7〜9,秀潤社(2002)