Android绘图之Matrix
一、概述
1. 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类。Android中的Matrix是一个3 x 3的矩阵,其内容如下

2.Matrix的对图像的处理可分为四类基本变换:
Translate 平移变换
Rotate 旋转变换
Scale 缩放变换
Skew 错切变换
针对每种变换,Android提供了pre、set和post三种操作方式。其中
set用于设置Matrix中的值。
pre是先乘,因为矩阵的乘法不满足交换律,因此先乘、后乘必须要严格区分。先乘相当于矩阵运算中的右乘。
post是后乘,因为矩阵的乘法不满足交换律,因此先乘、后乘必须要严格区分。后乘相当于矩阵运算中的左乘。除平移变换(Translate)外,旋转变换(Rotate)、缩放变换(Scale)和错切变换(Skew)都可以围绕一个中心点来进行,如果不指定,在默认情况下是围绕(0, 0)来进行相应的变换的。
二、常用操作
1.平移
matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());
2.缩放
matrix.setScale(2f, 2f);
3.旋转
//第一种方式
//旋转 围绕图片中心
matrix.setRotate(45f,view.getImageBitmap().getWidth()/2f,view.getImageBitmap().getHeight()/2f);
//平移
matrix.postTranslate(view.getImageBitmap().getWidth()*1.5f,0f); //第二种方式
//旋转 中心点(0,0)
matrix.setRotate(45f); //先将图片中心移到(0,0),旋转后再移到原位置
matrix.preTranslate(-view.getImageBitmap().getWidth()/2f,-view.getImageBitmap().getHeight()/2f);
matrix.postTranslate(view.getImageBitmap().getWidth()*2f,view.getImageBitmap().getHeight()/2f);
4.错切
matrix.setSkew(0.5f,0f);//水平
matrix.setSkew(0f,0.5f);//竖直
matrix.setSkew(0.5f,0.5f);//水平和数值
5.对称
1)x轴对称
float matrix_values[] = {1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f};
matrix.setValues(matrix_values);
2)Y轴对称
float matrix_values[] = {-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f};
matrix.setValues(matrix_values);
3)y=x对称
float matrix_values[] = {0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f};
matrix.setValues(matrix_values);
三、代码
1.xml文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rl"
>
<com.example.dhj.bitmapdemo.TransformMatrixView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/view"
/>
</RelativeLayout> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" > <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="135dp"
android:onClick="click"
android:text="平移" /> <Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/button"
android:layout_alignBottom="@+id/button"
android:layout_marginLeft="17dp"
android:layout_marginStart="17dp"
android:layout_toEndOf="@+id/button"
android:layout_toRightOf="@+id/button"
android:onClick="click"
android:text="旋转" /> <Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/button2"
android:layout_marginLeft="35dp"
android:layout_marginStart="35dp"
android:layout_toEndOf="@+id/button2"
android:layout_toRightOf="@+id/button2"
android:onClick="click"
android:text="水平倾斜" /> <Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/button5"
android:layout_alignBottom="@+id/button5"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:onClick="click"
android:text="竖直倾斜" /> <Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button2"
android:layout_alignStart="@+id/button2"
android:layout_below="@+id/button2"
android:onClick="click"
android:text="水平竖直倾斜" /> <Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button3"
android:layout_alignStart="@+id/button3"
android:layout_below="@+id/button3"
android:onClick="click"
android:text="x轴对称" /> <Button
android:id="@+id/button7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/button4"
android:layout_marginTop="15dp"
android:onClick="click"
android:text="y轴对称" /> <Button
android:id="@+id/button8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/button7"
android:layout_alignLeft="@+id/button5"
android:layout_alignStart="@+id/button5"
android:onClick="click"
android:text="y=x对称" /> <Button
android:id="@+id/button11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button6"
android:layout_alignStart="@+id/button6"
android:layout_alignTop="@+id/button8"
android:onClick="click"
android:text="缩放" /> </RelativeLayout> </FrameLayout>
2.自定义view
class TransformMatrixView extends ImageView
{
private Bitmap bitmap;
private Matrix matrix;
public TransformMatrixView(Context context)
{
super(context);
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.p1);
bitmap=resizeBitmap(b,162,251);
matrix = new Matrix();
setBackgroundColor(Color.parseColor("#3f51b5"));
} public TransformMatrixView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.p1);
bitmap=resizeBitmap(b,162,251);
matrix = new Matrix();
// setBackgroundColor(Color.parseColor("#3f51b5"));
} @Override
protected void onDraw(Canvas canvas)
{
// 画出原图像
canvas.drawBitmap(bitmap, 0, 0, null);
// 画出变换后的图像
canvas.drawBitmap(bitmap, matrix, null);
super.onDraw(canvas);
} @Override
public void setImageMatrix(Matrix matrix)
{
this.matrix.set(matrix);
super.setImageMatrix(matrix);
} public Bitmap getImageBitmap()
{
return bitmap;
} /**
* 使用Matrix将Bitmap压缩到指定大小
* @param bitmap
* @param w
* @param h
* @return
*/
public static Bitmap resizeBitmap(Bitmap bitmap, int w, int h)
{
int width = bitmap.getWidth();
int height = bitmap.getHeight(); float scaleWidth = ((float) w) / width;
float scaleHeight = ((float) h) / height; Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight); Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width,
height, matrix, true);
return resizedBitmap;
}
}
3.activity
public class MainActivity extends Activity {
private TransformMatrixView view;
Matrix matrix= new Matrix();
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
view= (TransformMatrixView) findViewById(R.id.view);
}
public void click(View v){
switch (v.getId()){
case R.id.button:
tranlate();
break;
case R.id.button2:
rorate();
break;
case R.id.button3:
skewhorizontal();
break;
case R.id.button4:
skewVertical();
break;
case R.id.button5:
skew();
break;
case R.id.button6:
symmetryHorizontal();
break;
case R.id.button7:
symmetryVertical();
break;
case R.id.button8:
symmetry();
break;
case R.id.button11:
scale();
break;
}
view.setImageMatrix(matrix);
// view.invalidate();
}
//平移
private void tranlate(){
// 输出图像的宽度和高度(162 x 251)
// Log.e("TestTransformMatrixActivity", "image size: width x height = " + view.getImageBitmap().getWidth() + " x " + view.getImageBitmap().getHeight());
// 1. 平移
matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());
// 在x方向平移view.getImageBitmap().getWidth(),在y轴方向view.getImageBitmap().getHeight()
}
//旋转
private void rorate(){
//第一种方式
//旋转 围绕图片中心
matrix.setRotate(45f,view.getImageBitmap().getWidth()/2f,view.getImageBitmap().getHeight()/2f);
//平移
matrix.postTranslate(view.getImageBitmap().getWidth()*1.5f,0f);
//第二种方式
//旋转 中心点(0,0)
matrix.setRotate(45f);
//先将图片中心移到(0,0),旋转后再移到原位置
matrix.preTranslate(-view.getImageBitmap().getWidth()/2f,-view.getImageBitmap().getHeight()/2f);
matrix.postTranslate(view.getImageBitmap().getWidth()*2f,view.getImageBitmap().getHeight()/2f);
}
//缩放
private void scale(){
matrix.setScale(2f, 2f);
matrix.postTranslate(view.getImageBitmap().getWidth(),view.getImageBitmap().getHeight());
}
//水平 倾斜
private void skewhorizontal(){
// matrix.setSkew(0.5f, 0f);
// matrix.postTranslate(view.getImageBitmap().getWidth(), 0f);
matrix.setSkew(0.5f,0f);
matrix.postTranslate(view.getImageBitmap().getWidth(),0f);
}
//竖直 倾斜
private void skewVertical(){
matrix.setSkew(0f,0.5f);
matrix.postTranslate(view.getImageBitmap().getWidth(),0f);
}
//倾斜 水平和竖直
private void skew(){
matrix.setSkew(0.5f,0.5f);
matrix.postTranslate(view.getImageBitmap().getWidth(),0f);
}
//x轴对称
private void symmetryHorizontal(){
float matrix_values[] = {1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f};
matrix.setValues(matrix_values);
matrix.postTranslate(0f,view.getImageBitmap().getHeight()*2);
}
//y轴对称
private void symmetryVertical(){
float matrix_values[] = {-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f};
matrix.setValues(matrix_values);
matrix.postTranslate(view.getImageBitmap().getWidth()*2,0f);
}
//对称 y=x
private void symmetry(){
float matrix_values[] = {0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f};
matrix.setValues(matrix_values);
matrix.postTranslate(view.getImageBitmap().getWidth()+view.getImageBitmap().getHeight(),
view.getImageBitmap().getHeight()+view.getImageBitmap().getWidth());
}
}
四、效果



参考:
Android中图像变换Matrix的原理、代码验证和应用
Android绘图之Matrix的更多相关文章
- 论文第5章:Android绘图平台的实现
面向移动设备的矢量绘图平台设计与实现 Design and Implementation of Mobile Device-oriented Vector Drawing Platform 引用本论文 ...
- Android群英传》读书笔记 (3) 第六章 Android绘图机制与处理技巧 + 第七章 Android动画机制与使用技巧
第六章 Android绘图机制与处理技巧 1.屏幕尺寸信息屏幕大小:屏幕对角线长度,单位“寸”:分辨率:手机屏幕像素点个数,例如720x1280分辨率:PPI(Pixels Per Inch):即DP ...
- 第三章 Android绘图机制与处理技巧
1.屏幕尺寸信息 屏幕大小:屏幕对角线长度,单位“寸”:分辨率:手机屏幕像素点个数,例如720x1280分辨率:PPI(Pixels Per Inch):即DPI(Dots Per Inch),它是对 ...
- Android群英传笔记——第六章:Android绘图机制与处理技巧
Android群英传笔记--第六章:Android绘图机制与处理技巧 一直在情调,时间都是可以自己调节的,不然世界上哪有这么多牛X的人 今天就开始读第六章了,算日子也刚好一个月了,一个月就读一半,这效 ...
- Android为TV端助力 转载:Android绘图Canvas十八般武器之Shader详解及实战篇(下)
LinearGradient 线性渐变渲染器 LinearGradient中文翻译过来就是线性渐变的意思.线性渐变通俗来讲就是给起点设置一个颜色值如#faf84d,终点设置一个颜色值如#CC423C, ...
- Android中图像变换Matrix的原理、代码验证和应用(一)
第一部分 Matrix的数学原理 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类.Android中的Matrix是一个3 x 3的矩阵,其内容如下: Matri ...
- android 绘图之Canvas,Paint类
Canvas,Paint 1.在android 绘图但中经常要用到Canvas和Paint类,Canvas好比是一张画布,上面已经有你想绘制图画的轮廓了,而Paint就好比是画笔,就要给Canvas进 ...
- Android绘图机制(四)——使用HelloCharts开源框架搭建一系列炫酷图表,柱形图,折线图,饼状图和动画特效,抽丝剥茧带你认识图表之美
Android绘图机制(四)--使用HelloCharts开源框架搭建一系列炫酷图表,柱形图,折线图,饼状图和动画特效,抽丝剥茧带你认识图表之美 这里为什么不继续把自定义View写下去呢,因为最近项目 ...
- Android绘图机制(三)——自定义View的实现方式以及半弧圆新控件
Android绘图机制(三)--自定义View的三种实现方式以及实战项目操作 在Android绘图机制(一)--自定义View的基础属性和方法 里说过,实现自定义View有三种方式,分别是 1.对现有 ...
随机推荐
- 第14篇 PSR-3规范(日志)
1. Specification 1.1 Basics The LoggerInterface exposes eight methods to write logs to the eight RFC ...
- Python基础-变量作用域
1.函数作用域介绍 函数作用域 Python中函数作用域分为4种情况: L:local,局部作用域,即函数中定义的变量: E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局 ...
- VMware网络模式介绍
VMWare提供了三种工作模式,它们是bridged(桥接模式).NAT(网络地址转换模式)和host-only(主机模式). Bridged 模式: 在桥接模式下,VMware虚拟机里的系统就像是 ...
- 【转】使用Jmeter针对ActiveMQ JMS Point To Point压力测试
准备工作 针对JMS类型的Sampler,需要额外的jar包(这里用的是apache ActiveMQ,将下载的AMQ apache-activemq-5.5.0根目录下的activemq-all-5 ...
- 1096 Consecutive Factors
题意: 给出一个正整数N,找到最长的连续的可分解因子.如N=630,可被分解为630=3*5*6*7,其中5*6*7是3个连续的因子. 思路: 首先,需要明确,对于任何一个整数,如果它是素数,则不可被 ...
- java 最差实践
HashMap size 陷阱: 错误写法: Map map = new HashMap(collection.size()); for (Object o : collection) { map.p ...
- Py修行路 python基础 (十六)面向对象编程的 继承 多态与多态性 封装
一.继承顺序: 多继承情况下,有两种方式:深度优先和广度优先 1.py3/py2 新式类的继承:在查找属性时遵循:广度优先 继承顺序是多条分支,按照从左往右的顺序,进行一步一步查找,一个分支走完会走另 ...
- 使用airmon-ng工具开启监听模式
使用ifconfig命令查看活动的网络接口 可以看出网卡已经激活了,然后将网卡设置为混杂模式 root@sch01ar:~# airmon-ng start wlan0 用ifconfig查看网卡是否 ...
- js中的Array
js中的Array 啥是ArrayLike对象 类似,下面这种对象的就是ArrayLike var arraylike = { 0: "a", 1: "b", ...
- python web指纹获取加目录扫描加端口扫描加判断robots.txt
前言: 总结上几次的信息收集构造出来的. 0x01: 首先今行web指纹识别,然后在进行robots是否存在.后面是目录扫描 然后到使用nmap命令扫描端口.(nmap模块在windows下使用会报停 ...