RGB (赤緑青) という色体系は、確かに人間の視神経に基づいた色体系ですが、実はあまり使いやすくありません。例えば、「(R=211, G=141, B=0) という色と同じ明るさの青紫」を作ろうとしても、大変な作業になります。
このような場合は、色相 (H), 彩度 (S), 明度 (V) の3つで色を表す HSV 色体系 (HSI とも呼ばれる) を用いると便利です。
色相 (hue) | 0〜360 の値をとり、0 で赤、120 で緑、240 で青、360 でまた赤とする。 |
彩度 (saturation) | 0〜1 の値をとり、0 で灰色 (白から黒までの彩りない色)、1 で鮮やかな色とする。 |
明度 (value 又は intensity) | 0〜1 の値をとり、0 で黒、1 で白とする。 |
RGB の値を入れて「RGB から HSV を計算」ボタンを押すと | |
HSV それぞれの値が求まり、 | |
逆に HSV の値を入れて「HSV から RGB を計算」ボタンを押すと | |
RGB それぞれの値が求まる、というプログラムを作ります。 |
まずは、次のようにフォームにコンポーネントを追加して下さい。
コンポーネント | Name プロパティ |
---|---|
「RGB から HSV を計算」ボタン | ButtonRGBtoHSV |
「色相」エディット | EditH |
「彩度」エディット | EditS |
「明度」エディット | EditV |
「HSV から RGB を計算」ボタン | ButtonHSVtoRGB |
それぞれのボタンのイベントハンドラの中身は、かなり複雑になるのでここでは説明しません。
※ 処理内容の詳細 (アルゴリズム) は少し専門的になるので、ブラックボックスとしておいても構いません。ただし、後の節でここで作成したプログラム(ユニット)を用いるので、少なくとも、「RGB と HSV との間の変換がこのプログラムでなされているのだ。」ということは理解しておいてください。
「RGB から HSV を計算」ボタンのイベントハンドラは次のようにして下さい。
// 「RGB から HSV を計算」ボタン procedure TFormCustomColor.ButtonRGBtoHSVClick(Sender: TObject); var h: Real; // 色相 hue s: Real; // 彩度 saturation v: Real; // 明度 value min: Integer; max: Integer; delta: Integer; begin if (SpinEditR.Value > SpinEditG.Value) then begin if (SpinEditR.Value > SpinEditB.Value) then begin max := SpinEditR.Value; end else begin max := SpinEditB.Value; end ; if (SpinEditG.Value < SpinEditB.Value) then begin min := SpinEditG.Value; end else begin min := SpinEditB.Value; end ; end else begin if (SpinEditG.Value > SpinEditB.Value) then begin max := SpinEditG.Value; end else begin max := SpinEditB.Value; end ; if (SpinEditR.Value < SpinEditB.Value) then begin min := SpinEditR.Value; end else begin min := SpinEditB.Value; end ; end ; v := max; if (max <> 0) then begin s := (max - min + 0.0) / max; end else begin s := 0; end ; if (s = 0) then begin h := 0; end else begin h := 0; delta := max - min; if (SpinEditR.Value = max) then begin h := (SpinEditG.Value - SpinEditB.Value + 0.0) / delta; end else begin if (SpinEditG.Value = max) then begin h := 2 + (SpinEditB.Value - SpinEditR.Value + 0.0) / delta; end else begin if (SpinEditB.Value = max) then begin h := 4 + (SpinEditR.Value - SpinEditG.Value) / delta; end ; end ; end ; h := h * 60; if (h < 0) then begin h := h + 360; end ; end ; EditH.Text := FloatToStr(h); EditS.Text := FloatToStr(s); EditV.Text := FloatToStr(v / 255); end;
「HSV から RGB を計算」ボタンのイベントハンドラは次のようにして下さい。
// 「HSV から RGB を計算」ボタン procedure TFormCustomColor.ButtonHSVtoRGBClick(Sender: TObject); var h: Real; // 色相 hue s: Real; // 彩度 saturation v: Real; // 明度 value f: Real; p: Real; q: Real; t: Real; begin h := StrToFloat(EditH.Text); s := StrToFloat(EditS.Text); v := StrToFloat(EditV.Text); if (s = 0) then begin SpinEditR.Value := Trunc(v * 255); SpinEditG.Value := Trunc(v * 255); SpinEditB.Value := Trunc(v * 255); end else begin if (h = 360) then begin h := 0; end ; h := h / 60; f := h - Int(h); p := v * (1 - s); q := v * (1 - (s * f)); t := v * (1 - (s * (1 - f))); Case (Trunc(h)) of 0: begin SpinEditR.Value := Trunc(v * 255); SpinEditG.Value := Trunc(t * 255); SpinEditB.Value := Trunc(p * 255); end; 1: begin SpinEditR.Value := Trunc(q * 255); SpinEditG.Value := Trunc(v * 255); SpinEditB.Value := Trunc(p * 255); end; 2: begin SpinEditR.Value := Trunc(p * 255); SpinEditG.Value := Trunc(v * 255); SpinEditB.Value := Trunc(t * 255); end; 3: begin SpinEditR.Value := Trunc(p * 255); SpinEditG.Value := Trunc(q * 255); SpinEditB.Value := Trunc(v * 255); end; 4: begin SpinEditR.Value := Trunc(t * 255); SpinEditG.Value := Trunc(p * 255); SpinEditB.Value := Trunc(v * 255); end; 5: begin SpinEditR.Value := Trunc(v * 255); SpinEditG.Value := Trunc(p * 255); SpinEditB.Value := Trunc(q * 255); end; end; end ; end;
※ 前節と同じく、このプログラム (ユニット) は customcolor.pas という名前で保存しておいてください。
正しく動くかどうか、確かめましょう。
RGB と HSV を相互変換する上記のイベントハンドラは、GIMP (1.2.0) というプログラムの一部を Delphi 向けに改変したものです。GIMP は GPL というライセンスに従って配布されており、そのため GIMP を改変したプログラムも GPL に従わなくてはなりません。
「RGB から HSV を計算」ボタンを押しても「HSV から RGB を計算」ボタンを押しても、左上のパネルに色が表示される、というようにプログラムに手を加えて下さい。
【応用課題 F-1】と同様に、スクロールバーによって HSV も調整出来るようにプログラムを改良して下さい。