I know, I know... such a riveting topic, just can't get enough!
So I felt quite embarrassed when Mario commented on my previous entry, stating that in fact I had misunderstood his method. Either just me being an idiot, or me being an idiot after a few drinks at the Max party.
He then proceeded to blog about the real deal. Indeed this requires less code, looks cleaner and more 1337 in every way! I then included the new method into my test run.
Here is Marios code:
Actionscript:
-
public static function getFirstNonTransparentPixel
( bmd:BitmapData
) 
oint
{
-
var r1:Rectangle = bmd.getColorBoundsRect( 0xff000000, 0, false );
-
if ( r1.width> 0 ){
-
var temp:BitmapData = new BitmapData( r1.width, 1, true, 0 );
-
temp.copyPixels( bmd, r1, new Point());
-
var r2:Rectangle = temp.getColorBoundsRect( 0xff000000, 0, false );
-
return r1.topLeft.add( r2.topLeft );
-
}
-
return null;
-
}
Here (once again) be the results:
Test with image w:100,h:100
testFirstBitmapLooping() first:(x=30, y=30)
testFirstBitmapLooping() test took : 3 milliseconds
testFirstBitmapFloodFill() first:(x=30, y=30)
testFirstBitmapFloodFill() test took : 4 milliseconds
testFirstBitmapHitTest() first:(x=30, y=30)
testFirstBitmapHitTest() test took : 1 milliseconds
testFirstBitmapMario() first:(x=30, y=30)
testFirstBitmapMario() test took : 1 milliseconds
Test with image w:500,h:500
testFirstBitmapLooping() first:(x=150, y=150)
testFirstBitmapLooping() test took : 30 milliseconds
testFirstBitmapFloodFill() first:(x=150, y=150)
testFirstBitmapFloodFill() test took : 17 milliseconds
testFirstBitmapHitTest() first:(x=150, y=150)
testFirstBitmapHitTest() test took : 1 milliseconds
testFirstBitmapMario() first:(x=150, y=150)
testFirstBitmapMario() test took : 3 milliseconds
Test with image w:1000,h:1000
testFirstBitmapLooping() first:(x=300, y=300)
testFirstBitmapLooping() test took : 62 milliseconds
testFirstBitmapFloodFill() first:(x=300, y=300)
testFirstBitmapFloodFill() test took : 41 milliseconds
testFirstBitmapHitTest() first:(x=300, y=300)
testFirstBitmapHitTest() test took : 7 milliseconds
testFirstBitmapMario() first:(x=300, y=300)
testFirstBitmapMario() test took : 10 milliseconds
Test with image w:2000,h:2000
testFirstBitmapLooping() first:(x=600, y=600)
testFirstBitmapLooping() test took : 306 milliseconds
testFirstBitmapFloodFill() first:(x=600, y=600)
testFirstBitmapFloodFill() test took : 96 milliseconds
testFirstBitmapHitTest() first:(x=600, y=600)
testFirstBitmapHitTest() test took : 32 milliseconds
testFirstBitmapMario() first:(x=600, y=600)
testFirstBitmapMario() test took : 55 milliseconds
...so it turns out this wasn't an entirely futile exercise after all! I felt like a schmuck having misunderstood Mario, but I'm quite chuffed that the HitTest method is faster (even if by a practically irrelevant amount).
To be sure, I ran the two competitors 20 times on a bitmap of 2000 by 2000 and took the averages:
Mario Average: :36.7
HitTest Average: :21.2
In any case, I got to better terms with some of the BitmapData methods, which is something we all should aspire to anyway
Thanks again Mario!
********** FINAL UPDATE (hopefully)************
Mario had a go at the HitTest version, and modified it slightly for even better performance:
Actionscript:
-
public static function getFirstNonTransparentPixel
( bmd:BitmapData
) 
oint
{
-
var hit_rect:Rectangle=new Rectangle(0,0,bmd.width,1);
-
var p:Point = new Point();
-
for( hit_rect.y = 0; hit_rect.y <bmd.height; hit_rect.y++ ){
-
if( bmd.hitTest( p, 0x01, hit_rect) ){
-
var hit_bmd:BitmapData=new BitmapData( bmd.width, 1, true, 0 );
-
hit_bmd.copyPixels( bmd, hit_rect, p );
-
return hit_rect.topLeft.add( hit_bmd.getColorBoundsRect(0xFF000000, 0, false).topLeft );
-
}
-
}
-
return null;
-
}
Mind you, I am testing this in debug player... I should use a release version with the release player, but for the sake of consistency with my previous posts I'll stick to my old "test suite".
Results:
HitTest Averages: :16
Mario Averages: :35.285714285714285
Hybrid Averages: :14.142857142857142
Now, finally, back to the code where I actually use this algo