NemoStein
NemoStein

Reputation: 2098

Calculate the size of a new BitmapData based on a Matrix

I'm trying to draw the contents of a BitmapData into another one, yet to be created.
But before drawing I need to scale and rotate the image, and the draw it.
My problem is that I don't know the size that the BitmapData will have after the transformation, so I can't create the new one to draw on it.

This method shows what I mean:

public function getTransformedBitmapData(origin:BitmapData):BitmapData
{
    var matrix:Matrix = new Matrix();

    // ajusting the anchor point and rotating
    matrix.translate(-origin.width / 2, -origin.height / 2);
    matrix.rotate(Math.PI / 4); // 45 deg
    matrix.translate(origin.width / 2, origin.height / 2);

    // scaling
    matrix.scale(1.5, 1.5);

    // Calculating the size of the new BitmapData
    var width:Number = 0; // I don't know this value!
    var height:Number = 0; // I don't know this value!

    // Creating and drawing (with transformation)
    var result:BitmapData = new BitmapData(width, height, true, 0);
    result.draw(origin, matrix);

    return result;
}

Some one knows what I should do to find out (calculate) the size of this image after the transformation?


This image illustrates the rotation in action, and what I want to find out:

enter image description here

Upvotes: 4

Views: 858

Answers (3)

NemoStein
NemoStein

Reputation: 2098

Ok, using @ansiart answer as starting point I managed to calculate the dimensions this way:

public function getTransformedBitmapData(origin:BitmapData):BitmapData
{
    var matrix:Matrix = new Matrix();

    // ajusting the anchor point and rotating
    matrix.translate(-origin.width / 2, -origin.height / 2);
    matrix.rotate(Math.PI / 4); // 45 deg
    matrix.translate(origin.width / 2, origin.height / 2);

    // scaling
    matrix.scale(1.5, 1.5);

    // Finding the four corners of the bounfing box after transformation
    var topLeft:Point = matrix.transformPoint(new Point(0, 0));
    var topRight:Point = matrix.transformPoint(new Point(origin.width, 0));
    var bottomLeft:Point = matrix.transformPoint(new Point(0, origin.height));
    var bottomRight:Point = matrix.transformPoint(new Point(origin.width, origin.height));

    // Calculating "who" is "where"
    var top:Number = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
    var bottom:Number = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
    var left:Number = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
    var right:Number = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);

    // Ajusting final position
    matrix.translate(-left, -top);

    // Calculating the size of the new BitmapData
    var width:Number = right - left;
    var height:Number = bottom - top;

    // Creating and drawing (with transformation)
    var result:BitmapData = new BitmapData(width, height, false, 0);
    result.draw(origin, matrix);

    return result;
}

I think that this can be a little overkill, but works.

Upvotes: 1

ansiart
ansiart

Reputation: 2571

matrix has a transformPoint method. This will make it easy to determine topLeft/bottomRight.

var matrix:Matrix = new Matrix();

// do stuff to matrix
var topLeft:Point   = matrix.transformPoint(new Point(0,0));
var bottomRight:Point   = matrix.transformPoint(new Point(width,height));

// determine bounds of rectangle based on points (note: bottomRight might be now the topLeft, so need to do testing

If you're going to draw into this new bitmap though, make sure to offset based on tx/ty.

Upvotes: 0

Endre Simo
Endre Simo

Reputation: 11541

There is no need to calculate the new bitmap size. You may create the new bitmapData with the same size as the original one, and set the transparency to true, and the fillColor parameter to 0x00 (this is the alpha value on a 32bit image). This way the new bitmapData will be filled only with the transformed object, the rest of the image data structure won't be affected.

Or there is another method, to define the placeholder bitmap data size by multiplying the original bitmapData width and height with the scaling ratio.

Upvotes: 0

Related Questions