上篇文章介绍了
Matrix基本原理方法
,这篇文章介绍下Matrix的其他比较常用的方法。
1、mapPoints
:计算一组点基于当前Matrix变换后的位置。
其有三个重载方法:
void mapPoints (float[] pts)
void mapPoints (float[] dst, float[] src)
void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount)
<1> void mapPoints(float [ ] pts) -- 计算结果依然放置pts中,示例如下:
//初始数据为三个点 (0, 0) (80, 100) (400, 300)
float[] pts = new float[] {0, 0, 80, 100, 400, 300};
//构造一个Matrix,并使其x轴坐标缩放0.5
Matrix mMatrix = new Matrix();
mMatrix.setScale(0.5f, 1f);
//输出原有的pts值
Logger.d("before:" + Arrays.toString(pts));
//调用mapPoints方法计算,即将Matrix的值映射至pts中
mMatrix.mapPoints(pts);
//属于计算后的pts值
Logger.d("after:" + Arrays.toString(pts));
<2> void mapPoints(float[ ] dst, float[ ] src) -- 用于存放原始数据与目标数据:
* 原始数据需要保留,用此方法
float[] src = new float[] {0, 0, 80, 100, 400, 300};
float[] dst = new float[] {0, 0, 0, 0, 0, 0};
mMatrix.setScale(0.5f, 1f);
Logger.d("before:\n" + "src:" + Arrays.toString(src) + " dst:" + Arrays.toString(dst));
mMatrix.mapPoints(dst, src);
Logger.d("after:\n" + "src:" + Arrays.toString(src) + " dst:" + Arrays.toString(dst));
<3> void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount) -- 可以指定只计算一部分数值:
* 将第二个第三个计算后存储在dst最初始位置
float[] src = new float[] {0, 0, 80, 100, 400, 300};
float[] dst = new float[6];
mMatrix.setScale(0.5f,1f);
Logger.d("before:\n" + "src:" + Arrays.toString(src) + " dst:" + Arrays.toString(dst));
mMatrix.mapPoints(dst,0,src,2,2);
Logger.d("before:\n" + "src:" + Arrays.toString(src) + " dst:" + Arrays.toString(dst));
2、mapRadius:
测量半径(由于圆可能会因为画布变换变成椭圆,所以此处测量的是平均半径)。
float mapRadius(float radius)
float radius = 100;
float result;
mMatrix.setScale(0.5f, 1f);
Logger.d("before:mapRadius " + radius);
result = mMatrix.mapRadius(radius);
Logger.d("after:mapRadius " + result);
3、mapRect:
测量矩阵变换后位置,将结果放置rect中:
其有两个重载方法(第二种与mapPoint同参数方法类似,故不做过多介绍):
boolean mapRect (RectF rect)
boolean mapRect (RectF dst, RectF src)
* 返回值是boolean值,表示矩阵经过变换后是否依然为矩阵(这里使用了斜切,故返回值是false)
RectF rectF = new RectF(400, 400, 1000, 800);
mMatrix.setScale(0.5f, 1f);
mMatrix.postSkew(1, 0);
Logger.d("before:mapRect:" + rectF.toString());
boolean result = mMatrix.mapRect(rectF);
Logger.d("after:mapRect:" + rectF.toString());
Logger.d("result:" + result);
4、mapVectors:
测量向量,与mapPoints的构造方法及使用基本相同,唯一的区别是测量向量不受位移的影响。
float[] src = new float[]{1000, 800};
float[] dst = new float[2];
// 构造一个matrix
Matrix matrix = new Matrix();
matrix.setScale(0.5f, 1f);
matrix.postTranslate(100,100);
// 计算向量, 不受位移影响
matrix.mapVectors(dst, src);
Log.i(TAG, "mapVectors: "+Arrays.toString(dst));
// 计算点
matrix.mapPoints(dst, src);
Log.i(TAG, "mapPoints: "+Arrays.toString(dst));
5、setPolyToPoly:
根据数组点参数将矩形变换成其他多边形。
* src:原始数组,存储内容为一组点(包含x,y坐标)
* srcIndex:原始数组开始位置
* dst:目标数组,存储内容为一组点(包含x,y坐标)
* dstIndex:目标数组开始位置
* pointCount:测控点的数量,取值范围(0~4)
boolean setPolyToPoly(float[] src, int srcIndex,
float[] dst, int dstIndex,
int pointCount)
下面通过一个具体的实例View,来看一下矩阵的setPolyToPoly方法产生的效果:
public class MatrixSetPolyToPolyView extends View {
private Matrix mMatrix;
private Bitmap mBitmap;
private Paint mPaint;
public MatrixSetPolyToPolyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initBitmapAndMatrix();
private void initBitmapAndMatrix() {
mPaint = new Paint();
mPaint.setColor(Color.BLUE);
mMatrix = new Matrix();
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.avatar);
float[] src = new float[] {0, 0, mBitmap.getWidth(), 0, mBitmap.getWidth(), mBitmap.getHeight(), 0,
mBitmap.getHeight()};
float[] dst = new float[] {0, 0, mBitmap.getWidth(), 100, mBitmap.getWidth(), mBitmap.getHeight() - 100, 0,
mBitmap.getHeight()};
//多边形变换
mMatrix.setPolyToPoly(src, 0, dst, 0, 4);
mMatrix.postTranslate(0, 200);
@Override
protected void onDraw(Canvas conDrawanvas) {
super.onDraw(conDrawanvas);
conDrawanvas.drawBitmap(mBitmap, mMatrix, mPaint);
实例效果如下:
6、setRectToRect:将源矩阵的内容添加到目标矩阵中。
* src:源区域
* dst:目标区域
* stf:缩放适配模式
boolean setRectToRect(RectF src, RectF dst, ScaleToFit stf)
其中stf参数类似于ImageView的ScaleType属性,但只有四个参数可供选择:
|
模式
|
摘要
|
|
CENTER
|
居中,对src
等比例缩放
,将其居中放置在dst中。
|
|
START
|
顶部,对src
等比例缩放
,将其放置在dst的左上角。
|
|
END
|
底部,对src
等比例缩放
,将其放置在dst的右下角。
|
|
FILL
|
充满,
拉伸
src的宽和高,使其完全填充满dst。
|
我们使用CENTE来举例说明,初始代码如下:
public class MatrixSetRectToRectView extends View {
private Matrix mMatrix;
private Bitmap mBitmap;
private Paint mPaint;
public MatrixSetRectToRectView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initBitmaAndMatrix();
private void initBitmaAndMatrix() {
mMatrix = new Matrix();
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.avatar);
mPaint = new Paint();
@Override
protected void onDraw(Canvas conDrawanvas) {
super.onDraw(conDrawanvas);
conDrawanvas.drawBitmap(mBitmap, mMatrix, mPaint);
代码很简单,我们使用一个自定义View来展示一张图片,效果如下:
下面我们使用setRectToRect方法,stf属性选择CENTER,代码如下:
public class MatrixSetRectToRectView extends View {
private Matrix mMatrix;
private Bitmap mBitmap;
private Paint mPaint;
private int mViewWidth, mViewHeight;
public MatrixSetRectToRectView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
Logger.d("MatrixSetRectToRectView--执行顺序1");
initBitmaAndMatrix();
private void initBitmaAndMatrix() {
mMatrix = new Matrix();
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.avatar);
mPaint = new Paint();
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Logger.d("onSizeChanged--执行顺序2");
mViewWidth = w;
mViewHeight = h;
@Override
protected void onDraw(Canvas conDrawanvas) {
super.onDraw(conDrawanvas);
Logger.d("onDraw--执行顺序3");
RectF src = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
RectF dst = new RectF(0, 0, mViewWidth, mViewHeight);
//使用矩阵的setRectToRect方法,stf属性选用CENTER(即等比居中显示)
mMatrix.setRectToRect(src, dst, ScaleToFit.CENTER);
//使用画布根据目标区域绘制mBitmap
conDrawanvas.drawBitmap(mBitmap, mMatrix, mPaint);
这里需要注意的一点是View的关键生命周期为(可自行验证):
构造View() –> onMeasure() –> onSizeChanged() –> onLayout() –> onDraw()。
故代码中三个方法执行顺序如下:
这样我们在绘制(onDraw)的时候已经获取到ImageView的mViewWidth和mViewHeight,而其均已设置为屏幕的宽高,故修改后的图片展示效果如下:
可以看到,原有的图片在源区域的基础上已经等比缩放居中至目标区域。
7、isIdentity:判断当前矩阵是否是单位矩阵。
boolean isIdentity()
8、isAffine:判断当前矩阵是否是仿射矩阵(需要API 21及以上)。
boolean isAffine()
较少使用,了解下仿射矩阵的概念即可:仿射变换其实就是二维坐标到二维坐标的线性变换,保持二维图形的“平直性”(即变换后直线还是直线不会打弯,圆弧还是圆弧)和“平行性”(指保持二维图形间的相对位置关系不变,平行线还是平行线,而直线上点的位置顺序不变),可以通过一系列的原子变换的复合来实现,原子变换就包括:平移、缩放、翻转、旋转和错切。这里除了透视可以改变z轴以外,其他的变换基本都是上述的原子变换。所以,只要最后一行是0,0,1则是仿射矩阵。
9、rectStaysRect:判断矩形经过变换后是否仍为矩形。
boolean rectStaysRect()
当矩阵是单位矩阵,或者只进行平移,缩放,以及旋转90度的倍数的时候,返回true。
10、reset:重置矩阵为单位矩阵。
void reset()
本篇基本讲解了Matrix的一些常用方法,在做图形变换的时候,某些方法还是会经常用到的,建议先阅读下上篇Matrix基本原理方法,理解可能会更深刻一些。
在Android开发中,矩阵是一个功能强大并且应用广泛的神器,例如:用它来制作动画效果、改变图片大小、给图片加各类滤镜等。对于矩阵,Android官方SDK为我们提供了一个强大的类Matrix(还有ColorMatrix)是一直困扰着我的问题,虽然大致能够调用相应的API,但却一直get不到其内在的梗。但是出来混总是别想着蒙混过关的,所以最近重新操起一年毕业的线性代数,再本着小事问老婆,大事问Google的心态,终于把多年不解的问题给破了。出于好记性不如烂笔头的原因,便有了本文。读完本文,相信你能够搞明白以下三个问题:1.为什么Matrix是个3X3的矩阵2.Matrix这个3X3的矩阵每个元
Android View 通过平移、旋转、缩放后,顶点映射之前写的这个文章,里面用到的是通过 矩形的4个点来映射出新的4个点。个人以为这就会得到正确的结果。最近呢,就想着,验证一下这个是不是正确的验证想法:“基于 变换后的 ltrb,加一个自定义 view layout;有最外层 view那么大;当 view 变换后,在 layout 上以 ltrb为圆心, 画出一个小圆”最终发现,旋转 用会有问题...
1 概述这里我们会详细讲解matrix的各个方法,以及它的用法。matrix叫做矩阵,在前面讲解 ColorFilter 的文章中,我们讲解了ColorMatrix,他是一个4*5的矩阵。而这里,我们讲解的Matrix不是用于处理颜色的,而是处理图形的。他是一个3*3的矩阵。2 原理先看看matrix的矩阵是什么样子的:这里可以查看Matrix的代码得到。那么这个矩阵分别代表了什么呢,这里通
在android的自定义View中,使用Matrix来转换坐标非常方便,其中有一个方法叫mapPoints,它的计算方式是怎么样的呢?首先来看看Matrix矩阵长得什么样?它是一个3x3的矩阵。
在编程里,它对应一个长度为9的float[]数组,通过以下变量准确取到数组中相应的值。
现在再来看看,每一位的含意:好了,我们现在来看一下,mapPoints的计算过程:
那么mapPoints的计算方式就如上所示了。...
1、Matrix : mapPoint() mapRect(src,dst)...根据矩阵将src内容转化并存储到dst中;
矩阵操作,preTranslate(dx,dy) = Matrix*t(dx,dy);
postTranslate(dx,dy) = t(dx,dy)*Matrux
2、Movie:根据api来看,应该代笔的就是电影,有duration 关于流和文件的操作
最近公司要我做平面识别,完全没头绪,想到AR上有这种功能就去找,最初找到PTAM,可是代码太久远了,没搞好,然后发现ORB_SLAM2,虽然不知道可不可以实现平面识别,不过把ORB_SLAM2给搬到了android studio上了,分享一下本来参考ORB_SLAM2在Android上的移植过程 (Android Studio 2.2+OpenCV 3.2+Cmake) 这篇文章的,可是没成功,就...
1 Matrix 在Android 中的运用
ImageView 缩放模式 setImageMatrix(mMatrix) 方法,可以自定义一个Matrix。 对 Bitmap 做相应的处理,如缩放,位移。
Matrix 可以对 Rect 和 点的集合做变换处理
public void mapPoints(float[] pts) {
mapPoints(pts, 0,...
通过前面的分析,我们知道了调整颜色矩阵可以改变一副图像的色彩效果,图像处理很大程度上就是在寻找处理图像的颜色矩阵。不仅仅可以通过Android系统提供的API来进行ColorMatrix的修改,同样可以精确地修改矩阵的值来实现颜色效果的处理。
下面我们就模拟一个4*5的颜色矩阵。通过修改矩阵中的值,一来验证全面所说的改变图像色彩效果的原理是否正确,二来对矩阵变换产生的作用效果有更清晰地认识。程序...
好了,前面主要讲了Animation,Animator 的使用,以及桌面火箭效果和水波纹效果,分别使用android框架和自己绘制实现,俗话说,工欲善其事,必先利其器,接下来几篇文章主要讲绘制中我们需要常使用的一些利器;
Paint:画笔
Canvas:画布
Matrix:变换矩阵
绘制动效确实就像拿着笔在画布上面画画一样,而Paint就是我们拿着的笔,Canvas就是使用的画布;
最近在项目中使用到了PhotoView来针对图片进行缩放处理,原本绘制在Bitmap上的内容位置就发生了偏移,在此记录一下解决步骤。在PhotoView缩放操作中,图片本身的大小是不变的,图片的所有平移缩放等操作都是采用Matrix类来操作public void setScale(float scale, float focalX, float focalY,boolean animate) {/...
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matr
在例子Android ApiDemos示例解析(74):Graphics->PolyToPoly 介绍在已知变换前后的坐标然后根据Matrix.setPolyToPoly 得到对于的变换矩阵。
此外Matrix也支持提供变换前后的两个矩形,通过setRectToRect 取得对应的变换矩阵。来看看setRectToRect 的定义:
public boolean setRectToRec...