Get first non transparent pixel in a bitmap Part III

I know, I know... such a riveting topic, just can't get enough! :D

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:
  1. public static function getFirstNonTransparentPixel( bmd:BitmapData ) :P oint{
  2.     var r1:Rectangle = bmd.getColorBoundsRect( 0xff000000, 0, false );
  3.     if ( r1.width> 0 ){
  4.         var temp:BitmapData = new BitmapData( r1.width, 1, true, 0 );
  5.         temp.copyPixels( bmd, r1, new Point());
  6.         var r2:Rectangle = temp.getColorBoundsRect( 0xff000000, 0, false );
  7.         return r1.topLeft.add( r2.topLeft );
  8.     }
  9.     return null;
  10. }

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:
  1. public static function getFirstNonTransparentPixel( bmd:BitmapData ) :P oint{
  2.     var hit_rect:Rectangle=new Rectangle(0,0,bmd.width,1);
  3.     var p:Point = new Point();
  4.     for( hit_rect.y = 0; hit_rect.y <bmd.height; hit_rect.y++ ){
  5.         if( bmd.hitTest( p, 0x01, hit_rect) ){
  6.         var hit_bmd:BitmapData=new BitmapData( bmd.width, 1, true, 0 );
  7.         hit_bmd.copyPixels( bmd, hit_rect, p );
  8.         return hit_rect.topLeft.add( hit_bmd.getColorBoundsRect(0xFF000000, 0, false).topLeft );
  9.         }
  10.     }
  11.     return null;
  12. }

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 ;)

Tags:

2 Responses to “Get first non transparent pixel in a bitmap Part III”

  1. Mario Klingemann Says:

    Holy cow – now I’ve got to take another deeper look at your code!

  2. Vinh Says:

    This is amazing, perfect for my project application. Its great work what you two have done just wanted to say thanks =)

Leave a Reply