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.,
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
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)
- ITU-R BT.601-625
- ITU-R BT.709-1250
- 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
) 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:
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); ColorRGB color = new ColorRGB(0, 0.5, 1); ColorRGB color = new ColorRGB(RGBSpaceName.sRGB, 0, 0.5, 1, true); ColorRGB color = new ColorRGB(new ICC("profile.icc")); ColorLab color = new ColorLab(50, 12, -12); ColorLab color = new ColorLab(new Whitepoint(WhitepointName.D50)); ColorCMYK color = new ColorCMYK(new ICC("CMYKprofile.icc"));
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 Converter = new ColorConverter(); ColorLab lab = new ColorLab(50, 12, -12); ColorRGB rgb = Converter.ToRGB(lab, RGBSpaceName.sRGB);
ColorConverter Converter = new ColorConverter(); ColorRGB rgb = new ColorRGB(RGBSpaceName.AdobeRGB, 0, 0.5, 1); ColorLab lab = Converter.ToLab(rgb, WhitepointName.D50); ColorLab lab = Converter.ToLab(rgb);
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(); ColorLab lab = new ColorLab(50, 12, -12); ColorRGB rgb = (ColorRGB)Converter.ToICC(lab, new ICC("profile.icc"));
And to find the difference between two colors, use the
ColorDifference class (not multithreading safe)
ColorLab lab1 = new ColorLab(0.5, 30, -12); ColorLab lab2 = new ColorLab(0.5, 40, -2); double difference = ColorDifference.GetDeltaE_CIEDE2000(lab1, lab2);
Or with the Din99c method:
ColorLCH99c din1 = new ColorLCH99c(50, 12, 120); ColorLCH99c din2 = new ColorLCH99c(50, 16, 140); double difference = ColorDifference.GetDeltaE_DIN99(din1, din2);
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(); ColorXYZ xyz = new ColorXYZ(new Whitepoint(WhitepointName.D50), 0, 0.5, 1); xyz = Converter.ToXYZ(xyz, WhitepointName.D65);
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
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.
- Click on this square to select an RGB value from the color picker
- The general settings
- The specific setting for each color
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.
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).
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.
For future version I have planned:
- Out of Gamut warning/check
- Render Intent calculation
- Better and faster ICC support
- 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
- 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