package sketchbook.colors{
/**
* 色操作を支援するクラスです。
*
ColorUtilを用いることで、RGB,HSB,HLS間の色の変換等を行うことができます。
* AS2との互換性保持の為、このクラスは色情報のやり取りに無名オブジェクト{r:uint, g:uint, b:uint}を用いています。
* AS3で色を操作する場合には、Colorクラスの使用を推奨します。
*
* @example
* var rgb:Object = {r:40, g:200, b:200}
* var hsb:Object = ColorUtils.RGB2HSB(rgb)
* trace(hsb.h,hsb.s,hsb.b)
* @see sketchbook.colors.Color
*/
public class ColorUtil{
public function ColorUtil(){
throw new Error("ColorUtil is static class");
}
/**
* 24ビットの色を、h,s,bを格納したオブジェクトに変換します。
* @param 24bit color.
* @returns HSB object {h:Hue, s:Saturation, b:Brightness}
*/
public static function getHSB(color:uint):Object
{
var rgbObj:Object = getRGB(color);
return RGB2HSB(rgbObj.r,rgbObj.g,rgbObj.b);
}
/**
* 24ビットの色を、h,l,sを格納したオブジェクトに変換します。
* @param 24bit color
* @returns HLS object {h:Hue, l:Luminous, s:Saturation}
*/
public static function getHLS(color:uint):Object{
var rgbObj:Object = getRGB(color);
return RGB2HLS(rgbObj.r, rgbObj.g, rgbObj.b)
}
/**
* 24ビットの色を、r,g,bを格納したオブジェクトに変換します。
*
* @param 24bit color
* @return Object that contains {r:Red, g:Green, b:Blue}
*/
public static function getRGB(rgb:uint):Object{
return {
r: rgb >> 16 & 0xff,
g: rgb >> 8 & 0xff,
b: rgb & 0xff
}
}
/**
* r,g,bを格納したオブジェクトの色を、HSBで定義しなおします。
*
* @param Object with property h, s, b
* @param hue 0-255
* @param saturation 0-255
* @param brightness 0-255
*/
public static function setHSB( col:Object, h:Number, s:Number, b:Number):void
{
var rgbObj:Object = HSB2RGB(h,s,b);
setRGB(col, rgbObj.r, rgbObj.g, rgbObj.b);
}
/**
* r,g,bを格納したオブジェクトの色を、HLSで定義しなおします。
*
* @param Object with property h, s, b
* @param hue 0-255
* @param luminus 0-255
* @param saturation 0-255
*/
public static function setHLS( col:Object, h:Number, l:Number, s:Number):void{
var rgbObj:Object = HLS2RGB(h,l,s);
setRGB(col, rgbObj.r, rgbObj.g, rgbObj.b);
}
/**
* Set Color.value with R,G,B.
*
* @param Object with property r, g, b
* @param red 0-255
* @param green 0-255
* @param blue 0-255
*/
public static function setRGB(obj:Object, r:uint, g:uint, b:uint):void{
r = (r < 0)? 0 : (r>255)? 255: Math.round(r);
g = (g < 0)? 0 : (g>255)? 255: Math.round(g);
b = (b < 0)? 0 : (b>255)? 255: Math.round(b);
obj.r = r<<16
obj.g = g<<8
obj.b = b
}
/**
* Create {h,s,b} Object from H, L, S value.
*
* @param hue
* @param luminous
* @param saturation
* @return {h:Hue, s:Saturation, b:Brightness}
*/
public static function HLS2HSB(h:Number, l:Number, s:Number):Object{
var rgbObj:Object = HLS2RGB(h,l,s);
return RGB2HSB(rgbObj.r, rgbObj.g, rgbObj.b);
}
/**
* H, L, Sの値から、{r,g,b}のオブジェクトを取得します。
*
* @param hue
* @param luminous
* @param saturation
* @return {r:Red, g:Green, b:Blue}
*/
public static function HLS2RGB(h:Number, l:Number, s:Number):Object{
var max:Number, min:Number;
h = (h<0)? h % 360+360 : (h>=360)? h%360: h;
l = (l<0)? 0 : (l>100)? 100: l;
s = (s<0)? 0 : (s>100)? 100: s;
l *= 0.01;
s *= 0.01;
if(s==0){
var val:Number = l * 255;
return {r:val, g:val, b:val};
}
if( l < 0.5){
max = l * (1+s) * 255
}else{
max = (l * (1-s) + s)*255
}
min = (2 * l)*255 - max;
return _hMinMax2RGB(h, min, max); //HSBとHLSの共通部分
}
/**
* Converts H, S, B values to {h:Hue, l:Luminous, s:Saturation} Object
*
* @param hue
* @param saturation
* @param brightness
* @return {h:Hue, l:Luminous, s:Saturation}
*/
public static function HSB2HLS(h:Number, s:Number, b:Number):Object{
var rgbObj:Object = HSB2RGB(h,s,b);
return RGB2HLS(rgbObj.r, rgbObj.g, rgbObj.b);
}
/**
* convert H, S, B values to {r:red, g:green, b:blue} Object
*
* @param hue 0-360
* @param saturation 0-100
* @param brightness 0-100
*
* @return contains r(0-255), g(0-255), n(0-255)
*/
public static function HSB2RGB(hue:Number, sat:Number, bri:Number):Object{
hue = (hue<0)? hue % 360+360 : (hue>=360)? hue%360: hue;
sat = (sat<0)? 0 : (sat>100)? 100: sat;
bri = (bri<0)? 0 : (bri>100)? 100: bri;
sat *= 0.01;
bri *= 0.01;
var val:Number
if(sat == 0){
val = bri*255;
return {r:val, g:val, b:val}
}
var max:Number = bri*255;
var min:Number = max*(1-sat);
return _hMinMax2RGB(hue, min, max);
}
/**
* convert R,G,B values to {h:huse,s:saturation,b:brightness} Object
*
* @param r Red value 0-255
* @param g Green value 0-255
* @param b Blue value 0-255
*
* @return contains h(0-360), s(0-100), b(0-100)
*/
public static function RGB2HSB(r:uint, g:uint, b:uint):Object{
r = (r < 0)? 0 : (r>255)? 255: Math.round(r);
g = (g < 0)? 0 : (g>255)? 255: Math.round(g);
b = (b < 0)? 0 : (b>255)? 255: Math.round(b);
var min:Number = Math.min(r, g, b);
var max:Number = Math.max(r, g, b);
//saturation
if(max==0){
//明度が0の時は黒
return {h:0, s: 0, b: 0}
}else{
var s:Number = (max - min)/max * 100;
}
//明度
//変数名b (BLUE) と混同しないように注意
var bri:Number = max / 255 * 100;
//色相
var h:Number = _getHue(r, b, g, max, min);
return {h:h, s:s, b:bri}
}
/**
* convert R,G,B values to {h:Hue,l:Luminous,s:Saturation} Object
*
* @param r Red value 0-255
* @param g Green value 0-255
* @param b Blue value 0-255
*
* @return contains {h:Hue,l:Luminous,s:Saturation}
*/
public static function RGB2HLS(r:uint, g:uint, b:uint):Object{
r = (r < 0)? 0 : (r>255)? 255: Math.round(r);
g = (g < 0)? 0 : (g>255)? 255: Math.round(g);
b = (b < 0)? 0 : (b>255)? 255: Math.round(b);
var min:Number = Math.min(r,g,b);
var max:Number = Math.max(r,g,b);
var l:Number = (max + min)*0.5 / 255 * 100;
var dist:Number = (max - min);
var h:Number
var s:Number
if(dist==0){
h = 0;
s = 0;
}else{
if( l < 127.5){
s = dist/(max+min)*100
}else{
s = dist/(510-max-min)*100
}
h = 360 - _getHue(r,g,b,max, min);
}
return {h:h, l:l, s:s}
}
public static function getLuminous( color:uint ) : uint
{
var r:uint = color >> 16 & 0xff;
var g:uint = color >> 8 & 0xff;
var b:uint = color & 0xff;
var min:Number = Math.min(r,g,b);
var max:Number = Math.max(r,g,b);
var l:Number = (max + min)*0.5 / 255 * 100;
return l;
}
/**
--------------------------------------------------------------------------------
INTERNAL METHOD
--------------------------------------------------------------------------------
*/
/*
* function: _hMinMax2RGB
*
* internal use only
*
* calcurates RGB used in hls, hsb conversion
*/
private static function _hMinMax2RGB(h:Number, min:Number, max:Number):Object{
var r:Number,g:Number,b:Number;
var area:Number = Math.floor(h / 60);
switch( area){
case 0:
r = max
//0 - 0, 60-255
g = min+h * (max-min)/ 60;
b = min
break;
case 1:
r = max-(h-60) * (max-min)/60;
g = max
b = min
break;
case 2:
r = min
g = max
b = min+(h-120) * (max-min)/60;
break;
case 3:
r = min
g = max-(h-180) * (max-min)/60;
b =max
break;
case 4:
r = min+(h-240) * (max-min)/60;
g = min
b = max
break;
case 5:
r = max
g = min
b = max-(h-300) * (max-min)/60;
break;
case 6:
r = max
//0 - 0, 60-255
g = min+h * (max-min)/ 60;
b = min
break;
}
r = Math.min(255, Math.max(0, Math.round(r)))
g = Math.min(255, Math.max(0, Math.round(g)))
b = Math.min(255, Math.max(0, Math.round(b)))
return {r:r, g:g, b:b}
}
/*
* funciton: _getHue
*
* internal use only
*
* calucurates hsb
*/
private static function _getHue(r:Number, g:Number, b:Number, max:Number, min:Number):Number{
var range:Number = max - min;
if(range==0){
return 0;
}
var rr:Number = (max - r)
var gg:Number = (max - g)
var bb:Number = (max - b)
var h:Number
switch(max){
case r:
h = bb - gg
break;
case g:
h = 2 *range+ rr - bb
break;
case b:
h = 4 *range+ gg - rr
break;
}
h*=-60;
h/=range;
h = (h<0)? h+360: h;
return h
}
}
}