

cOwOlor
by XR_XharpRazor & Eikyuu_KuroiKitsune
RGB, HSL, CMYK, all in one place, Generate Color Palettes
#RRGGBB
RGB
HSV
CMYK
CMY
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 ==|
.png)