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
Sweet! but how can i capture rotation/scaling too (I am running on ENTER_FRAME)
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;
}
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 ;)
@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.
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 :)
Greyson - I didn't test it, but it looks like you could try stageBMD.draw (clip, clip.transform.matrix); as well
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.
also,
The class or interface 'Rectangle' could not be loaded.
Oh sorry, I forgot to mention: this is AS3 guys.
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
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. :-)
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..