Colorize images in C#


[colorize]

This example produces some impressive results, but it’s actually quite simple. It uses ImageAttribute techniques demonstrated by several other examples to quickly manipulate an image’s colors.

Adjust Color

The following AdjustColor method starts the process of coloring an image.

// Adjust the image's colors.
private Image AdjustColor(Image image)
{
    // Make the ColorMatrix.
    ColorMatrix cm = GetColorMatrix();
    ImageAttributes attributes = new ImageAttributes();
    attributes.SetColorMatrix(cm);

    // Make the result image.
    return image.CopyImage(attributes);
}

This method calls the GetColorMatrix method described shortly to get a ColorMatrix object holding the values that you entered in the text boxes. It then creates an ImageAttribute object and uses its SetColorMatrix method to store the ColorMatrix in the ImageAttribute object. It finishes by calling the CopyImage extension method (also described shortly) to apply the color matrix to the image and returns the result.

GetColorMatrix

The following code shows the GetColorMatrix method.

// Return the matrix entered by the user.
private ColorMatrix GetColorMatrix()
{
    float[][] values = GetMatrix();
    if (values == null) return null;
    return new ColorMatrix(values);
}

The GetColorMatrix method calls the GetMatrix method to get a float[][] holding the values that you entered into the program’s text boxes.

The following code shows the GetMatrix method.

private float[][] GetMatrix()
{
    float[][] values = new float[][]
    {
        new float[5],
        new float[5],
        new float[5],
        new float[5],
        new float[5],
    };
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            float value;
            if (!float.TryParse(TextBoxes[i][j].Text, out value))
            {
                MessageBox.Show("Invalid entry");
                TextBoxes[i][j].Focus();
                return null;
            }
            values[i][j] = value;
        }
    }

    return values;
}

This method creates a float[][] and then fills it by looping through the rows and columns of the TextBoxes array, which holds references to the program’s TextBox controls.

The following code shows how the program initializes the TextBoxes array.

private TextBox[][] TextBoxes;

// Display the image converted to sepia tone.
private void Form1_Load(object sender, EventArgs e)
{
    TextBoxes = new TextBox[][]
    {
        new TextBox[] {txt00, txt01, txt02, txt03, txt04},
        new TextBox[] {txt10, txt11, txt12, txt13, txt14},
        new TextBox[] {txt20, txt21, txt22, txt23, txt24},
        new TextBox[] {txt30, txt31, txt32, txt33, txt34},
        new TextBox[] {txt40, txt41, txt42, txt43, txt44},
    };
}

The program declares the TextBoxes array at the class level. Its Form_Load event handler initializes the array.

To quickly recap, GetColorMatrix calls GetMatrix to get the float values that you entered and uses the array to create and return a ColorMatrix object. The GetMatrix method loops through the TextBoxes array to fill in the array that it returns.

CopyImage

The .NET Image class provides a couple of ways to create a copy of an image. The least sumbersome is to call its Clone method. Unfortunately that method returns a generic oobject, so you need to convert it into an Image if you want to use it as an Image.

Copying images is something I do a lot, so I decided to create the following two extension methods to make that easier.

public static class Extensions
{
    public static Image CopyImage(this Image image)
    {
        return (Image)image.Clone();
    }

    public static Image CopyImage(this Image image, ImageAttributes attributes)
    {
        Bitmap result = new Bitmap(image.Width, image.Height);
        using (Graphics gr = Graphics.FromImage(result))
        {
            Rectangle rect = new Rectangle(
                0, 0, image.Width, image.Height);
            gr.DrawImage(image, rect,
                0, 0, image.Width, image.Height,
                GraphicsUnit.Pixel, attributes);
        }
        return result;
    }
}

The first method clones the image, casts the result back into an Image, and returns the result. You can use it as in the following code.

Image copy_of_image = original_image.CopyImage();

The second method copies an image while applying an ImageAttributes object to it. That’s how this example colors images.

The second method creates a new Bitmap object that is the same size as the original image and makes an associated Graphics object. It makes a Rectangle sized to fit the image and then calls the Graphics object’s DrawImage method to draw the image onto the new Bitmap. (This is one of the reasons why I wanted to make an extension method. The methods for drawing an image onto another image is just plain awkward. With this method I don’t have to mess with creating a Rectangle and passing the coordinates, width, and height into the DrawImage method.)

The AdjustColor method shown earlier uses this second version of CopyImage in the following statement.

// Make the result image.
return image.CopyImage(attributes);

Conclusion

The example program includes several other details such as code to open and save files, and menu items that fill in matrix values for specific kinds of coloring such as red, green, sepia, and so forth. (The picture at the top of the post shows an image converted to sepia tone.)

Download the example to experiment and to see additional details.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in graphics, image processing and tagged , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.