|
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 )
{
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 * 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!
| You must Sign In to use this message board. |
|
| | Msgs 1 to 20 of 20 (Total in Forum: 20) (Refresh) | FirstPrevNext |
|
|
 |
|
|
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.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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.
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Here is the solution
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)
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello,
I'm happy somebody finds this useful 
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.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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 
thanks ivan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | 1.00/5 (2 votes) |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|