.NET Image Re-Coloring

This article was originally published in the "Chris Sells on .NET" newsletter

.NET provides extensive support for all kinds of fancy drawing techniques in the System.Drawing.Imaging namespace. For example, with the ImageAttributes class, you can map colors as the image is drawn:

using System.Drawing;
using System.Drawing.Imaging;

void panel2_Paint(object sender, PaintEventArgs e) {
  Graphics g = e.Graphics;
  using( Bitmap bmp = new Bitmap(@"INTL_NO.BMP") ) {
    // Set the image attribute's color mappings
    ColorMap[] colorMap = new ColorMap[1];
    colorMap[0] = new ColorMap();
    colorMap[0].OldColor = Color.Lime;
    colorMap[0].NewColor = Color.White;
    ImageAttributes attr = new ImageAttributes();
    attr.SetRemapTable(colorMap);

    // Draw using the color map
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    rect.Offset(...); // Center the image
    g.DrawImage(bmp, rect, 0, 0, rect.Width, rect.Height,
    g.PageUnit, attr);
  }
}

This code first sets up an array of ColorMap objects, each of which contain the old color to transform from and the new color to transform to. The color map is passed to a new ImageAttribute class via the SetRemapTable. The ImageAttribute object is then passed to the DrawImage function, which does the color mapping as the image is drawn. Figure 1 shows an example.

Figure 1: An example of mapping Color.Lime to Color.White

Transparency

Of course, just mapping to white or any other color isn’t useful if the image needs to be drawn on top of something else that you’d like to show through. For this case, there’s a special color called Transparent that will allow the mapped color to disappear instead of being replaced with another color:

ColorMap[] colorMap = new ColorMap[1];
colorMap[0] = new ColorMap();
colorMap[0].OldColor = bmp.GetPixel(0, bmp.Height - 1);
colorMap[0].NewColor = Color.Transparent;

The effects of using Color.Transparent can be seen in Figure 2.


Figure 2: Using Color.Transparent in a color map

This time, instead of hard-coding a color, the code used the color at the bottom left pixel as the color to replace, which is the convention used by other part so .NET. In fact, if you’re going to always draw a bitmap with a transparent color, and the color to be made transparent is in the bitmap itself in the bottom left pixel, you can save yourself the trouble of building a color map and use the MakeTransparent method instead:

// Make the bottom left pixel the transparent color
bmp.MakeTransparent();
g.DrawImage(bmp, rect);

If the pixel you’d like to use as the transparency color isn’t in the bottom left of the bitmap, you can also use the MakeTransparent overload that takes a color as an argument. Calling MakeTransparent actually replaces the pixels of the transparency color with the Color.Transparent value. Some raster formats allow that color value to be specified as one of their legal values, like the GIF and Windows Icon formats, but all Bitmap objects, regardless of the raster format, support the MakeTransparent method.

This material is excerpted from the forthcoming Addison-Wesley title: Programming Windows Forms Applications with C# by Chris Sells (0321116208). Please note the material presented here is an initial DRAFT of what will appear in the published book.