# Playing with ColorMatrix

**Sjaak Priester**on

**August 12th, 2003**

__Environment:__ VC++ 7.0, XP

### Introduction

GDI+, the new Windows graphics API, comes with a *ColorMatrix*. It's a pity that ColorMatrix is just a simple struct, without any member functions. And it's also a pity that Microsoft's documentation is very, very sketchy. It's a pity, because you can do some really nice things with color matrices. Some of these things are near to impossible with other means. That's why I wrote an extension class, *QColorMatrix*, to open up the possibilities of color matrices in GDI+.

I also wrote a mini-application, *Tinter*, to demonstrate some of the things you can do. See the pictures at the end of this article for the effects you can apply to bitmap pictures. Tinter changes the coloring of JPG, GIF, BMP, and TIFF files interactively, can convert the types into one another, and prints. Pretty impressive for an EXE of just over 70 Kb, I think.

### What Is a Color Matrix?

Just as the co-ordinates *x*, *y*, and *z* define a single point in 3D space, the three color components *R* (red), *G* (green), and *B* (blue) define a single point in color space. In 3D geometrics (and in 2D geometrics as well), *matrices* can be used to transform the position of a point, and, more importantly, the position of a group of points. Change the matrix, apply the matrix to a group of points, and all the points are moved together. If you apply the matrix to all the points in a specific scene, the whole scene is transformed.

A *color matrix* works the same way in color space. With a color matrix, you can change one specific color, say dark blue into light red, but you can also change all colors together, in a co-ordinated way. Just like a scene in 3D space, you can *scale*, *translate*, *rotate*, and *shear* the color space, or apply any combination of these basic transformations to it.

For technical reasons, points in 3D space are transformed with 4x4 matrices. A color in RGB color space can also be transformed with a 4x4 matrix. But as GDI+ works with a fourth 'color', *A* (alpha, or opacity) throughout, *ColorMatrix* is defined as a 5x5 matrix of REALs:

typedef struct { REAL m[5][5]; } ColorMatrix;

#### QColorMatrix

Microsoft leaves it to us to fill in the 25 REALs of ColorMatrix, which is no easy task for even a simple rotation. My class, *QColorMatrix*, adds some useful member functions to put meaningful values in the matrix. You can *scale*, *translate*, *rotate*, and *shear* the color space in one step. There are also two member functions for more complex, but very useful operations: one to set the *saturation* of the color space, and one to rotate the *hue*, while preserving the *luminance*. Better than trying to describe what this all means, I'll let you have a look at the pictures (yes, that's me!).

#### Tinter

*Tinter* is a mini-application, demonstrating what you can do with *QColorMatrix*. It is even a small tool in its own right, for correcting bitmap pictures—or disforming, if you like. You can change the *contrast*, *brightness*, *saturation*, and *hue*. You can even change the *gamma*, although this has nothing to do with color matrices. I just threw it in for free.

Tinter is built in MFC 7.0. Of course, your system must support GDI+, which currently only XP does. However, Windows 98 and later versions can be upgraded.

### More Information

There is not much information on color matrices on the Web. I leant heavily on a rather dense, 1993 article by Paul Haeberli, published by Silicon Graphics. Also, the documentation of SGI's Color Matrix Extension for OpenGL may come in useful.

Contrast | |||||

Brightness | |||||

Saturation | |||||

Hue | |||||

Gamma |

### Download

Download demo project and source - 63 Kb