看上图,这里表示了屏幕的坐标系,其中的x,y轴是大家所熟知的,但是其实,一个物体他是存在于一个三维空间的,所以必然会有z轴。我们的屏幕,就像是一个窗口,透过它,我们看到了屏幕后面的世界,那里面有各种物体,我们看到的是映射在x,y平面上的一个投射图像。屏幕就像是一个镜头一样,将里面的物体映射到x,y平面上,成为一个二维的图像。那么如果,我们把屏幕这个镜头沿着z轴,拉远或者拉进,那么图像会有什么变化呢,肯定会变小或者变大。就好比坐在飞机上透过窗口看地面的汽车,和在地面上看到的大小是不同的。
结论就是,在屏幕上显示的像素,不仅仅有x,y坐标,其实还有z轴的影响。所以这里对应的像素描述由一个3行一列的矩阵来表示:
x,y分别代表x,y轴上的坐标,而1代表屏幕在z轴上的坐标为默认的。如果将1变大,那么屏幕会拉远, 图形会变小
图像的平移原理:
假设一个点a坐标为(x0,y0)经过水平平移了b距离后变成了点c坐标为(x1,y1)。
因为是水平平移,所以a和b的y坐标的大小是相同的。但是a和b x的坐标点是不同的。
所以有如下公式:
X1 = x0 + b;
Y1 = y0;
怎么把它转换成矩阵呢?
高等数学中有个叫系数矩阵的东西。如下:
系数矩阵:
方程组可以写成矩阵的形式,由未知数的系数构成的矩阵就叫系数矩阵.比如上面的的方
程组的系数矩阵就是:x1 1 0 b x0
y1 = 0 1 0 * y0
1 0 0 1 1
教科书告诉你,计算规则是,第一个矩阵第一行的每个数字(2和1),各自乘以第二个矩阵第一列对应位置的数字(1和1),然后将乘积相加( 2 x 1 + 1 x 1),得到结果矩阵左上角的那个值3。
根据这个结果可知系数矩阵:
x1 = 1 * x0 + 0 * y0 + b * 1 = x0 + b;
y1 = 0 * x0 + 1 * y0 + 0 * 1 = y0;
图像旋转原理:
这里我们通过一个旋转变换来看看原理,其实一张图片围绕一个点旋转,也就是所有的点都围绕一个点旋转,所以只需要关注一个点的情况即可:
假定有一个点 ,相对坐标原点顺时针旋转后的情形,同时假定P点离坐标原点的距离为r,如下图:
那么就有:
换做矩阵运算就如下图: 最后把这个矩阵通过matrix.setValues的方法设置一下,然后通过canvas.drawBitmap(bmp, matrix, paint);就可以把 该旋转矩阵应用到bitmap上面了。 三角函数转换公式如下:sin(A+B)=sinAcosB+cosAsinB sin(A-B)=sinAcosB-cosAsinB cos(A+B)=cosAcosB-sinAsinB cos(A-B)=cosAcosB+sinAsinB
另外图像的复合变化:
设对给定的图像依次进行了基本变化F1、F2、F3…..、Fn,它们的变化矩阵分别为T1、T2、T3…..、Tn,图像复合变化的矩阵T可以表示为:T = TnTn-1…T1。
如果想要对图像进行先平移再旋转,只需要把他们两个矩阵相乘即可。
为什么相乘就可以达到先平移再旋转了?
论证一下:
x1 1 0 b x0
y1 = 0 1 0 * y0
1 0 0 1 1
是点(x0,y0)在x方向上平移b后的结果为点(x1,y1)。如果再进行旋转的角度为A,旋转后的点为(x2,y2),那么就有如下公式。
x2 x1 cosA -sinA 0
y2 = y1 * sinA cosA 0
1 1 0 0 1
又已知
x1 1 0 b x0
y1 = 0 1 0 * y0
1 0 0 1 1
所以可以得出
x2 1 0 b cosA -sinA 0 x0
y2 = 0 1 0 * sinA cosA 0 * y0
1 0 0 1 0 0 1 1
有关于变换的set方法都可以带来不同的效果,但是每个set都会把上个效果清除掉,例如依次调用了setSkew,setTranslate,那么最终只有setTranslate会起作用,那么如何才和将两种效果复合呢。Matrix给我们提供了很多方法。但是主要都是2类:
preXXXX:以pre开头,例如preTranslate postXXXX:以post开头,例如postScale
这里matrix前乘了一个scale矩阵,换算成数学式如下:
从上面可以看出,最终得出的matrix既包含了缩放信息也有平移信息。 后乘自然就是matrix在后面,而缩放矩阵在前面,由于矩阵前后乘并不等价,也就导致了他们的效果不同。我们来看看后乘的结果:
可以看到,结果跟上面不同,并且这也不是我们想要的结果,这里缩放没有更改,但是平移被减半了,换句话说,平移的距离也被缩放了。所以需要注意前后乘法的关系。