From Wakapon
Jump to: navigation, search
Line 3: Line 3:
 
For example, it makes sense to convert from a device-dependent [[Colorimetry#RGB|RGB]] space to a [[Colorimetry#HSL_and_HSV|HSL]] space since, even though they are both device-dependent, they are defined in the same "dependent space".
 
For example, it makes sense to convert from a device-dependent [[Colorimetry#RGB|RGB]] space to a [[Colorimetry#HSL_and_HSV|HSL]] space since, even though they are both device-dependent, they are defined in the same "dependent space".
  
Also, it makes sense to convert from 2 device-independent spaces like CIEXYZ and CIELAB.
+
Also, it makes sense to convert from 2 device-independent spaces like [[Colorimetry#CIE_XYZ|CIEXYZ]] and [[Colorimetry#CIE_LAB|CIELAB]].
  
 
Most importantly, the conversions between device-dependent color spaces and device-independent color spaces must '''always''' be accompanied by a [[Color_Profile|Color Profile]] that appropriately describes the ''dependence to the device''.
 
Most importantly, the conversions between device-dependent color spaces and device-independent color spaces must '''always''' be accompanied by a [[Color_Profile|Color Profile]] that appropriately describes the ''dependence to the device''.
  
'''NOTE:''' All conversions assume HDR color values, meaning no boundary in luminance except where indicated.
+
<!--'''NOTE:''' All conversions assume HDR color values, meaning no boundary in luminance except where indicated.-->
  
  
Line 26: Line 26:
 
  L = ( var_Max + var_Min ) / 2
 
  L = ( var_Max + var_Min ) / 2
 
   
 
   
  if ( del_Max == 0 )                     // This is a gray, no chroma...
+
  if ( del_Max == 0 )         // This is a gray, no chroma...
 
  {
 
  {
     H = 0                               // HSL results from 0 to 1
+
     H = 0                   // HSL results from 0 to 1
 
     S = 0
 
     S = 0
 
  }
 
  }
  else                                   // Chromatic data...
+
  else                       // Chromatic data...
 
  {
 
  {
 
     if ( L < 0.5 ) S = del_Max / ( var_Max + var_Min )
 
     if ( L < 0.5 ) S = del_Max / ( var_Max + var_Min )
Line 92: Line 92:
 
  V = var_Max
 
  V = var_Max
 
   
 
   
  if ( del_Max == 0 )                     // This is a gray, no chroma...
+
  if ( del_Max == 0 )         // This is a gray, no chroma...
 
  {
 
  {
     H = 0                               // HSV results from 0 to 1
+
     H = 0                     // HSV results from 0 to 1
 
     S = 0
 
     S = 0
 
  }
 
  }
  else                                   // Chromatic data...
+
  else                         // Chromatic data...
 
  {
 
  {
 
     S = del_Max / var_Max
 
     S = del_Max / var_Max
Line 117: Line 117:
 
* Output: RGB in [0,1]
 
* Output: RGB in [0,1]
  
  if ( S == 0 )                      //HSV from 0 to 1
+
  if ( S == 0 )                      // HSV from 0 to 1
 
  {
 
  {
 
     (R,G,B) = V
 
     (R,G,B) = V
Line 124: Line 124:
 
  {
 
  {
 
     var_h = H * 6
 
     var_h = H * 6
     if ( var_h == 6 ) var_h = 0      //H must be < 1
+
     if ( var_h == 6 ) var_h = 0      // H must be < 1
     var_i = int( var_h )            //Or ... var_i = floor( var_h )
+
     var_i = int( var_h )            // Or ... var_i = floor( var_h )
 
     var_1 = V * ( 1 - S )
 
     var_1 = V * ( 1 - S )
 
     var_2 = V * ( 1 - S * ( var_h - var_i ) )
 
     var_2 = V * ( 1 - S * ( var_h - var_i ) )
Line 137: Line 137:
 
     else                  { R = V    ; G = var_1 ; B = var_2 }
 
     else                  { R = V    ; G = var_1 ; B = var_2 }
 
  }
 
  }
 
 
==RGB / YUV==
 
  
  
Line 146: Line 143:
  
 
==XYZ / xyY==
 
==XYZ / xyY==
 +
(Source: http://www.easyrgb.com)
 +
 +
===XYZ &rarr; xyY===
 +
* Input: (Observer. = 2°, Illuminant = D65)
 +
** X in [0, 0.95047]
 +
** Y in [0, 1.00000]
 +
** Z in [0, 1.08883]
 +
* Output: xyY in [0,1]
 +
 +
Y = Y
 +
x = X / ( X + Y + Z )
 +
y = Y / ( X + Y + Z )
 +
 +
 +
===xyY &rarr; XYZ===
 +
* Input: xyY in [0,1]
 +
* Output: (Observer. = 2°, Illuminant = D65)
 +
** X in [0, 0.95047]
 +
** Y in [0, 1.00000]
 +
** Z in [0, 1.08883]
 +
 +
X = x * ( Y / y )
 +
Y = Y
 +
Z = ( 1 - x - y ) * ( Y / y )
 +
 +
  
 
==XYZ / Lab==
 
==XYZ / Lab==
 +
(Source: http://www.easyrgb.com)
 +
 +
Remember that [[Colorimetry#CIE_LAB|CIE L*a*b*]] is device-independent but needs a [[Colorimetry#White_Point|white point]] reference nevertheless.
 +
 +
Here, the [[Colorimetry#White_points_of_standard_illuminants|D65 illuminant]] is used.
 +
 +
===XYZ &rarr; L*a*b*===
 +
* Input: (Observer. = 2°, Illuminant = D65)
 +
** X in [0, 0.95047]
 +
** Y in [0, 1.00000]
 +
** Z in [0, 1.08883]
 +
* Output:
 +
** L* in [0,100]
 +
** a*, b* in [0,?]
 +
 +
var_X = X / ref_X          // ref_X = 0.95047  Observer= 2°, Illuminant= D65
 +
var_Y = Y / ref_Y          // ref_Y = 1.000
 +
var_Z = Z / ref_Z          // ref_Z = 1.08883
 +
 +
if ( var_X > 0.008856 ) var_X = var_X ^ ( 1/3 )
 +
else                    var_X = ( 7.787 * var_X ) + ( 16 / 116 )
 +
if ( var_Y > 0.008856 ) var_Y = var_Y ^ ( 1/3 )
 +
else                    var_Y = ( 7.787 * var_Y ) + ( 16 / 116 )
 +
if ( var_Z > 0.008856 ) var_Z = var_Z ^ ( 1/3 )
 +
else                    var_Z = ( 7.787 * var_Z ) + ( 16 / 116 )
 +
 +
CIE-L* = ( 116 * var_Y ) - 16
 +
CIE-a* = 500 * ( var_X - var_Y )
 +
CIE-b* = 200 * ( var_Y - var_Z )
 +
 +
===L*a*b* &rarr; XYZ===
 +
* Input:
 +
** L* in [0,100]
 +
** a*, b* in [0,?]
 +
* Output: (Observer. = 2°, Illuminant = D65)
 +
** X in [0, 0.95047]
 +
** Y in [0, 1.00000]
 +
** Z in [0, 1.08883]
 +
 +
var_Y = ( CIE-L* + 16 ) / 116
 +
var_X = CIE-a* / 500 + var_Y
 +
var_Z = var_Y - CIE-b* / 200
 +
 +
if ( var_Y^3 > 0.008856 ) var_Y = var_Y^3
 +
else                      var_Y = ( var_Y - 16 / 116 ) / 7.787
 +
if ( var_X^3 > 0.008856 ) var_X = var_X^3
 +
else                      var_X = ( var_X - 16 / 116 ) / 7.787
 +
if ( var_Z^3 > 0.008856 ) var_Z = var_Z^3
 +
else                      var_Z = ( var_Z - 16 / 116 ) / 7.787
 +
 +
X = ref_X * var_X    // ref_X = 0.95047    Observer= 2°, Illuminant= D65
 +
Y = ref_Y * var_Y    // ref_Y = 1.00000
 +
Z = ref_Z * var_Z    // ref_Z = 1.08883
 +
  
  

Revision as of 19:04, 1 January 2012

As seen in the Colorimetry page, it's important to understand the difference between Absolute (or device-independent) Color Space (.e.g. CIEXYZ, CIExyY, CIELAB) and device-dependent colors spaces (e.g. RGB, HSL, HSB, HSV).

For example, it makes sense to convert from a device-dependent RGB space to a HSL space since, even though they are both device-dependent, they are defined in the same "dependent space".

Also, it makes sense to convert from 2 device-independent spaces like CIEXYZ and CIELAB.

Most importantly, the conversions between device-dependent color spaces and device-independent color spaces must always be accompanied by a Color Profile that appropriately describes the dependence to the device.


Device-Dependent Color Space Conversions

Here, we will list the different conversions between device-dependent color spaces.

RGB / HSL

(Source: http://www.easyrgb.com)

RGB → HSL

  • Input: RGB in [0,1]
  • Output: HSL in [0,1]
var_Min = min( R, G, B )    // Min. value of RGB
var_Max = max( R, G, B )    // Max. value of RGB
del_Max = var_Max - var_Min // Delta RGB value

L = ( var_Max + var_Min ) / 2

if ( del_Max == 0 )         // This is a gray, no chroma...
{
   H = 0                    // HSL results from 0 to 1
   S = 0
}
else                        // Chromatic data...
{
   if ( L < 0.5 ) S = del_Max / ( var_Max + var_Min )
   else           S = del_Max / ( 2 - var_Max - var_Min )

   del_R = ( ( ( var_Max - var_R ) / 6 ) + ( del_Max / 2 ) ) / del_Max
   del_G = ( ( ( var_Max - var_G ) / 6 ) + ( del_Max / 2 ) ) / del_Max
   del_B = ( ( ( var_Max - var_B ) / 6 ) + ( del_Max / 2 ) ) / del_Max

   if      ( var_R == var_Max ) H = del_B - del_G
   else if ( var_G == var_Max ) H = ( 1 / 3 ) + del_R - del_B
   else if ( var_B == var_Max ) H = ( 2 / 3 ) + del_G - del_R

   if ( H < 0 ) H += 1
   if ( H > 1 ) H -= 1
}

HSL → RGB

  • Input: HSL in [0,1]
  • Output: RGB in [0,1]
if ( S == 0 )
{
   (R,G,B) = L;
}
else
{
   if ( L < 0.5 ) var_2 = L * ( 1 + S )
   else           var_2 = ( L + S ) - ( S * L )

   var_1 = 2 * L - var_2

   R = Hue_2_RGB( var_1, var_2, H + ( 1 / 3 ) ) 
   G = Hue_2_RGB( var_1, var_2, H )
   B = Hue_2_RGB( var_1, var_2, H - ( 1 / 3 ) )
}

Hue_2_RGB( v1, v2, vH )
{
   if ( vH < 0 ) vH += 1
   if ( vH > 1 ) vH -= 1
   if ( ( 6 * vH ) < 1 ) return ( v1 + ( v2 - v1 ) * 6 * vH )
   if ( ( 2 * vH ) < 1 ) return ( v2 )
   if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - vH ) * 6 )
   return ( v1 )
}


RGB / HSV

(Source: http://www.easyrgb.com)

RGB → HSV

  • Input: RGB in [0,1]
  • Output: HSV in [0,1]
var_Min = min( R, G, B )    // Min. value of RGB
var_Max = max( R, G, B )    // Max. value of RGB
del_Max = var_Max - var_Min // Delta RGB value 

V = var_Max

if ( del_Max == 0 )          // This is a gray, no chroma...
{
   H = 0                     // HSV results from 0 to 1
   S = 0
}
else                         // Chromatic data...
{
   S = del_Max / var_Max

   del_R = ( ( ( var_Max - var_R ) / 6 ) + ( del_Max / 2 ) ) / del_Max
   del_G = ( ( ( var_Max - var_G ) / 6 ) + ( del_Max / 2 ) ) / del_Max
   del_B = ( ( ( var_Max - var_B ) / 6 ) + ( del_Max / 2 ) ) / del_Max

   if      ( var_R == var_Max ) H = del_B - del_G
   else if ( var_G == var_Max ) H = ( 1 / 3 ) + del_R - del_B
   else if ( var_B == var_Max ) H = ( 2 / 3 ) + del_G - del_R

   if ( H < 0 ) H += 1
   if ( H > 1 ) H -= 1
}

HSV → RGB

  • Input: HSV in [0,1]
  • Output: RGB in [0,1]
if ( S == 0 )                       // HSV from 0 to 1
{
   (R,G,B) = V
}
else
{
   var_h = H * 6
   if ( var_h == 6 ) var_h = 0      // H must be < 1
   var_i = int( var_h )             // Or ... var_i = floor( var_h )
   var_1 = V * ( 1 - S )
   var_2 = V * ( 1 - S * ( var_h - var_i ) )
   var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) )

   if      ( var_i == 0 ) { R = V     ; G = var_3 ; B = var_1 }
   else if ( var_i == 1 ) { R = var_2 ; G = V     ; B = var_1 }
   else if ( var_i == 2 ) { R = var_1 ; G = V     ; B = var_3 }
   else if ( var_i == 3 ) { R = var_1 ; G = var_2 ; B = V     }
   else if ( var_i == 4 ) { R = var_3 ; G = var_1 ; B = V     }
   else                   { R = V     ; G = var_1 ; B = var_2 }
}


Device-Independent Color Space Conversions

Here, we will list the different conversions between device-independent color spaces.

XYZ / xyY

(Source: http://www.easyrgb.com)

XYZ → xyY

  • Input: (Observer. = 2°, Illuminant = D65)
    • X in [0, 0.95047]
    • Y in [0, 1.00000]
    • Z in [0, 1.08883]
  • Output: xyY in [0,1]
Y = Y
x = X / ( X + Y + Z )
y = Y / ( X + Y + Z )


xyY → XYZ

  • Input: xyY in [0,1]
  • Output: (Observer. = 2°, Illuminant = D65)
    • X in [0, 0.95047]
    • Y in [0, 1.00000]
    • Z in [0, 1.08883]
X = x * ( Y / y )
Y = Y
Z = ( 1 - x - y ) * ( Y / y )


XYZ / Lab

(Source: http://www.easyrgb.com)

Remember that CIE L*a*b* is device-independent but needs a white point reference nevertheless.

Here, the D65 illuminant is used.

XYZ → L*a*b*

  • Input: (Observer. = 2°, Illuminant = D65)
    • X in [0, 0.95047]
    • Y in [0, 1.00000]
    • Z in [0, 1.08883]
  • Output:
    • L* in [0,100]
    • a*, b* in [0,?]
var_X = X / ref_X          // ref_X = 0.95047   Observer= 2°, Illuminant= D65
var_Y = Y / ref_Y          // ref_Y = 1.000
var_Z = Z / ref_Z          // ref_Z = 1.08883

if ( var_X > 0.008856 ) var_X = var_X ^ ( 1/3 )
else                    var_X = ( 7.787 * var_X ) + ( 16 / 116 )
if ( var_Y > 0.008856 ) var_Y = var_Y ^ ( 1/3 )
else                    var_Y = ( 7.787 * var_Y ) + ( 16 / 116 )
if ( var_Z > 0.008856 ) var_Z = var_Z ^ ( 1/3 )
else                    var_Z = ( 7.787 * var_Z ) + ( 16 / 116 )

CIE-L* = ( 116 * var_Y ) - 16
CIE-a* = 500 * ( var_X - var_Y )
CIE-b* = 200 * ( var_Y - var_Z )

L*a*b* → XYZ

  • Input:
    • L* in [0,100]
    • a*, b* in [0,?]
  • Output: (Observer. = 2°, Illuminant = D65)
    • X in [0, 0.95047]
    • Y in [0, 1.00000]
    • Z in [0, 1.08883]
var_Y = ( CIE-L* + 16 ) / 116
var_X = CIE-a* / 500 + var_Y
var_Z = var_Y - CIE-b* / 200

if ( var_Y^3 > 0.008856 ) var_Y = var_Y^3
else                      var_Y = ( var_Y - 16 / 116 ) / 7.787
if ( var_X^3 > 0.008856 ) var_X = var_X^3
else                      var_X = ( var_X - 16 / 116 ) / 7.787
if ( var_Z^3 > 0.008856 ) var_Z = var_Z^3
else                      var_Z = ( var_Z - 16 / 116 ) / 7.787

X = ref_X * var_X     // ref_X = 0.95047     Observer= 2°, Illuminant= D65
Y = ref_Y * var_Y     // ref_Y = 1.00000
Z = ref_Z * var_Z     // ref_Z = 1.08883


Device-dependent / Device-independent Color Space Conversions

RGB (in sRGB) / XYZ

RGB (in Adobe RGB) / XYZ

RGB (with custom profile) / XYZ