« なぜ、素人によるFLASH製作ブームは去ったのか?について « » バトンについて、色んなタイプを生物として考えてみる。 »

2006年09月19日

 Flashで色のRGBやHSV(HSB)変換と管理をする。このエントリーを含むはてなブックマーク

クラスの例を作ったので貼っておきます。
カラーピッカーとかで使ってるアルゴリズムをゲームとかで使う関係で修正しました。
下手っぴですが、必要な部分だけ持ってくなり使うなり自由にしてください。

/*
 * ColorSet
 * 
 * 色の管理と、カラーコード⇔RGB分解⇔HSV分解を自動で行います。
 * 
 * HSVは本来はHSB(Brightness)とすべきですが、bがBlueと被るためv(Value)としてあります。
 * この表記はわりと一部で使用されているもので、WikiPedia等はHSVと表記しています。
 * HSBとHSVはまったく同じ意味です。
 * 
 * HSVの最大値はPhotoShopにあわせて、360、100、100となっています。
 * RGBはFlashの標準で255、255、255です。
 * cはRGBを統合したカラーコードですが、整数のみ返す仕様なので、
 * HSV、RGBに対して小数点以下で誤差が発生することがあります。
 * 
 * RGBが入力された時は直ちにHSVを計算せず、HSVが呼び出されるまでズレた状態になります。
 * これはHSVを使用しない場合に、計算量を抑えるためです。
 * 
 * @version	0.9
 * @author 	しっぽ
 * 
 */
class ColorSet
{
	static private var _RGB_MAX:Number = 255;
	static private var _H_MAX:Number = 360;
	static private var _SV_MAX:Number = 100;
	
	private var _r:Number = 255; // 赤色 0~255
	private var _g:Number = 255; // 緑色 0~255
	private var _b:Number = 255; // 青色 0~255
	
	private var _h:Number = 0; // 色相 0~360
	private var _s:Number = 0; // 再度 0~100
	private var _v:Number = 100; // 明度 0~100
	private var _rightnessHSV:Boolean = true; // RGBとHSVが同じ値をとっているかのフラグ。違う場合RGB優先。
	
	function ColorSet(arg_1:Object, arg_g:Number, arg_b:Number){
		if (arguments.length == 1){ // 値が1つの場合はカラーコードと考える。
			c = arguments[0];
		}else if (arguments.length == 3){ // 3つの値ならRGB
			_r = Number(arguments[0]);
			_g = arguments[1];
			_b = arguments[2];
		}else{ c = 0xffffff;} // 値が無い場合とかは白
		_rightnessHSV = false;
	}
	
	// RGB 普通の変数として使える。
	function get r():Number{	return _r;}
	function set r(arg:Number){
		_r = Math.min(Math.max(0, arg), _RGB_MAX);
		_rightnessHSV = false;
	}
	function get g():Number{	return _g;}
	function set g(arg:Number){
		_g = Math.min(Math.max(0, arg), _RGB_MAX);
		_rightnessHSV = false;
	}
	function get b():Number{	return _b;}
	function set b(arg:Number){
		_b = Math.min(Math.max(0, arg), _RGB_MAX);
		_rightnessHSV = false;
	}
	
	// カラー。 RGBの変動で自動的に変わる。
	function get c():Number{
		// RGBから統合。四捨五入をするので誤差あり。
		return Math.round(_r)*0x10000 + Math.round(_g)*0x100 + Math.round(_b);
	}
	function set c(arg_c:Number){
		arg_c = Math.min(Math.max(0, arg_c), 0xffffff);
		// RGBに分割。
		_r = Math.floor(arg_c / 0x10000);
		_g = Math.floor(arg_c / 0x100) % 0x100;
		_b = arg_c % 0x100;
		_rightnessHSV = false;
	}
	
	// HSV 呼び出された時にRGBとズレていれば計算し、そうでない場合は保存してある値を返す。
	function get h():Number{
		if (!_rightnessHSV) calcHSV();
		return _h;
	}
	function set h(arg:Number){
		if (!_rightnessHSV) calcHSV();
		_h = (arg % _H_MAX + _H_MAX) % _H_MAX;
		calcRGB();
	}
	function get s():Number{
		if (!_rightnessHSV) calcHSV();
		return _s;
	}
	function set s(arg:Number){
		if (!_rightnessHSV) calcHSV();
		_s = Math.min(Math.max(0, arg), _SV_MAX);
		calcRGB();
	}
	function get v():Number{
		if (!_rightnessHSV) calcHSV();
		return _v;
	}
	function set v(arg:Number){
		if (!_rightnessHSV) calcHSV();
		_v = Math.min(Math.max(0, arg), _SV_MAX);
		calcRGB();
	}
	
	// HSVから入力された時にRGBを計算する。
	private function calcRGB(){
		if (_s == 0){ // 無彩色
			_r = _g = _b = _v*_RGB_MAX/_SV_MAX;
		}else{
			var hi:Number = Math.floor(_h / (_H_MAX / 6)) % 6;
			var f:Number = _h / (_H_MAX / 6) - hi;
			var p:Number = _v / _SV_MAX * ( 1 - _s / _SV_MAX );
			var q:Number = _v / _SV_MAX * ( 1 - _s / _SV_MAX  * f);
			var t:Number = _v / _SV_MAX * ( 1 - _s / _SV_MAX  * ( 1 - f));
			
			switch (hi) { 
			case 0 : 
				_r = _v/_SV_MAX; _g = t; _b = p;
				break; 
			case 1 : 
				_r = q; _g = _v/_SV_MAX; _b = p;
				break; ;
			case 2 : 
				_r = p; _g = _v/_SV_MAX; _b = t;
				break; 
			case 3 : 
				_r = p; _g = q; _b = _v/_SV_MAX;
				break; 
			case 4 : 
				_r = t; _g = p; _b = _v/_SV_MAX;
				break; 
			case 5 : 
				_r = _v/_SV_MAX; _g = p; _b = q;
				break; 
			}
			_r *= _RGB_MAX;
			_g *= _RGB_MAX;
			_b *= _RGB_MAX;
		}
		_rightnessHSV = true;
	}
	// RGBから入力された時にHSVを計算する。
	private function calcHSV(){
		var maxRGB = Math.max(_r, Math.max(_g, _b));
		var difference = maxRGB - Math.min(_r, Math.min(_g, _b));
		if (maxRGB == 0){ // 最大値が0。つまり黒。
			_v = 0; // V以外の値は元の値を維持する。
		}else if (difference == 0){ // 全ての色が均一。つまり無彩色
			_v = maxRGB * _SV_MAX / _RGB_MAX;
			_s = 0; // Hは未定義になるため元の値を維持する。
		}else{ // 普通の色。
			_v = maxRGB * _SV_MAX / _RGB_MAX;
			_s = (difference / maxRGB)*_SV_MAX; 
			if (maxRGB == _r) _h = ((_g - _b)/difference + 0)*_H_MAX/6;
			else if (maxRGB == _g) _h = ((_b - _r)/difference + 2)*_H_MAX/6;
			else _h = ((_r - _g)/difference + 4)*_H_MAX/6;
			_h = (_h % _H_MAX + _H_MAX)%_H_MAX;
		}
		_rightnessHSV = true;
	}
	
	// 文字列変換
	function toString():String{
		if (!_rightnessHSV) calcHSV();
		return "color:" + colorCode + "(" + _r + ", " + _g + "," + _b +")(" + _h + ", " + _s + "," + _v + ")";
	}
	
	// カラーコードを文字列で返す
	function get colorCode():String{
		var ans = c.toString(16);
		var zero = "";
		for (var i = 0; i < 6 - ans.length; i++) zero += "0";
		return zero + ans;
	}
	
	/*
	 * カラーコードを文字列で入力する。#とか0xとかいうのも消してくれる。
	 * あと、f0aみたいな3文字を、ff00aaと解釈。
	 * fa03のような場合は00fa03と解釈。
	 */
	function set colorCode(arg:String){
		arg = arg.split("#").join("");
		arg = arg.split("0x").join("");
		if (arg.length == 3){
			arg = arg.substr(0, 1) + arg.substr(0, 1)
				+ arg.substr(1, 1) + arg.substr(1, 1)
				+ arg.substr(2, 1) + arg.substr(2, 1);
		}
		c = parseInt(arg, 16);
	}
	
	static function get RGB_MAX():Number{	return _RGB_MAX;}
	static function get H_MAX():Number{	return _H_MAX;}
	static function get SV_MAX():Number{	return _SV_MAX;}

バグとかあっても責任は負いません。

使い方。

2.0が分からない人は、上の部分を全部コピーしてColorSet.asという名前で.flaファイルと同じ場所に保存して下さい。
分かる人は適当にパッケージつけるか、まあ、改造するとか、好きにどうぞ。

testcolor = new ColorSet(0xff0000);
trace(testcolor.r); // 255;
trace(testcolor.h); // 0;
testcolor.h = 60; // 色相を60にする(色相60は黄色)
trace(testcolor.colorCode); //ffff00

こんな感じに使えます。
変数、r、g、b がそれぞれ、赤緑青の要素で最大255
変数、h、s、v がそれぞれ、色相、彩度、明度で、色相は最大360、彩度明度は最高100です。
変数、cで普通のカラーコードを返し、colorCodeでは文字列のカラーコードを返します。

変数に値を入力すると別の変数も全て影響を受けて変化します。
なので、入れた変数の彩度だけ変更してカラーコードを返す、みたいな使い方ができます。
HSV(HSB)って何って人はここらへんに説明があります

凄く関係ないけど、今までこうやってブログに貼り付けてる人の見て
みんな難しそうなの作るなーとか思ってたんだけど
自分のブログに貼り付けたらなんか元のより5割増しくらいに難しく見えるw
エディタって大切だね。

トラックバックURL

トラックバック

» 待受FLASH:colorstripe02 from diary - Bear Festa
携帯電話用待ち受けFlash第2弾作成。 colorstripe01と基本... [Read More]

コメント

1836   投稿者: Teena Howell (2007年09月03日 01:08)

spawneater supranormal unparrel yurucare nonapparent chitter nonconvertible mermithized
http://www.angelfire.com/aoyobu/2.html >am
http://www.angelfire.com/aoyobu/1.html

しっぽのブログ

コメントする

(サーバーが見つかりませんの表示になることがありますが、
正しく投稿されてることが多いです。
落ち着いて確認してみてください。)

はてなブックマーク