Rotate using Flex BitmapData and Matrix

Recently, I found myself in need of an image rotation component in Flex so that the rotation takes place on the client and saves the image back to the server.  The image source I use has a thumbnail 100×100 and the original image.    I wanted to load just the thumbnail to perform the rotation and then once I am done with rotating the image, apply the rotation to the original image size.

Rotating the thumbnail turns out to be easy when you redraw the BitmapData using a Matrix with the rotate property set to the desired rotation:

 // Pass in a reference to the Image Control
 private function rotateImageRight(img:Image):void
 {
 img.source = new Bitmap( rotateRight(img));
 }

private function rotateLeft(img:Image):BitmapData
 {
 var matrix:Matrix = new Matrix();
 matrix.rotate(-1*Math.PI/2);
 matrix.ty = img.content.width;
 var bd:BitmapData = getBitmapDataMatrix(img, matrix);
 return bd;
 }

private function rotateRight(img:Image):BitmapData
 {
 var matrix:Matrix = new Matrix();
 matrix.rotate(Math.PI/2);
 matrix.tx = img.content.height;
 var bd:BitmapData = getBitmapDataMatrix(img, matrix);
 return bd;
 }
 

The issue I ran into was that the Image Control couldn’t have any dimensions or the loaded data would progressively become smaller and smaller with each rotation.   So my Image control just loads the thumbnail source, but does not size the image.   You have to trust that the image thumb is really small or it will blow up the example application.  You could probably also use a Loader Class and attach the image to the stage after you size it, but I didn’t test that method.

Rotating the original image is not as easy.  I didn’t want to load the image until I was ready to save the rotation. When I want to save the rotation, I load the original image in the background, to an invisible Image control with fixed dimensions (it can be as small as you want), then I manipulate the BitmapData of the content because you need the original images width and height.   At first I tried to get this with contentWidth and contentHeight properties of the Image control, but I found it worked with the actual content.width and content.height:

 // Pass in reference to of the Image control with
 // the original image and the matrix

private function getBitmapDataMatrix(img:Image, matrix:Matrix) : BitmapData
 {
 var bd:BitmapData = new BitmapData(img.content.height, img.content.width);
 bd.draw(img.content, matrix);
 return bd;
 }
 

The returned BitmapData can be posted back to a server to write out to the users disk or you can display the data in another Image control.   In the example application I show the mothod for both using a trick that Doug McCune posted on his blog. Unfortunately, it only works for Firefox and fails for some larger images.

The rest of the work just invovles keeping track of rotated angle of the thumbnail so you can apply this to the original image that you load.  In my example the original image is loaded at the start so you can see it.  But it would be easy to make this inivisible and only load the original image when the users wants to save or output the rotated image.  You will need to have the as3corelib to run the example locally.

Example File (right-click to view source)

-Mr

9 Comments

  1. Hi! i have the same problem, the image become smaller and smaller with each rotation, have any idea to fix this problem? Thanks in advance

  2. Hi!
    Great post just exactly what I was looking for!! tried to use it and I came up with the same problem that Sebastian described. Image gets smaller and smaller after every turn.
    Is there any solution for this known problem?

    Would really be appreciated!!

    Thanks!

    Ramin

  3. For the people who are interested why? it happens, when you maintain aspect ratio, the image gets smaller and smaller with every turn…
    when not maintaining the ratio the rotation works like a charm… but still it’s not the way I want to work with images!!

  4. I have created as3corelib project and generated the .swc file for it and added that .swc file into this project, even then i am getting the sandbox violation error, can anyone help me out in solving this issue .

  5. Ohh, i got the reason, its not working for me in firefox, where as it is working in Internet Explorer, can anyone find the reason plz.

  6. Hi
    I need same function .

    But i have a dynamic lable.
    eg. var lbl:Lable= new Lable()
    lbl.Text=”ABC”;

    var bitmapData:BitmapData = new BitmapData(lbl.width, lbl.height);
    bitmapData.draw(lbl);

    var img:Image= new Image();
    img.source = new Bitmap(bitmapData);
    img.rotation=20;

    var matrix:Matrix = new Matrix();
    matrix.rotate(Math.PI/2);
    matrix.tx = img.content.height;
    var bd:BitmapData = getBitmapDataMatrix(img, matrix);
    img.source = new Bitmap(bd);

    but i got error:
    like that: img.content is null

    please try to help me

Comments are closed.