views:

832

answers:

1

Does anyone have an example of using the ImageSnapshot.captureBitmapData function with a rotation matrix? This is the code I'm using:

var matrix:Matrix = new Matrix();
matrix.rotate(degreesToRadians(90));
var bitmapData:BitmapData = ImageSnapshot.captureBitmapData(textInput, matrix);

But unfortunately this throws an error on the following line in ImageSnapshot.as:

data = new BitmapData(scaledWidth, scaledHeight, true, 0x00000000); // <-- THROWS ERROR HERE AS scaledWidth / scaledHeight are extremely small numbers (-1-e16 etc)
            data.draw(source, matrix, colorTransform,
                      blendMode, clipRect, smoothing);
        }
        finally
        {
            if (source is IUIComponent)
                finishPrintObject(IUIComponent(source), normalState); // <-- ERROR THROWN HERE, BUT CAUSE OF ERROR IS ABOVE
        }

What I'm trying to achieve is a rotated bitmap of a text input control (I'm trying to avoid embedding a font in the application). This code works just fine when I don't rotate the bitmap, but the minute I rotate it, it breaks.

Post-Accepted-Answer Edit

I was working with a loader class in my original problem, and I also wanted the text 270degrees - so here's the text which does that:

var matrix:Matrix = new Matrix();
                        matrix.rotate(Math.PI * 1.5);
                        matrix.translate(0, copyThis.width);

                        var bitmapData:BitmapData = ImageSnapshot.captureBitmapData(copyThis, new Matrix());
                        var rotatedBitmap : BitmapData = new BitmapData(bitmapData.height, bitmapData.width, false, 0xFFFF0000);

                        rotatedBitmap.draw(bitmapData, matrix);

                        loader.load(new Bitmap(rotatedBitmap));

Thank you!

+3  A: 

I have just been able to reproduce this so it indeed seems like bug in the ImageSnapshot class. All i can think of is that it's just not been tested using a rotation Matrix so it's been completely missed. Obviously trying to create a bitmapData less than 1x1 is the reason it's throwing the error. Can't seem anyway round it to be honest.

Would think your best bet could be to create your own simplified snap shot class, or to just use an identity matrix to get the original bitmap, and then copy that into a new bitmapData that can house the rotated version.

Edit

on another note... as flash components are registered from the top right, you also need to translate the matrix across by the original height. Though that may have solved the original problem but it still breaks. Here's a solution that uses a new BitmapData and transforms the one created by ImageSnapshot

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:Script>
     <![CDATA[
      import mx.graphics.ImageSnapshot;


      private function clickHandler(event : MouseEvent) : void
      {
       var matrix:Matrix = new Matrix();
       matrix.rotate(Math.PI / 2);
       matrix.translate(copyThis.height, 0);

       var bitmapData:BitmapData = ImageSnapshot.captureBitmapData(copyThis, new Matrix());
       var rotatedBitmap : BitmapData = new BitmapData(bitmapData.height, bitmapData.width, false, 0xFFFF0000);

       rotatedBitmap.draw(bitmapData, matrix);

       var g : Graphics = copyTo.graphics;

       g.clear();
       g.beginBitmapFill(rotatedBitmap);
       g.drawRect(0,0, rotatedBitmap.width, rotatedBitmap.height);
       g.endFill();
      }
     ]]>
    </mx:Script>

    <mx:VBox width="100%" height="100%" horizontalAlign="center">
     <mx:Canvas width="100%" height="100%">
      <mx:TextInput id="copyThis" text="COPY THIS"  horizontalCenter="0" verticalCenter="0"/>
     </mx:Canvas>
     <mx:Canvas id="copyTo" width="100%" height="100%" />
     <mx:Button id="copyIt" label="COPY IT" click="clickHandler(event)" />
    </mx:VBox>
</mx:Application>
James Hay
You sir, are brilliant :)I did try using an intermediate bitmap previously, but I couldn't get it to work - it was the missing translation!If I could award more points for the correct answer, I would :)Thank you!
Mark Ingram