Search code examples
actionscript-3bitmapbitmapdatapalettegetpixel

How to filter a specific color from a bitmapData object (or byte-array)


I'm looking for an efficient way to filter a specific color from a bitmapData object in ActionScript 3. Currently I use a loop with readByte32(). This takes about a second to process which is unacceptable. I have been trying to get paletteMap() to work but so far haven't been able to grasp its API (any truly useful links? Google has failed me...).

Here's my current logic, which I want to improve:

var n:int = bitmapData.width;
for (var i:int = 0; i < n; i++) {
 var m:int = bitmapData.height;
 for (var j:int = 0; j < m; j++) {
  var color:int = bitmapData.getPixel(i, j);
  if (color == 0xCACACA) {
   bitmapData.setPixel32(i, j, 0x00000000);
  }
 }
}

I can get slightly better performance from using Vectors but it's only marginally better...

var v:Vector.<uint> = bitmapData.getVector(bitmapData.rect);
var n:int = bitmapData.width * bitmapData.height;
for (var i:int = 0; i < n; i++) {
 var color:uint = v[i];
 v[i] = color == 0xFFCACACA ? 0x00000000 : color;
}
bitmapData.setVector(bitmapData.rect, v);

I really think there must be a better way to do this that only takes a few 100 milliseconds. If anyone can unlock the mysteries of bitmapData for me, you will be the new leader of my people.

PS I am using bitmapData.lock() and unlock(); I just didn't post the boilerplate stuff.


Solution

  • An easy way is using the threshold method. It's a bit cumbersome at first, but it's pretty fast (as fast as you'll get, I think)

    This will change every red pixel (considering red only a pixel whose value is exactly 0xffff0000) to blue (0xff0000ff).

    var colorToReplace:uint = 0xffff0000;
    var newColor:uint = 0xff0000ff;
    var maskToUse:uint = 0xffffffff;
    
    var rect:Rectangle = new Rectangle(0,0,bitmapData.width,bitmapData.height);
    var p:Point = new Point(0,0);
    bitmapData.threshold(bitmapData, rect, p, "==", colorToReplace, 
            newColor, maskToUse, true);