EVE系列芯片有个特别的功能,矩阵计算,这是构成图形处理学的基本公式,熟悉它就可以实现不少特殊的效果。
矩阵的公式如下:
,其中A-F对应EVE芯片的寄存器BITMAP_TRANSFORM_A~ BITMAP_TRANSFORM_F。
矩阵计算公式为:
即:
X’ = X * A + Y * B + C
Y’ = X * D + Y * E + F
默认的矩阵为:
即X’ = X,Y’ = Y
还需要了解什么是齐次坐标和变换通式。齐次坐标是用一个n+1维向量表示一个n维向量的方法。二维点[x y]用[X Y H]表示,H可以是任意值,正常化齐次坐标H为1。变换通式T:
EVE芯片不支持G, H, I这3个参数(G, H透视变换,实现3D显示重要的因子),所以这3个参数的值为:0, 0, 1,即FT8xx的变换通式T为:
计算公式为:
EVE芯片用整数来表示A - F, 256表示1.0,所以0.5即为数字128,2为数字512,以此类推。下面的公式里都会用原始数字表示,而代码里面则会变成原始数字乘以256。
旋转,放大缩小功能都是基于矩阵计算实现的,也就是说也可以直接运算结果实现这些基本功能。
1. 比例变换
将图形放大或缩小的变换方法。
,其中A表示X方向上的缩放大小,E表示Y方向。CMD_SCALE就是这部分的实现。
1.0表示原图大小,小于1.0表示缩小,大于1.0表示放大。比如0.5表示缩小到原来的一半。
2. 旋转
,CMD_ROTATE是这部分的实现。
sin和cos的取值范围为[0…1], 表示角度,为正时逆时针旋转,为负时正时针旋转。默认的旋转点为左上角。
3. 平移
,CMD_TRANSLATE是这部分的实现。
取值范围-8388606~8388607,即平移像素点x256。正数++是从右向左移动,即:
4. 水平错切变换
水平错切变换的效果就是让所有点的x坐标保持不变,而对应的y坐标则按比例发生平移,且平移的大小和该点到x轴的垂直距离成正比。
假定一个点经过错切变换后得到
,对于水平错切而言,应该有如下关系:
用矩阵表示就是:
显示的效果是:
ftWrDispCmd(BITMAP_TRANSFORM_B(100));
ftWrDispCmd(BITMAP_TRANSFORM_C(-12 * 256));
ftWrDispCmd(VERTEX2F((LCD_WIDTH / 2 - 30) * 16, (LCD_HEIGHT / 2 - 30) * 16));
BITMAP_TRANSFORM_B写入的参数是100,即100/256,数字越小,斜率越小,更改BITMAP_TRANSFORM_C的目的是改变X轴的起始地址。实际显示效果如下图:
注意:图片有被切掉的原因还是因为handle中BITMAP_SIZE部分的大小定义不匹配导致。
5. 垂直错切变换
同理,垂直错切变换的效果就是让所有点的y坐标保持不变,而对应的x坐标则按比例发生平移,且平移的大小和该点到y轴的垂直距离成正比。
它的参数是:
ftWrDispCmd(BITMAP_TRANSFORM_D(100));
ftWrDispCmd(BITMAP_TRANSFORM_F(-12 * 256));
ftWrDispCmd(VERTEX2F((LCD_WIDTH / 2 - 30) * 16, (LCD_HEIGHT / 2 - 30) * 16));
实际显示效果如下:
6. 对称变化
a) X轴的对称变换
测试代码:
ftWrDispCmd(BITMAP_TRANSFORM_A(256));
ftWrDispCmd(BITMAP_TRANSFORM_B(0));
ftWrDispCmd(BITMAP_TRANSFORM_C(0));
ftWrDispCmd(BITMAP_TRANSFORM_D(0));
ftWrDispCmd(BITMAP_TRANSFORM_E((int16_t)-256));
ftWrDispCmd(BITMAP_TRANSFORM_F(60 * 256));//偏移图片高度
显示结果:
b) Y轴的对称变换
测试代码:
ftWrDispCmd(BITMAP_TRANSFORM_A((int16_t)-256));
ftWrDispCmd(BITMAP_TRANSFORM_B(0));
ftWrDispCmd(BITMAP_TRANSFORM_C(60*256));
ftWrDispCmd(BITMAP_TRANSFORM_D(0));
ftWrDispCmd(BITMAP_TRANSFORM_E((int16_t)256));
ftWrDispCmd(BITMAP_TRANSFORM_F(0));
显示结果如下:
c. 45度平分线的对称变换
测试代码:
ftWrDispCmd(BITMAP_TRANSFORM_A(0));
ftWrDispCmd(BITMAP_TRANSFORM_B((int16_t)256));
ftWrDispCmd(BITMAP_TRANSFORM_C(0 * 256));
ftWrDispCmd(BITMAP_TRANSFORM_D((int16_t)256));
ftWrDispCmd(BITMAP_TRANSFORM_E(0));
ftWrDispCmd(BITMAP_TRANSFORM_F(0 * 256));
显示结果:
d. -45度平分线的对称变换
测试代码:
ftWrDispCmd(BITMAP_TRANSFORM_A(0));
ftWrDispCmd(BITMAP_TRANSFORM_B((int16_t)-256));
ftWrDispCmd(BITMAP_TRANSFORM_C(60 * 256));
ftWrDispCmd(BITMAP_TRANSFORM_D((int16_t)-256));
ftWrDispCmd(BITMAP_TRANSFORM_E(0));
ftWrDispCmd(BITMAP_TRANSFORM_F(60 * 256));
显示结果:
e. 坐标原点的对称变换
测试代码:
ftWrDispCmd(BITMAP_TRANSFORM_A((int16_t)-256));
ftWrDispCmd(BITMAP_TRANSFORM_B(0));
ftWrDispCmd(BITMAP_TRANSFORM_C(60 * 256));
ftWrDispCmd(BITMAP_TRANSFORM_D(0));
ftWrDispCmd(BITMAP_TRANSFORM_E((int16_t)-256));
ftWrDispCmd(BITMAP_TRANSFORM_F(60 * 256));
显示结果:
二维组合变换
由多个基本变换的连续实施而成的复杂变换,又称基本变换的级连。数学上就是多个矩阵的乘法,这里就说明了为什么需要用到齐次坐标(两个3x3的矩阵相乘得到的还是3x3的矩阵)。
最常用的是居中旋转的例子,如果用CMD的方式,即:
CMD_TRANSLATE
CMD_ROTATE
CMD_TRANSLATE
那如果直接采用写矩阵的方式,以上面的图片为例:
平移
旋转:
平移
最终的计算结果:
所有参数都乘以256即得到矩阵:
测试代码:
ftWrDispCmd(BITMAP_TRANSFORM_A((int16_t)181));
ftWrDispCmd(BITMAP_TRANSFORM_B((int16_t)-181));
ftWrDispCmd(BITMAP_TRANSFORM_C(30 * 256));
ftWrDispCmd(BITMAP_TRANSFORM_D((int16_t)181));
ftWrDispCmd(BITMAP_TRANSFORM_E((int16_t)181));
ftWrDispCmd(BITMAP_TRANSFORM_F(-12 * 256));
显示结果如下: