AS3: наиболее эффективный способ создания тонированной копии BitmapData - PullRequest
0 голосов
/ 21 мая 2018

У меня есть BitmapData, который генерируется draw с DisplayObject.Я хотел бы создать чистую белую силуэтную копию этого BitmapData.Кажется, что для этого есть два подхода:

  1. Применить ColorTransform к DisplayObject и затем получить новый BitmapData с такими же размерами draw it.
  2. Создайте новый BitmapData, затем copyPixels оригинал, затем примените ColorTransform через BitmapData.colorTransform.

Ни один BitmapData не будет отображаться внутри Bitmap,поэтому применение ColorTransform к этому не вариант.Вместо этого они превратятся в скворца Texture.

Какой метод будет более эффективным?Я бы сам выполнил несколько тестов, но я обеспокоен, что ответ будет зависеть от размера и сложности прорисовываемого объекта DisplayObject.Возможно, метод copyPixels был бы лучше, когда размер маленький, и хуже, если он большой, а метод draw был бы лучше, если бы отображаемый объект DisplayObject был простым, и хуже, если он сложный.Кроме того, методы copyPixels и BitmapData.colorTransform выполняются на GPU?Если так, то я полагаю, что это склонит вещи в их пользу.

1 Ответ

0 голосов
/ 21 мая 2018

Итак, я сделал несколько тестов, и в лучшем из возможных сценариев для метода рисования, где DisplayObject для рисования был просто цветным прямоугольником, рисование всегда было быстрее, чем copyPixels, примерно на 33%, независимо от размера.Затем я попытался использовать несколько сложных DisplayObject с множеством фигур внутри, и в этих случаях отрисовка была на 300-400% медленнее.Таким образом, ответ «это зависит».Но я должен сказать, что использование метода draw имеет потенциал увеличения скорости максимум на 33%, но огромный потенциал снижения при сложном DisplayObject.

Я провел дополнительное тестирование copyPixelsМетод / colorTransform против метода getPixels / setPixels, и, что примечательно, метод getPixels / setPixels был в 20 раз медленнее!Вот мой метод copyPixels:

var start_time:int = getTimer();
var s1:S1 = new S1(); //S1 is simply a 100x100 red circle
var bmd1:BitmapData = new BitmapData(s1.width,s1.height,true,0x00000000);
bmd1.drawWithQuality(s1,null,null,null,null,false,StageQuality.HIGH);
var bmd2:BitmapData;
var sourceRect:Rectangle = new Rectangle(0,0,bmd1.width,bmd1.height);
var point00:Point = new Point();
var colorTransform:ColorTransform = new ColorTransform(0,0,0,1,255,255,255,0);
var w:uint = bmd1.width,
    h:uint = bmd1.height,
    pixelHex:uint,
    pixelAlpha:uint;
var ba:ByteArray;
for (var i:uint=0; i<1000; i++) {
    bmd2 = new BitmapData(w,h,true,0x00000000);
    bmd2.copyPixels(bmd1,sourceRect,point00);
    bmd2.colorTransform(sourceRect,colorTransform);
}
trace("execution time: ", getTimer()-start_time); //execution time:  74

А вот мой метод getPixels для цикла:

for (var i:uint=0; i<1000; i++) {
    ba = bmd1.getPixels(sourceRect);
    ba.position = 0;
    while (ba.bytesAvailable > 0) {
        pixelHex = ba.readUnsignedInt();
        pixelAlpha = pixelHex >>> 24;
        if (pixelAlpha > 0) {
            ba.position -= 4;
            ba.writeUnsignedInt((pixelAlpha<<24)|0xffffff);
        }
    }
    ba.position = 0;
    bmd2 = new BitmapData(w,h,true,0x00000000);
    bmd2.setPixels(sourceRect,ba);
}
trace("execution time: ", getTimer()-start_time); //execution time:  1349
...