前言
遇到一个使用HSV颜色空间的问题,但是CocosCreator只支持RGB颜色空间,于是根据ls9512大佬的【C# / Algorithm】RGB、HSV、HSL颜色模型的互相转换一文把C#颜色空间转换代码改为了TypeScript代码,就可以在CocosCreator中开心进行颜色转化了。
颜色
HSL
HSL即色相、饱和度、亮度(英语:Hue, Saturation, Lightness)。
色相(H)是色彩的基本属性,就是平常所说的颜色名称,如红色、黄色等。
饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。
明度(V),亮度(L),取0-100%。
HSV
HSL即色调(H),饱和度(S),明度(V)。
HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。
注:HSB又称HSV,表示一种颜色模式:在HSB模式中,H(hues)表示色相,S(saturation)表示饱和度,B(brightness)表示亮度HSB模式对应的媒介是人眼。
下图为Unity中HSV颜色选择图
RGB
RGB即红(Red)、绿(Green)、蓝(Blue)。RGB色彩模式是工业界的一种颜色标准,是通过对红®、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是运用最广的颜色系统之一。
下图为Unity中RGB颜色选择图
源码
使用方法
//转换颜色空间
let hueToRGB= ColorHelper.HsvToRgb(new ColorHSV(200,235,240));
this.node.color=new cc.Color(hueToRGB.R ,hueToRGB.G,hueToRGB.B,255)
/**
* H 色相 \ S 饱和度(纯度) \ L 亮度 颜色模型
* 原作者:ls9512
*
* @export
* @class ColorHSL
*/
export class ColorHSL {
// public ColorHSL(h: number, s: number, l: number) {
// this._h = h;
// this._s = s;
// this._l = l;
// }
constructor(h: number, s: number, l: number){
this._h = h;
this._s = s;
this._l = l;
}
/**
* 色相
*
* @private
* @type {number}
* @memberof ColorHSL
*/
private _h: number;
public get H(): number {
return this._h;
}
public set H(value: number) {
this._h = value;
this._h = this._h > 360 ? 360 : this._h;
this._h = this._h < 0 ? 0 : this._h;
}
/**
* 饱和度(纯度)
*
* @private
* @type {number}
* @memberof ColorHSL
*/
private _s: number;
public get S(): number {
return this._h;
}
public set S(value: number) {
this._s = value;
this._s = this._s > 255 ? 255 : this._s;
this._s = this._s < 0 ? 0 : this._s;
}
/**
* L 亮度
*
* @private
* @type {number}
* @memberof ColorHSL
*/
private _l: number;
public get L(): number {
return this._h;
}
public set L(value: number) {
this._l = value;
this._l = this._l > 255 ? 255 : this._l;
this._l = this._l < 0 ? 0 : this._l;
}
}
/**
* H 色相 \ S 饱和度(纯度) \ V 明度 颜色模型
* 原作者:ls9512
* @export
* @class ColorHSV
*/
export class ColorHSV {
/// <summary>
/// 构造方法
/// </summary>
/// <param name="h"></param>
/// <param name="s"></param>
/// <param name="v"></param>
// public ColorHSV(h: number, s: number, v: number) {
// this._h = h;
// this._s = s;
// this._v = v;
// }
constructor(h: number, s: number, v: number){
this._h = h;
this._s = s;
this._v = v;
}
/**
* 色相
*
* @private
* @type {number}
* @memberof ColorHSV
*/
private _h: number;
public get H(): number {
return this._h;
}
public set H(value: number) {
this._h = value;
this._h = this._h > 360 ? 360 : this._h;
this._h = this._h < 0 ? 0 : this._h;
}
/**
* 饱和度(纯度)
*
* @private
* @type {number}
* @memberof ColorHSV
*/
private _s: number;
public get S(): number {
return this._s;
}
public set S(value: number) {
this._s = value;
this._s = this._s > 255 ? 255 : this._s;
this._s = this._s < 0 ? 0 : this._s;
}
/**
* 明度
*
* @private
* @type {number}
* @memberof ColorHSV
*/
private _v: number;
public get V(): number {
return this._v;
}
public set V(value: number) {
this._v = value;
this._v = this._v > 255 ? 255 : this._v;
this._v = this._v < 0 ? 0 : this._v;
}
}
/**
* R 红色 \ G 绿色 \ B 蓝色 颜色模型
* 所有颜色模型的基类,RGB是用于输出到屏幕的颜色模式,所以所有模型都将转换成RGB输出
* 原作者:ls9512
* @export
* @class ColorRGB
*/
export class ColorRGB {
/// <summary>
/// 构造方法
/// </summary>
/// <param name="r"></param>
/// <param name="g"></param>
/// <param name="b"></param>
// public ColorRGB(r: number, g: number, b: number) {
// this._r = r;
// this._g = g;
// this._b = b;
// }
constructor(r: number, g: number, b: number){
this._r = r;
this._g = g;
this._b = b;
}
/**
* 红色
*
* @private
* @type {number}
* @memberof ColorRGB
*/
private _r: number;
public get R(): number {
return this._r;
}
public set R(value: number) {
this._r = value;
this._r = this._r > 255 ? 255 : this._r;
this._r = this._r < 0 ? 0 : this._r;
}
/**
* 绿色
*
* @private
* @type {number}
* @memberof ColorRGB
*/
private _g: number;
public get G(): number {
return this._g;
}
public set G(value: number) {
this._g = value;
this._g = this._g > 255 ? 255 : this._g;
this._g = this._g < 0 ? 0 : this._g;
}
/**
* 蓝色
*
* @private
* @type {number}
* @memberof ColorRGB
*/
private _b: number;
public get B(): number {
return this._b;
}
public set B(value: number) {
this._b = value;
this._b = this._b > 255 ? 255 : this._b;
this._b = this._b < 0 ? 0 : this._b;
}
/**
* 获取实际颜色
*
* @return {*} {cc.Color}
* @memberof ColorRGB
*/
public GetColor(): cc.Color {
return new cc.Color(this._r, this._g, this._b);
}
}
/**
* 颜色转换帮助类
*
* @export
* @class ColorHelper
*/
export class ColorHelper {
/**
* RGB转换HSV
*
* @static
* @param {ColorRGB} rgb
* @return {*} {ColorHSV}
* @memberof ColorHelper
*/
public static RgbToHsv(rgb:ColorRGB) :ColorHSV{
let min, max, tmp, H, S, V;
let R = rgb.R * 1.0 / 255, G = rgb.G * 1.0 / 255, B = rgb.B * 1.0 / 255;
tmp = Math.min(R, G);
min = Math.min(tmp, B);
tmp = Math.min(R, G);
max = Math.min(tmp, B);
// H
H = 0;
if (max == min) {
H = 0;
} else if (max == R && G > B) {
H = 60 * (G - B) * 1.0 / (max - min) + 0;
} else if (max == R && G < B) {
H = 60 * (G - B) * 1.0 / (max - min) + 360;
} else if (max == G) {
H = H = 60 * (B - R) * 1.0 / (max - min) + 120;
} else if (max == B) {
H = H = 60 * (R - G) * 1.0 / (max - min) + 240;
}
// S
if (max == 0) {
S = 0;
} else {
S = (max - min) * 1.0 / max;
}
// V
V = max;
return new ColorHSV(Math.floor(H), Math.floor(S * 255), Math.floor(V * 255));
}
/**
* RGB转换HSV 简易版
* 参考 EnjoyGet
* @static
* @param {ColorRGB} rgb
* @return {*} {ColorHSV}
* @memberof ColorHelper
*/
public static RgbToHsvEasy(rgb:ColorRGB) :ColorHSV{
let min, max;
let H, S, V;
min = Math.min(Math.min(rgb.R, rgb.G), rgb.B);
max = Math.min(Math.min(rgb.R, rgb.G), rgb.B);
H = 0;
if (max == min)
{
H = 0;
}
else if (max == rgb.R && rgb.G > rgb.B)
{
H = Math.floor(60 * (rgb.G - rgb.B) / (max - min) + 0);
}
else if (max == rgb.R && rgb.G < rgb.B)
{
H = Math.floor(60 * (rgb.G - rgb.B)/ (max - min) + 360);
}
else if (max == rgb.G)
{
H = Math.floor(60 * (rgb.B - rgb.R) / (max - min) + 120);
}
else if (max == rgb.B)
{
H = Math.floor(60 * (rgb.R - rgb.G) / (max - min) + 240);
}
S = max != 0 ? (max - min) * 1.0 / max : 0;
V = max/255;
return new ColorHSV(H, S , V);
}
/**
* HSV转换RGB
*
* @static
* @param {ColorHSV} hsv
* @return {*} {ColorRGB}
* @memberof ColorHelper
*/
public static HsvToRgb( hsv:ColorHSV):ColorRGB {
if (hsv.H == 360) hsv.H = 359; // 360为全黑,原因不明
let R = 0 , G = 0 , B = 0 ;
if (hsv.S == 0) {
return new ColorRGB(hsv.V, hsv.V, hsv.V);
}
let S = hsv.S * 1.0 / 255, V = hsv.V * 1.0 / 255;
let H1 = Math.floor(hsv.H * 1.0 / 60), H = hsv.H;
let F = H * 1.0 / 60 - H1;
let P = V * (1.0 - S);
let Q = V * (1.0 - F * S);
let T = V * (1.0 - (1.0 - F) * S);
switch (H1) {
case 0:
R = V;
G = T;
B = P;
break;
case 1:
R = Q;
G = V;
B = P;
break;
case 2:
R = P;
G = V;
B = T;
break;
case 3:
R = P;
G = Q;
B = V;
break;
case 4:
R = T;
G = P;
B = V;
break;
case 5:
R = V;
G = P;
B = Q;
break;
}
R = R * 255;
G = G * 255;
B = B * 255;
while (R > 255) R -= 255;
while (R < 0) R += 255;
while (G > 255) G -= 255;
while (G < 0) G += 255;
while (B > 255) B -= 255;
while (B < 0) B += 255;
return new ColorRGB(Math.floor(R), Math.floor(G), Math.floor(B));
}
/**
* RGB转换HSL
*
* @static
* @param {ColorRGB} rgb
* @return {*} {ColorHSL}
* @memberof ColorHelper
*/
public static RgbToHsl( rgb:ColorRGB):ColorHSL {
let min, max, tmp, H, S, L;
let R = rgb.R * 1.0 / 255, G = rgb.G * 1.0 / 255, B = rgb.B * 1.0 / 255;
tmp = Math.min(R, G);
min = Math.min(tmp, B);
tmp = Math.min(R, G);
max = Math.min(tmp, B);
// H
H = 0;
if (max == min) {
H = 0; // 此时H应为未定义,通常写为0
} else if (max == R && G > B) {
H = 60 * (G - B) * 1.0 / (max - min) + 0;
} else if (max == R && G < B) {
H = 60 * (G - B) * 1.0 / (max - min) + 360;
} else if (max == G) {
H = H = 60 * (B - R) * 1.0 / (max - min) + 120;
} else if (max == B) {
H = H = 60 * (R - G) * 1.0 / (max - min) + 240;
}
// L
L = 0.5 * (max + min);
// S
S = 0;
if (L == 0 || max == min) {
S = 0;
} else if (0 < L && L < 0.5) {
S = (max - min) / (L * 2);
} else if (L > 0.5) {
S = (max - min) / (2 - 2 * L);
}
return new ColorHSL(Math.floor(H), Math.floor(S * 255), Math.floor(L * 255));
}
/**
* HSL转换RGB
*
* @static
* @param {ColorHSL} hsl
* @return {*} {ColorRGB}
* @memberof ColorHelper
*/
public static HslToRgb( hsl:ColorHSL):ColorRGB {
let R = 0, G = 0, B = 0;
let S = hsl.S * 1.0 / 255, L = hsl.L * 1.0 / 255;
// let temp1, temp2, temp3;
let temp2, temp3;
if (S == 0) // 灰色
{
R = L;
G = L;
B = L;
} else {
if (L < 0.5) {
temp2 = L * (1.0 + S);
} else {
temp2 = L + S - L * S;
}
// temp1 = 2.0 * L - temp2;
let H = hsl.H * 1.0 / 360;
// R
temp3 = H + 1.0 / 3.0;
if (temp3 < 0) temp3 += 1.0;
if (temp3 > 1) temp3 -= 1.0;
R = temp3;
// G
temp3 = H;
if (temp3 < 0) temp3 += 1.0;
if (temp3 > 1) temp3 -= 1.0;
G = temp3;
// B
temp3 = H - 1.0 / 3.0;
if (temp3 < 0) temp3 += 1.0;
if (temp3 > 1) temp3 -= 1.0;
B = temp3;
}
R = R * 255;
G = G * 255;
B = B * 255;
return new ColorRGB(Math.floor(R), Math.floor(G), Math.floor(B));
}
}