Как отфильтровать определенный цвет из объекта bitmapData (или байтового массива) - PullRequest
4 голосов
/ 22 июня 2010

Я ищу эффективный способ фильтрации определенного цвета из объекта bitmapData в ActionScript 3. В настоящее время я использую цикл с readByte32 (). Обработка занимает около секунды, что недопустимо. Я пытался заставить работать paletteMap (), но до сих пор не смог понять его API (какие-нибудь действительно полезные ссылки? Google подвел меня ...).

Вот моя текущая логика, которую я хочу улучшить:

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

Я действительно думаю, что должен быть лучший способ сделать это, который занимает всего несколько 100 миллисекунд. Если кто-нибудь сможет открыть для меня тайны bitmapData, вы станете новым лидером моего народа.

PS Я использую bitmapData.lock () и unlock (); Я просто не опубликовал шаблонные материалы.

Ответы [ 2 ]

4 голосов
/ 22 июня 2010

Простой способ - использование метода 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 голос
/ 22 июня 2010

Flash имеет API для языка, похожего на шейдер, под названием pixel bender , который может быть полезен вам в этом случае. Вот учебник от Adobe о том, как применить фильтр пиксельного бендера к изображению во флэш-памяти .

В противном случае вы можете обрабатывать строки одновременно. (Обратите внимание, что небольшая ошибка в вашем коде заключалась в повторном получении высоты на каждой итерации ширины):

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

Обработка займет немного больше времени, но по крайней мере ваш дисплей не будет заблокирован.

...