top of page
Colorful Leaves

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

= 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 ==|

© Memo2007Ultra
bottom of page