Image processing
Color space conversion
Converting between RGB and HSV color space
RGBとHSVの相互変換

HSVカラーモデルは色を色相(Hue)彩度(Saturation)明度(Value)の3つの成分で表現します。 それぞれの成分は色の色味、鮮やかさ、明るさに相当します。 この方式は加法混色や減法混色といった色を混ぜ合わせる方式より、直感的に色の調節ができるとされています。

HSVカラーモデルとHSBカラーモデルは同一のものであり、Javaでは予めRGBからHSBに変換するRGBtoHSB関数が提供されています。 このRGBtoHSB関数はHSBの各値を0.0から1.0までの浮動小数点数で返します。

1. RGBからHSVへの変換(Converts from RGB color space to HSV color space)

RGBからHSVに変換するには以下の式を使用します。 この式のRGB値は0から255までの値を取ります。 HSVの値を求めるにはまず、RGBの3つの値から最大値と最小値を求める必要があります。

max = Math.max(red, Math.max(green, blue))
min = Math.min(red, Math.min(green, blue))

hueの値を求めるには4通りに分けて考える必要があります。 以下の式は0から360までの値を返します。

hue = 0                                                  if(max == min)
hue = (60 * (green - blue) / (max - min) + 360) mod 360  if(max == red)
hue = (60 * (blue - red) / (max - min)) + 120            if(max == green)
hue = (60 * (red - green) / (max - min)) + 240           if(max == blue)

2番目の式は負の値になる可能性があります。 これを回避するため360を加算し、その剰余を求めています。

saturationは条件式に応じて異なる2つの式を使います。 以下の式は0から255までの値を返します。

saturation = 0                                           if(max == 0)
saturation = (255 * ((max - min) / max))                 otherwise

valueには最大値を格納します。 valueは0から255までの値を取ります。

value = max

上記の式を使い、RGBをHSVに変換するコードを以下に示します。

java : Converts from RGB space to HSV space
public int[] RGBtoHSV(int red, int green, int blue){ int[] hsv = new int[3]; float max = Math.max(red, Math.max(green, blue)); float min = Math.min(red, Math.min(green, blue)); // h if(max == min){ hsv[0] = 0; } else if(max == red){ hsv[0] = (60 * (green - blue) / (max - min) + 360) % 360; } else if(max == green){ hsv[0] = (60 * (blue - red) / (max - min)) + 120; } else if(max == blue){ hsv[0] = (60 * (red - green) / (max - min)) + 240; } // s if(max == 0){ hsv[1] = 0; } else{ hsv[1] = (255 * ((max - min) / max)); } // v hsv[2] = max; return hsv; }

このプログラムはRGBの各値を受け取り、HSVの値を格納した配列を返します。

2. HSVからRGBへの変換(Converts from HSV color space to RGB color space)

HSVからRGBに変換するには以下の式を使用します。 この式のhueは0から360までの値を取り、saturationとvalueは0から255までの値を取ります。 RGBに変換するにはまず以下の式を計算する必要があります。

hi = Math.floor(hue / 60.0f) % 6
f  = (hue / 60.0f) - Math.floor(hue / 60.0f)
p  = Math.round(value * (1.0f - (saturation / 255.0f)))
q  = Math.round(value * (1.0f - (saturation / 255.0f) * f))
t  = Math.round(value * (1.0f - (saturation / 255.0f) * (1.0f - f)))

2番目の式でhiによる減算を行うと値が変わります。 例えば、hueが360のとき切り捨てでは6になりますが、その剰余を求めるhiでは0になります。

後はhiの値に応じてRGBの各値に格納する変数を変えるだけです。

red = value, green = t,     blue = p           if(hi == 0)
red = q,     green = value, blue = p           if(hi == 1)
red = p,     green = value, blue = t           if(hi == 2)
red = p,     green = q,     blue = value       if(hi == 3)
red = t,     green = p,     blue = value       if(hi == 4)
red = value, green = p,     blue = q           if(hi == 5)

上記の式を使い、HSVをRGBに変換するコードを以下に示します。

java : Converts from HSV space to RGB space
public int[] HSVtoRGB(int h, int s, int v){ float f; int i, p, q, t; int[] rgb = new int[3]; i = (int)Math.floor(h / 60.0f) % 6; f = (float)(h / 60.0f) - (float)Math.floor(h / 60.0f); p = (int)Math.round(v * (1.0f - (s / 255.0f))); q = (int)Math.round(v * (1.0f - (s / 255.0f) * f)); t = (int)Math.round(v * (1.0f - (s / 255.0f) * (1.0f - f))); switch(i){ case 0 : rgb[0] = v; rgb[1] = t; rgb[2] = p; break; case 1 : rgb[0] = q; rgb[1] = v; rgb[2] = p; break; case 2 : rgb[0] = p; rgb[1] = v; rgb[2] = t; break; case 3 : rgb[0] = p; rgb[1] = q; rgb[2] = v; break; case 4 : rgb[0] = t; rgb[1] = p; rgb[2] = v; break; case 5 : rgb[0] = v; rgb[1] = p; rgb[2] = q; break; } return rgb; }

プログラム内では小数点以下の計算が発生します。 なるべく正確に変換するにはMath.round(四捨五入)、Math.floor(切り捨て)、Math.ceil(切り上げ)などを正しく使う必要があります。 Javaでは浮動小数点数をint型にキャストすると自動的に小数点以下の値が切り捨てられます。