2012-10-10 07:59:04 +02:00
|
|
|
/*
|
|
|
|
----------------------------------------------------
|
2012-11-21 11:11:19 +01:00
|
|
|
Color Space : 1.2 : 2012.11.06
|
|
|
|
----------------------------------------------------
|
|
|
|
https://github.com/mudcube/Color.Space.js
|
2012-10-10 07:59:04 +02:00
|
|
|
----------------------------------------------------
|
|
|
|
RGBA <-> HSLA <-> W3
|
|
|
|
RGBA <-> HSVA
|
|
|
|
RGBA <-> CMY <-> CMYK
|
|
|
|
RGBA <-> HEX24 <-> W3
|
|
|
|
RGBA <-> HEX32
|
|
|
|
RGBA <-> W3
|
|
|
|
----------------------------------------------------
|
|
|
|
Examples
|
|
|
|
----------------------------------------------------
|
|
|
|
Color.Space(0x99ff0000, "HEX32>RGBA>HSLA>W3"); // outputs "hsla(60,100%,17%,0.6)"
|
|
|
|
Color.Space(0xFF0000, "HEX24>RGB>HSL"); // convert hex24 to HSL object.
|
|
|
|
----------------------------------------------------
|
|
|
|
W3 values
|
|
|
|
----------------------------------------------------
|
|
|
|
rgb(255,0,0)
|
|
|
|
rgba(255,0,0,1)
|
|
|
|
rgb(100%,0%,0%)
|
|
|
|
rgba(100%,0%,0%,1)
|
|
|
|
hsl(120, 100%, 50%)
|
|
|
|
hsla(120, 100%, 50%, 1)
|
|
|
|
#000000
|
|
|
|
*/
|
|
|
|
|
2012-11-21 11:11:19 +01:00
|
|
|
if (typeof(Color) === "undefined") var Color = {};
|
2012-10-10 07:59:04 +02:00
|
|
|
if (typeof(Color.Space) === "undefined") Color.Space = {};
|
|
|
|
|
2012-11-06 22:06:08 +01:00
|
|
|
(function () { "use strict";
|
2012-10-10 07:59:04 +02:00
|
|
|
|
2012-11-21 11:11:19 +01:00
|
|
|
var useEval = false; // caches functions for quicker access.
|
|
|
|
|
2012-10-10 07:59:04 +02:00
|
|
|
var functions = {
|
|
|
|
// holds generated cached conversion functions.
|
|
|
|
};
|
2012-11-21 11:11:19 +01:00
|
|
|
|
2012-10-10 07:59:04 +02:00
|
|
|
var shortcuts = {
|
|
|
|
"HEX24>HSL": "HEX24>RGB>HSL",
|
|
|
|
"HEX32>HSLA": "HEX32>RGBA>HSLA",
|
|
|
|
"HEX24>CMYK": "HEX24>RGB>CMY>CMYK",
|
|
|
|
"RGB>CMYK": "RGB>CMY>CMYK"
|
|
|
|
};
|
|
|
|
|
|
|
|
var root = Color.Space = function(color, route) {
|
|
|
|
if (shortcuts[route]) { // shortcut available
|
|
|
|
route = shortcuts[route];
|
|
|
|
}
|
|
|
|
var r = route.split(">");
|
|
|
|
// check whether color is an [], if so, convert to {}
|
|
|
|
if (typeof(color) === "object" && color[0] >= 0) { // array
|
|
|
|
var type = r[0];
|
|
|
|
var tmp = {};
|
|
|
|
for(var i = 0; i < type.length; i ++) {
|
|
|
|
var str = type.substr(i, 1);
|
|
|
|
tmp[str] = color[i];
|
|
|
|
}
|
|
|
|
color = tmp;
|
|
|
|
}
|
|
|
|
if (functions[route]) { // cached function available
|
|
|
|
return functions[route](color);
|
|
|
|
}
|
|
|
|
var f = "color";
|
|
|
|
for (var pos = 1, key = r[0]; pos < r.length; pos ++) {
|
|
|
|
if (pos > 1) { // recycle previous
|
|
|
|
key = key.substr(key.indexOf("_") + 1);
|
|
|
|
}
|
|
|
|
key += (pos === 0 ? "" : "_") + r[pos];
|
|
|
|
color = root[key](color);
|
2012-11-21 11:11:19 +01:00
|
|
|
if (useEval) {
|
|
|
|
f = "Color.Space."+key+"("+f+")";
|
|
|
|
}
|
2012-11-06 20:59:07 +01:00
|
|
|
}
|
2012-11-21 11:11:19 +01:00
|
|
|
if (useEval) {
|
|
|
|
functions[route] = eval("(function(color) { return "+f+" })");
|
|
|
|
}
|
2012-10-10 07:59:04 +02:00
|
|
|
return color;
|
|
|
|
};
|
|
|
|
|
|
|
|
// W3C - RGB + RGBA
|
|
|
|
|
|
|
|
root.RGB_W3 = function(o) {
|
|
|
|
return "rgb(" + (o.R >> 0) + "," + (o.G >> 0) + "," + (o.B >> 0) + ")";
|
|
|
|
};
|
|
|
|
|
|
|
|
root.RGBA_W3 = function(o) {
|
|
|
|
var alpha = typeof(o.A) === "number" ? o.A / 255 : 1;
|
|
|
|
return "rgba(" + (o.R >> 0) + "," + (o.G >> 0) + "," + (o.B >> 0) + "," + alpha + ")";
|
|
|
|
};
|
|
|
|
|
|
|
|
root.W3_RGB = function(o) {
|
|
|
|
var o = o.substr(4, o.length - 5).split(",");
|
|
|
|
return {
|
|
|
|
R: parseInt(o[0]),
|
|
|
|
G: parseInt(o[1]),
|
|
|
|
B: parseInt(o[2])
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
root.W3_RGBA = function(o) {
|
|
|
|
var o = o.substr(5, o.length - 6).split(",");
|
|
|
|
return {
|
|
|
|
R: parseInt(o[0]),
|
|
|
|
G: parseInt(o[1]),
|
|
|
|
B: parseInt(o[2]),
|
|
|
|
A: parseFloat(o[3]) * 255
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// W3C - HSL + HSLA
|
|
|
|
|
|
|
|
root.HSL_W3 = function(o) {
|
|
|
|
return "hsl(" + ((o.H + 0.5) >> 0) + "," + ((o.S + 0.5) >> 0) + "%," + ((o.L + 0.5) >> 0) + "%)";
|
|
|
|
};
|
|
|
|
|
|
|
|
root.HSLA_W3 = function(o) {
|
|
|
|
var alpha = typeof(o.A) === "number" ? o.A / 255 : 1;
|
|
|
|
return "hsla(" + ((o.H + 0.5) >> 0) + "," + ((o.S + 0.5) >> 0) + "%," + ((o.L + 0.5) >> 0) + "%," + alpha + ")";
|
|
|
|
};
|
|
|
|
|
|
|
|
root.W3_HSL = function(o) {
|
|
|
|
var o = o.substr(4, o.length - 5).split(",");
|
|
|
|
return {
|
|
|
|
H: parseInt(o[0]),
|
|
|
|
S: parseInt(o[1]),
|
|
|
|
L: parseInt(o[2])
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
root.W3_HSLA = function(o) {
|
|
|
|
var o = o.substr(5, o.length - 6).split(",");
|
|
|
|
return {
|
|
|
|
H: parseInt(o[0]),
|
|
|
|
S: parseInt(o[1]),
|
|
|
|
L: parseInt(o[2]),
|
|
|
|
A: parseFloat(o[3]) * 255
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// W3 HEX = "FFFFFF" | "FFFFFFFF"
|
|
|
|
|
|
|
|
root.W3_HEX =
|
|
|
|
root.W3_HEX24 = function (o) {
|
|
|
|
if (o.substr(0, 1) === "#") o = o.substr(1);
|
|
|
|
if (o.length === 3) o = o[0] + o[0] + o[1] + o[1] + o[2] + o[2];
|
|
|
|
return parseInt("0x" + o);
|
|
|
|
};
|
|
|
|
|
|
|
|
root.W3_HEX32 = function (o) {
|
|
|
|
if (o.substr(0, 1) === "#") o = o.substr(1);
|
|
|
|
if (o.length === 6) {
|
|
|
|
return parseInt("0xFF" + o);
|
|
|
|
} else {
|
|
|
|
return parseInt("0x" + o);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// HEX = 0x000000 -> 0xFFFFFF
|
|
|
|
|
|
|
|
root.HEX_W3 =
|
|
|
|
root.HEX24_W3 = function (o, maxLength) {
|
|
|
|
if (!maxLength) maxLength = 6;
|
|
|
|
if (!o) o = 0;
|
|
|
|
var z = o.toString(16);
|
|
|
|
// when string is lesser than maxLength
|
|
|
|
var n = z.length;
|
|
|
|
while (n < maxLength) {
|
|
|
|
z = "0" + z;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
// when string is greater than maxLength
|
|
|
|
var n = z.length;
|
|
|
|
while (n > maxLength) {
|
|
|
|
z = z.substr(1);
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
return "#" + z;
|
|
|
|
};
|
|
|
|
|
|
|
|
root.HEX32_W3 = function(o) {
|
|
|
|
return root.HEX_W3(o, 8);
|
|
|
|
};
|
|
|
|
|
|
|
|
root.HEX_RGB =
|
|
|
|
root.HEX24_RGB = function (o) {
|
|
|
|
return {
|
|
|
|
R: (o >> 16),
|
|
|
|
G: (o >> 8) & 0xFF,
|
|
|
|
B: o & 0xFF
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// HEX32 = 0x00000000 -> 0xFFFFFFFF
|
|
|
|
|
|
|
|
root.HEX32_RGBA = function (o) {
|
|
|
|
return {
|
|
|
|
R: o >>> 16 & 0xFF,
|
|
|
|
G: o >>> 8 & 0xFF,
|
|
|
|
B: o & 0xFF,
|
|
|
|
A: o >>> 24
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// RGBA = R: Red / G: Green / B: Blue / A: Alpha
|
|
|
|
|
|
|
|
root.RGBA_HEX32 = function (o) {
|
|
|
|
return (o.A << 24 | o.R << 16 | o.G << 8 | o.B) >>> 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
// RGB = R: Red / G: Green / B: Blue
|
|
|
|
|
|
|
|
root.RGB_HEX24 =
|
|
|
|
root.RGB_HEX = function (o) {
|
|
|
|
if (o.R < 0) o.R = 0;
|
|
|
|
if (o.G < 0) o.G = 0;
|
|
|
|
if (o.B < 0) o.B = 0;
|
|
|
|
if (o.R > 255) o.R = 255;
|
|
|
|
if (o.G > 255) o.G = 255;
|
|
|
|
if (o.B > 255) o.B = 255;
|
|
|
|
return o.R << 16 | o.G << 8 | o.B;
|
|
|
|
};
|
|
|
|
|
|
|
|
root.RGB_CMY = function (o) {
|
|
|
|
return {
|
|
|
|
C: 1 - (o.R / 255),
|
|
|
|
M: 1 - (o.G / 255),
|
|
|
|
Y: 1 - (o.B / 255)
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
root.RGBA_HSLA =
|
|
|
|
root.RGB_HSL = function (o) { // RGB from 0 to 1
|
|
|
|
var _R = o.R / 255,
|
|
|
|
_G = o.G / 255,
|
|
|
|
_B = o.B / 255,
|
|
|
|
min = Math.min(_R, _G, _B),
|
|
|
|
max = Math.max(_R, _G, _B),
|
|
|
|
D = max - min,
|
|
|
|
H,
|
|
|
|
S,
|
|
|
|
L = (max + min) / 2;
|
|
|
|
if (D === 0) { // No chroma
|
|
|
|
H = 0;
|
|
|
|
S = 0;
|
|
|
|
} else { // Chromatic data
|
|
|
|
if (L < 0.5) S = D / (max + min);
|
|
|
|
else S = D / (2 - max - min);
|
|
|
|
var DR = (((max - _R) / 6) + (D / 2)) / D;
|
|
|
|
var DG = (((max - _G) / 6) + (D / 2)) / D;
|
|
|
|
var DB = (((max - _B) / 6) + (D / 2)) / D;
|
|
|
|
if (_R === max) H = DB - DG;
|
|
|
|
else if (_G === max) H = (1 / 3) + DR - DB;
|
|
|
|
else if (_B === max) H = (2 / 3) + DG - DR;
|
|
|
|
if (H < 0) H += 1;
|
|
|
|
if (H > 1) H -= 1;
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
H: H * 360,
|
|
|
|
S: S * 100,
|
|
|
|
L: L * 100,
|
|
|
|
A: o.A
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
root.RGBA_HSVA =
|
|
|
|
root.RGB_HSV = function (o) { //- RGB from 0 to 255
|
|
|
|
var _R = o.R / 255,
|
|
|
|
_G = o.G / 255,
|
|
|
|
_B = o.B / 255,
|
|
|
|
min = Math.min(_R, _G, _B),
|
|
|
|
max = Math.max(_R, _G, _B),
|
|
|
|
D = max - min,
|
|
|
|
H,
|
|
|
|
S,
|
|
|
|
V = max;
|
|
|
|
if (D === 0) { // No chroma
|
|
|
|
H = 0;
|
|
|
|
S = 0;
|
|
|
|
} else { // Chromatic data
|
|
|
|
S = D / max;
|
|
|
|
var DR = (((max - _R) / 6) + (D / 2)) / D;
|
|
|
|
var DG = (((max - _G) / 6) + (D / 2)) / D;
|
|
|
|
var DB = (((max - _B) / 6) + (D / 2)) / D;
|
|
|
|
if (_R === max) H = DB - DG;
|
|
|
|
else if (_G === max) H = (1 / 3) + DR - DB;
|
|
|
|
else if (_B === max) H = (2 / 3) + DG - DR;
|
|
|
|
if (H < 0) H += 1;
|
|
|
|
if (H > 1) H -= 1;
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
H: H * 360,
|
|
|
|
S: S * 100,
|
|
|
|
V: V * 100,
|
|
|
|
A: o.A
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// CMY = C: Cyan / M: Magenta / Y: Yellow
|
|
|
|
|
|
|
|
root.CMY_RGB = function (o) {
|
|
|
|
return {
|
|
|
|
R: Math.max(0, (1 - o.C) * 255),
|
|
|
|
G: Math.max(0, (1 - o.M) * 255),
|
|
|
|
B: Math.max(0, (1 - o.Y) * 255)
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
root.CMY_CMYK = function (o) {
|
|
|
|
var C = o.C;
|
|
|
|
var M = o.M;
|
|
|
|
var Y = o.Y;
|
|
|
|
var K = Math.min(Y, Math.min(M, Math.min(C, 1)));
|
|
|
|
C = Math.round((C - K) / (1 - K) * 100);
|
|
|
|
M = Math.round((M - K) / (1 - K) * 100);
|
|
|
|
Y = Math.round((Y - K) / (1 - K) * 100);
|
|
|
|
K = Math.round(K * 100);
|
|
|
|
return {
|
|
|
|
C: C,
|
|
|
|
M: M,
|
|
|
|
Y: Y,
|
|
|
|
K: K
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// CMYK = C: Cyan / M: Magenta / Y: Yellow / K: Key (black)
|
|
|
|
|
|
|
|
root.CMYK_CMY = function (o) {
|
|
|
|
return {
|
|
|
|
C: (o.C * (1 - o.K) + o.K),
|
|
|
|
M: (o.M * (1 - o.K) + o.K),
|
|
|
|
Y: (o.Y * (1 - o.K) + o.K)
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// HSL (1978) = H: Hue / S: Saturation / L: Lightess
|
|
|
|
// en.wikipedia.org/wiki/HSL_and_HSV
|
|
|
|
|
|
|
|
root.HSLA_RGBA =
|
|
|
|
root.HSL_RGB = function (o) {
|
|
|
|
var H = o.H / 360;
|
|
|
|
var S = o.S / 100;
|
|
|
|
var L = o.L / 100;
|
|
|
|
var R, G, B;
|
|
|
|
var temp1, temp2, temp3;
|
|
|
|
if (S === 0) {
|
|
|
|
R = G = B = L;
|
|
|
|
} else {
|
|
|
|
if (L < 0.5) temp2 = L * (1 + S);
|
|
|
|
else temp2 = (L + S) - (S * L);
|
|
|
|
temp1 = 2 * L - temp2;
|
|
|
|
// calculate red
|
|
|
|
temp3 = H + (1 / 3);
|
|
|
|
if (temp3 < 0) temp3 += 1;
|
|
|
|
if (temp3 > 1) temp3 -= 1;
|
|
|
|
if ((6 * temp3) < 1) R = temp1 + (temp2 - temp1) * 6 * temp3;
|
|
|
|
else if ((2 * temp3) < 1) R = temp2;
|
|
|
|
else if ((3 * temp3) < 2) R = temp1 + (temp2 - temp1) * ((2 / 3) - temp3) * 6;
|
|
|
|
else R = temp1;
|
|
|
|
// calculate green
|
|
|
|
temp3 = H;
|
|
|
|
if (temp3 < 0) temp3 += 1;
|
|
|
|
if (temp3 > 1) temp3 -= 1;
|
|
|
|
if ((6 * temp3) < 1) G = temp1 + (temp2 - temp1) * 6 * temp3;
|
|
|
|
else if ((2 * temp3) < 1) G = temp2;
|
|
|
|
else if ((3 * temp3) < 2) G = temp1 + (temp2 - temp1) * ((2 / 3) - temp3) * 6;
|
|
|
|
else G = temp1;
|
|
|
|
// calculate blue
|
|
|
|
temp3 = H - (1 / 3);
|
|
|
|
if (temp3 < 0) temp3 += 1;
|
|
|
|
if (temp3 > 1) temp3 -= 1;
|
|
|
|
if ((6 * temp3) < 1) B = temp1 + (temp2 - temp1) * 6 * temp3;
|
|
|
|
else if ((2 * temp3) < 1) B = temp2;
|
|
|
|
else if ((3 * temp3) < 2) B = temp1 + (temp2 - temp1) * ((2 / 3) - temp3) * 6;
|
|
|
|
else B = temp1;
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
R: R * 255,
|
|
|
|
G: G * 255,
|
|
|
|
B: B * 255,
|
|
|
|
A: o.A
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// HSV (1978) = H: Hue / S: Saturation / V: Value
|
|
|
|
// en.wikipedia.org/wiki/HSL_and_HSV
|
|
|
|
|
|
|
|
root.HSVA_RGBA =
|
|
|
|
root.HSV_RGB = function (o) {
|
|
|
|
var H = o.H / 360;
|
|
|
|
var S = o.S / 100;
|
|
|
|
var V = o.V / 100;
|
2012-11-06 22:06:08 +01:00
|
|
|
var R, G, B, D, A, C;
|
2012-10-10 07:59:04 +02:00
|
|
|
if (S === 0) {
|
|
|
|
R = G = B = Math.round(V * 255);
|
|
|
|
} else {
|
|
|
|
if (H >= 1) H = 0;
|
|
|
|
H = 6 * H;
|
|
|
|
D = H - Math.floor(H);
|
|
|
|
A = Math.round(255 * V * (1 - S));
|
|
|
|
B = Math.round(255 * V * (1 - (S * D)));
|
|
|
|
C = Math.round(255 * V * (1 - (S * (1 - D))));
|
|
|
|
V = Math.round(255 * V);
|
|
|
|
switch (Math.floor(H)) {
|
|
|
|
case 0:
|
|
|
|
R = V;
|
|
|
|
G = C;
|
|
|
|
B = A;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
R = B;
|
|
|
|
G = V;
|
|
|
|
B = A;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
R = A;
|
|
|
|
G = V;
|
|
|
|
B = C;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
R = A;
|
|
|
|
G = B;
|
|
|
|
B = V;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
R = C;
|
|
|
|
G = A;
|
|
|
|
B = V;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
R = V;
|
|
|
|
G = A;
|
|
|
|
B = B;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
R: R,
|
|
|
|
G: G,
|
|
|
|
B: B,
|
|
|
|
A: o.A
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
})();
|