如何从bitmapData对象(或字节数组)中过滤特定颜色

时间:2010-06-22 09:01:18

标签: actionscript-3 bitmap bitmapdata palette getpixel

我正在寻找一种从ActionScript 3中的bitmapData对象中过滤特定颜色的有效方法。目前我使用了一个带有readByte32()的循环。这需要大约一秒的时间来处理,这是不可接受的。我一直试图让paletteMap()工作,但到目前为止还没有能够掌握它的API(任何真正有用的链接?谷歌让我失望......)。

这是我目前的逻辑,我想改进:

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);
  }
 }
}

使用向量可以获得稍微好一点的性能,但它只是稍微好一些......

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);

我真的认为必须有一个更好的方法,只需要几百毫秒。如果有人能为我解开bitmapData的奥秘,你将成为我的人民的新领导者。

PS我正在使用bitmapData.lock()和unlock();我只是没有发布样板文件。

2 个答案:

答案 0 :(得分:4)

一种简单的方法是使用threshold方法。起初它有点麻烦,但速度非常快(我想你会得到的速度快)

这会将每个红色像素(仅红色,只有一个像素,其值正好是0xffff0000)更改为蓝色(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);

答案 1 :(得分:1)

Flash有一个着色器的API,就像名为pixel bender的语言一样,在这种情况下可能对您有用。以下是adobe关于如何apply a pixel bender filter to an image in flash的教程。

否则您可以一次处理行。 (注意代码中的一个小错误是在每次宽度迭代时重新获得高度):

private var currentRow:Number = 0;
private var timer:Timer;
public function processImage(event:Event=null):void
{
    var m:int = bitmapData.height;
    for (var j:int = 0; j < m; j++)
    {
        if (bitmapData.getPixel(currentRow, j) == 0xCACACA)
        {
            bitmapData.setPixel32(currentRow, j, 0x00000000);
        }
    }

    currentRow++;
    if(currentRow < bitmapData.width)
    {
        timer = new Timer(1, 500);
        timer.addEventListener(TimerEvent.COMPLETE, processImage);
        timer.start();
    }
}

处理时间会稍长,但至少不会阻止显示。