Recipe 8.12. Using Threshold
You want to change the value of some pixels in a bitmap, based on their current value.
Use the threshold( ) method of the BitmapData class.
The threshold( ) method is probably the most complex in the BitmapData API, but quite powerful once you understand how it works. The method uses two BitmapData objects:
Here is the syntax for the method:
destBitmap.threshold(sourceBitmap, sourceRect, destPoint, operation, threshold, color, mask, copySource)
We've already covered
The destPoint parameter specifies the point in the destBitmap at which the pixels start to be affected. Picture the sourceBitmap overlaid on destBitmap , with its top-left corner on this point. If you want to use 0, 0 as the origin, just pass new Point( ) to this parameter.
The operation parameter is one of six strings that are equivalent to the comparison operators in ActionScript. They are < , <= , > , >= , == , and != . For example, if you specify < as an operation, the test passes for a given pixel if its value is less than the threshold value, and it fails if it is greater than that.
. Each pixel is compared against this value. You can pass a full 32-bit number in here, and compare each pixel against that, but it may not give you the results you expected. The reason is the way color values work. For example, a pixel of 100 percent red (
The mask parameter is the hardest for most people to grasp. All it is doing is isolating a particular color channel. Normally you would just pass a hexadecimal value here, with two zeros ( 00 ) for each color channel that you want to mask out, and FF for the channel you want to use. For example, 0x00FF0000 isolates the red channel, and 0xFF000000 isolates the alpha channel. See Figure 8-4 for a breakdown of the channels in a hexadecimal color value.
Figure 8-4. The breakdown of a hexadecimal number
The next two parameters determine what happens when a pixel passes or fails a comparison. The
parameter is the color the corresponding pixel is set to in the
if the comparison passes. The
parameter determines what happens if it fails. If this is
's pixel value for that pixel is
Now let's see a few examples in action. Here's some sample code that creates a source and destination bitmap and creates some
var srcBmp:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xffffffff); srcBmp.perlinNoise(200, 100, 2, 1000, false, true, 1, true); var destBmp:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xffffffff); var image:Bitmap = new Bitmap(destBmp); addChild(image); destBmp.threshold(srcBmp, // sourceBitmap srcBmp.rect, // sourceRectangle new Point( ), // destPoint "<", // operator 0x00880000, // threshold 0x00000000, // color 0x00ff0000, // mask true); // copySource
Here the method checks to see if a given pixel's red channel (since this is defined in the mask) is less than 0x00880000 . If so, it makes that pixel transparent. If not, it copies over the source pixel. Since the Perlin noise was created in grayscale, it doesn't matter which of the three color channels (red, green, or blue) you use. If you are using a full color image as a source, you might want to experiment with different channels to see which gives you the desired effect:
One thing to note is that there is no reason why the source and destination bitmaps cannot be the same bitmap. You can use a bitmap's own pixel data as a threshold. However, realize that you are permanently altering that bitmap, so you won't be able to repeat the operation with the same result, if needed.
As with many of the
destBmp.applyFilter(destBmp, destBmp.rect, new Point( ), new DropShadowFilter( ));
Recipes 8.13, 8.14, and 8.15 for other ways to manipulate the content in a bitmap.