我正在尝试编写一个Android应用程序,让我在图像上绘制图形,然后缩放和缩放图像,图形保留在图像上的同一位置,同时更改图形实时。
然而,我一直有很多问题让它在保持图像中心的同时放大。我编写了代码,我有一个更新图像的线程。使用我通过ArrayBlockingQueue创建的名为“PendingUpdate”的类传递更新。此更新包含所需的缩放级别,该缩放级别应该是图像像素与画布像素和图像中心的比率。但是,下面的代码使我在缩放时平移,这让我很困惑。
//Scale the image
canvas.scale(pendingUpdate.getZoom(), pendingUpdate.getZoom());
//Translate the image
double updateCx = pendingUpdate.getCenter().getX();
double updateCy = pendingUpdate.getCenter().getY();
double halfCanvasWidthInImagePixels = pendingUpdate.getZoom()*(canvas.getWidth()/2);
double halfCanvasHeightInImagePixels = pendingUpdate.getZoom()*(canvas.getHeight()/2);
double imageTranslateX = updateCx - halfCanvasWidthInImagePixels;
double imageTranslateY = updateCy - halfCanvasHeightInImagePixels;
canvas.translate(-(float)imageTranslateX, -(float)imageTranslateY);
canvas.drawBitmap(pendingUpdate.getImage(), matrix, new Paint());
感谢您的帮助!
编辑:这是完整的功能,如果这有帮助,我也可以发布PendingUpdate,但它只是一个数据类。
private void doDraw(Canvas canvas, PendingUpdate pendingUpdate) {
int iWidth = pendingUpdate.getImage().getWidth();
int iHeight = pendingUpdate.getImage().getHeight();
Matrix matrix = new Matrix();
canvas.drawColor(Color.BLACK);
//TODO: add scrolling functionality to this
if(pendingUpdate.getZoom()>0) {
//Scale the image
canvas.scale(pendingUpdate.getZoom(), pendingUpdate.getZoom());
//Translate the image
double updateCx = pendingUpdate.getCenter().getX();
double updateCy = pendingUpdate.getCenter().getY();
double halfCanvasWidthInImagePixels = pendingUpdate.getZoom()*(canvas.getWidth()/2);
double halfCanvasHeightInImagePixels = pendingUpdate.getZoom()*(canvas.getHeight()/2);
double imageTranslateX = updateCx - halfCanvasWidthInImagePixels;
double imageTranslateY = updateCy - halfCanvasHeightInImagePixels;
canvas.translate(-(float)imageTranslateX, -(float)imageTranslateY);
canvas.drawBitmap(pendingUpdate.getImage(), matrix, new Paint());
}else {
//matrix.postTranslate(canvas.getWidth()-iWidth/2, canvas.getWidth()-iHeight/2);
canvas.drawBitmap(pendingUpdate.getImage(),
(canvas.getWidth()-iWidth)/2,
(canvas.getHeight()-iHeight)/2, null);
}
//TODO: draw other stuff on canvas here such as current location
}
编辑2:这就是我最终让它发挥作用的方式,只是在翻译之前对其进行缩放。
private void doDraw(Canvas canvas, PendingUpdate pendingUpdate) {
int iWidth = pendingUpdate.getImage().getWidth();
int iHeight = pendingUpdate.getImage().getHeight();
canvas.drawColor(Color.BLACK);
//TODO: add scrolling functionality to this
if(pendingUpdate.getZoom()>0) {
//Scale the image
canvas.save();
double updateCx = pendingUpdate.getCenter().getX();
double updateCy = pendingUpdate.getCenter().getY();
double halfCanvasWidthInImagePixels = (canvas.getWidth()/2);
double halfCanvasHeightInImagePixels = (canvas.getHeight()/2);
double imageTranslateX = updateCx - halfCanvasWidthInImagePixels;
double imageTranslateY = updateCy - halfCanvasHeightInImagePixels;
//canvas.scale(pendingUpdate.getZoom(), pendingUpdate.getZoom(), (float)pendingUpdate.getCenter().getX(), (float)pendingUpdate.getCenter().getY());
canvas.scale(pendingUpdate.getZoom(),
pendingUpdate.getZoom(),
canvas.getWidth()/2,
canvas.getHeight()/2);
canvas.translate(-(float)imageTranslateX,
-(float)imageTranslateY);
canvas.drawBitmap(pendingUpdate.getImage(), 0, 0, null);
canvas.restore();
}else {
//TODO: update this so it displays image scaled to screen and updates current zoom somehow
canvas.drawBitmap(pendingUpdate.getImage(),
(canvas.getWidth()-iWidth)/2,
(canvas.getHeight()-iHeight)/2, null);
}
//TODO: draw other stuff on canvas here such as current location
}
}
答案 0 :(得分:1)
如果我是你,我会使用Canvas.scale(float sx, float sy, float px, float py)
方法,它完全符合您的要求。
但是看看你的代码我认为你可能会一次搞乱太多的转换,这很难调试。
总是(我的意思是总是)如果你打算在Canvas.save()
获得的初始矩阵上调用Canvas.restore()
和Canvas
改变它。这是因为您可以使用的Canvas
可能是画布,例如:整个窗口只剪切设置为当前绘制自身的控件的边界。
使用Canvas
方法提供的矩阵变换方法,并使用最简单的调用绘制位图。
根据这两个建议,查看我刚刚编写的整个View
,将bitmap
缩放3
,将点(16,16)
设置为枢轴(未更改的点 - 缩放中心)。经过测试 - 工作。
public class DrawingView extends View {
Bitmap bitmap;
public DrawingView(Context context) {
super(context);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
}
@Override
protected void onDraw(Canvas canvas) {
float sx = 3;
float sy = 3;
float px = 16;
float py = 16;
canvas.save();
canvas.scale(sx, sy, px, py);
canvas.drawBitmap(bitmap, 0, 0, null);
canvas.restore();
}
}