【Android】画图之Matrix
来源:互联网 发布:nginx实现session共享 编辑:程序博客网 时间:2024/05/17 08:36
Android画图之Matrix
Matrix的操作,总共分为translate(平移),rotate(旋转),scale(缩放)和skew(倾斜)四种,每一种变换在
Android的API里都提供了set, post和pre三种操作方式,除了translate,其他三种操作都可以指定中心点。
set是直接设置Matrix的值,每次set一次,整个Matrix的数组都会变掉。
post是后乘,当前的矩阵乘以参数给出的矩阵。可以连续多次使用post,来完成所需的整个变换。例如,要将一个图片旋
转30度,然后平移到(100,100)的地方,那么可以这样做:
复制到剪贴板 Java代码
1. Matrix m = new Matrix();
2.
3. m.postRotate(30);
4.
5. m.postTranslate(100, 100);
6.
7. Matrix m = new Matrix();
8.
9. m.postRotate(30);
10.
11.m.postTranslate(100, 100);
复制到剪贴板 Java代码
1. package eoeandroid.demo;
2.
3. import android.content.Context;
4. import android.graphics.Bitmap;
5. import android.graphics.Canvas;
6. import android.graphics.Matrix;
7. import android.graphics.Rect;
8. import android.graphics.drawable.BitmapDrawable;
9. import android.util.DisplayMetrics;
10.import android.view.MotionEvent;
11.import android.view.View;
12.
13.public class MyView extends View {
14.
15.private Bitmap mBitmap;
16.
17.private Matrix mMatrix = new Matrix();
18.
19.public MyView(Context context) {
20.
21.super(context);
22.
23.initialize();
24.
25.}
26.
27.private void initialize() {
28.
29.Bitmap bmp = ((BitmapDrawable)getResources().getDrawable(R.drawable.show)).getBitmap();
30.
31.mBitmap = bmp;
32.
33./*首先,将缩放为100*100。这里scale的参数是比例。有一点要注意,如果直接用100/
34.bmp.getWidth()的话,会得到0,因为是整型相除,所以必须其中有一个是float型的,直接用100f就好。*/
35.
36.mMatrix.setScale(100f/bmp.getWidth(), 100f/bmp.getHeight());
37.
38.//平移到(100,100)处
39.
40.mMatrix.postTranslate(100, 100);
41.
42.//倾斜x和y轴,以(100,100)为中心。
43.
44.mMatrix.postSkew(0.2f, 0.2f, 100, 100);
45.
46.}
47.
48.@Override
49.protected void onDraw(Canvas canvas) {
50.
51.// super.onDraw(canvas); //如果界面上还有其他元素需要绘制,只需要将这句话写上就行了。
52.
53.canvas.drawBitmap(mBitmap, mMatrix, null);
54.
55.}
56.
57.}
以前在线性代数中学习了矩阵,对矩阵的基本运算有一些了解,前段时间在使用GDI+的时候再次学习如何使用矩阵来变化图像,看了之后在这里总结说明。
首先大家看看下面这个3 x 3的矩阵,这个矩阵被分割成4部分。为什么分割成4部分,在后面详细说明。
首先给大家举个简单的例子:现设点P0(x0, y0)进行平移后,移到P(x,y),其中x方向的平移量为△x,y方向的平移量为△y,那么,点P(x,y)的坐标为:
x = x0 + △x
y = y0 + △y
采用矩阵表达上述如下:
上述也类似与图像的平移,通过上述矩阵我们发现,只需要修改矩阵右上角的2个元素就可以了。
我们回头看上述矩阵的划分:
为了验证上面的功能划分,我们举个具体的例子:现设点P0(x0,y0)进行平移后,移到P(x,y),其中x放大a倍,y放大b倍,
矩阵就是:,按照类似前面“平移”的方法就验证。
图像的旋转稍微复杂:现设点P0(x0, y0)旋转θ角后的对有点为P(x, y)。通过使用向量,我们得到如下:
x0 = r cosα
y0 = r sinα
x = r cos(α-θ) = x0 cosθ+ y0 sinθ
y = r sia(α-θ) = -x0 sinθ+y0 cosθ
于是我们得到矩阵:
如果图像围绕着某个点(a,b)旋转呢?则先要将坐标平移到该点,再进行旋转,然后将旋转后的图像平移回到原来的坐标原点,在后面的篇幅中我们将详细介绍。
从高等数学方面给大家介绍了Matrix,本篇幅我们就结合Android中的android.graphics.Matrix来具体说明,还记得我们前面说的图像旋转的矩阵:
从最简单的旋转90度的是:
在android.graphics.Matrix中有对应旋转的函数:
Matrix matrix = new Matrix();
matrix.setRotate(90);
Test.Log(MAXTRIX_TAG,”setRotate(90):%s” , matrix.toString());
查看运行后的矩阵的值(通过Log输出):
与上面的公式基本完全一样(android.graphics.Matrix采用的是浮点数,而我们采用的整数)。
有了上面的例子,相信大家就可以亲自尝试了。通过上面的例子我们也发现,我们也可以直接来初始化矩阵,比如说要旋转30度:
前面给大家介绍了这么多,下面我们开始介绍图像的镜像,分为2种:水平镜像、垂直镜像。先介绍如何实现垂直镜像,什么是垂直镜像就不详细说明。图像的垂直镜像变化也可以用矩阵变化的表示,设点P0(x0,y0 )进行镜像后的对应点为P(x,y ),图像的高度为fHeight,宽度为fWidth,原图像中的P0(x0,y0 )经过垂直镜像后的坐标变为(x0 ,fHeight- y0);
x = x0
y = fHeight – y0
推导出相应的矩阵是:
finalfloat f[] = {1.0F,0.0F,0.0F,0.0F,-1.0F,120.0F,0.0F,0.0F,1.0F};
Matrix matrix = new Matrix();
matrix.setValues(f);
按照上述方法运行后的结果:
至于水平镜像采用类似的方法,大家可以自己去试试吧。
实际上,使用下面的方式也可以实现垂直镜像:
Matrix matrix = new Matrix();
matrix.setScale (1.0,-1.0);
matrix.postTraslate(0, fHeight);
这就是我们将在后面的篇幅中详细说明。
什么是对称变换?具体的理论就不详细说明了,图像的镜像就是对称变换中的一种。
利用上面的总结做个具体的例子,产生与直线y= – x对称的反射图形,代码片段如下:
当前矩阵输出是:
图像变换的效果如下:
什么是图像的错切变换(Shear transformation)?我们还是直接看图片错切变换后是的效果:
对图像的错切变换做个总结:
x = x0 + b*y0;
y = d*x0 + y0;
这里再次给大家介绍一个需要注意的地方:
通过以上,我们发现Matrix的setXXXX()函数,在调用时调用了一次reset(),这个在复合变换时需要注意。
Preconcats matrix or Postconcats matrix?
从最基本的高等数学开始,Matrix的基本操作包括:+、*。Matrix的乘法不满足交换律,也就是说A*B ≠B*A。
还有2种常见的矩阵:
有了上面的基础,下面我们开始进入主题。由于矩阵不满足交换律,所以用矩阵B乘以矩阵A,需要考虑是左乘(B*A),还是右乘(A*B)。在Android的android.graphics.Matrix中为我们提供了类似的方法,也就是我们本篇幅要说明的 Preconcats matrix 与 Postconcats matrix。下面我们还是通过具体的例子还说明:
通过输出的信息,我们分析其运行过程如下:
看了上面的输出信息。我们得出结论:Preconcats matrix相当于右乘矩阵,Postconcats matrix相当于左乘矩阵。
上一篇副中,我们说到:
其运行过程的详细分析就不在这里多说了。
我们留下一个话题:如果图像围绕着某个点P(a,b)旋转,则先要将坐标系平移到该点,再进行旋转,然后将旋转后的图像平移回到原来的坐标原点。
我们需要3步:
1. 平移 ——将坐标系平移到点P(a,b);
2. 旋转 ——以原点为中心旋转图像;
3. 平移 ——将旋转后的图像平移回到原来的坐标原点;
相比较前面说的图像的几何变化(基本的图像几何变化),这里需要平移——旋转——平移,这种需要多种图像的几何变化就叫做图像的复合变化。
设对给定的图像依次进行了基本变化F1、F2、F3…..、Fn,它们的变化矩阵分别为T1、T2、T3…..、Tn,图像复合变化的矩阵T可以表示为:T = TnTn-1…T1。
按照上面的原则,围绕着某个点(a,b)旋转θ的变化矩阵序列是:
按照上面的公式,我们列举一个简单的例子:围绕(100,100)旋转30度(sin 30 = 0.5 ,cos 30 = 0.866)
floatf[]= { 0.866F, -0.5F,63.4F,0.5F, 0.866F,-36.6F,0.0F, 0.0F, 1.0F };
matrix = new Matrix ();
matrix.setValues (f);
旋转后的图像如下:
Android为我们提供了更加简单的方法,如下:
Matrix matrix = newMatrix ();
matrix.setRotate (30,100,100);
矩阵运行后的实际结果:
与我们前面通过公式获取得到的矩阵完全一样。
在这里我们提供另外一种方法,也可以达到同样的效果:
float a = 100.0F,b = 100.0F;
matrix = new Matrix ();
matrix.setTranslate (a,b);
matrix.preRotate (30);
matrix.preTranslate (-a,-b);
将在后面的篇幅中为大家详细解析
通过类似的方法,我们还可以得到:相对点P(a,b)的比例[sx,sy]变化矩阵
本文将讲述如何如何在Android中使用Matrix实现图片的缩放和旋转,通过本文学习,你将学会如何通过Matrix操作图像。
代码示例:
直接上代码了,我在代码中附带了详细的解释,代码如下:
- package com.eoeandroid.demo.testcode;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Matrix;
- import android.graphics.drawable.BitmapDrawable;
- import android.os.Bundle;
- import android.view.ViewGroup.LayoutParams;
- import android.widget.ImageView;
- import android.widget.LinearLayout;
- import android.widget.ImageView.ScaleType;
- public class bitmaptest extends Activity {
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- setTitle("eoeAndroid教程: 缩放和旋转图片 -by:IceskYsl");
- LinearLayout linLayout = new LinearLayout(this);
- // 加载需要操作的图片,这里是eoeAndroid的logo图片
- Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
- R.drawable.eoe_android);
- //获取这个图片的宽和高
- int width = bitmapOrg.getWidth();
- int height = bitmapOrg.getHeight();
- //定义预转换成的图片的宽度和高度
- int newWidth = 200;
- int newHeight = 200;
- //计算缩放率,新尺寸除原始尺寸
- float scaleWidth = ((float) newWidth) / width;
- float scaleHeight = ((float) newHeight) / height;
- // 创建操作图片用的matrix对象
- Matrix matrix = new Matrix();
- // 缩放图片动作
- matrix.postScale(scaleWidth, scaleHeight);
- //旋转图片 动作
- matrix.postRotate(45);
- // 创建新的图片
- Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
- width, height, matrix, true);
- //将上面创建的Bitmap转换成Drawable对象,使得其可以使用在ImageView, ImageButton中
- BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
- //创建一个ImageView
- ImageView imageView = new ImageView(this);
- // 设置ImageView的图片为上面转换的图片
- imageView.setImageDrawable(bmd);
- //将图片居中显示
- imageView.setScaleType(ScaleType.CENTER);
- //将ImageView添加到布局模板中
- linLayout.addView(imageView,
- new LinearLayout.LayoutParams(
- LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT
- )
- );
- // 设置为本activity的模板
- setContentView(linLayout);
- }
- }
这里没用定义XML布局模板,而是直接在代码中生成了需要的模板和视图组件,你可以可以定义XML模板,其他原理是一样的。
在游戏开发中,自定义View是一个相当重要的功能,下面先讲一讲在View上绘制所需的四个基本主键:
Bitmap:用于容纳像素点(android.graphics.Bitmap)
Canvas:负责调用绘制方法,是整个过程的入口
要绘制的对象:比如绘制一个Bitmap,矩形或者圆
Paint: 设置绘制图形的颜色和样式
Matrix:它包含一个3x3的矩阵,用于做变换匹配(图像处理中有讲),Matrix没有一个结构体,它必须被初始化,通过实现reset()方法或者set..()方法来实现。
下面来看代码:
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
//import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Canvas;
import android.graphics.Paint;
//import android.graphics.Rect;
public class TestMartix extends Activity {
//新建Bitmap,Canvas和Paint
private Bitmap img,r_img;
private Canvas canvas;
private Paint paint;
//由于是自定义view,所以不需要调用Layout文件
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//调用自定义View
setContentView(new MyView(this));
}
public class MyView extends View{
//View的初始化
public MyView(Context context) {
super(context);
//BitmapFactory:从源创建一个Bitmap对象,这些源包括:文件,流或者数组
img = BitmapFactory.decodeResource(getResources(),R.drawable.img);
//新建一个Matrix对象
Matrix matrix = new Matrix();
//让矩阵实现翻转,参数为FLOAT型
matrix.postRotate(90);
//matrix.postRotate(0);
//获取Bitmap的高与宽
int width = img.getWidth();
int height = img.getHeight();
//源Bitmap通过一个Matrix变化后,返回一个不可变的Bitmap
b_img = Bitmap.createBitmap(img, 0, 0, width, height, matrix, true);
paint = new Paint();
}
//在自定义VIEW时,必须实现此方法
public void onDraw(Canvas canvas){
//在重写父类的方法时,必须先调用父类的方法
super.onDraw(canvas);
//利用Canvas在View上绘制一个Bitmap,并设置它的样式和颜色
canvas.drawBitmap(b_img, 10, 10, paint);
//该方法是用来更新View的方法,多与线程结合使用。
//this.invalidate ()
//下面三段代码用于在View上绘制一个实心矩形,设置颜色为绿色,
//paint.setColor(Color.GREEN);
//paint.setAntiAlias(true);
//canvas.drawRect(new Rect(30,30,100,100), paint);
}
}
}
- Android画图之Matrix
- Android画图之Matrix
- Android画图之Matrix
- 【Android】画图之Matrix
- Android画图之Matrix
- Android画图之Matrix
- Android画图之Matrix
- Android画图之Matrix
- Android画图之Matrix(一)
- Android画图之Matrix(一)
- Android画图之Matrix(二)
- Android画图之Matrix(一)
- Android画图之Matrix(一)
- Android画图之Matrix(二)
- Android画图之Matrix(一)
- Android画图之Matrix(二)
- Android画图之Matrix(一)
- Android画图之Matrix(二)
- 一致性hash算法( consistent hashing )
- 数据库设计范式
- 通过web.xml传递初始参数
- 一名计算机讲师给计算机同学的几点建议
- android中调用相册里面的图片并返回
- 【Android】画图之Matrix
- GPU软件体系
- win7 x64 sp1系统在 VS 2010旗舰版下配置OpenCV 2.3.1
- 技术不好~紧张
- android 轮循的处理 Handler
- JVM terminated.Exit code = -1的错
- 验证码
- Hadoop1.0 Eclipse Plugin-作业提交
- 回调函数说明