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

A VB.NET class useful for color manipulation

By , 7 Jul 2003
 

Introduction

Although windows seems to have some color management build into, none of this is found in any of the .NET classes, at least to my knowledge. Similarly, GDI and GDI+ contain almost no provisions for color manipulation or colorimetric image processing (there's is a color matrix, but no convolution or any more advanced image processing. It is also hard to operate on linear-light RGB values instead of gamma-corrected R*G*B* values). It seems Microsoft has no concern for the underlying principles and foundations of image processing and colorimetry, instead going for a simple pragmatic 'look I can adjust brightness or hue' type of approach ... Nothing wrong with that, but we expected more from a such a comprehensive framework as .NET (maybe we DO have to have a look at java and Java Advanced Imaging, or JAI, which seems built on a much more researched foundation). The net result (hehe) is that for my colorimetric imaging research I needed to write a support library, at first in VB6. This library has now been converted to VB.NET.

Background

An introduction to color is useful, check out Charles Poynton page to name but one.

Using the code

The library of mostly shared functions and subroutines and is not written for speed, instead I hope it is clear and easy to read. It makes heavy use of overloading and needs another class called Algebra to run, which is included in the download. Its main use is moving from one color space to another and applying gamma-correction using arrays of color triplets, but it also contains some routines for supporting image processing using unmanaged pointers, and GDI+. The supported color spaces are (a * in the notation means a non-linear light color space, e.g. after gamma-correction):

  • Generic RGB and R*G*B*. User must, obviously, provide a transform to go to other color spaces here as there are literally 100's of RGB color spaces!
  • ITU Rec 709 sRGB and sR*G*B*. A standard RGB color space used on the web, monitors and in printers.
  • CIE XYZ. A human vision based tristimulus color space encompassing all visible colors.
  • CIE L*a*b*. A perceputally uniform color space. In this space the Euclidean metric is proportional to color differences as perceived by a human observer, albeit under a rather restricted set of viewing conditions.

The library also defines several whitepoints

  • CIE D65: Noon daylight simulation with color temperature of 6500 K
  • CIE D55: Daylight simulation with color temperature of 5500 K
  • CIE A: Tungsten illumination with color temperature of 3800 K
  • CIE C: Fluorescent illumination with correlated color temperature about 5200 K
  • CIE D93: Color temperature of 9300 K, similar to some computer monitor
  • HDTVD65: High-definition television whitepoint at 6500 K

Several types of polynomial transforms between color spaces are supported, from a 3x3 linear transform to a highly non-linear, 20-term transform. The class also provides a way to compute this transform, given a set of colors in an input color space, and their desired mappings in an output color space (based on the singular value decomposition solution provided by the algebra class. Note that this routine was converted from 'Numerical Recipes in C', a well known set of numerical routines). The class also allows the use of a lookup-table or LUT to be applied prior to the polynomial transformation.

The simplest is to check out the code in the download

Sample code using the class

Here is a piece of C# code that runs through an image and transforms every pixel using a given polynomial transform and lookup table. This code also demonstrates the use of unmanaged pointers in C#, which greatly improves the speed over using managed GDI+ classes with GetPixel and SetPixel. This is not possible in VB.NET! It is assumed that the Color.vb class has been properly imported.

public static unsafe void PolynomialTransform(Bitmap objBitmap, 
    float[,]Transform, float[,] LUT )
{
//Do LUT and polynomial transform on whole image ... 
//Use unmanaged pointers to go FAST. In Memory RGB values 
//are stored in the order B-G-R!!!!!! 

int x, y, iPtrPixel0; 

Rectangle rect = new Rectangle(0,0,objBitmap.Width,objBitmap.Height);
System.Drawing.Imaging.BitmapData bitmapData = objBitmap.LockBits(rect, 
System.Drawing.Imaging.ImageLockMode.ReadWrite,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);

iPtrPixel0 = bitmapData.Scan0.ToInt32();

//Byte pointer and corresponding managed array type 
byte * byPixel;
byte[] bySafePixel = new byte[3];

for (y = 0; y < bitmapData.Height; y ++)
  {
  byPixel = (byte *)(iPtrPixel0 + y * bitmapData.Stride);
  for (x = 0; x < bitmapData.Width; x ++)
    {
    bySafePixel[2] = *byPixel;
    bySafePixel[1] = *(byPixel + 1);
    bySafePixel[0] = *(byPixel + 2);

    Color.GammaRGBToGammasRGB(bySafePixel, Transform, LUT);
    *byPixel = bySafePixel[2];
    byPixel ++;
    *byPixel = bySafePixel[1];
    byPixel ++;
    *byPixel = bySafePixel[0];
    byPixel ++;
    }
  }
objBitmap.UnlockBits(bitmapData);
}

Points of Interest

No special points of intrest,except that even using unmanaged pointers, image processing in .NET is still pretty sloooow!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

yvdh
Software Developer (Senior)
Belgium Belgium
Member
Physicist, Biomedical Engineer, Phd in engineering. Specific expertise is in medical photography and it's related image processing, and in colourimetry.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionC Codememberstixoffire8 Apr '08 - 13:19 
Do you write in C , C++ ?
 
How can I get in touch with you. I am looking for someone to do a very small project.
GeneralRe: C Codememberyvdh8 Apr '08 - 20:55 
Hello,
 
I use to write in C in a Unix environment (X11 and Motif), and a little on Windows but the productivity is much higher in C# and Vb.net so I am very rusty. This library should be callable from C, but I have never tried it ... Consequently, I will not be available to write something for you, sorry (I also have way too much other work). If you have specific questions about the library I will try to answer them.
 
Yves
QuestionHow to use.memberAlexandros5413 Sep '07 - 7:19 
Hi guys! I wish to know how to use this code to convert RGB to the various colorspaces that are supported by the code. How to install this library and how to use. I am kind of new to programming so please understand me.
AnswerRe: How to use.memberyvdh13 Sep '07 - 12:06 
Mmm, this is not really the place for this but here it is anyway:
 
1) Start a visual studio project (You can use the free 'developer express' version)
2) Add a reference to the file containing the library
3) Optionally import the namespace using 'Imports' keyword
4) call the methods of the library, see the example.
 
Good luck
 

GeneralRotation of ControlsmemberJK Rajesh6 Jun '07 - 0:07 
My application needs to implement the Picture Rotation and Text Rotation Functionality as it is in Microsoft Office2003 with Rotation Handles. I need the similar kind of UI...is there any user control or an OCX which might help me achieve tht kind of a functionality. the picture should rotate withing the picturebox as we drag the mouse using the Rotation Handle. Hope the question is understood.Looking for a soulution at the earliest.

 
Yusuf Shabbir
Software Engineer
GeneralRe: Rotation of ControlsmemberVincent DUVERNET (Nolmë Informatique)24 Jun '07 - 8:06 
hum, don't sure I'm all understood.
Do you look for something like this (french link) :
http://www.supinfo-projects.com/fr/2004/gdi_csharp_graphic_graphical_device_interface/5/

GeneralConvert RGB to CMYK ColorsmemberMetexim8 Apr '06 - 0:44 
Hello,
I have a problem with my application. My application is an album building software which allows the users to create their own album. I am converting the entire album into PDF Format. While printing the client reported that there is a problem with the color. He says that he wants the Image to be genearted in CMYK color format (for printing purpose) but we our generating it in RGB. We used the SetOutputChannel property of the ImageAttribute Class to do that but it doesnt seem to work. My Question is how can i generate the Image in CMYK color Space using VB.Net. It would be really good to know it soon.
 
Thank You

 
Yusuf Shabbir
GeneralRe: Convert RGB to CMYK ColorsmemberVincent DUVERNET (Nolmë Informatique)3 Oct '06 - 8:34 
Here is the solution Poke tongue | ;-P
 
http://semmix.pl/color/extrans/etr10.htm
 
Transformation RGB, CMY, CMYK
Formal transformation of the components RGB into the components CMY or inversely is as follows:
 
we have color RGB=(r,g,b) then color CMY=(1-r,1-g,1-b)
we have color CMY=(c,m,y) then color RGB=(1-c,1-m,1-y).
 
Transformation of CMY into CMYK is presented as algorithm:
 
k=min(c,m,y), CMYK=(c-k,m-k,y-k,k)
GeneralRe: Convert RGB to CMYK ColorsmemberVincent DUVERNET (Nolmë Informatique)3 Oct '06 - 11:10 
Another good site :
 
http://www.easyrgb.com/math.php?MATH=M11#text11
QuestionRe: Convert RGB to CMYK ColorsmemberJK Rajesh5 Jun '07 - 20:34 
Hello Vincent,
Thank You for your valuable suggestions...it was really of great help.I got a nother problem,i.e,my application needs to implement the Picture Rotation and Text Rotation Functionality as it is in Microsoft Office2003 with Rotation Handles. I need the similar kind of UI...is there any user control or an OCX which might help me achieve tht kind of a functionality. the picture should rotate withing the picturebox as we drag the mouse using the Rotation Handle. Hope the question is understood.Looking for a soulution at the earliest.
 
Than You
Yusuf Shabbir

Generaljust what I am looking for!memberivan 4525 Oct '05 - 6:12 
Excellent article, I have been trying to write code to convert color-managed TIFF (Adobe RGB) into a web ready jpeg (sRGB) in the .NET environment and this is a great help.
 
To use your example function to acheive the above I am a bit unsure of what to use as Polynomial transform and LUT parameters, I will continue reading through the code, but if you can give me any guidance it would be v. helpful thanks.
 

 

 
Ivan
GeneralRe: just what I am looking for!memberyvdh25 Oct '05 - 7:17 
Hello,
 
I'm happy somebody finds this useful Smile | :)
 
Anyway, regarding your problem, the chain would be something like:
 
Adobe gamma-corrected RGB pixel value [0 - 255] (usually notated r*g*b*) ->
Adobe linear-light RGB [0.0 - 1.0] after inverse gamma correction (rgb) -> transform from Adobe RGB to sRGB [0.0 - 1.0] (RGB)-> gamma-corrected sRGB [0 - 255](R*G*B*).
 
You do not need any LUT, just a polynomial transform in its simplest incarnation: the linear transform (a 3 x 3 matrix). Look for this transform on the web, or compute it yourself using e.g. the paper at http://www.babelcolor.com/download/RGB%20Coordinates%20of%20the%20Macbeth%20ColorChecker.pdf[^]
 
In this paper they go around to CIE XYZ to perform a compensation in whitepoint, but this is not required in your case because Adobe RGB and sRGB have the same whitepoint. This means you get:
 

|R|
|G| = [XYZ to sRGB][Adobe RGB to XYZ][r g b]t (t = transpose)
|B|
 
So you just have to multiply the 2 required matrices from the paper with each other, giving you one 3 x 3 matrix which does your transform. This will obvioulsy also be a lot faster ....
 

Some caution: Adobe RGB has a bigger gamut than sRGB so some colors that exist in Adobe RGB do NOT exist in sRGB and will be clipped, especially in the greens ....
 
Good luck,
 
P.S. I will try to update the source for the library, together with a help file explaining the functions.
 


GeneralRe: just what I am looking for!memberivan 4525 Oct '05 - 23:36 
Thanks - thats very helpful, I am learning a lot this week!
 
I understand I think how to create a matrix to convert AdobeRGB to sRGB, but not sure how to use that with your library as the function Color.GammaRGBToGammasRGB requires a float array for both the transform and a LUT parameter?
 
I've got as far as (utilising the c# example in your article)

float[,] fTransform = new float[3,3];
 
fM[0,0]=3.2406F; fM[0,1]=-1.5372F; fM[0,2]=-0.4986F;
fM[1,0]=-0.9689F; fM[1,1]=1.8758F; fM[1,2]=0.0415F;
fM[2,0]=0.0557F; fM[2,1]=-0.2040F; fM[2,2]=1.0570F;
 
bm = new Bitmap(outputPhoto);
outputPhoto = Tools.PolynomialTransform(bm,fTransform,???);
 

 
Is has been a long time since I have looked at this kind of maths and I'm finding it difficult to comprehend still -
If I do not need a LUT then what parameters can I pass to Color.GammaRGBToGammasRGB with the transformation matrix?
 
excuse my ignorance - all help greatly appreciated Smile | :)
 
thanks
ivan
 

 


GeneralRe: just what I am looking for!memberivan 4525 Oct '05 - 23:52 
Sorry i have just noticed the code I pasted in has used the wrong variable names - (fTransform is the same as fM). The question remains the same however!
thanks

GeneralRe: just what I am looking for!memberyvdh25 Oct '05 - 23:59 
You need to modify the PolynomialTransform function (or add an overloaded version) so that it doesn't take a LUT...
 
To do this you would modify the innerpart of the loops as follows:
 
float[] fRGB = new float[3];
float[] fTransformRGB = new float[3];
 
//Apply inverse Gamma correction
ColorUtil.GammaRGBToRGB(bySafePixel, fRGB);
 
//Apply transform
ColorUtil.RGBTosRGB(fRGB, fTransformRGB, fTransform);
 
//Apply Gamma correction
ColorUtil.RGBToGammaRGB(fTransformRGB, bySafePixel);

 
I need a LUT because my input RGB color space may not have a linear response to luminance, and the LUT corrects for this.
 
Yves
 
-- modified at 5:59 Wednesday 26th October, 2005
GeneralRe: just what I am looking for!memberivan 452 Nov '05 - 0:09 
I finally have it all working perfectly - thanks for all your help.
 
I have one more question however -
 

//Apply inverse Gamma correction
ColorUtil.GammaRGBToRGB(bySafePixel, fRGB);
//Apply transform
ColorUtil.TransformColor(fRGB, fTransformRGB, fTransform);
//Apply Gamma correction
ColorUtil.RGBToGammaRGB(fTransformRGB, bySafePixel);

 
I am calling the above code twice to transform from AdobeRGB to XYZ, then XYZ to sRGB, and I was originally hoping I could multiply the two matrices (AdobeRGB->XYZ and XYZ->sRGB) together to halve the processing time. It seems that I need to call the gamma correction and inverse gamma correction before and after each colour space transformation so it does not seem to be possible to use a multiplied/combined matrix?
Am i missing something that would enable me to do this?
 
thanks
Ivan
 

GeneralRe: just what I am looking for!memberyvdh8 Dec '08 - 2:24 
Sorry I missed this reply ...
You should be able to multiply your matrices.
So we get:
 
R*G*B* -> RGB -> XYZ -> sRGB -> sR*G*B*
should become
 
R*G*B* -> RGB -> sRGB -> sR*G*B* using a combined transform!
 
Yves
GeneralConstruct YCbCr imagessussYawen4 Mar '04 - 21:08 
I'm reading a YCbCr image byte by byte from the parallel port and all I want
to do is to display the image on the screen using C#. I wonder how I can do
it. Ways that I can think of include:
 
1. Convert to RGB and construct a Bitmap object (Is there any simple way to
do the conversion?)
 
2. Construct an Image object with YCbCr pixel format (I should that Image
has a Flags property which includes YCbCr color space. But how can I make
use of this?)
 
A thousand thanks.
 
Yawen
 

GeneralRe: Construct YCbCr imagesmemberyvdh4 Mar '04 - 22:37 
I havent tried creating YCbCr images, but to convert to RGB, read
http://www.poynton.com/ColorFAQ.html. It actually involves some 3 by 3 matrix operations. Use the Algebra class included in my article to help you. If you are interested I have updated versions of these. If you write a conversion for one color triplet to another, please send it to me so I can include it in the library.
 

good luck,
 
Yves

GeneralRe: Construct YCbCr imagesmemberyyyychan7 Mar '04 - 21:15 
Thanks very much. It looks useful at a first glance. I'll look into it.
 
Yawen
Questionsource code link broken ?memberBillWoodruff14 Jul '03 - 22:27 
Hi, this looks interesting, but can't get to source code.
 
best, Bill Woodruff
dotScience
Chiang Mai, Thailand
 
"The greater the social and cultural distances between people, the more magical the light that can spring from their contact." Milan Kundera in Testaments Trahis

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 8 Jul 2003
Article Copyright 2003 by yvdh
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid