topical media & game development
#graphic-flex-image-effects-04-Flex-PosterizeTest.ax
#graphic-flex-image-effects-04-Flex-PosterizeTest.ax
[swf]
[flash]
flex
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.BlendMode;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.geom.Rectangle;
[SWF(width=900, height=300, backgroundColor=0x000000)]
Demonstrates how an image can be posterized through calls to the paletteMap() method of BitmapData.
public class @ax-graphic-flex-image-effects-04-Flex-PosterizeTest extends graphic_flex_image_effects_04_Flex_LevelsTest {
Run after the image loads in super class. This copies the loaded image twice and applies posterization to
both copies before adding them to the stage.
override protected function runPostImageLoad():void {
var bitmapData:BitmapData = _loadedBitmap.bitmapData;
addChild(_loadedBitmap);
var clone:BitmapData = bitmapData.clone();
// posterizes first clone to 4 levels
posterize(clone, 4);
var bitmap:Bitmap = new Bitmap(clone);
bitmap.x = bitmapData.width;
addChild(bitmap);
clone = bitmapData.clone();
// posterizes first clone to 2 levels
posterize(clone, 2);
bitmap = new Bitmap(clone);
bitmap.x = bitmapData.width*2;
addChild(bitmap);
}
Posterizes the specified image, reducing its number of colors, using the number of levels specified.
parameter: bitmapData The image to which to apply the posterization.
parameter: levels The number of colors in each channel to reduce the image to.
private function posterize(bitmapData:BitmapData, levels:uint):void {
// creates a new image with the image data from a single channel used in all three channels
var red:BitmapData = makeImageFromChannel(bitmapData, BitmapDataChannel.RED);
var green:BitmapData = makeImageFromChannel(bitmapData, BitmapDataChannel.GREEN);
var blue:BitmapData = makeImageFromChannel(bitmapData, BitmapDataChannel.BLUE);
// stores the channel image data into a vector for easy access
var sourceChannels:Vector.<BitmapData> = new Vector.<BitmapData>();
sourceChannels.push(red);
sourceChannels.push(green);
sourceChannels.push(blue);
// creates three new BitmapData instances that can be used to manipulate each color channel
red = new BitmapData(bitmapData.width, bitmapData.height);
green = red.clone();
blue = red.clone();
// stores what will be the adjusted channel image data into a vector for easy access
var adjustedChannels:Vector.<BitmapData> = new Vector.<BitmapData>();
adjustedChannels.push(red);
adjustedChannels.push(green);
adjustedChannels.push(blue);
var channelData:BitmapData;
var threshold:uint;
var colorTransform:ColorTransform;
var brightness:uint;
var j:uint;
// can reduce levels by 1 since the number of loops should be one less than the number of levels;
// for instance, a single iteration of the loop will produce an image of two colors, so a levels
// setting of 2 only needs to result in 1 loop
levels--;
for (var i:uint = 0; i < levels; i++) {
// threshold will be higher on lower iterations of the loop, resulting in images with more black
// for the lower iterations and images with more white for the higher iterations
threshold = 255*((levels-i)/(levels+1));
// the lower the iteration, the more the resulting channel image will be brightened before it
// is layered in the composite adjusted channel
brightness = 255*((levels-i-1)/levels);
colorTransform = new ColorTransform(1, 1, 1, 1, brightness, brightness, brightness);
// run through all three color channels
for (j = 0; j < 3; j++) {
// grab the original data
channelData = sourceChannels[j].clone();
// set the levels on the data to reduce the colors to 2
setLevels(channelData, threshold, threshold, threshold);
// draw the thresholded image into the adjusted channel after brightening it,
// using MULTIPLY to overlay the grays
adjustedChannels[j].draw(channelData, null, colorTransform, BlendMode.MULTIPLY);
}
}
// copy the adjusted channels into the original image
copyChannel(red, bitmapData, BitmapDataChannel.RED);
copyChannel(green, bitmapData, BitmapDataChannel.GREEN);
copyChannel(blue, bitmapData, BitmapDataChannel.BLUE);
}
Creates a new grayscale image using the data from a single channel, copying that channel's
data into each channel of the new image.
parameter: bitmapData The image from which to copy the channel data.
parameter: channel The channel to create the grayscale image from.
private function makeImageFromChannel(
bitmapData:BitmapData,
channel:uint
):BitmapData {
var clone:BitmapData = bitmapData.clone();
var rect:Rectangle = clone.rect;
var pt:Point = new Point();
// copy the same channel into all three channels of the new image
clone.copyChannel(bitmapData, rect, pt, channel, BitmapDataChannel.RED);
clone.copyChannel(bitmapData, rect, pt, channel, BitmapDataChannel.GREEN);
clone.copyChannel(bitmapData, rect, pt, channel, BitmapDataChannel.BLUE);
return clone;
}
Copies the channel from the source into the destination bitmap data.
parameter: source The image from which to copy the channel data.
parameter: destination The image to copy the channel data into.
parameter: channel The channel to copy.
private function copyChannel(
source:BitmapData,
destination:BitmapData,
channel:uint
):void {
destination.copyChannel(source, source.rect, new Point(), channel, channel);
}
}
}
(C) Æliens
04/09/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.