

cOwOlor
by XR_XharpRazor & Eikyuu_KuroiKitsune
RGB, HSL, CMYK, all in one place, Generate Color Palettes​
#RRGGBB
RGB​
HSV
CMYK
YIQ
conversions, HOW !?
how everything works behind the scene
a few Notations and Revisions
LERP_MAPPING is heavily used when it comes to color conversion
function LERP_MAPPING( Vin , Ain , Bin , Aout , Bout )
{
t = ( Vin - Ain ) / ( Bin - Ain )
return ( Bout - Ain ) * t + Aout
}
a lot of explaination uses the concept of length
therefore, sometimes we may use "strips" or "meters" to represent the strength or an amount of the channel
the "=" is used to represent the positive part,
the "." is used to represent the compliment part
strength : 000- ---- ---- ---- ---- ---- ---- -255
RED : ==== ==== ==== ==== ==== ==== ==== ====
GREEN : ==== ==== ==== ==== ==== ==== .... ....
BLUE : .... .... .... .... .... .... .... ....
​
which is equivalent to RGB(255,192,0) or #FFC000
from RGB to HSV
assume that the RGB input is :
R1 : ==== ==== ==== ==== ==== ==== .... ....
G1 : ==== ==== ==== ==== .... .... .... ....
B1 : ==== ==== .... .... .... .... .... ....
the Max Channel is actually V​, in this example, it's Red
Vout = max(R1, G1, B1)
|--- ---- --- V --- ---- ---|
R1 : ==== ==== ==== ==== ==== ==== .... ....
G1 : ==== ==== ==== ==== .... .... .... ....
B1 : ==== ==== .... .... .... .... .... ....
now we will stretch R and G and B until the max channel reaches 255
we will do this stretching by multiplying every channel by a number, say "factorStretchV"
before :
​
R1 : ==== ==== ==== ==== ==== ==== .... ....
G1 : ==== ==== ==== ==== .... .... .... ....
B1 : ==== ==== .... .... .... .... .... ....
​
after :
​
R2 : ==== ==== ==== ==== ==== ==== ==== ====
G2 : ==== ==== ==== ==== ==== =... .... ....
B2 : ==== ==== ===. .... .... .... .... ....
but we need to know, what is factorStretchV
MaxCannel * factorStretchV = 255
factorStretchV = 255 / MaxChannel
​​
R2 = R1 * factorStretchV
G2 = G1 * factorStretchV
B2 = B1 * factorStretchV
​​
//MaxChannel is V is well
Warning
If MaxChannel is 0, this means that no RGB at all, which means this color is black.
If we ignore this fact, then we are diving by 0
here, if we take the compliment of each channel, the Max is S​ ,
in this example, it's Blue's Compliment
R2p : ==== ==== ==== ==== ==== ==== ==== ==== : R2n
G2p : ==== ==== ==== ==== ==== =... .... .... : G2n
B2p : ==== ==== ===. .... .... .... .... .... : B2n
| ---- ---- - S ---- ---|
Sout = 255 - min( R2p , G2p , B2p )
​​
or
​​
Sout = max( 255 - R2p , 255 - G2p , 255 - B2p )
​
or
​
R2n = 255 - R2p
G2n = 255 - G2p
B2n = 255 - B2p
Sout = max(R2n , G2n , B2n)
in this case, we can introduce the concept of a "wanderer" :
the color channel that is not the max or min, it is in between, "walking around" between the other 2 channels
​
at this point
among R2, G2, B2, one of them is 255, one of them is the minimum, one of them is in between​
based on who is the wanderer, who is the max, who is the min, the Hue can be determined
if ( R is max , G = B ){
Hue = 0 (red)
}
else if ( R is max , G is wander , B is min ){
when G is B , then Hue is 0
when G is R , then Hue is 60 (yellow)
use LERP_MAPPING
}
else if ( R = G , B is min ){
Hue = 60 (yellow)
}
else if ( R is wander , G is max , B is min ){
when R is G , then Hue is 60 (yellow)
when R is B , then Hue is 120 (green)
use LERP_MAPPING
}
else if ( R = B , G is max ){
Hue = 120 (green)
}
else if ( R is min , G is max , B is wander ){
when B is R , then Hue is 120 (green)
when B is G , then Hue is 180 (cyan)
use LERP_MAPPING
}
else if ( R is min , G = B ){
Hue = 180 (cyan)
}
else if ( R is min , G is wander , B is max ){
when G is B , then Hue is 180 (cyan)
when G is R , then Hue is 240 (blue)
use LERP_MAPPING
}
else if ( R = G , B is max ){
Hue = 240 (blue)
}
else if ( R is wander , G is min , B is max ){
when R is G , then Hue is 240 (blue)
when R is B , then Hue is 300 (magenta)
use LERP_MAPPING
}
else if ( R = B , G is min ){
Hue = 300 (magenta)
}
else if ( R is max , G is min , B is wander ){
when B is R , then Hue is 300 (magenta)
when B is G , then Hue is 360 (red)
use LERP_MAPPING
}
to convert from HSV to RGB
​
back at we were converting RGB to HSV,
recall the following :
V = max(R1, G1, B1)
​
factorStretchV = 255 / V
​​
R2p = R1 * factorStretchV
G2p = G1 * factorStretchV
B2p = B1 * factorStretchV
​​
R2n = 255 - R2p
G2n = 255 - G2p
B2n = 255 - B2p
S = max(R2n, G2n, B2n)
​
H = BIG_SELECT_CASE_LERP_MAPPING(R1, G1, B1)​​​
|--- ---- --- V --- ---- ---|​
R1 : ==== ==== ==== ==== ==== ==== .... ....
G1 : ==== ==== ==== ==== .... .... .... ....
B1 : ==== ==== .... .... .... .... .... ....
​​​
R2p : ==== ==== ==== ==== ==== ==== ==== ==== : R2n
G2p : ==== ==== ==== ==== ==== =... .... .... : G2n
B2p : ==== ==== ===. .... .... .... .... .... : B2n
| ---- ---- - S ---- ---|
first we need to determine who is max, who is wanderer, who is min by using the Hue
note that min is 255 - Saturation
if ( Hue = 60 ){
R2p is 255
G2p is min
B2p is min
}
else if ( 0 < Hue < 60 ){
R2p is 255
B2p is min
G2p is in between, use LERP_MAPPING
}
else if ( Hue = 60 ){
R2p is 255
G2p is 255
B2p is min
}
else if ( 60 < Hue < 120 ){
use LERP_MAPPING
R2p is in between, use LERP_MAPPING
G2p is 255
B2p is min
}
else if ( Hue = 120 ){
R2p is min
G2p is 255
B2p is min
}
else if ( 120 < Hue < 180 ){
R2p is min
G2p is 255
B2p is in between, use LERP_MAPPING
}
else if ( Hue = 180 ){
R2p is min
G2p is 255
B2p is 255
}
else if ( 180 < Hue < 240 ){
R2p is min
G2p is in between, use LERP_MAPPING
B2p is 255
}
else if ( R = G , B is max ){
Hue = 240 (blue)
}
else if ( R is wander , G is min , B is max ){
use LERP_MAPPING
R2p is in between, use LERP_MAPPING
G2p is min
B2p is 255
}
else if ( Hue = 300 ){
R2p is 255
G2p is min
B2p is 255
}
else if ( 300 < Hue < 360 ){
R2p is 255
G2p is min
B2p is in between, use LERP_MAPPING
}
with all the R2p and G2p and B2p found, R1, G1, B1 can be found by using factorStretchV
from RGB to CMYK
assume that the RGB input is :
Rp : ==== ==== ==== ==== ==== ==== .... .... : Rn
Gp : ==== ==== ==== ==== .... .... .... .... : Gn
Bp : ==== ==== .... .... .... .... .... .... : Bn
here the MaxChannel is Red
Black is 255 - MaxChannel
|--- ---- -- Max -- ---- ---| |-- K --|
Rp : ==== ==== ==== ==== ==== ==== .... .... : Rn
Gp : ==== ==== ==== ==== .... .... .... .... : Gn
Bp : ==== ==== .... .... .... .... .... .... : Bn
note that :
Cyan is "not Red"
Magenta is "not Green"
Yellow is "not Blue"
C = Max - Rp (C is 0 in this example)
M = Max - Gp
Y = Max - Bp
​
|--- ---- ---- -- 255 -- ---- ---- ---|
|=== ==== = R:max = ==== ===| |== K ==|
|=== === G === ===| |== M ==| .... ....
|== B ==| |=== === Y === ===| .... ....
to convert from CMYK to RGB
​
first we need to know what is max base on K
|--- ---- ---- -- 255 -- ---- ---- ---|
|=R? ==== ===| |=== ==== =C=| |== K ==|
|=G? ==== ===| |=== ==== =M=| |== K ==|
|=B? ==== ===| |=== ==== =Y=| |== K ==|
then based on the given C and M and Y
we can then calculate R and G and B
in this case, one of C, M, Y has to be 0
or otherwise, the Max wont be the Max
|--- ---- ---- -- 255 -- ---- ---- ---|
|=== ==== = R:max = ==== ===| |== K ==|
|=== === G === ===| |== M ==| |== K ==|
|== B ==| |=== === Y === ===| |== K ==|