As my Simple Actionscript Color Separator Class seemed to be popular, I thought that I would expand on the concept of color in Flash a bit by providing a demonstration of the ColorMatrixFilter. Mostly this is for my own gratification as I have been investigating bitmap manipulation with ActionScript 3.0 and color is a big part of that (There are also convolution and displacement filtering capabilities and I will eventually be posting simple examples of those).
So, the quick recap is that each pixel is made up of 4 channels: Red, Green, Blue and an Alpha channel that controls opacity. These channels are expressed as hexadecimal and aggregated together into a neat 32bit number (See the previous color post for more details). When the ColorMatrixFilter is applied, the Flash player will iterate over every pixel in a bitmap and apply the rules of the filter on an individual basis. This is particularly powerful, but, as one might expect with a ColorMatrixFilter, there is a matrix. In this case, it is a 4 x 5 matrix where each row represents a channel of the bitmap and the columns represent the channels as well as an offset. So the rows correspond to Red, Green, Blue and Alpha and the columns represent Red, Gree, Blue, Alpha and Offset.
For any given pixel, the final channel values are expressed as the sum of the products added to the offset. That probably didn't make as much sense as I might hope, so let's consider the following matrix, known as the identity matrix. This is a good place to begin as this has no impact on the final color:
In order to determine what the final red channel will be we consider the four existing channel values of the target pixel. Taking the first row of information from the matrix, we multiply the first column by the value of the red channel, the second column by the value of the green channel, the third column by the value of the blue channel and the fourth column by the value of the alpha channel. We then sum those numbers together and add the result to the offset. The offset is handy for a couple of reasons. First, Flash will truncate any value that is less than 00 or greater than FF. So, if the sum of the products is less than 0 (if we used negative multipliers in the matrix, for example), a positive offset could potentially prevent the channel information from being set to 0 and thus completely darkened. Likewise, if the value exceeded FF, a negative offset value could prevent the image from being washed out. The second reason to use the offset is if you just want to make a gross color shift, it is a lot easier to add the value than to work out the other relationships.
This process repeats for each channel of pixel color information:
RedNew = (RedOld*Multiplier_redRED) + (BlueOld*Multiplier_redGREEN) + (GreenOld*Multiplier_redBLUE) + (AlphaOld*Multiplier_redALPHA) + Offset_red
GreenNew = (RedOld*Multiplier_greenRED) + (BlueOld*Multiplier_greenGREEN) + (GreenOld*Multiplier_greenBLUE) + (AlphaOld*Multiplier_greenALPHA) + Offset_green
BlueNew = (RedOld*Multiplier_blueRED) + (BlueOld*Multiplier_blueGREEN) + (GreenOld*Multiplier_blueBLUE) + (AlphaOld*Multiplier_blueALPHA) + Offset_blue
AlphaNew = (RedOld*Multiplier_alphaRED) + (BlueOld*Multiplier_alphaGREEN) + (GreenOld*Multiplier_alphaBLUE) + (AlphaOld*Multiplier_alphaALPHA) + Offset_alpha
The identity matrix above does nothing as the corresponding color/alpha value for each channel is only multiplied by 1 and the other values are multiplied by 0 and there is no offset value.
I was discussing this capability with a designer at work and he wondered aloud why this might be necessary if you weren't interested in creating your own image manipulation software (like Photoshop or Fireworks). The first thought that came to mind (mostly just pondering as this has been an exercise of getting to know Flash capabilities as opposed to pressing project requirements) was for use in a thumbnail system. When a thumbnail is selected, the application could change the appearance to black-and-white to denote its state. Additionally, if one were making a game, I can think of several situations where simple color changes of the background and/or foreground objects could convey gameplay state changes. And I'm sure you could throb a background color to catch the eye of the lucky 1000th visitor today so that the poor sap can click the link and receive his prize - Flash is only good for web banner advertisements, right? (phanboys heralding the eventual release of HTML5 as messianic liberator of the masses can plant their puckered proboscises on my pale posterior.)
So, anyway, here is a chance to play with the effects of the Actionscript 3 ColorMatrixFilter on an embedded image and a UIComponent (a Canvas with children in this case). [View Source enabled and also note the applied matrix has been exposed so you can see what's changing]
BTW: The image was shot in downtown Cancun several years ago of what has to be the scariest power hookup I have seen.
[UPDATE] Here is a link to Foundation ActionScript 3.0 Image Effects that I have been using a primary source for understanding, well, ActionScript image effects. I'm still slowly working through the book, as I am trying to digest as much as possible with actual projects, but it has been thus far well written and I am looking forward to the discussions on more advanced topics.