Monday, August 24, 2009

Adjusting image colors in Flex

Recently I was working on some Macadamian project and got a task of processing images. Actually I had to load different images, and as some of them were the same, just with different colors, I decided to try adjusting image colors programmatically. There are several ways in Flash Player API to do this, but in all cases what you are basically doing it’s changing the red, green and blue values of the image. The two main ways to change the RGB values is to either use a ColorMatrixFilter or ColorTransform. I’ll introduce in nutshell the difference between those two.

ColorTransform

ColorTransform adjusts the values of the red, green and blue channels of a display object. The color transform is applied differently while manipulating a bitmap and display object. For a display object it is a property of the transform object. For bitmaps it is passed as a parameter to the colorTransform method. To adjust the color you either create a new instance of ColorTransform or get a reference to an existing one and change the red, green and blue values and/or offsets. It’s possible to adjust also color brightness.


ColorMatrixFilter

The ColorMatrix filter uses a 4 x 5 matrix for modifying color values. Unlike the ColorTransform, which universally adjusts the red, green and blue channels, the ColorMatrixFilter changes each pixel. The speed of the ColorMatrixFilter depends on the size of image (number of pixels).


Now I'll explain shortly how the application works. It's quite simple. When user chooses a color, we retrieve from event's uint color property the red, green and blue values' bits apparently, using bitwise operators:

_R = event.color >> 16 & 0xFF;
_G = event.color >> 8 & 0xFF;
_B = event.color & 0xFF;


After we got the color channels, we need to create a color filter matrix. Don't forget that matrix elements should be in 0 to 1 range. As we have _R, _G, _B values that can have values 0-255, I've devided theim to 255 in order I can get a number from 0-1.


It's left only to construct the filter matrix. Here's the one I needed:

var matrix:Array = new Array();
matrix = matrix.concat([_R, 0, 0, 0, 0]); // red
matrix = matrix.concat([0, _G, 0, 0, 0]); // green
matrix = matrix.concat([0, 0, _B, 0, 0]); // blue
matrix = matrix.concat([0, 0, 0, 1, 0]); // alpha


Note that for modifying the way color channels are transformed, you need just to change the matrix' _R, _G, _B values' places.

For example if you want to have in the picture only the light/dark tones of chosen color, use this matrix ;)

var matrix:Array = new Array();
matrix = matrix.concat([_R, 0, 0, 0, 0]); // red
matrix = matrix.concat([_G, 0, 0, 0, 0]); // green
matrix = matrix.concat([_B, 0, 0, 0, 0]); // blue
matrix = matrix.concat([0, 0, 0, 1, 0]); // alpha


The very last step - applying the filter matrix to image:

var filter:ColorMatrixFilter = new ColorMatrixFilter(matrix);
var filters:Array = new Array();
filters.push(filter);
target.filters = filters;


You can find the source code here.