Phil Wright : Component Factory

Tuesday, July 19, 2005

.NET2, ColorMatrix Reloaded

The Matrix Connection

Despite the headline this blog entry has absolutely nothing to do with the Matrix set of films. In fact it is about using the ColorMatrix capability of the ImageAttributes class for drawing images.

Not only does that description not fit into the title but there is no chance you would have read the entry without the Reloaded part of the name. A marketing guy would call this technique a Teaser. The rest of us call this very sneaky.

If I was selling fish fingers, or any other food, then this would be called a breach of the trade descriptions act and the local council would be onto me. In fact they would already have closed me down. Luckily no one cares about accurate descriptions in the software industry and so we will continue without fear.

Drawing a Disabled Image

I am in the closing stages of writing a Button control and want to make it look good when it was disabled. There are two ways to handle this issue. The easiest solution for me is to get the developer to provide two images, one for when the control is disabled and another for when it is enabled.

Not only is this lazy but it demands extra work from the developer to use my control. The whole point of our library is to make the developers application look good with a minimum of effort from the developer himself. So the alternative solution, and the one I am taking, is to take the enabled image and then draw it in a disabled appearance.

In the past I have used the ControlPaint.DrawImageDisabled method provided by the framework but I am no longer happy with that solution. I want to provide more flexibility in the appearance and so let the developer choose a variety of different ways the image could be manipulated.

Enter The ColorMatrix

This is where the ColorMatrix comes into play because it can be used to modify the colors of the image when it is being drawn. So now my button control allows the developer to specify an enumeration of different ColorMatrix settings to be applied.

Here is a picture with three buttons. The name of the enumeration value is used as the button text and the image is drawn in the named style.



The first is called normal and has no color modification applied. In the second the matrix is used to convert from color to a black and white scale. Last of all the disabled appearance is achieved by using a gray scale but also making the colors 10% brighter than normal. This gives a more subtle look and feel.

GrayScale Matrix Code

new ColorMatrix(new float[][]{

new float[]{0.3f,0.3f,0.3f,0,0},
new float[]{0.59f,0.59f,0.59f,0,0},
new float[]{0.11f,0.11f,0.11f,0,0},
new float[]{0,0,0,1,0},
new float[]{0,0,0,0,1}

});

The first three lines of the matrix are used to convert the Red, Green and Blue colors of the pixel in that order. The fourth line is used to convert the alpha channel and the fifth line for adding/subtracting values.

So in this example the fourth and fifth lines use a value of 1 to show they are leaving the alpha channel alone and not applying any addition/subtraction.

The values in column 0, 1 and 2 of the first three lines are the same because in order to convert to a grayscale we need to ensure that the RGB values are the same for the R, G and B. Notice that the 0.3, 0.59 and 0.11 values add up to exactly 1.

These three relative factors are used because the eye has better acuity in the green range than in the red and the red is better than the blue. Hence we want to take more account of the green (0.59) than the red (0.3) than the blue (0.11).

Color Intensity

There is no limit to the color manipulation you can achieve and so I also added some extra enumeration values for making the image lighter or darker in appearance. These might prove useful in many different situations. Here they are in operation.



Breaking Point

As an experiment I tried converting just two of the colors to grayscale and leaving the third alone. In the example below you can see GrayScale R where the blue and green have been gray scaled but the red left alone. Below that are the other two versions for blue and green variations.



The reason they are not coming out perfectly is that the three circles are not filled with pure red, pure green and pure blue. Hence the conversion is not achieving the exact effect I was intending. I have decided to leave these enumeration options in the code although they will not be used very often.

Pain Points

By providing these different effects out of the box the developer has more options in presenting the button image. They might decide to have the button appear gray scaled normally but become full color when the mouse tracks over it. Alternatively they might want to use a darker version of the image normally and only use the normal image on hot tracking.

The important point is the developer provides just a single image and can then apply different effects without needing to create them using a separate package, such as Paint Shop Pro. To use a really stupid management style phrase, we are removing a Pain Point for the developer.

2 Comments:

  • Phil, these components are looking really good. Just one question - the button you show as disabled doesn't appear to have the button text grayed out. Is this intentional?

    By Anonymous Matt Breckon, at 7:12 am  

  • That is because I only altered the image effect property on the control for the sake of creating the picture for the blog.

    The actual disabled mode uses the appropriate disable text color. You can of course override the colors and effects for each control state, Enabled, Disabled, Tracking, Pressed etc...

    By Blogger Phil Wright, at 7:48 am  

Post a Comment

<< Home