I have a BitmapData
which is generated by draw
ing a DisplayObject
. I would like to create a pure white silhouette copy of that BitmapData
. It seems there would be two approaches to do so:
ColorTransform
to the DisplayObject
and then have a new BitmapData
with the same dimensions draw
it.BitmapData
, then copyPixels
the original, then apply a ColorTransform
via BitmapData.colorTransform
.Neither BitmapData
will be displayed inside a Bitmap
, so applying a ColorTransform
to that is not an option. They will instead be turned into a Starling Texture
.
Which method would be more efficient? I would run some benchmarks myself, but I'm concerned the answer would be dependent on the size and complexity of the DisplayObject being drawn. Perhaps the copyPixels
method would be better when the size is small and worse if it's large, and the draw
method would be better if the DisplayObject to be drawn is simple and worse if it's complex. Also, are the copyPixels and BitmapData.colorTransform methods done on the GPU? If so, I suppose that would tilt things in their favor.
So I did some benchmarks, and in the best possible scenario for the draw method, where the DisplayObject
to be drawn was simply a colored rectangle, draw was always faster than copyPixels by around 33%, regardless of size. Then I tried using some complex DisplayObject
s with lots of shapes inside, and in those cases, draw was 300% to 400% slower. So the answer is "it depends". But I have to say, using the draw method has an upside potential of a 33% speed increase at most, but an enormous downside potential if the DisplayObject
is complex.
I did some additional testing of the copyPixels/colorTransform method against the getPixels/setPixels method, and remarkably the getPixels/setPixels method was 20x slower! Here is my copyPixels method:
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
And here is my getPixels method for loop:
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