Android拍照或从图库选择图片并裁剪
程序员文章站
2024-03-06 19:37:38
今天看《第一行代码》上面关于拍照和从相册选取图片那一部分,发现始终出不来效果,所以搜索其他资料学习一下相关知识,写一个简单的demo。
一、 拍照选择图片...
今天看《第一行代码》上面关于拍照和从相册选取图片那一部分,发现始终出不来效果,所以搜索其他资料学习一下相关知识,写一个简单的demo。
一、 拍照选择图片
1、使用隐式intent启动相机
//构建隐式intent intent intent = new intent(mediastore.action_image_capture); //调用系统相机 startactivityforresult(intent, 1);
2、处理相机拍照返回的结果
//用户点击了取消 if(data == null){ return; }else{ bundle extras = data.getextras(); if (extras != null){ //获得拍的照片 bitmap bm = extras.getparcelable("data"); } }
二、 从图库选择图片
1、构建内容选择隐式intent
intent intent = new intent(intent.action_get_content);
2、设置内容类型为图片
intent.settype("image/*");
3、启动图片选择
startactivityforresult(intent, 2);
4、处理图片选择结果
if (data == null){ return; }else{ //用户从图库选择图片后会返回所选图片的uri uri uri; //获取到用户所选图片的uri uri = data.getdata(); }
三、 裁剪选择的图片
从相机拍照得到的是bitmap类型,所以我们需要先将其转化为文件uri以供裁剪。同时我们还要顺便将相机拍的照片保存到本地。
/** * 将bitmap写入sd卡中的一个文件中,并返回写入文件的uri * @param bm * @param dirpath * @return */ private uri savebitmap(bitmap bm, string dirpath) { //新建文件夹用于存放裁剪后的图片 file tmpdir = new file(environment.getexternalstoragedirectory() + "/" + dirpath); if (!tmpdir.exists()){ tmpdir.mkdir(); } //新建文件存储裁剪后的图片 file img = new file(tmpdir.getabsolutepath() + "/avator.png"); try { //打开文件输出流 fileoutputstream fos = new fileoutputstream(img); //将bitmap压缩后写入输出流(参数依次为图片格式、图片质量和输出流) bm.compress(bitmap.compressformat.png, 85, fos); //刷新输出流 fos.flush(); //关闭输出流 fos.close(); //返回file类型的uri return uri.fromfile(img); } catch (filenotfoundexception e) { e.printstacktrace(); return null; } catch (ioexception e) { e.printstacktrace(); return null; } }
从图库选择的图片返回的是content类型的uri,我们需要转化为文件类型的uri才能进行裁剪。
/** * 将content类型的uri转化为文件类型的uri * @param uri * @return */ private uri converturi(uri uri){ inputstream is; try { //uri ----> inputstream is = getcontentresolver().openinputstream(uri); //inputstream ----> bitmap bitmap bm = bitmapfactory.decodestream(is); //关闭流 is.close(); return savebitmap(bm, "temp"); } catch (filenotfoundexception e) { e.printstacktrace(); return null; } catch (ioexception e) { e.printstacktrace(); return null; } }
下面便是设置裁剪的参数,用隐式intent方式启动裁剪程序
/** * 通过uri传递图像信息以供裁剪 * @param uri */ private void startimagezoom(uri uri){ //构建隐式intent来启动裁剪程序 intent intent = new intent("com.android.camera.action.crop"); //设置数据uri和类型为图片类型 intent.setdataandtype(uri, "image/*"); //显示view为可裁剪的 intent.putextra("crop", true); //裁剪的宽高的比例为1:1 intent.putextra("aspectx", 1); intent.putextra("aspecty", 1); //输出图片的宽高均为150 intent.putextra("outputx", 150); intent.putextra("outputy", 150); //裁剪之后的数据是通过intent返回 intent.putextra("return-data", true); startactivityforresult(intent, crop_code); }
下面是完整的布局文件和java文件
--------------------------------------------------------------------------------
activity_main.xml文件
<?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/show_image" android:layout_width="match_parent" android:layout_height="300dp"/> <button android:id="@+id/choose_camera" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="摄像头"/> <button android:id="@+id/choose_gallery" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="相册"/> </linearlayout>
mainactivity.java文件
public class mainactivity extends appcompatactivity implements view.onclicklistener { //用于展示选择的图片 private imageview mimageview; private static final int camera_code = 1; private static final int gallery_code = 2; private static final int crop_code = 3; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); initview(); } private void initview() { mimageview = (imageview) findviewbyid(r.id.show_image); button choosecamera = (button) findviewbyid(r.id.choose_camera); choosecamera.setonclicklistener(this); button choosegallery = (button) findviewbyid(r.id.choose_gallery); choosegallery.setonclicklistener(this); } @override public void onclick(view view) { switch (view.getid()){ case r.id.choose_camera: //拍照选择 choosefromcamera(); break; case r.id.choose_gallery: //从相册选取 choosefromgallery(); break; default: break; } } /** * 拍照选择图片 */ private void choosefromcamera() { //构建隐式intent intent intent = new intent(mediastore.action_image_capture); //调用系统相机 startactivityforresult(intent, camera_code); } /** * 从相册选择图片 */ private void choosefromgallery() { //构建一个内容选择的intent intent intent = new intent(intent.action_get_content); //设置选择类型为图片类型 intent.settype("image/*"); //打开图片选择 startactivityforresult(intent, gallery_code); } @override protected void onactivityresult(int requestcode, int resultcode, intent data) { switch (requestcode){ case camera_code: //用户点击了取消 if(data == null){ return; }else{ bundle extras = data.getextras(); if (extras != null){ //获得拍的照片 bitmap bm = extras.getparcelable("data"); //将bitmap转化为uri uri uri = savebitmap(bm, "temp"); //启动图像裁剪 startimagezoom(uri); } } break; case gallery_code: if (data == null){ return; }else{ //用户从图库选择图片后会返回所选图片的uri uri uri; //获取到用户所选图片的uri uri = data.getdata(); //返回的uri为content类型的uri,不能进行复制等操作,需要转换为文件uri uri = converturi(uri); startimagezoom(uri); } break; case crop_code: if (data == null){ return; }else{ bundle extras = data.getextras(); if (extras != null){ //获取到裁剪后的图像 bitmap bm = extras.getparcelable("data"); mimageview.setimagebitmap(bm); } } break; default: break; } } /** * 将content类型的uri转化为文件类型的uri * @param uri * @return */ private uri converturi(uri uri){ inputstream is; try { //uri ----> inputstream is = getcontentresolver().openinputstream(uri); //inputstream ----> bitmap bitmap bm = bitmapfactory.decodestream(is); //关闭流 is.close(); return savebitmap(bm, "temp"); } catch (filenotfoundexception e) { e.printstacktrace(); return null; } catch (ioexception e) { e.printstacktrace(); return null; } } /** * 将bitmap写入sd卡中的一个文件中,并返回写入文件的uri * @param bm * @param dirpath * @return */ private uri savebitmap(bitmap bm, string dirpath) { //新建文件夹用于存放裁剪后的图片 file tmpdir = new file(environment.getexternalstoragedirectory() + "/" + dirpath); if (!tmpdir.exists()){ tmpdir.mkdir(); } //新建文件存储裁剪后的图片 file img = new file(tmpdir.getabsolutepath() + "/avator.png"); try { //打开文件输出流 fileoutputstream fos = new fileoutputstream(img); //将bitmap压缩后写入输出流(参数依次为图片格式、图片质量和输出流) bm.compress(bitmap.compressformat.png, 85, fos); //刷新输出流 fos.flush(); //关闭输出流 fos.close(); //返回file类型的uri return uri.fromfile(img); } catch (filenotfoundexception e) { e.printstacktrace(); return null; } catch (ioexception e) { e.printstacktrace(); return null; } } /** * 通过uri传递图像信息以供裁剪 * @param uri */ private void startimagezoom(uri uri){ //构建隐式intent来启动裁剪程序 intent intent = new intent("com.android.camera.action.crop"); //设置数据uri和类型为图片类型 intent.setdataandtype(uri, "image/*"); //显示view为可裁剪的 intent.putextra("crop", true); //裁剪的宽高的比例为1:1 intent.putextra("aspectx", 1); intent.putextra("aspecty", 1); //输出图片的宽高均为150 intent.putextra("outputx", 150); intent.putextra("outputy", 150); //裁剪之后的数据是通过intent返回 intent.putextra("return-data", true); startactivityforresult(intent, crop_code); } }
注:最后还需要在androidmanifest文件中加入存储卡读写权限
复制代码 代码如下:
<uses-permission android:name="android.permission.write_external_storage"/>
<uses-permission android:name="android.permission.read_external_storage"/>
<uses-permission android:name="android.permission.read_external_storage"/>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Java类的定义以及执行顺序学习教程