Fsmv
Fsmv

Reputation: 1176

Image changes size as it's rotated. How do I stop this?

I'm making a game for Android and I need to rotate an image. When I rotate it obviously it's dimensions change. For example when it's rotated 45 degrees (it's square but I'd like this to work for any rectangle so it's a more general solution) it's width and height become the length of the diagonal, which is longer than the original. After some algebra you can work out that the scale factor is sqrt(2). But the only way I know of to rotate a bitmap is with a matrix. Ex:

matrix.postRotate(degrees);
rotated = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, true);

Using this method the size of the bitmap remains constant so to fit the rotated image in the content of the image must shrink. Which causes my problem.

What I have now should work but when run doesn't. Probably because it's overly complex, never the less, here it is:

     float totalRotated = 0;

public void rotate(float degrees){
    if(mBitmap != null){
        float increment = (float)((mBitmap.getWidth()/45.0)*(Math.sqrt(2)-1));
        totalRotated += degrees;
        totalRotated -= (float)((int)totalRotated/360)*360;
        matrix.reset();
        matrix.setRotate(totalRotated);
        rotated = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, true);
        rotated = Bitmap.createScaledBitmap(rotated, (int)(mBitmap.getWidth()+(((Math.abs(Math.abs(((int)totalRotated%90)-45)-45)))*increment)), (int)(mBitmap.getHeight()+(((Math.abs(Math.abs(((int)totalRotated%90)-45)-45)))*increment)), true);
    }
}

Using the Log.d function I was able to determine that the dimensions set in the last statement are what I expect them to be but the image doesn't change size. Since this doesn't even work, I need a better way to do this or a way to fix my method. Also my method only works for squares. So, how can I do this?

EDIT: My method does work, I just didn't call setBounds() This can't be the only way to do it though, this is so inefficient.

Upvotes: 1

Views: 7517

Answers (2)

RoboCop87
RoboCop87

Reputation: 837

I tried Gabe's solution and got the same errors that Ramesh and Regis got. This worked for me:

        double radians = Math.toRadians(totalRotated);
        double sin = Math.abs(Math.sin(radians));
        double cos = Math.abs(Math.cos(radians));
        // figure out total width and height of new bitmap
        final int width = mBitmap.getWidth();
        final int height = mBitmap.getHeight();
        final int newWidth = (int) (width * cos + height * sin);
        final int newHeight = (int) (width * sin + height * cos);
        // set up matrix
        final Matrix tf = new Matrix();
        tf.postRotate((float) Math.toDegrees(radians), width / 2, height / 2);
        tf.postTranslate(
            (newWidth - width) / 2,
            (newHeight - height) / 2);
        // create new bitmap by rotating mBitmap with canvas
        final Bitmap rotatedBmp = Bitmap.createBitmap(
            newWidth, newHeight, Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(rotatedBmp);
        canvas.drawBitmap(mBitmap, tf, null);

Upvotes: 0

Gabe
Gabe

Reputation: 86718

It's not clear what you're looking for, so here's a function based on yours that attempts to compute the proper width and height of the new bitmap and do the rotation by creating just a single bitmap.

float totalRotated = 0;

public void rotate(float degrees){
    if(mBitmap != null){
        // compute the absolute rotation
        totalRotated = (totalRotated + degrees) % 360;
        // precompute some trig functions
        double radians = Math.toRadians(totalRotated);
        double sin = Math.abs(Math.sin(radians));
        double cos = Math.abs(Math.cos(radians));
        // figure out total width and height of new bitmap
        int newWidth = mBitmap.getWidth() * cos + mBitmap.getHeight() * sin;
        int newHeight = mBitmap.getWidth() * sin + mBitmap.getHeight() * cos;
        // set up matrix
        matrix.reset();
        matrix.setRotate(totalRotated);
        // create new bitmap by rotating mBitmap
        rotated = Bitmap.createBitmap(mBitmap, 0, 0,
                                      newWidth, newHeight, matrix, true);
    }
}

Upvotes: 1

Related Questions