Reputation: 1176
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
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
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