Android知识点总结:Android选取、拍照与裁剪图片相关流程分析
来源:互联网 发布:mac ps cs6永久序列号 编辑:程序博客网 时间:2024/04/30 09:25
图片裁剪
Android中图片的选取与裁剪是非常常见的功能,由于手机型号众多,难免在兼容性上出现问题。常 见情况就是出现闪退,无法选取图片。这方面的问题在以前的博客中曾经有过介绍,具体可以参考以下两篇博文。
关于拍照闪退的一种情况: http://blog.csdn.net/lidec/article/details/46699111
关于上传图片闪退的一种情况的:http://blog.csdn.net/lidec/article/details/46707245
这两篇文章分别描述了由于内存溢出和uri格式转换问题导致的选取图片出错。
现在我们仔细分析一下Android拍照,选取图片的流程。下文主要分析选取图片时uri的相关格式与路径的转换,图片存储位置,图片命名等问题,了解了这些问题,图片才能真正为我们所用。
下面代码主要来源于开源中国的安卓App,对其进行了摘取和注释,写成Moudle的形式,方便我们的使用,可以从下面的地址进行下载
http://download.csdn.net/detail/lidec/9344717
路径设置
//拍照相关 private final static int CROP = 200; //保存裁剪后照片的路径 private final static String FILE_SAVEPATH = Environment .getExternalStorageDirectory().getAbsolutePath() + "/vonchenchen/Portrait/"; //保存直接拍照后未经剪裁照片的路径 private final static String FILE_SAVEPATH_CAMERA = Environment .getExternalStorageDirectory().getAbsolutePath() + "/vonchenchen/Camera/"; //裁剪后照片的前缀名 文件名:FILE_SAVENAME + timeStamp + ".jpg" private final static String FILE_SAVENAME_CROP = "vonchenchen"; //直接拍照后照片的前缀名 文件名:FILE_SAVENAME_CAMERA + timeStamp + ".jpg"/other private final static String FILE_SAVENAME_CAMERA = "vonchenchen";
主要设置文件名前缀和存储路径,存储路径分为拍照后照片的存储路径和裁剪后照片的存储路径。
拍照过程
拍照的原理是通过intent开启系统相机的拍照程序,我们可以指定拍照后照片存储的位置,并使用onActivityResult在拍照完毕后得到照片。
/** * 拍照 */ private void startTakePhoto() { Intent intent; // 判断是否挂载了SD卡 String savePath = ""; String storageState = Environment.getExternalStorageState(); if (storageState.equals(Environment.MEDIA_MOUNTED)) { savePath = FILE_SAVEPATH_CAMERA; File savedir = new File(savePath); if (!savedir.exists()) { savedir.mkdirs(); } } // 没有挂载SD卡,无法保存文件 if (StringUtils.isEmpty(savePath)) { Toast.makeText(this, "无法保存照片,请检查SD卡是否挂载", Toast.LENGTH_SHORT); return; } String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss") .format(new Date()); String fileName = FILE_SAVENAME_CAMERA + timeStamp + ".jpg";// 照片命名 File out = new File(savePath, fileName); Uri uri = Uri.fromFile(out); origUri = uri; //***********************指定拍摄照片后,得到照片的Uri************************* theLarge = savePath + fileName;// 该照片的绝对路径 intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, ImageUtils.REQUEST_CODE_GETIMAGE_BYCAMERA); }
选取照片
如果使用选取本地照片,那么uri就是本地的了。同样也是开启一个intent,调用系统的照片列表,选择后为我们返回一个Uri,这个uri就是照片的路径。注意,这个uri的头
可能有多种,如果得到的是content:// ,我们可以通过系统的Media获取这个相片的路径,如果返回的头是file://,则直接取其后半部分,就是照片的路径。我们可以通过发送一
个系统广播,指定某个file://的照片进入Media,这样就可以使其得到标准的uri。由于这种方式有延迟,此处直接使用截去file重新拼凑路径的方法。
/** * 选择图片 */ private void startImagePick() { Intent intent; if (Build.VERSION.SDK_INT < 19) { intent = new Intent(); intent.setAction(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); startActivityForResult(Intent.createChooser(intent, "选择图片"), ImageUtils.REQUEST_CODE_GETIMAGE_BYCROP); } else { //ACTION_PICK 可以显示详细的选择样式 intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); intent.setType("image/*"); startActivityForResult(Intent.createChooser(intent, "选择图片"), ImageUtils.REQUEST_CODE_GETIMAGE_BYCROP); } }
裁剪图片
当完成拍照或者选取照片时,系统程序会返回我们的程序,并执行onActivityResult。此时我们可以获取目标图片的uri,如果是拍照的话,那么我们拍摄的图片已经存入了
我们设定的路径中。这样,我们就可以拿着选取图片的uri,进行裁剪操作,同样,裁剪也是一个系统应用,需要我们使用startActivity开启这个应用。
/** * 拍照后裁剪 * @param data 原始图片Uri */ private void startActionCrop(Uri data) { Intent intent = new Intent("com.android.camera.action.CROP"); //data 这个uri必须经过new File出来 intent.setDataAndType(data, "image/*"); //指定裁剪后的图片的保存路径 intent.putExtra("output", <span style="color:#ff0000;">getUploadTempFile</span>(data)); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1);// 裁剪框比例 intent.putExtra("aspectY", 1); intent.putExtra("outputX", CROP);// 输出图片大小 intent.putExtra("outputY", CROP); intent.putExtra("scale", true);// 去黑边 intent.putExtra("scaleUpIfNeeded", true);// 去黑边 startActivityForResult(intent, ImageUtils.REQUEST_CODE_GETIMAGE_BYSDCARD); }
getUploadTempFile函数分析
这个函数指定了裁剪完图片后的存储位置和文件名,通过传入已经获取到的图片Uri,对这个Uri进行处理,并根据这些信息在FILE_SAVENAME_CROP指定的路径中创建
图片Uri。这个Uri最终被设置给用来开启剪裁图片的intent。
/** * 在指定裁剪 * @param uri * @return */ private Uri getUploadTempFile(Uri uri) { String storageState = Environment.getExternalStorageState(); if (storageState.equals(Environment.MEDIA_MOUNTED)) { File savedir = new File(FILE_SAVEPATH); if (!savedir.exists()) { savedir.mkdirs(); } } else { Toast.makeText(this, "无法保存上传的头像,请检查SD卡是否挂载", Toast.LENGTH_SHORT).show(); return null; } String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss") .format(new Date()); //将uri转换为绝对路径, 如果是file:// 开头的uri,获取路径 String thePath = ImageUtils.getAbsolutePathFromNoStandardUri(uri); // 如果是标准Uri if (StringUtils.isEmpty(thePath)) { //将uri转换为绝对路径, 如果是content:// 开头的uri,获取路径 thePath = ImageUtils.getAbsoluteImagePath(this, uri); } String ext = StringUtils.getFileFormat(thePath); ext = StringUtils.isEmpty(ext) ? "jpg" : ext; // 裁剪完毕的照片命名 String cropFileName = FILE_SAVENAME_CROP + timeStamp + "." + ext; // 裁剪头像的绝对路径 protraitPath = FILE_SAVEPATH + cropFileName; protraitFile = new File(protraitPath); Uri cropUri = Uri.fromFile(protraitFile); return cropUri; }
下面我们看看我们所拼凑的路径,下图为非标准的uri, file:// 后面的字符串就是我们的路径
获取结果
onActivityResult相当于一个中转站,用于获取选择图片的结果 以及拿着这些结果(图片的uri)开启图片裁剪的应用。代码如下:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnIntent) { switch (requestCode) { case ImageUtils.REQUEST_CODE_GETIMAGE_BYCAMERA: //开启拍照 //origUri 是我们指定的拍照完毕后存储的uri startActionCrop(origUri); // 拍照后裁剪 break; case ImageUtils.REQUEST_CODE_GETIMAGE_BYCROP: //开启选取本地图片 if(imageReturnIntent != null) { //我们选择完图片后返回其Uri startActionCrop(imageReturnIntent.getData());// 选图后裁剪 } break; case ImageUtils.REQUEST_CODE_GETIMAGE_BYSDCARD: //开启图片剪裁 boolean b = protraitFile.exists(); if (!StringUtils.isEmpty(protraitPath) && protraitFile.exists()) { //protraitPath 是我们为裁剪后指定的图片的Uri protraitBitmap = ImageUtils.convertToBitmap(protraitPath, 200, 200); mImageView.setImageBitmap(protraitBitmap); } break; } }
这里,我们得到了最终剪裁后图片的Uri,并拿到其对应的路径,这样,无论是显示,还是上传或者其他功能,都在我们的掌控之中了。
1 0
- Android知识点总结:Android选取、拍照与裁剪图片相关流程分析
- Android启动相机拍照、相册选取图片,裁剪图片
- android拍照图片选取与图片剪裁
- Android拍照、相册选取、裁剪图片综合Demo
- android图片选取与调用系统裁剪
- android 打开默认的系统相册,或拍照选取图片,并图片裁剪;
- android调用系统拍照程序和从图库选取图片,返回后调用系统裁剪工具
- android调用系统拍照程序和从图库选取图片,返回后调用系统裁剪工具
- android调用系统拍照程序和从图库选取图片,返回后调用系统裁剪工具
- android打开相册选取图片或打开相机拍照并进行裁剪
- Android 7.0 之拍照与图片裁剪适配
- Android选取相册图片并裁剪
- 【Android实战】图片选取、拍摄、裁剪、上传
- Android从相册选取图片并裁剪
- android头像相册/拍照选取,裁剪及上传综合案例
- Android调用相册或相机拍照选取照片并裁剪
- android头像相册/拍照选取,裁剪及上传综合案例
- Android调用相册或相机拍照选取照片并裁剪
- 如果5.0环境,不能自动引入RecycleView CardView
- QQ分组实现,可收缩---ExpandableListView
- StringUtils
- installling Debian Desktop System
- FastJSON、Gson和Jackson性能对比
- Android知识点总结:Android选取、拍照与裁剪图片相关流程分析
- springmvc怎么重定向,从一个controller跳到另一个controller
- 利用HtmlParse获取Html内容并提取
- js的不稳定?
- Java常用的日期工具类
- 更强的微光闪烁效果--第三方开源--Shimmer-android
- redis(7)、redis持久化
- oj分类
- 获取异常的字符串信息