浅谈Android中拍照、从相册选择图片并截图相关知识点
前言
我们在Android开发中经常会需要使用相机或者从相册中选取图片的情况,今天就把这里面相关的知识点总结下,方便以后开发的时候使用。
1、相机拍照并可自定义截图功能
我们先来看如何使用Intent来打开照相机,相信这段代码大伙应该很熟悉了。代码如下:
//打开照相机,进行拍照
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//设置照片的临时保存路径
intent.putExtra(MediaStore.EXTRA_OUTPUT, mTempImageUri);
startActivityForResult(intent, TAKE_PHOTO_BY_CAMERA);
这段代码中我们看到,对于第四行设置了拍照后图片的保存路径。这个我们可以自定义的。然后我们通过startActivityForResult来打开相机,并接受相关的数据。
下面我们来看下相机拍摄后的处理逻辑。代码如下:
/**
* 处理照相或者相册返回的图片数据
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode==Activity.RESULT_OK){
switch (requestCode){
//处理相机
case TAKE_PHOTO_BY_CAMERA:
if(mCrop) {
//对指定路径下的图片进行裁剪
cropCameraImage(mTempImageUri, DEFAULT_CROP_X, DEFAULT_CROP_Y, CROP_PHOTO);
}else {
mBitmap = getThumbnail(mTempImageUri, mImageWidth, mImageHeight);
setResult(true);
}
break;
//处理相册
case SELECT_PHOTO_BY_ALBUM:
Uri selectedPhotoUri=data.getData();
//对图片进行裁剪
if(mCrop) {
cropAlbumImage(selectedPhotoUri, mTempImageUri, DEFAULT_CROP_X, DEFAULT_CROP_Y, CROP_PHOTO);
}else {
//否则就将图片压缩成指定大小返回
mBitmap = getThumbnail(selectedPhotoUri, mImageWidth, mImageHeight);
setResult(true);
}
break;
//裁剪图片
case CROP_PHOTO:
if(data!=null) {
/**
* 如果想使用data.getParcelableExtra("data")获取bitmap
* 只需要在裁剪时设置return-data为true即可
*/
if(mReturnData){
mBitmap = data.getParcelableExtra("data");
if (mBitmap == null) {
setResult(false);
}
}else {
Uri originalUri = data.getData();
if (originalUri == null) {
originalUri = mTempImageUri;
}
//获取缩略图
mBitmap = getThumbnail(originalUri, mImageWidth, mImageHeight);
}
}
setResult(true);
break;
default:
break;
}
}else {
setResult(false);
}
super.onActivityResult(requestCode, resultCode, data);
}
我们来看代码的12-20行,我们看到这段代码会产生一个分支,如果crop为true,那么会调用cropCameraImage方法对拍摄的图片进行截图。否则的话就返回指定大小的图片(bitmap)给调用者。我们分开来看。
1、拍照并截图。相关代码如下:
/**
* 对照相机拍摄的图片进行裁剪
* @param uri
* @param outputX
* @param outputY
* @param requestCode
*/
private void cropCameraImage(Uri uri, int outputX, int outputY, int requestCode){
//相机拍摄的图片像素较高,不使用return-data属性使用Uri返回
mReturnData=false;
cropImage(uri,uri,outputX,outputY,mReturnData,requestCode);
}
我们看到里面调用了cropImage方法(从相册取图也使用了这个方法)。由于现在相机像素都很高,生成的图片很大,往往有5M+的大小。不建议使用return-data属性,这样会占用很大的内存。我们这边使用Uri。下面会详细介绍。
cropImage方法的介绍。
/**
*
* @param sourceUri
* @param outputUri
* @param outputX
* @param outputY
* @param returnData
* @param requestCode
*/
private void cropImage(Uri sourceUri,Uri outputUri,int outputX,int outputY,boolean returnData,int requestCode) {
try {
/**
* 下面解释各个参数的详细信息
*/
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(sourceUri, "image/*");
//发送裁剪信号
intent.putExtra("crop", "true");
//X,Y方向上的比例(1:1就是正方形,2:1就是长方形)
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
//裁剪区的宽,高
intent.putExtra("outputX", outputX);
intent.putExtra("outputY", outputY);
//是否保留比例
intent.putExtra("scale", true);
if(returnData) {
//是否将数据保留在Bitmap中返回(注意:小图片可以使用return-data:true的设置,大图片的话建议使用extra_output)
intent.putExtra("return-data", returnData);
}else {
//设置裁剪后的图片路径覆盖相机拍摄图片路径
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
}
//裁剪后图片的后缀名
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
//没有人脸检测
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, requestCode);
} catch (Exception ex) {
setResult(false);
}
}
在代码的27-32行我们看到通过returnData我们设置是否使用return-data属性。设置了return-data属性,Android系统会自动返回bitmap对象给我们,如:onActivityResult中的data.getParcelableExtra这种方法。这样对于小图片当然非常方便。但是对于大图片会造成内存消耗过高,应用程序产生异常。在最后我们看cropImage方法也是调用了startActivityForResult方法,只不过它的参数是CROP_PHOTO。
2、直接生成指定大小的图片
下面我们来介绍不使用截图,直接将生成指定大小图片并返回的方法,即代码中的getThumbnail方法。这一段代码是可以实现将图片缩小成指定长宽的尺寸。代码如下:
/**
* @param uri
* @param width
* @param height
* @return
* @throws IOException
*/
public Bitmap getThumbnail(Uri uri,int width,int height){
Bitmap bitmap=null;
InputStream input=null;
try {
ContentResolver resolver = getContentResolver();
input = resolver.openInputStream(uri);
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
/**
* 如果设置inJustDecodeBounds为true,仍可以获取到bitmap信息,但完全不用分配内存,因为没有获取像素,所以我们可以利用得到的Bitmap的大小,
* 重新压缩图片,然后在内存中生成一个更小的Bitmap,这样即便是一个4MB的JPG,我们也可以随心所欲地把他压缩到任意大小,从而节省了内存
*/
onlyBoundsOptions.inJustDecodeBounds = true;
onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
if(input!=null) {
input.close();
}
if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) {
return bitmap;
}
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
/**
* 计算Bitmap的缩放比例
*/
bitmapOptions.inSampleSize = calculateInSampleSize(onlyBoundsOptions, width, height);
bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
input = resolver.openInputStream(uri);
bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
}catch (Exception ex){
return bitmap;
}finally {
if(input!=null){
try {
input.close();
}catch (IOException ioEx){}
}
}
return bitmap;
}
这种方法的原理可以参考我的另一篇文章:http://www.cnblogs.com/dreamGong/p/5255528.html。通过介绍我们知道了相机拍摄图片并且进行截图和指定大小图片获取的相关方法。相信聪明的你也一定知道从相册取图肯定也是类似的。的确,从上面onActivityResult方法中我们看到从相册取图也是大同小异的。最后我再来介绍下onActivityResult方法中的CROP_PHOTO的相关逻辑。代码如下:
/**
* 如果想使用data.getParcelableExtra("data")获取bitmap
* 只需要在裁剪时设置return-data为true即可
*/
if(mReturnData){
mBitmap = data.getParcelableExtra("data");
if (mBitmap == null) {
setResult(false);
}
}else {
Uri originalUri = data.getData();
if (originalUri == null) {
originalUri = mTempImageUri;
}
//获取缩略图
mBitmap = getThumbnail(originalUri, mImageWidth, mImageHeight);
}
我们看到如果我们设置了retuan-data属性,是可以使用getParcelabelExtra方法来直接获取bitmap的。如果我们设置return-data为false。设置intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);cropImage方法的29行。我们可以通过获取Uri,然后重新生成一张bitmap返回给调用者。
参考文档
https://my.oschina.net/ryanhoo/blog/86842
附整个代码的逻辑
http://files.cnblogs.com/files/dreamGong/PhotoHelper.rar
浅谈Android中拍照、从相册选择图片并截图相关知识点的更多相关文章
- HTML5 Plus 拍照或者相册选择图片上传
HBuilder+HTML5 Plus+MUI实现拍照或者相册选择图片上传,利用HTML5 Plus的Camera.Gallery.IO.Storage和Uploader来实现手机APP拍照或者从相册 ...
- 浅谈Android中Serializable和Parcelable使用区别
版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.概述 Android开发的时候,我们时长遇到传递对象的需求,但是我们无法将对象的引用传给Activity或者Fragment,我们需要将这些对象 ...
- 浅谈android中只使用一个TextView实现高仿京东,淘宝各种倒计时
今天给大家带来的是只使用一个TextView实现一个高仿京东.淘宝.唯品会等各种电商APP的活动倒计时.近期公司一直加班也没来得及时间去整理,今天难得歇息想把这个分享给大家.只求共同学习,以及自己兴许 ...
- 浅谈Android中Activity的生命周期
引言 我想对于Android开发人员来说,Activity是再熟悉不过了,今天我们就来探讨下Activity的生命周期.熟悉的掌握Activity对于开发健壮的Android应用程序来说至关重要.下面 ...
- 浅谈android中的目录结构
之前在android游戏开发中就遇到本地数据存储的问题:一般情形之下就将动态数据写入SD中存储,在没有SD卡的手机上就需另作处理了;再有在开发android应用的过程中,总要去调试APP,安装时又想去 ...
- 浅谈Android中的startActivityForResult和setResult方法
引言 我们知道,如果想打开一个新的Activity我们可以使用startActivity方法.今天我们介绍的startActivityForResult不仅可以打开全新的Activity,而且当新的A ...
- 浅谈Android中layout_weight
引言 在开发android过程中,我们经常需要对界面进行按比例进行布局,我们一般都会使用layout_属性来进行设置.今天这篇文章我们就来简单介绍下layout_weight的使用和布局原理.随着做项 ...
- 浅谈Android中的事件分发机制
View事件分发机制的本质就是就是MotionEvent事件的分发过程,即MotionEvent产生后是怎样在View之间传递及处理的. 首先介绍一下什么是MotionEvent.所谓MotionEv ...
- 浅谈Android中的组播(多播)
组播使用UDP对一定范围内的地址发送相同的一组Packet,即一次可以向多个接受者发出信息,其与单播的主要区别是地址的形式.IP协议分配了一定范围的地址空间给多播(多播只能使用这个范围内的IP),IP ...
随机推荐
- Red Hat Enterprise Linux Server 6.5安装GCC 4.9.2
现在很多程序员都应用GCC,怎样才能更好的应用GCC.目前,GCC可以用来编译C/C++.FORTRAN.JAVA.OBJC.ADA等语言的程序,可根据需要选择安装支持的语言.本文以在RedHat L ...
- 10 Biggest Business Mistakes That Every Entrepreneur Should Avoid
原文链接:http://www.huffingtonpost.com/syed-balkhi/10-biggest-business-mista_b_7626978.html When I start ...
- shell中各种括号的作用()、(())、[]、[[]]、{}
一.小括号,圆括号() 1.单小括号 () ①命令组.括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用.括号中多个命令之间用分号隔开,最后一个命令可以没有 ...
- Java中图片压缩处理
原文http://cuisuqiang.iteye.com/blog/2045855 整理文档,搜刮出一个Java做图片压缩的代码,稍微整理精简一下做下分享. 首先,要压缩的图片格式不能说动态图片,你 ...
- ubuntu下新建用户
ubuntu下新建用户和RedHat系列的linux有点不一样 新建用户的命令是useradd,修改密码是passwd,如下: sudo useradd zhuhui sudo passwd 1234 ...
- Linux 使用iftop命令查看服务器流量
简介 iftop是类似于linux下面top的实时流量监控工具. iftop可以用来监控网卡的实时流量(可以指定网段).反向解析IP.显示端口信息等,详细的将会在后面的使用参数中说明. 安装 # yu ...
- hadoop io PART1
数据正确性检测的技术,通常使用checksum,在数据进行传输前,计算一个checksum值,传输到目标地之后,再根据新的文件计算checksum值,如果不匹配,则说明数据损坏或被改变.只能校验,不提 ...
- The Engine Document of JustWeEngine
JustWeEngine - Android FrameWork An easy open source Android Native Game FrameWork. Github Game core ...
- POJ3250[USACO2006Nov]Bad Hair Day[单调栈]
Bad Hair Day Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17774 Accepted: 6000 Des ...
- Strust2初之体验
Struts2的第一个案例 首先我们需要引入架包 entity: package cn.happy.entity; /** * Entity Object * @author Happy * */ p ...