在二维的平面上,对图片进行处理时,主要可以分为平移,缩放和旋转,如果是直接对图片坐标进行处理显然是很复杂的,这是我们就可以用到矩阵,在矩阵中有单位矩阵这么个概念,我的理解就是这是一个标准的坐标系,其他的变换都是基于这个坐标来的,可能理解有出入,不过这我能想到跟实际相关联的。
下面先来看看2D图形变换中的
平移:
我们先假设平面上有一点(x,y),这个点向x,y方向上平移了dx,dy,变换后的坐标(X,Y)=(x+dx,y+dy),用矩阵表示:
1 0 dx x X 1 0 dx [ 0 1 dy ][y] = [Y] 我们可以发现平移变换矩阵是: [0 1 dy] 0 0 1 1 1 0 0 1
缩放:
同样的假设平面上一点坐标(x,y),在x,y方向上缩放了sx,sy,变换后的坐标(X,Y)=(sx*x,sy*y),用矩阵表示:
sx 0 0 x X sx 0 0 [ 0 sy 0 ][y] = [Y] 我们可以发现缩放变换矩阵是: [0 sy 0] 0 0 1 1 1 0 0 1
旋转:
旋转稍微复杂一点,不过先同样假设一点坐标(x,y)到原点的坐标是R,到x轴的坐标是β,以原点为圆心,旋转θ度,那么变换后的坐标是:x=R*cosβ,y=R*sinβ,X=Rcos(β+θ),Y=sin(β+θ),对X,Y进行合角公式变换:
X=R*cosβ*cosθ-R*sinβ*sinθ=x*cosθ-y*sinθ
Y=R*sinβ*cosθ+R*cosβ*sinθ=y*cosθ+x*sinθ,用矩阵表示:
cosθ -sinθ 0 x X cosθ -sinθ 0 [ sinθ cosθ 0 ][y] = [Y] 我们可以发现旋转变换矩阵是: [sinθ cosθ 0] 0 0 1 1 1 0 0 1
根据我自己的理解,矩阵就是坐标系,单位矩阵就是标准坐标系,对于二维平面,可以用3x3的单位矩阵表示。对于矩阵的理解(限于二维平面):第一行我理解是x的变换,第二行理解为y的变换,第三行就是常数了,正好与上面的对应上。对于矩阵的变换其实就是对坐标系的变换,不知道是不是可以这样去理解。
![](/qrcode.jpg)
接下来看看Android中Matrix是如何变换的:先看Android是如何描述这个类的:
* The Matrix class holds a 3x3 matrix for transforming coordinates.
解释:矩阵类用一个3x3的矩阵对坐标进行转换。(方法基本都是native的,就没必要看源码了)
来看看Matrix是如何作用的:
private void initMatrix(){ float[] arr = {1,0,0, 0,1,0, 0,0,1}; StringBuilder builder = new StringBuilder(); Matrix matrix = new Matrix(); matrix.setValues(arr); matrix.setTranslate(2,2); // matrix.setScale(2,2); // matrix.setRotate((float) Math.toDegrees(Math.PI/3)); matrix.getValues(arr); builder.append("{"); for (float v : arr) { builder.append(v+","); } builder.append("}"); Log.d(TAG, "initMatrix: arr = "+builder); }
输出结果(三次分别输出,与上面设置的方法对应):
initMatrix: arr = {1.0,0.0,2.0, 0.0,1.0,2.0, 0.0,0.0,1.0,} initMatrix: arr = {2.0,0.0,0.0, 0.0,2.0,0.0, 0.0,0.0,1.0,} initMatrix: arr = {0.49999997,-0.86602545,0.0, 0.86602545,0.49999997, 0.0, 0.0, 0.0, 1.0,}
转换后是不是就和上面是一样了,可以好好体会下。这个还是比较抽象的,不过理解了就比较简单了。
上面我们得到了一个转换矩阵,现在我们就用这个矩阵来转换一个矩形,看看矩形有什么变化:
private void initMatrix(){ float[] arr = {1,0,0, 0,1,0, 0,0,1}; StringBuilder builder = new StringBuilder(); Matrix matrix = new Matrix(); matrix.setValues(arr); // matrix.setTranslate(2,2); matrix.setScale(2,2); // matrix.setRotate((float) Math.toDegrees(Math.PI/3)); RectF rect = new RectF(); rect.set(0,0,6,6); matrix.mapRect(rect); Log.d(TAG, "initMatrix: rect = "+rect.left+" "+rect.top+" "+rect.right+" "+rect.bottom); matrix.getValues(arr); builder.append("{"); for (float v : arr) { builder.append(v+","); } builder.append("}"); Log.d(TAG, "initMatrix: arr = "+builder.toString()); }
输出结果(三次分别输出,与上面设置的方法对应),主要是看矩形输出结果:
initMatrix: rect = 2.0 2.0 8.0 8.0 initMatrix: rect = 0.0 0.0 12.0 12.0 initMatrix: rect = -5.1961527 0.0 2.9999998 8.196153如果这个矩形是一个图片,那这样变换就是图片的变换了。