侧边栏壁纸
博主头像
Z同学博主等级

工作磨平激情前,坚持技术的热忱。 欢迎光临Z同学的技术小站。 分享最新的互联网知识。

  • 累计撰写 290 篇文章
  • 累计创建 57 个标签
  • 累计收到 98 条评论

Android Matrix 与Bitmap

Z同学
2020-09-18 / 0 评论 / 0 点赞 / 685 阅读 / 3,617 字
温馨提示:
本文最后更新于 2021-11-18,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

前言

通过Matrix 管理Bitmap 对象的旋转,缩放,位移,倾斜等基本操作逻辑。

主要探讨在自定义View 之中通过onDraw() 绘制Bitmap。

然后在重构onTouchEvent()事件, 对Bitmap对象进行 旋转,缩放,位移,倾斜操作。

正文

首先,我们要在onDraw之中 通过Matrix 控制,进行绘制Bitmap


Matrix bitmapMatrix = new Matrix();

onDraw(Canvas canvas){
canvas.drawBitmap(drawBitmap, bitmapMatrix, new Paint());
}

下面介绍Matrix 的关键方法:

我们通常使用的Matrix复合原理,而在函数上的名称方式就分别为:per(前乘),post(后乘),set(设置)。

set 相关的方法:

set 使用的不是矩阵乘法,而是直接覆盖掉原来的数值,所以,使用设置可能会导致之前的操作失效。

//控制Matrix进行位移。  直接将对象移动到指定的坐标点
setTranslate(float dx,float dy):

//控制Matrix进行倾斜,kx、ky为X、Y方向上的比例。
setSkew(float kx,float ky):
//控制Matrix以px、py为轴心进行倾斜,kx、ky为X、Y方向上的倾斜比例。
setSkew(float kx,float ky,float px,float py):

//控制Matrix进行depress角度的旋转,轴心为(0,0)。
setRotate(float degrees):
//控制Matrix进行depress角度的旋转,轴心为(px,py)。
setRotate(float degrees,float px,float py):

//设置Matrix进行缩放,sx、sy为X、Y方向上的缩放比例。 
setScale(float sx,float sy):
//设置Matrix以(px,py)为轴心进行缩放,sx、sy为X、Y方向上的缩放比例。
setScale(float sx,float sy,float px,float py):

pre 相关的方法:

pre 采用矩阵右乘算法,表示一个矩阵与一个特殊矩阵前乘后构造出的结果矩阵。

也就是说,采用该类方法进行的调整,会利用到之前操作的值进行计算。

//长和宽放大缩小的比例  ,x轴为宽,y轴为高
preScale(float sx, float sy) 
//长和宽放大缩小的比例 ,上一个是以中心点进行缩放,这个是以指定坐标点(px,py)为缩放中心进行缩放
preScale(float sx, float sy, float px, float py)
//旋转角度 角度范围360 ,绕指定坐标点进行旋转
preRotate(float degrees, float px, float py)
//旋转角度 角度360 ,绕中心原点旋转
preRotate(float degrees)

// 移动到 指定坐标点
preTranslate(float dx, float dy)

//Matrix进行倾斜,kx、ky为X、Y方向上的比例 ,px 和py 设置倾斜轴心
preSkew(float kx, float ky, float px, float py)
preSkew(float kx, float ky)

post相关的方法:

post采用矩阵左乘算法,表示一个矩阵与一个特殊矩阵后乘后构造出的结果矩阵。
也就是说,采用该类方法进行的调整,会利用到之前操作的值进行计算。

//长和宽放大缩小的比例  ,x轴为宽,y轴为高; 这个值是一个比值 例如:sx=0.5 ;sy = 1: 代表宽度为原先的0.5倍,高度不变,进行缩放
postScale(float sx, float sy) 
//长和宽放大缩小的比例 ,上一个是以中心点进行缩放,这个是以指定坐标点(px,py)为缩放中心进行缩放
postScale(float sx, float sy, float px, float py)


//旋转角度 角度范围360 ,绕指定坐标点进行旋转
postRotate(float degrees, float px, float py)
//旋转角度 角度360 ,绕中心原点旋转
postRotate(float degrees)

// 移动到 指定坐标点
postTranslate(float dx, float dy)

//Matrix进行倾斜,kx、ky为X、Y方向上的比例 ,px 和py 设置倾斜轴心
postSkew(float kx, float ky, float px, float py)
postSkew(float kx, float ky)

pre和post 不是指执行方法按照顺序进行的执行,而是指采用不同的矩阵计算模式而已。两者在有些情况下,执行得到的结果是类似的。

我们会发现,post 和per 到底有和区别? 函数起到的功能也是一样。

用缩放 进行简单举例

post :M' = S(sx, sy) * M
pre  : M' = M * S(sx, sy)

在数学上,两者的区别就在于一个是前乘,一个是后乘。

但是通常我们简单应用时,采用post 就能满足我们大部分的需求了。

至于为什么会有post和pre? 那是因为矩阵算法不满足交换律,也就是说,前乘和后乘的结果有时是不一样的。

所以,pre和post 都会利用到上一步操作的结果矩阵,进行当前运算。而set直接将矩阵参数改为当前矩阵值。

然后你就整合形变参数进行修改就可以了。

关于Matrix 其他方法的介绍

//判断是否是单位矩阵
isIdentity()
//判断是否是仿射矩阵
isAffine()
//判断该矩阵是否可以将一个矩形依然变换为一个矩形
rectStaysRect()
//重置矩阵 所有计算和参数结果抛弃,恢复为单位矩阵模式。
reset()

//设置按照sin 和cos 进行旋转 。  其实和xxxRotate 差不多了。只是上面的要求角度值,而在这里 要求的是sin和cos值
setSinCos(float sinValue, float cosValue, float px, float py)
setSinCos(float sinValue, float cosValue)

//翻转矩阵结果 可以理解为左右镜像 
invert(Matrix inverse)
// 将src 的结果,变为dst 。 然后采用ScaleToFit 模式
setRectToRect(RectF src, RectF dst, ScaleToFit stf)

ScaleToFit 有如下四个值:

FILL: 可能会变换矩形的长宽比,保证变换和目标矩阵长宽一致。

START:保持坐标变换前矩形的长宽比,并最大限度的填充变换后的矩形。至少有一边和目标矩形重叠。左上对齐。

CENTER: 保持坐标变换前矩形的长宽比,并最大限度的填充变换后的矩形。至少有一边和目标矩形重叠。

END:保持坐标变换前矩形的长宽比,并最大限度的填充变换后的矩形。至少有一边和目标矩形重叠。右下对齐。

image.png

之后还有例如:

//通过指定的1-4个点,原始坐标以及变化后的坐标,来得到一个变换矩阵。
//可以实现 平移,旋转,缩放,倾斜(平行四边形,梯形等倾斜)等效果
setPolyToPoly(float[] src, int srcIndex,float[] dst, int dstIndex,int pointCount)
//映射点的值到指定的数组中,这个方法可以在矩阵变换以后,给出指定点的值。可以将矩阵数据存储为数组,然后后续还能进行恢复等操作
mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,int pointCount)
mapPoints(float[] dst, float[] src)
mapPoints(float[] pts)

//与上面的mapPoionts基本类似,这里是将一个矩阵作用于一个向量.注意,平移产生的向量没有变化
mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex,int vectorCount)
mapVectors(float[] dst, float[] src)
mapVectors(float[] vecs)

//返回值即是调用的rectStaysRect(),这个方法前面有讲过,这里把src中指定的矩形的左上角和右下角的两个点的坐标,写入dst中。
mapRect(RectF dst, RectF src)
mapRect(RectF rect)
//返回一个圆圈半径的平均值,将matrix作用于一个指定radius半径的圆,随后返回的平均半径
mapRadius(float radius)

以上就是相关配置了。

所有的操作都可以针对Matrix 进行变化,变化后,直接传到canvas进行绘制。

可以任意修改我们的图片显示效果。

Android 的所有图片旋转,移动,放大,都是采用Matrix矩阵算法进行处理的。
而且 矩阵不影响图片的原始数据,只是影响图片的显示效果。

0

评论区