Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simultaneous rotation, translation, and scaling of bitmap in android canvas

I'm trying to show a picture, which can be zoomed and panned, and that rotates with a compass reading. With the code below, all three actions kind of work, but they influence each other.

Here is what I want to achieve:
1. Rotate around the center of the screen
2. Scale leaving the same part of the picture in the center
3. Pan to the desired spot in the picture

Here is what is actually happening with the code below:
1. Rotation works as intended, around the center of the screen
2. Scaling works, but it scales around the center of the picture
3. Translation only works as intended if angle is zero, otherwise it's moving in a wrong direction

// the center of the view port
float centerX = screen.right/2;
float centerY = screen.bottom/2;

Matrix m = new Matrix();
m.preRotate(angle, centerX, centerY);
m.preScale(mScaleFactor, mScaleFactor, centerX, centerY);

// scaling the amount of translation, 
// rotating the translation here gave crazy results
float x = mPosX / mScaleFactor;
float y = mPosY / mScaleFactor;
m.preTranslate(x, y);

canvas.drawBitmap(pic, m, null);

If I translate first, and later rotate, the translation works as intended but the rotation is not around the center of the view port anymore.

How can I apply all three transformations, without them influencing each other?

like image 604
modemuser Avatar asked Nov 13 '22 06:11

modemuser


1 Answers

I'm not sure about the scaling around the centre of the image, but as for the translation being in the wrong direction is it not as a consequence of you rotating the image but not the translations? Maybe try something like this:

float x = (mPosX*(cos(angle) + sin(angle)) / mScaleFactor;
float y = (mPosY*(cos(angle) - sin(angle)) / mScaleFactor;
m.preTranslate(x, y);

Also does the matrix object have a method to apply an affine transformation directly? Because then you won't need to think about the order of operations.

The affine transformation might look something like this:

M = |mScaleFactor*cos(angle)       sin(angle)            x|
    |     -sin(angle)          mScaleFactor*cos(angle)   y|
    |          0                         0               1|

But this will rotate around the corner of the image so you need to use the preTranslate() function first like so:

Mt.preTranslate(-centerX,-centerY);

And APPLY Mt to pic before applying M and then after you need to apply -Mt

like image 122
Dan Avatar answered Nov 16 '22 02:11

Dan