これまで色をRGBそれぞれ256通りずつで表現してきました.これはディスプレイに表示する場合もこのようにRGBそれぞれの大きさに合わせて発光させているようなので,PCにとっては大変明確な表現なのですが,人間からしてみると理解しづらい表現となっています.
考えてみると日常生活では色を表現するときに「薄い緑」とか「明るめの黄色」というようになると思います.それが急に光の三原色で表現するようになるから理解しづらいのです.ということで理解しづらいRGBの表現を日常で表現しているやりかたにそっくりなHSV表現に変換してみたいと思います.こうすることで今までと変わった加工ができるようになります.
これはGIMPで色をHSV表現で選択するときの画面です.周りの円の部分は色相環と呼ばれるもので,普段「濃い赤」「薄い黄色」のように使っている「赤」や「黄色」の部分を表しています.真ん中の三角形は明度や彩度を表します.左下の頂点程明度は低く,右下の頂点程彩度が低くなります.
HSVはそれぞれH(Hue),S(Saturation),V(Value of Brightness) の事で,Hは色相環において赤を0度としたときの角度で表現されます.なので,今回Hは360段階,SとVは256段階で表します.上の色相環の中心を彩度ゼロの点として半径256の円盤を考え,それが明度の段階ごとに256枚並んだ円柱を考えると大変わかりやすいです.
typedef struct{ unsigned char b; unsigned char g; unsigned char r; }Rgb; typedef struct{ unsigned int h; unsigned char s; unsigned char v; }Hsv; typedef struct{ unsigned int height; unsigned int width; Rgb *rgb; Hsv *hsv; }Image;
SとVは256段階なのでchar型で良いのですが,Hは360段階なので int型にする必要があります.また,Image構造体を変更したので Create_ImageやFree_Image,Imagecopyもそれに合わせて変更しています.準備は整ったのでRGBからHSVに変更するRgb_to_Hsvと, HSVからRGBに変更するためのHsv_to_Rgbを定義します.
maxをRGBの3つの値の最大値とし,minをRGBの最小値とすると,Vは
で表せます.ここでmaxがゼロであればその色は黒なので S,H共に0を入れておきます.またSは次のようになります.
Hは少し複雑で,Rがmaxのとき
となり,Gがmaxのとき
となり,Bがmaxのとき
というふうになります. Hは0から359の値をとるのでHがマイナスになれば360を足してやります.
HSVからRGBへの変換はRGBからHSVへの変換より複雑です. Sがゼロのとき
となります.それ以外の場合は以下のようになります.
今回はmain関数の中で単にHSVに変換しなにもせずにRGBに戻しています.次からいろいろとHSVの成分を弄ってみたいと思います.