【问题标题】:Android image transformation with matrix, translate touch coordinates backAndroid图像转换矩阵,将触摸坐标翻译回来
【发布时间】:2012-12-12 03:14:00
【问题描述】:

我正在为 android 构建一个“导航类型”应用程序。

对于导航部分,我正在构建一个 Activity,用户可以在其中使用触摸事件移动和缩放地图(这是一个位图),还可以使用指南针围绕屏幕中心旋转地图。

我使用 Matrix 来缩放、转置和旋转图像,然后将其绘制到画布上。

以下是加载视图时调用的代码,以使图像在屏幕中居中:

    image = new Matrix();
    image.setScale(zoom, zoom);

    image_center = new PointF(bmp.getWidth() / 2, bmp.getHeight() / 2);

    float centerScaledWidth = image_center.x * zoom;
    float centerScaledHeigth = image_center.y * zoom;

    image.postTranslate(
            screen_center.x -  centerScaledWidth, 
            screen_center.y - centerScaledHeigth);

图片的旋转是使用postRotate方法进行的。

然后在onDraw()方法中我只调用

  canvas.drawBitmap(bmp, image, drawPaint);

问题是,当用户触摸屏幕时,我想在图像上触摸点,但显然我无法获得正确的位置。 我试图反转 image 矩阵并转换触摸点,但它不起作用。

有人知道如何翻译点坐标吗?

编辑

我正在使用此代码进行翻译。 dxdy 是从 onTouch 监听器获取的翻译值。 *new_center* 是一个浮点值数组,格式为 {x0, y0, x1, y1...}

  Matrix translated = new Matrix();
  Matrix inverted = new Matrix();

  translated.set(image);
  translated.postTranslate(dx, dy);

  translated.invert(inverted);
  inverted.mapPoints(new_center);
  translated.mapPoints(new_center);

  Log.i("new_center", new_center[0]+" "+new_center[1]);

其实我试过用 as *new_center = {0,0}*:

仅应用 translated 矩阵,我得到了 bmp 的 (0,0) 点和屏幕的 (0,0) 点之间的距离,但似乎不是考虑到轮换。

inverted 矩阵应用于我得到这些结果的点,以各种可能的方式移动图像。

  12-26 13:26:08.481: I/new_center(11537): 1.9073486E-6 -1.4901161E-7
  12-26 13:26:08.581: I/new_center(11537): 0.0 -3.874302E-7
  12-26 13:26:08.631: I/new_center(11537): 1.9073486E-6 1.2516975E-6
  12-26 13:26:08.781: I/new_center(11537): -1.9073486E-6 -5.364418E-7
  12-26 13:26:08.951: I/new_center(11537): 0.0 2.682209E-7
  12-26 13:26:09.093: I/new_center(11537): 0.0 7.003546E-7

相反,我正在查看图像上转换的坐标。

我的思路对吗?

【问题讨论】:

  • 向我们展示一些用于点取消翻译的代码、一些运行时值和一些预期结果

标签: android matrix image-rotation


【解决方案1】:

好的,我明白了。

首先我将旋转与图像的平移和缩放分开。

因为我创建了一个自定义 ImageView,所以这很简单。我将旋转应用于 ImageView 的 canvas,并将其他转换应用于图像矩阵。

我通过一个全局矩阵变量来跟踪画布的矩阵。

一些代码:

要为相应的 onTouch 事件设置正确的移动,首先我“旋转回来”从 onTouch 传递的点(start 和 stop 个点)使用 canvas

的矩阵的逆矩阵

然后我计算 x 和 y 之间的差异,并将其应用于 image 矩阵。

  float[] movement = {start.x, start.y, stop.x, stop.y};

  Matrix c_t = new Matrix();
  canvas.invert(c_t);
  c_t.mapPoints(movement);

  float dx = movement[2] - movement[0];
  float dy = movement[3] - movement[1];

  image.postTranslate(dx, dy);

如果您想检查图像移动是否不超过其大小,请在 image.postTranslate(dx, dy); 之前输入以下代码:

  float[] new_center = {screen_center.x, screen_center.y};

  Matrix copy = new Matrix();
  copy.set(image);
  copy.postTranslate(dx, dy);

  Matrix translated = new Matrix();
  copy.invert(translated);
  translated.mapPoints(new_center);

  if ((new_center[0] > 0) && (new_center[0] < bmp.getWidth()) && 
    (new_center[1] > 0) && (new_center[1] < bmp.getHeight())) {

        // you can remove the image.postTranslate and copy the "copy" matrix instead
        image.set(copy);
  ...

需要注意的是:

A) 图像的中心旋转是屏幕的中心,所以在画布旋转过程中不会改变坐标

B) 可以使用屏幕中心的坐标来获取图像的旋转中心。

使用此方法,您还可以将每个触摸事件转换为图像坐标。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    • 2022-01-25
    相关资源
    最近更新 更多