セカンドライフでHSVとRGBを相互変換してみよう

投稿日: 更新日:

HSVというのは、いわゆるHSV色空間のことです。
これは、Hue(色相)、Saturation(彩度)、Value(明度)を表しておりましています。

ご存知?の通りRGBの色空間から、HSVの色空間へ変換が可能でして、
これを利用すれば、今のRGBの色から、少し濃い色にしたり、逆に薄い色にしたり、
明るい色にしたり、暗い色にしたり、色相を反転させたり、いろいろできるわけです。

そしてこちらが、関数と逆関数です。スキニツカテイイヨー(あんまりテストしてないので・・・)

float	fractF(float x) { if(x >= 0) { return(x - (integer)x); } else { return(1.0 + (x - (integer)x));}}

vector getRgbFromHsv(vector hsv) {
	vector rgb = <hsv.z, hsv.z, hsv.z>;
	if(hsv.y > 0.0) {
		hsv.x *= 6.0;
		integer	i = (integer)hsv.x;
		float	f = fractF(hsv.x);
		if(i == 0) {
			rgb.y *= 1.0 - hsv.y * (1.0 - f);
			rgb.z *= 1.0 - hsv.y;
		}
		else if(i == 1) {
			rgb.x *= 1.0 - hsv.y * f;
			rgb.z *= 1.0 - hsv.y;
		}
		else if(i == 2) {
			rgb.x *= 1.0 - hsv.y;
			rgb.z *= 1.0 - hsv.y * (1.0 - f);
		}
		else if(i == 3) {
			rgb.x *= 1.0 - hsv.y;
			rgb.y *= 1.0 - hsv.y * f;
		}
		else if(i == 4) {
			rgb.x *= 1.0 - hsv.y * (1.0 - f);
			rgb.y *= 1.0 - hsv.y;
		}
		else if(i == 5) {
			rgb.y *= 1.0 - hsv.y;
			rgb.z *= 1.0 - hsv.y * f;
		}
	}
	return(rgb);
}

vector getHsvFromRgb(vector rgb) {
	float min = llListStatistics(LIST_STAT_MIN, [rgb.x, rgb.y, rgb.z]);
	float max = llListStatistics(LIST_STAT_MAX, [rgb.x, rgb.y, rgb.z]);
	vector hsv = <max - min, max - min, max>;
	if(hsv.x > 0.0) {
		if(max == rgb.x) {
			hsv.x = (rgb.y - rgb.z) / hsv.x;
			if (hsv.x < 0.0) {
				hsv.x += 6.0;
			}
		}
		else if(max == rgb.y) {
			hsv.x = 2.0 + (rgb.z - rgb.x) / hsv.x;
		}
		else {
			hsv.x = 4.0 + (rgb.x - rgb.y) / hsv.x;
		}
	}
	hsv.x /= 6.0;
	if(max != 0.0) {
		hsv.y /= max;
	}
	return(hsv);
}

default {
	state_entry() {
	}
	touch_start(integer total_number) {
		vector color	= <0.5, 0.7, 0.2>;
		vector hsv		= getHsvFromRgb(color);
		vector rgb		= getRgbFromHsv(hsv);
		llOwnerSay((string) hsv);
		llOwnerSay((string) rgb);
	}
}

色相は0→1が360度に対応していますので、
1を超えたら、また0→1へを繰り返します。

余談ですが、HLS色空間というものもあります。
こちらは少し、また計算式が変わってきています。詳しいことはこちらに。

以上


そしていつものおまけ
GLSL でおなじみの lerp や fract はよく使用するので、準備しておくと便利です。

float	fractF(float x) { if(x >= 0) { return(x - (integer)x); } else { return(1.0 + (x - (integer)x));}}
float	minF(float x, float xmin) { if(x > xmin) { return xmin; } else {return x;}}
float	maxF(float x, float xmax) { if(x < xmax) { return xmax; } else {return x;}}
vector	lerpV(vector A, vector B, float r) { return(A * (1.0 - r) + B * r); }
float	lerpF(float  a, float  b, float r) { return(a * (1.0 - r) + b * r); }
integer	lerpI(float  a, float  b, float r) { return((integer)(a * (1.0 - r) + b * r)); }
float	limitF(float x, float xmin, float xmax) { if(x > xmax) { return xmax; } else if(x < xmin) { return xmin; } else {return x;}}
integer	limitI(float x, float xmin, float xmax) { if(x > xmax) { return (integer)xmax; } else if(x < xmin) { return (integer)xmin; } else {return (integer)x;}}
float	normalizeF(float x, float xmin, float xmax) { return (x - xmin) / (xmax - xmin); }
広告

コメントをどうぞ(承認された後に公開されます。メールアドレスの記入は自由ですが、記入した場合でも一般公開されることはありません)

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中