Android中关于矩阵(Matrix)前乘后乘的一些认识

在上一篇文章中,我们讲到,在Android中,scale(缩放),rotation(旋转)和 translation(平移)都是以矩阵(Matrix)的形式定义的,实际上在图形学中,这些平面图形的变换都是以矩阵的形式存在的。先来回顾一下,下面,左中右分别scale(缩放),rotation(旋转)和 translation(平移)在Android中的矩阵表示:


如果只是单纯的应用某一个变换,我们都知道直接用矩阵去乘上对应的点就可以了。但是对于缩放和旋转来说,它们的轴点是基于原点(0,0)的,如下图,我们将它缩小1倍,代码如下:

	public void onDraw(Canvas canvas){			
		canvas.drawBitmap(bitmap, 0, 0, null);		
		matrix.reset();		
		matrix.postScale(0.5f, 0.5f);
		canvas.drawBitmap(bitmap, matrix, null);			
	}	

则其效果如右图所示:

                                      

那么我们如果想让它基于图片中心缩放,应该该怎么办?我们上一篇文章也说过了,要用到组合变换,

1)先将图片由中心平移到原点,这是应用变换 T

2)对图应用缩放变换 S 

3)再将图片平移回到中心,应用变换 -T

下面给出它们的组合变换的公式:


在Android中的代码如下:

	public void onDraw(Canvas canvas){			
		canvas.drawBitmap(bitmap, 0, 0, null);		
		matrix.reset();		
		matrix.postScale(0.5f, 0.5f);
		matrix.preTranslate(-pivotX, -pivotY);
		matrix.postTranslate(pivotX, pivotY);
		canvas.drawBitmap(bitmap, matrix, null);			
	}	
我们看一下加上平移之后的效果图(其中pivotX 和 pivotY 是图片的中心):


我们看到代码中,我们在进行了scale之后呢,还给图片设置了下面两个平移的变换:

		matrix.preTranslate(-pivotX, -pivotY);
		matrix.postTranslate(pivotX, pivotY);
什么是PreTranlsate呢,什么又是postTranslate呢?我们先来看一下Android中的定义吧。

preTranslate:

    /**
     * Preconcats the matrix with the specified translation.
     * M' = M * T(dx, dy)
     */
    public boolean preTranslate(float dx, float dy) {
        return native_preTranslate(native_instance, dx, dy);
    }

postTranslate:

    /**
     * Postconcats the matrix with the specified translation.
     * M' = T(dx, dy) * M
     */
    public boolean postTranslate(float dx, float dy) {
        return native_postTranslate(native_instance, dx, dy);
    }

我们可以看到,pre是拿当前的矩阵乘以T,而post是拿T来乘以当前的矩阵,(矩阵的乘法是不满足交换率的,所以这两种乘法的结果是不一样的)

在图形学中,矩阵M右乘A,表示的是  A * M,而矩阵 M 左乘 A,则表示的是 M * A,可以形象地理解为右乘就是从右边乘进来,左乘就是从左边乘进来。

一比较,我们可以看出,pre其实执行的就是右乘的操作,而post执行的就是左乘的操作。

这是因为,在图像处理中,越靠近右边的矩阵越先执行,所以pre(也就是先的意思)所设置的矩阵T(Scale,Rotation也是一样的)就会先于其一开始设置的Scale执行,而post(后的意思)的因为是左乘,所以它会放在最左边,那么就会最后执行。

所以,上面三步的意思其实就是:

1)在当前的矩阵左边加一个Scale的操作,因为之前没有其的操作(reset了),那么当前的矩阵其实就只是 S 了。

2)在当前的矩阵(S)执行,先执行一个平移到原点的操作(preTranslate),其实也就是进行右乘(S * T)。

3)在当前的矩阵(S * T)执行,再执行一个从原点平移到中心点的操作(postTranslate),也就是进行一个左乘(-T * S * T)。

这就是Android中矩阵(Matrix)前乘和后乘所对应的图形学中矩阵中右乘和左乘的操作了。

不知道理解有没有错误,如有错误 ,希望有朋友能够指正,谢谢大家,另祝大家新年快乐!

下面是上一篇文章,关于图形学中矩阵和图形变换的关系,有兴趣的朋友也可以读一下:

2D平面中关于矩阵(Matrix)跟图形变换的讲解

阅读更多

没有更多推荐了,返回首页