热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[Android]android.graphics.Camera实现图像的旋转、缩放,配合Matrix实现图像的倾斜

android.graphics.Camera可以对图像执行一些比较复杂的操作,诸如旋转与绽放,与Matrix可实现图像的倾斜。个人总结Camera与Matrix的一些区别如下:

android.graphics.Camera可以对图像执行一些比较复杂的操作,诸如旋转与绽放,与Matrix可实现图像的倾斜。

个人总结Camera与Matrix的一些区别如下:

  1. Camera的rotate()相关方法是指定某一维度上旋转指定的角度。
  2. Matrix的rotate()相关方法实现的效果是顺时针旋转指定的角度;与Camera指定Z轴旋转效果相同,但方向相反。

  3. Camera的translate()方法根据某一维度上视点的位移实现图像的缩放,与Matrix的scale()相关方法作用效果相似,只是Matrix的scale()相关方法是直接指定缩放比例。

  4. Camera不支持倾斜操作,Matrix可以直接实现倾斜操作。


本文为练习Camera的使用。实现效果图如下:



Camera的处理结果只是生成一个Matrix,该Matrix用于Bitmap或Canvas绘制Bitmap时才能产生旋转或缩放的效果。

代码如下:

package lab.sodino.camera;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

/**
 * Camera与Matrix的比较:
* Camera的rotate()相关方法是指定某一维度上旋转指定的角度。
* Matrix的rotate()相关方法实现的效果是顺时针旋转指定的角度;与Camera指定Z轴旋转效果相同,但方向相反。
* * Camera的translate()方法根据某一维度上视点的位移实现图像的缩放,与Matrix的scale()相关方法作用效果相似, * 只是Matrix的scale()相关方法是直接指定缩放比例。
* * Camera不支持倾斜操作,Matrix可以直接实现倾斜操作。
* * @author Sodino E-mail:sodinoopen@hotmail.com * @version Time:2011-9-26 下午04:17:49 */ public class ActCamera extends Activity implements OnSeekBarChangeListener { private Camera camera; // views private SeekBar seekbarXRotate; private SeekBar seekbarYRotate; private SeekBar seekbarZRotate; private TextView txtXRotate; private TextView txtYRotate; private TextView txtZRotate; private SeekBar seekbarXSkew; private SeekBar seekbarYSkew; private SeekBar seekbarZTranslate; private TextView txtXTranslate; private TextView txtYTranslate; private TextView txtZTranslate; private ImageView imgResult; // integer params private int rotateX, rotateY, rotateZ; private float skewX, skewY; private int translateZ; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // camera camera = new Camera(); // initViews // rotate seekbarXRotate = (SeekBar) findViewById(R.id.seekbarXRotate); seekbarXRotate.setOnSeekBarChangeListener(this); seekbarYRotate = (SeekBar) findViewById(R.id.seekbarYRotate); seekbarYRotate.setOnSeekBarChangeListener(this); seekbarZRotate = (SeekBar) findViewById(R.id.seekbarZRotate); seekbarZRotate.setOnSeekBarChangeListener(this); txtXRotate = (TextView) findViewById(R.id.txtXRotate); txtYRotate = (TextView) findViewById(R.id.txtYRotate); txtZRotate = (TextView) findViewById(R.id.txtZRotate); // translate seekbarXSkew = (SeekBar) findViewById(R.id.seekbarXSkew); seekbarXSkew.setOnSeekBarChangeListener(this); seekbarYSkew = (SeekBar) findViewById(R.id.seekbarYSkew); seekbarYSkew.setOnSeekBarChangeListener(this); seekbarZTranslate = (SeekBar) findViewById(R.id.seekbarZTranslate); seekbarZTranslate.setOnSeekBarChangeListener(this); txtXTranslate = (TextView) findViewById(R.id.txtXSkew); txtYTranslate = (TextView) findViewById(R.id.txtYSkew); txtZTranslate = (TextView) findViewById(R.id.txtZTranslate); imgResult = (ImageView) findViewById(R.id.imgResult); // refresh refreshImage(); } private void refreshImage() { // 获取待处理的图像 BitmapDrawable tmpBitDra = (BitmapDrawable) getResources().getDrawable(R.drawable.honeycomb); Bitmap tmpBit = tmpBitDra.getBitmap(); // 开始处理图像 // 1.获取处理矩阵 // 记录一下初始状态。save()和restore()可以将图像过渡得柔和一些。 // Each save should be balanced with a call to restore(). camera.save(); Matrix matrix = new Matrix(); // rotate camera.rotateX(rotateX); camera.rotateY(rotateY); camera.rotateZ(rotateZ); // translate camera.translate(0, 0, translateZ); camera.getMatrix(matrix); // 恢复到之前的初始状态。 camera.restore(); // 设置图像处理的中心点 matrix.preTranslate(tmpBit.getWidth() >> 1, tmpBit.getHeight() >> 1); matrix.preSkew(skewX, skewY); // matrix.postSkew(skewX, skewY); // 直接setSkew(),则前面处理的rotate()、translate()等等都将无效。 // matrix.setSkew(skewX, skewY); // 2.通过矩阵生成新图像(或直接作用于Canvas) Log.d("ANDROID_LAB", " height=" + tmpBit.getHeight()); Bitmap newBit = null; try { // 经过矩阵转换后的图像宽高有可能不大于0,此时会抛出IllegalArgumentException newBit = Bitmap.createBitmap(tmpBit, 0, 0, tmpBit.getWidth(), tmpBit.getHeight(), matrix, true); } catch (IllegalArgumentException iae) { iae.printStackTrace(); } if (newBit != null) { imgResult.setImageBitmap(newBit); } } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (seekBar == seekbarXRotate) { txtXRotate.setText(progress + "゜"); rotateX = progress; } else if (seekBar == seekbarYRotate) { txtYRotate.setText(progress + "゜"); rotateY = progress; } else if (seekBar == seekbarZRotate) { txtZRotate.setText(progress + "゜"); rotateZ = progress; } else if (seekBar == seekbarXSkew) { skewX = (progress - 100) * 1.0f / 100; txtXTranslate.setText(String.valueOf(skewX)); } else if (seekBar == seekbarYSkew) { skewY = (progress - 100) * 1.0f / 100; txtYTranslate.setText(String.valueOf(skewY)); } else if (seekBar == seekbarZTranslate) { translateZ = progress - 100; txtZTranslate.setText(String.valueOf(translateZ)); } refreshImage(); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }



本文内容归CSDN博客博主Sodino 所有

转载请注明出处:http://blog.csdn.net/sodino/article/details/6823315


推荐阅读
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 在Kubernetes上部署JupyterHub的步骤和实验依赖
    本文介绍了在Kubernetes上部署JupyterHub的步骤和实验所需的依赖,包括安装Docker和K8s,使用kubeadm进行安装,以及更新下载的镜像等。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • 面向对象之3:封装的总结及实现方法
    本文总结了面向对象中封装的概念和好处,以及在Java中如何实现封装。封装是将过程和数据用一个外壳隐藏起来,只能通过提供的接口进行访问。适当的封装可以提高程序的理解性和维护性,增强程序的安全性。在Java中,封装可以通过将属性私有化并使用权限修饰符来实现,同时可以通过方法来访问属性并加入限制条件。 ... [详细]
  • (三)多表代码生成的实现方法
    本文介绍了一种实现多表代码生成的方法,使用了java代码和org.jeecg框架中的相关类和接口。通过设置主表配置,可以生成父子表的数据模型。 ... [详细]
author-avatar
埃博拉网络科技
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有