Saturday, 9 August 2008

Colour transformation in .NET and GDI+... aka "What Is The Matrix?"

I've been working on some code that converts colour photographs uploaded by users to black-and-white. To do this, I'm using the following code to render an image onto a canvas, using GDI+, and applying a colour transformation in the process:

private Bitmap ApplyMatrix(Bitmap source) {
    ColorMatrix matrix = //TODO: determine appropriate colour matrix! 

    Bitmap result = new Bitmap(source.Width, source.Height);
    Rectangle sourceRectangle = new Rectangle(0, 0, source.Width, source.Height);
    using (Graphics g = Graphics.FromImage(result)) {
        g.SmoothingMode = SmoothingMode.HighQuality;
        g.CompositingQuality = CompositingQuality.HighQuality;
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;

        ImageAttributes ia = new ImageAttributes();
        ia.SetColorMatrix(matrix);

        Point upperLeft = new Point(0, 0);
        Point upperRight = new Point(result.Width, 0);
        Point lowerLeft = new Point(0, result.Height);
        Point[] destinationPoints = new Point[] { upperLeft, upperRight, lowerLeft };
        g.DrawImage(source, destinationPoints, sourceRectangle, GraphicsUnit.Pixel, ia);
    }
    return (result);
}

The key to these colour transformations is a ColorMatrix - the GDI+ colour model lets you treat the <R,G,B> elements of a colour as a point in three-dimensional colour space, and apply geometric transformations to that point using matrix multiplication. There's some in-depth discussion of this at http://www.codeproject.com/KB/GDI-plus/colormatrix.aspx.

"Nobody can be told what the matrix is... you have to see it for yourself."

imageEven once you've got your head around the underlying mathematics, it's still not easy to work out what matrix values you need to achieve a particular result, so I've hacked together a WinForms app that'll let you tweak the values in real time and see what effect they have.  Nothing fancy - just a bunch of numeric up/down boxes, with tooltips explaining what effect they'll have on the resulting image.

You can download ColorMatrixLab (source and binary) here:

(requires the Microsoft .NET 2.0 framework.)