android开发 交换方向,Android开发之图像处理那点事——变换

本文深入探讨了Android中图像变换的四种基本操作——平移、缩放、旋转和错切,通过3x3的变换矩阵进行阐述。介绍了Matrix类在Android系统中的应用,以及如何使用Matrix进行图像变换,包括平移、缩放、旋转和平切的代码示例,强调了变换顺序对结果的影响,并提供了简单的Demo演示。
摘要由CSDN通过智能技术生成

继上一篇《Android开发之图像处理那点事——滤镜》,这次我们来讲一下图片的变换操作,本篇主要是介绍常见的图像变换4种操作(平移、缩放、旋转、错切)

对于图像的颜色处理,Andriod系统给我们提供一个很方便的颜色矩阵类ColorMatrix,同样的,Android系统也给图像的变换处理提供了矩阵类Matrix,相比颜色矩阵的4 * 5,变换矩阵来得更加简单,它是由一个3 * 3的数字矩阵组成,我们来了解一下变换原理。

变换矩阵

在上一篇文章中,我们讲到像素点的颜色是由RGBA1组成的,分别代表红、绿、蓝、透明度各通道值还有颜色偏移量,在变换矩阵中也是类似的,像素点的位置是由矩阵C(X、Y、L)组成的,分别代表像素点在X、Y轴的位置还有偏移量。

e944ddbfabd0

变换矩阵

根据矩阵的乘法,我们可以得出下面的等式:

X1 = a * X + b * Y + c

Y1 = d * X + e * Y + f

L = g * X + h * Y + i

当a=1,b和c=0,可以知道X1=1X+0+0=1X,

当e=1,d和f=0,可以知道Y1=0+1Y+0=1Y

当i=1,g和h=0,可以知道1=0+0+1=1

由此我们可以得到变换矩阵的单位矩阵:

e944ddbfabd0

单位矩阵

在日常开发中,我们涉及到的图像变换大致有平移、缩放、旋转、错切(很少),这些操作就是对这3 * 3的矩阵做数值上的调整,和上一篇讲颜色矩阵变化是类似的,不清楚的朋友,具体可以参考上一篇文章的讲解,下面我们快速过一下流程。

平移操作

像素点的平移其实就是对像素点的x和y坐标进行移动,如下图,从点p1移动到点p,假设p1(x1,y1)分别平移了x0和y0距离得到p(x,y),

e944ddbfabd0

平移操作

得到的公式就是:

x = x1 + x0

y = y1 + y0

矩阵所表现出来的形式:

e944ddbfabd0

平移操作

缩放操作

对于单个像素点是不存在缩放操作的,但如果是一系列的像素点,我们就可以根据x和y轴做一定比例的缩放,假设缩放比例为K1,得到的公式是:

x = K1 * x0

y = k1 * y0

矩阵所表现出来的形式:

e944ddbfabd0

缩放操作

旋转操作

像素点的旋转是围绕一个点旋转一定的角度得到新的像素点位置,为了便于理解,这里带上一张图:

e944ddbfabd0

旋转操作

如上图以原点为中心旋转,点(x0,y0)旋转了β°角度到了p(x,y),假设斜边为r,根据三角函数我们可以知道:

x0 = r * cosα

y0 = r * sinα

那么x和y就是x0和y0旋转了α角度后,再旋转了β角度,根据三角函数可以推出:

x = r * cos(α + β) = r * cosα * cosβ - r * sinα * sinβ = x0 * cosβ - y0 * sinβ

y = r * sin(α + β) = r * sinα * cosβ + r * cosα * sinβ = y0 * cosβ + x0 * sinβ

将上面的式子代入,根据推导公式,我们可以知道矩阵的表现形式为:

e944ddbfabd0

旋转操作

错切操作

这个平时用的比较少,大概了解一下就可以,错切分为水平错切和垂直错切。

水平错切效果就是让所有像素点的Y轴坐标不变,X轴坐标按照比例进行平移,且平移的大小与该点到Y轴的距离成成正比,计算公式为:

x = x0 + k1 * y0

y = y0

矩阵变现形式为:

e944ddbfabd0

水平错切

垂直错切让所有像素点的X轴坐标不变,Y轴坐标按照比例进行平移,且平移的大小与该点到X轴的距离成成正比,计算公式为:

x = x0

y = y0+ k2 * x0

矩阵变现形式为:

e944ddbfabd0

垂直错切

两个方向都错切,公式为:

x = x0 + k1 * y0

y = k2 * x0 * y0

e944ddbfabd0

水平/垂直错切

根据以上的矩阵表现方式,我们可以推出图像的变换规律为:

e944ddbfabd0

矩阵变换规律

Matrix

了解了各种变换原理后,我们来看下Matrix类,这是Android系统给我们提供的图像变换矩阵类,打开源码,我们可以看到这9个常量:

public static final int MSCALE_X = 0; //!< use with getValues/setValues

public static final int MSKEW_X = 1; //!< use with getValues/setValues

public static final int MTRANS_X = 2; //!< use with getValues/setValues

public static final int MSKEW_Y = 3; //!< use with getValues/setValues

public static final int MSCALE_Y = 4; //!< use with getValues/setValues

public static final int MTRANS_Y = 5; //!< use with getValues/setValues

public static final int MPERSP_0 = 6; //!< use with getValues/setValues

public static final int MPERSP_1 = 7; //!< use with getValues/setValues

public static final int MPERSP_2 = 8; //!< use with getValues/setValues

我们把它按3 * 3的矩阵形式排开,可以得到:

e944ddbfabd0

矩阵

对比下刚才上面我们推导的矩阵表现形式,怎么样,是不是更有感觉了,我们可以得到如下信息:

MTRANS_X、MTRANS_Y 决定了平移(Translate)

MSCALE_X、MSCALE_Y 决定了缩放( Scale)

MSCALE_X、MSKEW_X、MSCALE_Y、MSKEW_Y 决定了旋转( Rotate)

MSKEW_X、MSKEW_Y 决定了错切( Skew)

其实图像的变换操作无非就是对这个3 * 3的矩阵进行值的变化,而Matrix类只是帮我们封装好了这些操作,让我们无需关心细节,更加专注业务的实现,我们可以在Matrix中找到各操作对应的调用方法:

e944ddbfabd0

矩阵的操作方法

简单的看个小Demo:

e944ddbfabd0

上面分别对图像进行了平移、缩放、旋转、错切操作,贴一下核心代码:

Matrix matrix = new Matrix();

matrix.setTranslate(50, 50);//x,y坐标平移50像素

canvas.drawBitmap(mBitmap, matrix, null);

Matrix matrix = new Matrix();

matrix.setScale(2, 2);//x,y坐标放大原来2倍

canvas.drawBitmap(mBitmap, matrix, null);

Matrix matrix = new Matrix();

matrix.setRotate(20);//x,y坐标旋转20度

canvas.drawBitmap(mBitmap, matrix, null);

Matrix matrix = new Matrix();

matrix.setSkew(2, 2);//x,y坐标按比例错切平移2

canvas.drawBitmap(mBitmap, matrix, null);

当然这些操作也是可以组合起来的,Matrix里提供了一系列的postXXX,preXXX方法:

e944ddbfabd0

矩阵的操作方法

其实就是线性代数中矩阵的左乘和右乘,由于矩阵的乘法是不满足乘法交换律的,所以变换操作的执行顺序是对结果有影响的,继续来个小Demo:

e944ddbfabd0

先平移,再放大,再旋转

实现代码:

Matrix matrix = new Matrix();

matrix.setTranslate(200, 200);

matrix.postScale(2, 2);

matrix.postRotate(20);

canvas.drawBitmap(mBitmap, matrix, null);

e944ddbfabd0

先平移,再旋转,再放大

实现代码:

Matrix matrix = new Matrix();

matrix.setTranslate(200, 200);

matrix.preScale(2, 2);

matrix.preRotate(20);

canvas.drawBitmap(mBitmap, matrix, null);

简单粗暴可以这样理解:Matrix操作是一系列的任务存放在一个队列里,pre是把当前任务插入队列前,post是插入队列后,set则是清空队列所有任务,再入队。

这些看似很简单很基础的东西却恰恰是最重要的,它可以创造出很多东西,比如图片的自由手势缩放,微博上面的自定义贴纸,美图秀秀里的相框拼接等效果都离不开它。

源码下载:

这里附上源码地址(欢迎Star,欢迎Fork):BeautyImageDemo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值