HomeC# Color Transformation Applications in C# GD...
Color Transformation Applications in C# GDI+ Programming
In this last installment of the series related to color transformation in GDI+, we will delve into two typical types of color transformation applications: one is color remapping and the other is color channel isolating.
Contributed by Xianzhong Zhu Rating: / 6 July 30, 2008
Now, let’s start with what color remapping is and how we can use it in real scenarios.
Color Remapping
As far as color mapping is concerned, the commonly-used color palette under the GDI environment may come to mind. By adjusting the standard colors via the color palette, we can redefine the values of the color indexes in the color palette. A typical application is the fading in and out effects with an image via the color palette technique. However, the color palette can only be utilized when the number of the colors is less than 256. When the number of the colors on the screen is greater than 256, the color palette technique can no longer take effect. GDI+ introduces a new form of ‘color remapping’ that redefines the specified colors. It is mainly based on the idea of the color palette,
In GDI+, the colors of an image can be adjusted when they are rendered according to the facts of the requests. The key to achieving this result is to redefine the colors, i.e. color remapping. In fact, color remapping is the process of converting the colors in an image according to a color remap table, which, in fact, is an array of ColorMap structures. Each ColorMap structure in the array has an oldColor member and a newColor member.
Let’s consider the following typical scenario. During the course of making a television program, the background color is generally set blue. In this case, when the background needs to be changed or the videos need to be synthesized, the blue color in the background can be weeded out so as to maintain the main picture. Based on this, let’s consider how to weed out the background color of an image.
The commonly-used solution to solve the above problem is to replace the background color with a transparent color. In fact, GDI+ has introduced a class named ColorMap to perform this function, where some kind of color redirection relation is defined. Furthermore, we can substitute any of the other colors in the image using ColorMap.
When GDI+ draws an image, each pixel of the image is compared to the array of old colors. If a pixel's color matches an old color, its color is changed to the corresponding new color. The colors are changed only for rendering—the color values of the image itself (stored in an Image or Bitmap object) are not changed.
To draw a remapped image, initialize an array of ColorMap structures. Pass the address of that array to the SetRemapTable method of an ImageAttributes object, and then pass the address of the ImageAttributes object to the Graphics::DrawImage method of a Graphics object.
Let’s examine several signatures of the SetRemapTable method in detail.
public void SetRemapTable (ColorMap[] map);
public void SetRemapTable ( ColorMap[] map,ColorAdjustType type);
For easy use, let’s also list the definition of the ColorMap class disassembled using Luts Roeder’s .NET Reflector:
In this sample, the code creates a color remap table that consists of a single ColorMap structure. The oldColor member of the ColorMap structure is blue and the newColor member is white. The image is drawn once without remapping and once with remapping. This will help us indirectly pull the foreground image out of the original one. The remapping process changes all the blue pixels to white.
Take a look at the running-time snapshot, as is shown in Figure 1.
Figure 1—the running-time snapshot
Apparently, the right image in Figure 1 corresponds to the one in which the blue background is cleared away after the color remapping.
Look more carefully at the associated programming:
Graphics graphics = this.CreateGraphics();
graphics.Clear(Color.White);
//load the original image with blue background
Bitmap image = new Bitmap("Nemo_Blue.bmp");
ImageAttributes imageAttributes = new ImageAttributes();
int width = image.Width;
int height = image.Height;
//substitute blue for white to achieve the expected aim
//render the new image with the background color weeded out
graphics.DrawImage(image,
new Rectangle(width + 80, 50, width, height), //target rectangle
0, 0, // upper left corner of the source image
width, // width of the source image
height, // height of the source image
GraphicsUnit.Pixel,
//color info
imageAttributes);
Note that we’ve only built one ColorMap object, meaning we only execute the color remapping once. So, if you want to eleminate other colors you have to define more ColorMap objects and continue to apply the related color remapping.
With the color remapping application discussed, let’s take a look at another use of color transformation — isolating the color channel.
Quite a few readers may be familiar with Adobe’s PhotoShop, the famous two dimensional picture and image processing software. One thing PhotoShop supports is color channel isolating. By decomposing the original compound image into three isolated r/g/b channels, we can edit the current image more easily. With all this work done, we can compose the three channels again.
In fact, color mapping is a kind of color filtering. If we use the color transformation matrices to set the related color saturation to zero, then this color will be invisible when outputed.
Using the tools in GDI+, we can use the SetOutputChannel method of the ImageAttributes class to output the individual color channels. But, regrettably, the SetOutputChannel method only supports outputting the C/M/Y/K channels. In fact, with the help of different color transformation matrices, we can also succeed in outputting the individual R/G/B channels. Next, we will see an example that accomplishes this using the color transformation matrix technique.
Isolating R/G/B Channel Demo
As usual, let’s visualize the finished line. Figure 2 demonstrates the related running-time snapshot.
Figure 2—using the color transformation matrix to isolate the R/G/B channel
In Figure 2, the original compound image is rendered at the upper left corner, with the other three being the images maintaining the R/G/B channels.
Now, let’s dig into the "how-to's" of the above sample. The following lists the souce code with detailed explanations.
Graphics graphics = this.CreateGraphics();
graphics.Clear(Color.White);
//load the image
Bitmap image = new Bitmap("jieba.bmp");
//render the source image
graphics.DrawImage(image, 50, 50);
//get the necessary data required by the later rendering operation
int width = image.Width;
int height = image.Height;
ImageAttributes imageAttributes = new ImageAttributes();
//set up the red channel
float[][] colorMatrixElements =
{
new float[]{1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
new float[]{0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
new float[]{0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
new float[]{0.0f, 0.0f, 0.0f, 1.0f, 0.0f},
new float[]{0.0f, 0.0f, 0.0f, 0.0f, 1.0f}
};
ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);
//enable the color transformation matrix
imageAttributes.SetColorMatrix(
colorMatrix,
ColorMatrixFlag.Default,
ColorAdjustType.Bitmap);
//use the above color transformation matrix to render the new picture
//corresponding to the one in the red channel
graphics.TranslateTransform(width + 60, 50);
graphics.DrawImage(image, new Rectangle(0, 0, width, height),
By using the color transformation matrices we’ve easily taken out the independent R/G/B channels. This resembles the function that PhotoShop has provided. However, the above sample is the simplest application of color transformation. You can easily find out that if you modify the R/G/B/A component at the main diagonal in the color transformation matrix, you can obtain some special and even miraculous effects.
To further grasp the above idea, I recommend that you test the SetOutputChannel method of the ImageAttributes class so you can output the C/M/Y/K channels in order to make a good comparison with the idea supplied in this article.
In this series of articles, we mainly discussed the color transformation matrices related calculations, such as translating, scaling, rotating, and shearing. We realized that the 5x5 color transformation matrix plays the central role. Within each sample, we also became familiar with several classes provided by GDI+. In fact, what GDI+ can do is far more than what these few samples can accomplish.
In the last installment, we examined the two most common ways to use color transformation matrices and gave two sample applications. Although it’s easy to weed out the background of an image and take out the three independent R/G/B channels, it’s rather difficult for GDI+ to provide the popular drag & drop support for editing such intermediate or even end images. In the following articles, I’m going to write a screen capturing application using both GDI+ and GDI, through which you will acquaint yourself with the shortcomings of GDI+.