Как отфильтровать определенный цвет из объекта bitmapData (или массива байтов)

Я ищу эффективный способ фильтрации определенного цвета из объекта bitmapData в ActionScript 3. В настоящее время я использую цикл с readByte32(). Обработка занимает около секунды, что неприемлемо. Я пытался заставить panelMap() работать, но до сих пор не смог понять его 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(); Я просто не публиковал шаблонный материал.


person user372950    schedule 22.06.2010    source источник


Ответы (2)


Самый простой способ — использовать порог< /а> метод. Поначалу это немного громоздко, но довольно быстро (думаю, настолько быстро, насколько вы сможете)

Это изменит каждый красный пиксель (учитывая красный только пиксель, значение которого точно равно 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);
person Juan Pablo Califano    schedule 22.06.2010
comment
Спасибо, позвольте мне попробовать это и сравнить производительность. Я вернусь к вам. - person user372950; 23.06.2010
comment
Просто великолепно. Использование threshold() более чем в 100 раз быстрее, чем мои попытки выше. Не верится, что такой сложный метод работает так быстро. Большое спасибо! - person user372950; 23.06.2010
comment
@jpwrunyan. Без проблем. Я думаю, что threshold делает здесь почти то же самое, что и ваш код. Однако большая разница в том, что он работает изначально; это всегда будет лучше любого ActionScript. Как правило, всякий раз, когда вы видите кучу вызовов setPixel/getPixel, особенно в тесном цикле, попытайтесь найти способ заменить их нативным эквивалентом. Если это невозможно, может помочь сгибатель пикселей, но он не будет таким быстрым, как нативный код. - person Juan Pablo Califano; 23.06.2010

У Flash есть API для шейдероподобного языка под названием модуль сгибания пикселей, который может вам пригодиться. в таком случае. Вот руководство от 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();
    }
}

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

person James Fassett    schedule 22.06.2010
comment
Спасибо, что указали на ошибку в первой версии с двойным циклом! Однако я не уверен, почему вы используете таймер выше. Я не анимирую эффект. Я просто обрабатываю изображение и должен удалить из изображения очень специфический цвет (заменив его на 0x00000000). - person user372950; 23.06.2010