June 23, 2008
How to draw anything into a BitmapData properly

Looks like Eric has a little problem with getting a sprite with an non 0/0 registration point correctly drawn into a BitmapData object. Here's help. The problem is that by default the draw() command works in such a way that the registration point will line up with the upper left corner of the bitmapData. So what has to be done is to offset the sprite by the amount it's off from that point using the second argument which is a drawing matrix. You can retrieve a clips "real" registration point by using the getBounds() method. Feed the negative of the upper left corner into the drawing matrix and off you go:


function snapClip( clip:DisplayObject ):BitmapData
{
var bounds:Rectangle = clip.getBounds( clip );
var bitmap:BitmapData = new BitmapData( int( bounds.width + 0.5 ), int( bounds.height + 0.5 ), true, 0 );
bitmap.draw( clip, new Matrix(1,0,0,1,-bounds.x,-bounds.y) );
return bitmap;
}

So if you have a spirite named "testclip" on your stage, this will take a (non-scaled, non-rotated) bitmap snapshot of it:

var bitmap:BitmapData = snapClip( testclip );

Posted at June 23, 2008 05:10 PM | Further reading
Comments

Sweet! but how can i capture rotation/scaling too (I am running on ENTER_FRAME)

Posted by: ericd on June 23, 2008 05:28 PM

I'm pretty sure that by clever using the clip's transfrom.concatenatedMatrix there's a way to do this really nicely, but for a quick fix, just replace "clip" with "clip.parent" and it will hopefully work - but I'm really not sure if this works in any case, but at least in my quick test it seems to.

function snapClip( clip:DisplayObject ):BitmapData
{
var bounds:Rectangle = clip.getBounds( clip.parent );

var bitmap:BitmapData = new BitmapData( int( bounds.width + 0.5 ), int( bounds.height + 0.5 ), true, 0 );

bitmap.draw( clip.parent, new Matrix(1,0,0,1,-bounds.x,-bounds.y) );
return bitmap;
}

Posted by: Mario Klingemann on June 23, 2008 05:53 PM

Just as a quick tip, it's sometimes easier/more readable to do it like this:

var matrix=new Matrix();
matrix.translate(-bounds.x,-bounds.y);
/*maybe possitive numbers, don't remember ^^ */
bitmap.draw( clip.parent, matrix );

It is specially nicer when you work with rotation (Matrix.rotate()) and scale (Matrix.scale()) ^^
Oh, and remember to scale/rotate/translate the matrix in the correct order, or it will not work properly ;)

Posted by: Cay on June 24, 2008 10:38 PM

@cay: your way is slower + it's a good thing for everyone to be able to see that the Matrix constructor has some handy parameters.

Posted by: laz9 on June 27, 2008 07:26 PM

Alright, I figured out how to apply this to my situation, and in case anyone else has a similar setup, this may help.

In my situation, I had a bitmapData object the size of the stage and wanted to draw slash marks on it that were movieClips and were both scaled, rotated, and had a non-0 registration point. Assuming the bitmapData and bitmap objects are already setup and added to the stage, add this code:


var matrix:Matrix = new Matrix ();

matrix.scale (clip.scaleX, clip.scaleY);
matrix.rotate (clip.rotation * (Math.PI/180));
matix.translate (clip.x, clip.y);

stageBMD.draw (clip, matrix);


Note: the matrix.rotate function takes the angle in radians ( the * (Math.PI/180) converts the clips rotation to radians) - if you already have an angle in radians, don't convert it. Also, as Cay noted, make sure you keep the scale, rotate, translate in that order, or the positioning will get messed up when you rotate.

Hope this helped somebody - you guys sure helped me :)

Posted by: Greyson Parrelli on July 27, 2008 01:06 AM

Greyson - I didn't test it, but it looks like you could try stageBMD.draw (clip, clip.transform.matrix); as well

Posted by: Mario Klingemann on July 27, 2008 01:01 PM

not sure what to do with this now. plugged in the code but I get the following compiling errors:

The class or interface 'DisplayObject' could not be loaded.

Posted by: avery on October 8, 2008 06:25 AM

also,
The class or interface 'Rectangle' could not be loaded.

Posted by: on October 8, 2008 06:28 AM

Oh sorry, I forgot to mention: this is AS3 guys.

Posted by: Mario Klingemann on October 8, 2008 11:09 AM

as3 eh? damn. i'm working exclusively in as2 based on some other code i'm using. is there anyway, using your bitmap exporter code, to save multiple movie clips in the same jpg?

thanks again

Posted by: avery on October 8, 2008 03:20 PM

I had to figure this out on my own months ago when I created the SpringyTiles thing at the top of my blog. Each sprite had to be offset as I sliced up BitmapData from the image. It took a while. Wish I'd had this post back then. :-)

Posted by: polyGeek on November 8, 2008 07:29 PM

this is very useful for drawing movieclips on the stage...but how can i translate the x and y positions of a nested movieclip..?i've tried parent.parent and root too...but both these methods produce incorrect results...
please help me..

Posted by: ravi on August 19, 2009 12:53 PM

Wow, massive thanks to everyone who contributed on this post! I'm using it for generative art purposes.

Posted by: Fin on March 20, 2010 02:46 AM

AND my code is as follows(once you create a bitmap):

function drawIt(mcToDraw:DisplayObject):BitmapData {
var bounds:Rectangle = this.getBounds( mcToDraw );
bmp.draw( mcToDraw, mcToDraw.transform.matrix)
}

drawIt(myReallyNiceMC)

Just pass the MC you want it to draw! :D

Posted by: Fin on March 20, 2010 02:47 AM

I just spent 3-4 hours trying to figure this out. I'm still too angry to be truly thankful.

Posted by: on May 24, 2010 06:21 AM
Post a comment
Name:


Email Address:


URL:


Comments:


Remember info?



Thank you!
Most Visited Entries
Sketches, Works & Source Code
Popular on Aviary

Lectures
Contact
Backlog
In Love with
Powered by
Movable Type 2.661

© Copyright Mario Klingemann

Syndicate this site:
RSS 1.0 - RSS 2.0

Quasimondo @ flickr
Quasimondo @ LinkedIn
Quasimondo @ Twitter
Quasimondo @ Facebook
Quasimondo @ MySpace
Quasimondo is a Bright
Citizen of the TRansnational Republic
My other blog in german
Impressum


My family name is written Klingemann,
not Klingelmann, Klingeman, Klingaman, Kingemann,
Kindermann, Killingaman, Klingman, Klingmann, Klingonman
Klingemman, Cleangerman, Klingerman or Kleangerman