Android Matrix图形变换
2015-06-26 01:15
531 查看
平移变换
从坐标(x0,y0)变换到(x, y)
x = x0 + △x
y =y0 + △y
坐标x,y写作矩阵C
[ x
y
1 ]
原坐标x0,y0写作矩阵B
[x0
y0
1 ]
想通过矩阵B得到矩阵C,根据矩阵乘法公式,
x = a*x0 + b*y0 + c*1, 由于x = x0 + △x, 所以推导出, a = 1, b = 0, c = △x
y = d*x0 + e*y0 + f * 1, 由于x = x0 + △x, 所以推导出, d = 0, e = 1, f = △y
1 = g *x0 + h*y0+ i*1 , 所以推导出,g = 0, h = 0 ,i= 1
由上述推导可得左乘矩阵B的矩阵A为:
[ 1 0 △x
0 1 △y
0 0 1 ]
旋转变换
如图所示,点(x0, y0)以o为圆心,旋转θ角度,到一个新的点(x,y),四个点分别用公式表示:
x0 = rcosα
y0 = rsinα
x = rcos(α+θ) = rcosαcosθ - rsinαsinθ = x0cosθ - y0sinθ
y = rsin(α+θ) = rsinαcosθ + rcosαsinθ = y0cosθ + x0sinθ
坐标x,y写作矩阵C
[ x
y
1 ]
原坐标x0,y0写作矩阵B
[x0
y0
1 ]
想通过矩阵B得到矩阵C,根据矩阵乘法公式,
x = a*x0 + b*y0 + c*1, 由于x = x0cosθ - y0sinθ, 所以推导出, a = cosθ, b = -sinθ, c = 0
y = d*x0 + e*y0 + f * 1, 由于x = y0cosθ + x0sinθ, 所以推导出, d = sinθ, e = cosθ, f = 0
1 = g *x0 + h*y0+ i*1 , 所以推导出,g = 0, h = 0 ,i= 1
由上述推导可得左乘矩阵B的矩阵A为:
[ cosθ -sinθ 0
sinθ cosθ 0
0 0 1 ]
缩放变换
如图,坐标公式
x = k*x0
y = k*y0
坐标x,y写作矩阵C
[ x
y
1 ]
原坐标x0,y0写作矩阵B
[x0
y0
1 ]
想通过矩阵B得到矩阵C,根据矩阵乘法公式,
x = a*x0 + b*y0 + c*1, 由于x = kx0, 所以推导出, a = k1, b =0, c = 0
y = d*x0 + e*y0 + f * 1, 由于x =ky0, 所以推导出, d = 0, e = k2, f = 0
1 = g *x0 + h*y0+ i*1 , 所以推导出,g = 0, h = 0 ,i= 1
由上述推导可得左乘矩阵B的矩阵A为:
[ k1 0 0
0 k2 0
0 0 1 ]
错切变换
水平错切:
垂直错切:
如图,坐标公式:
x = x0 + k1 * y0
y = k2*x0 + y0
坐标x,y写作矩阵C
[ x
y
1 ]
原坐标x0,y0写作矩阵B
[x0
y0
1 ]
想通过矩阵B得到矩阵C,根据矩阵乘法公式,
x = a*x0 + b*y0 + c*1, 由于x = x0 + k1*y0 , 所以推导出, a = 1, b =k1, c = 0
y = d*x0 + e*y0 + f * 1, 由于y =k2*x0 + y0, 所以推导出, d = k2, e = 1, f = 0
1 = g *x0 + h*y0+ i*1 , 所以推导出,g = 0, h = 0 ,i= 1
由上述推导可得左乘矩阵B的矩阵A为:
[ 1 k1 0
k2 1 0
0 0 1 ]
由以上几个推导看出,对于矩阵:
[ a b c
d e
f
g h i ]
a,e 控制缩放,b,d 控制错切,c,f 控制平移
下面用一个例子说明:
创建一个Activity,布局文件:
Activity:
以上代码,setImageMatrix方法通过用户输入,改变Matrix内部数组的值,并用这个Matrix绘制新的Bitmap,来改变图片的显示效果。getMatrix方法用于把EditText里面的数字赋值到 mMatrix数组中。
下面运行这个例子,尝试几个变换:
缩放:
平移:
错切:
旋转30°:
Matrix类提供了一些方法直接实现以上的一些效果:
setRotate:旋转
setSkew:错切
setTranslate:平移
setScale:缩放
如果需要做组合变换,可以使用postXXX/preXXX方法:
postScale/postSkew/postTranslate/postRotate
preScale/preSkew/preTranslate/preRotate
post和pre的区别是,以postTranslate为例,M' = T(dx, dy) * M,新的矩阵是由这个平移变换的矩阵左乘M矩阵,意味着最后做平移这个变换。
preTranslate:M' = M * T(dx, dy),右乘M矩阵,意味着这个平移变换在M的变换之前发生。
从坐标(x0,y0)变换到(x, y)
x = x0 + △x
y =y0 + △y
坐标x,y写作矩阵C
[ x
y
1 ]
原坐标x0,y0写作矩阵B
[x0
y0
1 ]
想通过矩阵B得到矩阵C,根据矩阵乘法公式,
x = a*x0 + b*y0 + c*1, 由于x = x0 + △x, 所以推导出, a = 1, b = 0, c = △x
y = d*x0 + e*y0 + f * 1, 由于x = x0 + △x, 所以推导出, d = 0, e = 1, f = △y
1 = g *x0 + h*y0+ i*1 , 所以推导出,g = 0, h = 0 ,i= 1
由上述推导可得左乘矩阵B的矩阵A为:
[ 1 0 △x
0 1 △y
0 0 1 ]
旋转变换
如图所示,点(x0, y0)以o为圆心,旋转θ角度,到一个新的点(x,y),四个点分别用公式表示:
x0 = rcosα
y0 = rsinα
x = rcos(α+θ) = rcosαcosθ - rsinαsinθ = x0cosθ - y0sinθ
y = rsin(α+θ) = rsinαcosθ + rcosαsinθ = y0cosθ + x0sinθ
坐标x,y写作矩阵C
[ x
y
1 ]
原坐标x0,y0写作矩阵B
[x0
y0
1 ]
想通过矩阵B得到矩阵C,根据矩阵乘法公式,
x = a*x0 + b*y0 + c*1, 由于x = x0cosθ - y0sinθ, 所以推导出, a = cosθ, b = -sinθ, c = 0
y = d*x0 + e*y0 + f * 1, 由于x = y0cosθ + x0sinθ, 所以推导出, d = sinθ, e = cosθ, f = 0
1 = g *x0 + h*y0+ i*1 , 所以推导出,g = 0, h = 0 ,i= 1
由上述推导可得左乘矩阵B的矩阵A为:
[ cosθ -sinθ 0
sinθ cosθ 0
0 0 1 ]
缩放变换
如图,坐标公式
x = k*x0
y = k*y0
坐标x,y写作矩阵C
[ x
y
1 ]
原坐标x0,y0写作矩阵B
[x0
y0
1 ]
想通过矩阵B得到矩阵C,根据矩阵乘法公式,
x = a*x0 + b*y0 + c*1, 由于x = kx0, 所以推导出, a = k1, b =0, c = 0
y = d*x0 + e*y0 + f * 1, 由于x =ky0, 所以推导出, d = 0, e = k2, f = 0
1 = g *x0 + h*y0+ i*1 , 所以推导出,g = 0, h = 0 ,i= 1
由上述推导可得左乘矩阵B的矩阵A为:
[ k1 0 0
0 k2 0
0 0 1 ]
错切变换
水平错切:
垂直错切:
如图,坐标公式:
x = x0 + k1 * y0
y = k2*x0 + y0
坐标x,y写作矩阵C
[ x
y
1 ]
原坐标x0,y0写作矩阵B
[x0
y0
1 ]
想通过矩阵B得到矩阵C,根据矩阵乘法公式,
x = a*x0 + b*y0 + c*1, 由于x = x0 + k1*y0 , 所以推导出, a = 1, b =k1, c = 0
y = d*x0 + e*y0 + f * 1, 由于y =k2*x0 + y0, 所以推导出, d = k2, e = 1, f = 0
1 = g *x0 + h*y0+ i*1 , 所以推导出,g = 0, h = 0 ,i= 1
由上述推导可得左乘矩阵B的矩阵A为:
[ 1 k1 0
k2 1 0
0 0 1 ]
由以上几个推导看出,对于矩阵:
[ a b c
d e
f
g h i ]
a,e 控制缩放,b,d 控制错切,c,f 控制平移
下面用一个例子说明:
创建一个Activity,布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/imageview" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginTop="10dp" android:layout_weight="2" /> <GridLayout android:id="@+id/group" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="3" android:columnCount="3" android:rowCount="3" > </GridLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="btnChange" android:text="Change" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="btnReset" android:text="Reset" /> </LinearLayout> </LinearLayout>最上面是显示图片的ImageView,下方GridView中会通过代码增加3*3的EditText,用于控制Matrix的值。
Activity:
public class MainActivity extends ActionBarActivity { private ImageView mImageView; private GridLayout mGroup; private int mEtWidth, mEtHeight; private EditText[] mEts = new EditText[9]; private float[] mMatrix = new float[9]; private Bitmap originBitmap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageView = (ImageView) findViewById(R.id.imageview); mGroup = (GridLayout) findViewById(R.id.group); originBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dragon); mImageView.setImageBitmap(originBitmap); // GridView的大小确定后, // 计算其中每个EditText应有的大小(3*3), // 并添加到GridView中。 mGroup.post(new Runnable() { @Override public void run() { mEtWidth = mGroup.getWidth() / 3; mEtHeight = mGroup.getHeight() / 3; addEts(); } }); } public void btnChange(View view) { getMatrix(); setImageMatrix(); } public void btnReset(View view) { initMatrix(); getMatrix(); setImageMatrix(); } private void setImageMatrix() { Bitmap newBitmap = Bitmap.createBitmap(originBitmap.getWidth(), originBitmap.getHeight(), Bitmap.Config.ARGB_8888); // 设置新的Matrix. Matrix matrix = new Matrix(); matrix.setValues(mMatrix); // 使用新的Matrix绘制Bitmap Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); Canvas canvas = new Canvas(newBitmap); canvas.drawBitmap(originBitmap, matrix, paint); mImageView.setImageBitmap(newBitmap); } private void addEts() { for (int i = 0; i < 9; i++) { EditText editText = new EditText(MainActivity.this); editText.setBackground(getResources().getDrawable( R.drawable.common_textfield_background)); //editText.setInputType(InputType.TYPE_CLASS_NUMBER // | InputType.TYPE_NUMBER_FLAG_DECIMAL); mEts[i] = editText; mGroup.addView(editText, mEtWidth, mEtHeight); } } //将输入框内的数字组装成为Matrix内数组的值 private void getMatrix() { for (int i = 0; i < 9; i++) { String etNum = mEts[i].getText().toString(); if (TextUtils.isEmpty(etNum)) { mEts[i].setText("0"); etNum = "0"; } mMatrix[i] = Float.valueOf(etNum); } } /** * 初始化矩阵数组为: [ 1 0 0 ,0 1 0 ,0 0 1 ] * */ private void initMatrix() { for (int i = 0; i < 9; i++) { if (i % 4 == 0) { mEts[i].setText(String.valueOf(1)); } else { mEts[i].setText(String.valueOf(0)); } } } }
以上代码,setImageMatrix方法通过用户输入,改变Matrix内部数组的值,并用这个Matrix绘制新的Bitmap,来改变图片的显示效果。getMatrix方法用于把EditText里面的数字赋值到 mMatrix数组中。
下面运行这个例子,尝试几个变换:
缩放:
平移:
错切:
旋转30°:
Matrix类提供了一些方法直接实现以上的一些效果:
setRotate:旋转
setSkew:错切
setTranslate:平移
setScale:缩放
如果需要做组合变换,可以使用postXXX/preXXX方法:
postScale/postSkew/postTranslate/postRotate
preScale/preSkew/preTranslate/preRotate
post和pre的区别是,以postTranslate为例,M' = T(dx, dy) * M,新的矩阵是由这个平移变换的矩阵左乘M矩阵,意味着最后做平移这个变换。
preTranslate:M' = M * T(dx, dy),右乘M矩阵,意味着这个平移变换在M的变换之前发生。
相关文章推荐
- android 三种定位方式 介绍
- Android的动画效果浅解析
- android 读取手机联系人
- xarmain使用Forms编译android工程出现support_r19.0.1.zip支持包错误
- Android中的Activity常见样式
- Android高级界面组件的学习(二)
- android 顶部横向滑动菜单效果
- Android同时使用多个library时android-support-v4.jar冲突问题。
- android 无法保存裁剪图片
- 常用Android开源框架
- android获取音频绝对地址
- android 自定义dialog,窗口动画
- android之java程序性能优化
- Material设计非得靠Android L吗?看过来,自定View仿elevation效果!
- Android应用实例之有道辞典
- Android中fragment切换状态
- 在ubuntu上搭建android开发环境(1)——安装ubuntu
- android项目的目录结构
- Activity回传值实例
- 菜鸟学Android笔记(四十二):Include指令及九大隐式对象