Click here to Skip to main content
Click here to Skip to main content

Colorspaces and Conversions

, 24 Nov 2013
Rate this:
Please Sign up or sign in to vote.
A library for colormodels and spaces, correct color-conversions and color-difference calculation.

Introduction  

I stumbled across many color conversion libraries/tools that didn't take in account that an RGB color isn't per se defined. It's important to know what exact RGB colorspace this value is in (e.g., sRGB, AdobeRGB, or ProPhotoRGB) because they have different reference whites, different gamma values and different Chromaticity coordinates. Likewise things are important for other colormodels, too.

Because I needed those features for another software, wanted to learn a bit more about this whole color stuff and make the internet a better place, I wrote this library.

There are also some small GUIs: 

  • Conversion: convert to and from all supported colormodels
  • Color Difference: calculates the difference between two colors in various ways
  • Speed: measures the time it takes to convert from one colormodel to another

Background  

There are several different colormodels and spaces included in the library:

  • CIE XYZ (CIE 1931 2°) 
  • CIE Yxy (CIE 1931 2°) 
  • CIE L*a*b* (CIE 1976)
  • CIE L*u*v* (CIE 1976)
  • CIE LCHab
  • CIE LCHuv 
  • DIN99 (LCH99) 
  • DIN99b (LCH99b)
  • DIN99c (LCH99c)
  • DIN99d (LCH99d)
  • RGB 
    • NTSCRGB
    • BruceRGB
    • CIERGB
    • AdobeRGB
    • AppleRGB
    • ProPhotoRGB 
    • sRGB
    • WideGamutRGB
    • BestRGB
    • BetaRGB 
    • ColorMatchRGB
    • DonRGB4
    • EktaSpacePS5
    • PAL_SECAMRGB
    • SMPTE_C_RGB
  • HSV 
  • HSL
  • CMY
  • CMYK
  • YCbCr
    • ITU-R BT.601-625
    • ITU-R_BT.601-525
    • ITU-R-BT.709-1125
    • ITU-R BT.709-1250 
  • Gray
  • DEF
  • Bef
  • BCH
  • X-Channel Color (with X from 2 to 15)
  • ICC Profiles (alpha status)

Also it is possible to do chromatic adaption and change the reference white.

The conversion between those colormodels looks like this:

If you want to know more about how the conversion works: 

Of course you can also look at the code (ColorManagment->Color_Conversion.cs #region Conversions) or simply ask me.

Using the code 

Using the library is quite simple but still gives you all possibilities to define or convert a color.

Lets have a look at the static part of the ColorConverter class. There are some settings that are used if not defined otherwise. Those settings are:

  • ChromaticAdaptionMethod: The chromatic adaption method that will be used for conversions
  • ReferenceWhite: The reference white that will be used for colors if not stated otherwise
  • StandardColorspace: The standard colorspace that will be used if not stated otherwise
  • PreferredRenderingIntent: The preferred rendering intent that will be used if not stated otherwise and available within the ICC profile
  • StandardYCbCrSpace: The standard colorspace that will be used for YCbCr colors if not stated otherwise

Also, before you start using the library you should initiate the ColorConverter class. There won't be an error if you don't but this way everything will work controlled:

ColorConverter.Init(); 

Here are some examples for creating a new color. There are some more possibilities, just try it out as you need it. The code is documented so you'll see the explanation.

ColorRGB color = new ColorRGB(RGBSpaceName.sRGB);   //new RGB color in sRGB space
ColorRGB color = new ColorRGB(0, 0.5, 1);           //new RGB color in standard RGB space from settings
ColorRGB color = new ColorRGB(RGBSpaceName.sRGB, 0, 0.5, 1, true); //new linear RGB color in sRGB
ColorRGB color = new ColorRGB(new ICC("profile.icc"));  //new RGB color from an ICC profile
ColorLab color = new ColorLab(50, 12, -12); //new Lab color with reference white from settings
ColorLab color = new ColorLab(new Whitepoint(WhitepointName.D50));  //new Lab color with D50 reference white
ColorCMYK color = new ColorCMYK(new ICC("CMYKprofile.icc"));    //CMY(K) colors have to have an ICC profile

To convert from one color to another, use the ColorConverter class. Note that if you use multithreading, each thread has to have its own instance of the ColorConverter class!

ColorConverter Converter = new ColorConverter();    //create a new instance of a ColorConverter
ColorLab lab = new ColorLab(50, 12, -12);  //create a Lab color
ColorRGB rgb = Converter.ToRGB(lab, RGBSpaceName.sRGB);  //convert it to an RGB color in AdobeRGB colorspace 
ColorConverter Converter = new ColorConverter();    //create a new instance of a ColorConverter
ColorRGB rgb = new ColorRGB(RGBSpaceName.AdobeRGB, 0, 0.5, 1);  //create an RGB color
ColorLab lab = Converter.ToLab(rgb, WhitepointName.D50);    //convert it to a Lab color with D50 reference white
ColorLab lab = Converter.ToLab(rgb);                        //or convert it to a Lab color with the default reference white 

Converting with ICC profiles is a little bit different and may not work correctly yet. I couldn't test it thoroughly yet because of lack of different profiles and comparison with correct values. Nevertheless I add it here and if you find any mistakes/bugs, please report them to me. 

ColorConverter Converter = new ColorConverter();    //create a new instance of a ColorConverter
ColorLab lab = new ColorLab(50, 12, -12);  //create a Lab color
ColorRGB rgb = (ColorRGB)Converter.ToICC(lab, new ICC("profile.icc"));  //convert a color with an ICC profile

And to find the difference between two colors, use the ColorDifference class (not multithreading safe)

ColorLab lab1 = new ColorLab(0.5, 30, -12); //create the first Lab color
ColorLab lab2 = new ColorLab(0.5, 40, -2);  //create the second Lab color
double difference = ColorDifference.GetDeltaE_CIEDE2000(lab1, lab2);    //calculate the difference with CIE DE 2000 method 

Or with the Din99c method:

ColorLCH99c din1 = new ColorLCH99c(50, 12, 120);    //create the first DIN99c color
ColorLCH99c din2 = new ColorLCH99c(50, 16, 140);    //create the second DIN99c color
double difference = ColorDifference.GetDeltaE_DIN99(din1, din2);    //calculate the difference with the DIN99 method

For some methods you can also use GetDeltaC to get the Chroma difference and with GetDeltaH you can get the Hue difference.

For chromatic adaption, simply convert from one XYZ color to another:

ColorConverter Converter = new ColorConverter();    //create a new instance of a ColorConverter
ColorXYZ xyz = new ColorXYZ(new Whitepoint(WhitepointName.D50), 0, 0.5, 1);  //create a XYZ color with D50 reference white
xyz = Converter.ToXYZ(xyz, WhitepointName.D65);  //convert it to a XYZ color with a different reference white

If it's necessary to do chromatic adaption inbetween a conversion, say, from RGB to Lab, it is done automatically of course and you don't have to worry about it. I just wanted to mention that you can also do it explicitly.

 Since version 3.0 there is also the namespace Light available. It contains a few colormodels that stores all values as either byte (8 bit - BColor) or ushorts(16 bit - UColor) and generally is more lightweight than the standard color classes. The lightweight classes are working like the normal classes and the ColorConverter class  can be used for conversions, too.

Using the GUIs  

Conversion 

If you simply want to know how some color is represented in another colorspace you can use this GUI. Type in the values of your known color and press the "Convert" button next to the boxes. 

  1. Click on this square to select an RGB value from the color picker 
  2. The general settings
  3. The specific setting for each color 

Color Difference

To compare two colors use this GUI to see the difference calculated in different ways. On the right side are the general settings. To calculate the difference, select and set the two colors you want to compare and click on "Compare". To set the values, select the channel and type the value in the textbox above. The results will be below. Delta E is the difference, Delta H is the Hue difference and Delta C is the Chroma difference. 

Speed

To see how fast a conversion is, use this GUI. You can also see what difference multithreading makes. On the right side you can set the number of iterations and the general settings as well as the number of threads to use. Once you have set the colors like you want them, click on "Start" and wait for the result. The total time is the time it took for all iterations (in milliseconds) and the time per iteration is the average time it took for one conversion (in microseconds).

Limitations

As already noted before, ICC profiles are still in alpha and haven't been tested thoroughly. If you know some stuff about ICC profiles and how the conversion with them works, I'd appreciate any help.  And since it's not really finished yet, the conversion speed with ICC profiles is rather slow (compared to the normal conversion). 

Points of Interest   

Well, learning how all those colorspaces work certainly broke my brain several times but now (I think) I understand it. So, if you have any questions on how anything from this stuff works, don't hesitate to ask.

Planned

For future version I have planned:

  • Out of Gamut warning/check
  • Render Intent calculation 
  • Better and faster ICC support

History

  • July 2013 - Version 1.0 (library and GUI)  
  • September 2013 - Version 2.0 (library and three GUIs) 
    • Changed the structure of the RGB color
    • Separated the conversion from the color class to new conversion class
    • Added several new colormodels
    • Added ICC support
    • Added chromatic adaption
    • Added the color difference class
    • Added GUIs for the color difference and for speed measurement
    • Improved conversion speed massively
  • November 2013 - Version 3.0 (library and three GUIs)
    • fixed a bug in LCHuv calculation
    • fixed a bug in Delta E CMC calculation
    • fixed other minor bugs
    • fixed a mistake and added DIN99 colors in Color.Copy()
    • fixed ColorDifference CMC methods: Lab has to have D65 reference white
    • added Delta E CMC calculation with custom l:c values
    • added conversion from DIN99c and DIN99d to all other colormodels
    • added Light version for colors: store values in bytes or ushorts for smaller memory print
    • added DEF, Bef and BCH colormodels with all conversions

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

Share

About the Author

No Biography provided

Comments and Discussions

 
QuestionRGB to CMYK PinmemberDarren Schroeder24-Jul-14 8:06 
QuestionConverting between two ICC profiles Pinmemberasi.lazar1-Jul-14 3:42 
AnswerRe: Converting between two ICC profiles PinmemberJohannes Bildstein6-Jul-14 20:46 
GeneralRe: Converting between two ICC profiles PinmemberRoger Breton12-Jul-14 14:08 
GeneralRe: Converting between two ICC profiles PinmemberJohannes Bildstein20-Jul-14 9:49 
GeneralRe: Converting between two ICC profiles PinmemberRoger Breton8-Aug-14 12:53 
GeneralRe: Converting between two ICC profiles PinmemberRoger Breton8-Aug-14 13:01 
GeneralRe: Converting between two ICC profiles PinmemberRoger Breton8-Aug-14 13:14 
GeneralRe: Converting between two ICC profiles PinmemberMember 1035772212-Aug-14 9:21 
GeneralRe: Converting between two ICC profiles PinmemberRoger Breton13-Aug-14 16:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 24 Nov 2013
Article Copyright 2013 by Johannes Bildstein
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid