首页 > 解决方案 > 使用 Android Canvas.drawBitmapMesh 会产生意想不到的位图转换

问题描述

使用Canvas.drawBitmapMesh(),我可以更改图像以模拟透视变化,但是图像的更改方式是出乎意料的。

原始图像 > 变换图像

原始图像>>>>> 一对一变换>>>>一个一个的网格

canvas.drawBitmapMesh(myBitmap, 1, 1, fourPoints, 0, null, 0, null);

匹配 myBitmap的int[] fourPoints尺寸,除了左上点向右移动和右上点向左移动。

POINT: 768.0, 0.0
POINT: 2304.0, 0.0
POINT: 0.0, 2304.0
POINT: 3072.0, 2304.0

请注意,上面的右图有一个意想不到的对角线“折叠”。这与我在下面生成的图像相反(不使用 Android Canvas drawBitmapMesh)。

预期转变:

预期的

我将上述预期结果称为“平滑线”转换。

增加网格

我尝试将用于转换的定义网格增加到 2×2 大小。它掩盖了问题,但“折叠”的问题仍然存在。

二乘二网格

使用二乘二网格

canvas.drawBitmapMesh(myBitmap, 2, 2, ninePoints, 0, null, 0, null);

与底部的int[] ninePointsmyBitmap 尺寸相匹配,但其余部分经过调整以创建梯形。

POINT: 768.0, 0.0
POINT: 1536.0, 0.0
POINT: 2304.0, 0.0
POINT: 384.0, 1152.0
POINT: 1536.0, 1152.0
POINT: 2688.0, 1152.0
POINT: 0.0, 2304.0
POINT: 1536.0, 2304.0
POINT: 3072.0, 2304.0

从编码的角度来看,不断增加网格的大小直到它接近“平滑线”的结果是没有问题的,但这似乎会浪费 CPU 处理。也许有一个技巧可以让这个函数做我所期望的而不是对角线“折叠”线?所以我想知道是否有一种方法可以拥有一个一个接一个的网格并获得可能更有效的“平滑线”。

标签: androidimage-processingbitmapandroid-canvasandroid-bitmap

解决方案


您必须为此使用透视矩阵。

初始化一个矩阵,将源点转换为目标点(应该是 4 个点):

Matrix m = new Matrix();
m.setPolyToPoly(srcPoints,0,dstPoints,0,4)

其中源点和目标点是点的浮点数组,表示为 {x1,y1,x2,y2,x3,y3,x4,y4}

然后用

canvas.drawBitmapMesh(myBitmap, m, null);

null 可以替换为可以定义为使用抗锯齿过滤器的 Paint 对象。


推荐阅读