Today I encountered this blog post from Zevan (which blog is REALLY a good daily reading I suggest everyone to take) about bitmapData merging and I started tweaking some code doing some benchmarks to find out which way is the most performing. Here are my tests:
First strike (Zevan’s one): copyPixels
[SWF(width=650, height=650)]
var loader:Loader = new Loader();
loader.load(new URLRequest("http://actionsnippet.com/wp-content/chair.jpg"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
var w:Number;
var h:Number;
var rows:Number = 20;
var cols:Number = 20;
var tiles:Vector. = new Vector.();
var locX:Vector. = new Vector.();
var locY:Vector. = new Vector.();
var rX:Vector. = new Vector.();
var rY:Vector. = new Vector.();
var sX:Vector. = new Vector.();
var sY:Vector. = new Vector.();
function onLoaded(evt:Event):void{
w = evt.target.width;
h = evt.target.height;
var image:BitmapData = Bitmap(evt.target.content).bitmapData;
var tileWidth:Number = w / cols;
var tileHeight:Number = h / rows;
var inc:int = 0;
var pnt:Point = new Point();
var rect:Rectangle = new Rectangle(0,0,tileWidth,tileHeight);
var startTime:Number = getTimer();
for (var i:int = 0; i
in my machine (mbp, osx) it takes ~27 ms to extract data and ~2-3ms each iteration for setting data on the canvas bitmapData
Second strike: getVector\setVector
[SWF(width=650, height=650)]
var loader:Loader = new Loader();
loader.load(new URLRequest("http://actionsnippet.com/wp-content/chair.jpg"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
var w:Number;
var h:Number;
var rows:Number = 20;
var cols:Number = 20;
var tiles:Vector.> = new Vector.>();
var tileRect:Rectangle;
var locX:Vector. = new Vector.();
var locY:Vector. = new Vector.();
var rX:Vector. = new Vector.();
var rY:Vector. = new Vector.();
var sX:Vector. = new Vector.();
var sY:Vector. = new Vector.();
function onLoaded(evt:Event):void{
w = evt.target.width;
h = evt.target.height;
var image:BitmapData = Bitmap(evt.target.content).bitmapData;
var tileWidth:Number = w / cols;
var tileHeight:Number = h / rows;
tileRect = new Rectangle(0,0,tileWidth,tileHeight);
var inc:int = 0;
var pnt:Point = new Point();
var rect:Rectangle = new Rectangle(0,0,tileWidth,tileHeight);
var startTime:Number = getTimer();
for (var i:int = 0; i;
var startTime:Number = getTimer();
for (var i:int = 0; i
on my machine it takes only ~9 ms to extract tiles slices (yes, 3 times faster!!!) and ~1ms for pushing them all in the canvas for each loop iteration
Third strike: getPixels\setPixels
[SWF(width=650, height=650)]
var loader:Loader = new Loader();
loader.load(new URLRequest("http://actionsnippet.com/wp-content/chair.jpg"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
var w:Number;
var h:Number;
var rows:Number = 20;
var cols:Number = 20;
var tiles:Vector. = new Vector.();
var tileRect:Rectangle;
var locX:Vector. = new Vector.();
var locY:Vector. = new Vector.();
var rX:Vector. = new Vector.();
var rY:Vector. = new Vector.();
var sX:Vector. = new Vector.();
var sY:Vector. = new Vector.();
function onLoaded(evt:Event):void{
w = evt.target.width;
h = evt.target.height;
var image:BitmapData = Bitmap(evt.target.content).bitmapData;
var tileWidth:Number = w / cols;
var tileHeight:Number = h / rows;
tileRect = new Rectangle(0,0,tileWidth,tileHeight);
var inc:int = 0;
var pnt:Point = new Point();
var rect:Rectangle = new Rectangle(0,0,tileWidth,tileHeight);
var startTime:Number = getTimer();
for (var i:int = 0; i
a nice one, ~ 17 ms to extract and ~2ms to loop on my mac, faster than copyPixels but vectors are still leading...
Fourth strike: merge
[SWF(width=650, height=650)]
var loader:Loader = new Loader();
loader.load(new URLRequest("http://actionsnippet.com/wp-content/chair.jpg"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
var w:Number;
var h:Number;
var rows:Number = 20;
var cols:Number = 20;
var tiles:Vector. = new Vector.();
var locX:Vector. = new Vector.();
var locY:Vector. = new Vector.();
var rX:Vector. = new Vector.();
var rY:Vector. = new Vector.();
var sX:Vector. = new Vector.();
var sY:Vector. = new Vector.();
function onLoaded(evt:Event):void{
w = evt.target.width;
h = evt.target.height;
var image:BitmapData = Bitmap(evt.target.content).bitmapData;
var tileWidth:Number = w / cols;
var tileHeight:Number = h / rows;
var inc:int = 0;
var pnt:Point = new Point();
var rect:Rectangle = new Rectangle(0,0,tileWidth,tileHeight);
var startTime:Number = getTimer();
for (var i:int = 0; i
~36 ms to extract and ~12ms to merge tiles on the canvas!!!...too slow all the way...:\
There are still some methods left such as getPixel\setPixel, getPixel32\setPixel32, and copyChannel but they're a too much restrictive choice because they're handling one pixel, or channel at time therefore a further loop would be required to get them doing this task.
Summary:
getVector\setVector : ~9ms\~1ms
getPixels\setPixels: ~17ms\~2ms
copyPixels: ~27ms\~2-3ms
merge: ~36ms\~12ms
make your choice
NOTE: these benchmarks are valid from flash player 10 because we (both me and Zevan) used the Vector native type to store lists of typed data. To make them valid for previous version of the player make sure to replace vectors with arrays and check other types are already supported by the target player.
stay tuned