对于图像的色彩处理,Android系统提供了ColorMatrix颜色矩阵来帮助我们进行图像处理。而对于图像的图形变化,Android系统也是通过来进行处理的,每个像素点都表达了其坐标的X、Y信息。Android的图形变换矩阵是一个3x3的矩阵,如图(1)所示。
当使用变换矩阵去处理每一个像素点的时候,与颜色矩阵的矩阵乘法一样,计算公式如下所示。
X1 = a * X + b * Y + c
Y1 = d * X + e * Y + f
l = g * X + h * Y + i
通常情况下,会让g=h=0,i=1,这是使 l = g * x + h *y + i恒成立。因此,只需要关注上面几个参数就可以了。
与色彩变换矩阵的初始矩阵一样,图像变换矩阵也有一个初始矩阵。很明显,就是对直角元素a、e、i我1,其他元素我0的矩阵,如图(2)所示。
图像的变化处理通常包含以下四类基本变化
● Translate——平移变换
● Rotate——选择变换
● Scale——缩放变换
● Skew——错切变换
▶ 平移变换
平移变换的坐标值变换过程如图(3)所示,即将每个像素点都进行平移变换。
当从p(X0,Y0)平移到p(X,Y),坐标值发送了如下所示的变换
X = X0 + △X
Y = Y0 + △Y
如果写成矩阵形式就是如图(4)所示。
通过技计算可发现如下等式。
X = X0 + △X
Y = Y0 + △Y
这也就是前面所说的实现平移过程的平移公式,图(4)所示矩阵也就是平移变换矩阵。
▶ 旋转变换
选择变换即指一个点围绕一个旋转中心旋转到一个新的点,如图(5)所示。
当从p(x0,y0),以坐标原点为旋转中心旋转到p(x ,y)点时,可以将点的坐标都表达成OP与X轴正方向夹角的函数表达式,如下所示。
x0 = r cosα
y0 = r sinα
x = r cos(α + θ)= r cosα cosθ - r sinα sinθ = x0cosθ - y0sinθ
y = r sin(α + θ)= r sinα cosθ - r cosα sinθ = x0cosθ + y0sinθ
如果写错矩阵形式就是如图(6)所示。
通过计算,可以还原以上公式,图(6)所示矩阵也及时旋转变换矩阵。
前面是以坐标原点为旋转中心的旋转变换,如果以任意点O为旋转中心来进行旋转变换,通常需要以下三个步骤。
● 将坐标原点平移到O点。
● 使用前面说的以坐标原点为中心的旋转方法进行旋转变换。
● 将坐标原点还原。
通过上面三个步骤,实现了任意点为旋转中心的旋转变换。
▶ 缩放变换
一个像素点是不存在缩放概念的,但是由于图像是由很多个像素点组成的,如果将每个点的坐标都进行相同比例的缩放,最终就会形成整个图像缩放的效果,缩放效果的计算公式如下。
x = K1 * x0
y = K2 * y0
如果写成矩阵形式,就如图(7)所示。
通过计算,就可以还原以上等式,因此图(7)所示矩阵即为缩放变换矩阵。
▶ 错切变换
错切变换(skew)在数学上又称为Shear mapping(可译为“剪切变换”)或者Transvection(缩并),它是一种比较特殊的线性变换。错切变换的效果就是让所有点的X坐标(或者y坐标)保持不变,而对应的Y坐标(或者X坐标)则按比例发生平移,且平移的大小和该点到X轴(或Y轴)的垂直距离成正比。
错切变换通常包好两种——水平错切和垂直错切,分别如图(8)、图(9)所示。
错切变换的计算公式如下所示。
x = x0 + K1 * Y0
y = K2 * x0 * y0
如果写成矩阵形式,就如果(10)所示。
通过计算,就可以还原到以上等式。因此图(10)所示矩阵即为错切变换矩阵。
有上面的分析可以发现,这个3*3的矩阵与颜色变换矩阵一样,每个位置的元素所表示的功能是有规律的,总结规律如图(11)所示。
可以发现,A、B、C、D、E、F、这六个矩阵元素分别对应一下变换。
● A和E控制Scale——缩放变换
● B和D控制Skew——错切变换
● C和F控制Trans——平移变换
● A、B、C、D共同控制Rotate——选择变换
在了解了矩阵变换规律后,通过类似色彩矩阵中模拟矩阵的例子来模拟一下变形矩阵。整个代码与模拟颜色矩阵所使用的代码基本一致。在图形变换矩阵中,同样通过一个一维数组来模拟矩阵,并通过setValues()方法将一个一维数组转换为图形变换矩阵,代码如下所示。
private float[] mImageMatrix = new float[9];
Matrix matrix = new Matrix();
matrix.setValues(mImageMatrix );
当获得了变换矩阵后,就可以通过以下代码将一个图像一这个变换矩阵的形式绘制出来。
canvas.drawBitmap(bitmap,matrix,null);
运行时程序后,初始界面如图(12)所示。
(12)模拟变形矩阵
当然,与色彩矩阵一样,Android系统同样提供了一些API来简化矩阵的运算。我们不必每次都去设置矩阵的每一个元素值。Android中使用Matri类来封装矩阵,并提供以下几个操作方法来实现上面的四种变换方式。
● matri X .setRotate()——选择变换
● matri X .setTranslate()——平移变换
● matri X .setScale()——缩放变换
● matri X .setSkew()——错切变换
● pre()和post()——提供矩阵的前乘后乘运算
Matri类的set方法会重置矩阵所有值,而post和pre方法不会,这两个方法常用来实现矩阵的混合作用。不过要注意的是,矩阵运算不能满足变换率,所以矩阵乘法的前乘和后乘是两种不同的运算方式。举个例子来说,比如需要实现以下效果。
● 先平移到(300,100)
● 在选择45度
● 最后平移到(200,200)
如果使用后乘算法,表示当当前矩阵上参数代表的矩阵,带入如下所示。
matrix.setRotate(45);
matrix.postTranslate(200,200);
如果使用前乘运算,表示参数代表的矩阵乘上当前矩阵,代码如下所示。
matrix.setTranslate(200,200);
matrix.preRotate(45);