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

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

= 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