安卓画布中位图的同时旋转、平移和缩放

5

我想展示一张可以缩放、平移和随罗盘读数旋转的图片。使用下面的代码,这三个动作有点起到了作用,但它们会相互影响。

以下是我想要实现的目标:
1. 围绕屏幕中心旋转
2. 缩放,保持图片中心的同一部分
3. 平移到图片中所需的位置

而使用下面的代码时,实际上发生的情况是:
1. 旋转按预期方式工作,围绕屏幕中心旋转
2. 缩放有效,但它是围绕图片中心缩放的
3. 只有当angle为零时,平移才按预期工作,否则它会朝错误的方向移动

// 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);

如果我先进行翻译,然后再旋转,那么翻译就按预期工作了,但旋转不再围绕视口中心。

我如何应用这三种变换,而不会相互影响?

1个回答

1

我不确定关于图像中心的缩放,但是对于翻译方向错误是否不是因为您旋转了图像而没有旋转翻译?也许可以尝试这样:

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

矩阵对象是否直接具有应用仿射变换的方法?这样,您就不需要考虑操作顺序。

仿射变换可能看起来像这样:

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

但是这将围绕图像的角落旋转,因此您需要首先使用preTranslate()函数,如下所示:

Mt.preTranslate(-centerX,-centerY);

在应用 M 之前,先将 Mt 应用于图片,然后在应用完 M 后,需要再次应用 -Mt。


旋转翻译似乎只是偏移旋转,但我也觉得这正是我需要的。Android矩阵是3x3的,所以我猜它们已经是仿射变换了? - modemuser
那么也许尝试直接设置矩阵而不是使用那些preRotate、preScale方法会更好?那么你的矩阵应该类似于上面帖子中的编辑。 - Dan
使用这个矩阵,平移是有效的,但缩放会旋转图片,旋转也会缩放图片,并且旋转发生在图片的一个角落。就像打地鼠一样,但还是感谢您的建议。 - modemuser
缩放和旋转不应该相互干扰,这很奇怪,你尝试过角度为0吗?或者使用角度但mScaleFactor = 1?至于围绕角落旋转,那是有道理的,我会再次编辑。 - Dan
只有当mScaleFactor=1或angle=0时,缩放和旋转才能无干扰地工作。否则,我认为使用正确值的单个矩阵是解决此问题的正确方法。 - modemuser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接