Android 拍照或从相册取图片并裁剪

2024-06-21 15:18

本文主要是介绍Android 拍照或从相册取图片并裁剪,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android 拍照或从相册取图片并裁剪


转载自:http://www.cnblogs.com/w-y-f/p/4028379.html

  在Android中,Intent触发Camera程序,拍好照片后,将会返回数据,但是考虑到内存问题,Camera不会将全尺寸的图像返回给调用的Activity,一般情况下,有可能返回的是缩略图,比如120*160px。

    这是为什么呢?这不是一个Bug,而是经过精心设计的,却对开发者不透明。

    比如摄像头800W像素,根据我目前设置拍出来的图片尺寸为3200*2400px。有人说,那就返回呗,大不了耗1-2M的内存,不错,这个尺寸的图片确实只有1.8M左右的大小。但是你想不到的是,这个尺寸对应的Bitmap会耗光你应用程序的所有内存。Android出于安全性考虑,只会给你一个寒碜的缩略图。

    在Android2.3中,默认的Bitmap为32位,类型是ARGB_8888,也就意味着一个像素点占用4个字节的内存。我们来做一个简单的计算题:3200*2400*4 bytes =   30M,所以用拍照得到的图片需要裁剪处理后使用。

Android裁剪图片的Intent附加数据的具体含义,拿图说事儿:

    Intent("com.android.camera.action.CROP")对应的所有可选数据都一目了然。在了解上面个个选项的含义之后,我们将目光着眼于三个极为重要的选项:

    data、MediaStore.EXTRA_OUTPUT以及return-data。

    data和MediaStore.EXTRA_OUTPUT都是可选的传入数据选项,你可以选择设置data为Bitmap,或者将相应的数据与URI关联起来,你也可以选择是否返回数据(return-data: true)。

    为什么还有不用返回数据的选项?如果对URI足够了解的话,应该知道URI与File相似,你所有的操作如裁剪将数据都保存在了URI中,你已经持有了相应的URI,也就无需多此一举,再返回Bitmap了。

    前面已经说到,可以设置data为Bitmap,但是这种操作的限制在于,你的Bitmap不能太大。因此,我们前进的思路似乎明确了:截大图用URI,小图用Bitmap。

    我将这个思路整理成一张图片:

 

从相册截图

    在上面,我就拍照截图这一需求进行了详细的分析,试图让大家了解Android本身的限制,以及我们应当采取的实现方案。

    根据我们的分析与总结,图片的来源有拍照和相册,而可采取的操作有

  • 使用Bitmap并返回数据
  • 使用Uri不返回数据

    前面我们了解到,使用Bitmap有可能会导致图片过大,而不能返回实际大小的图片,我将采用大图Uri,小图Bitmap的数据存储方式。

    我们将要使用到URI来保存拍照后的图片:

private static final String IMAGE_FILE_LOCATION = "file:///sdcard/temp.jpg";//temp file
Uri imageUri = Uri.parse(IMAGE_FILE_LOCATION);//The Uri to store the big bitmap

    不难知道,我们从相册选取图片的Action为Intent.ACTION_GET_CONTENT。

    根据我们上一篇博客的分析,我准备好了两个实例的Intent。

    一、从相册截大图:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);intent.setType("image/*");intent.putExtra("crop", "true");intent.putExtra("aspectX", 2);intent.putExtra("aspectY", 1);intent.putExtra("outputX", 600);intent.putExtra("outputY", 300);intent.putExtra("scale", true);intent.putExtra("return-data", false);intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());intent.putExtra("noFaceDetection", true); // no face detection

startActivityForResult(intent, CHOOSE_BIG_PICTURE);

    二、从相册截小图

Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);intent.setType("image/*");intent.putExtra("crop", "true");intent.putExtra("aspectX", 2);intent.putExtra("aspectY", 1);intent.putExtra("outputX", 200);intent.putExtra("outputY", 100);intent.putExtra("scale", true);intent.putExtra("return-data", true);intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());intent.putExtra("noFaceDetection", true); // no face detection

startActivityForResult(intent, CHOOSE_SMALL_PICTURE);

    三、对应的onActivityResult可以这样处理返回的数据

switch (requestCode) {case CHOOSE_BIG_PICTURE:Log.d(TAG, "CHOOSE_BIG_PICTURE: data = " + data);//it seems to be nullif(imageUri != null){Bitmap bitmap = decodeUriAsBitmap(imageUri);//decode bitmap
imageView.setImageBitmap(bitmap);}break;case CHOOSE_SMALL_PICTURE:if(data != null){Bitmap bitmap = data.getParcelableExtra("data");imageView.setImageBitmap(bitmap);}else{Log.e(TAG, "CHOOSE_SMALL_PICTURE: data = " + data);}break;default:break;}private Bitmap decodeUriAsBitmap(Uri uri){Bitmap bitmap = null;try {bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));} catch (FileNotFoundException e) {e.printStackTrace();return null;}return bitmap;}

拍照截图

    拍照截图有点儿特殊,要知道,现在的Android智能手机的摄像头都是几百万的像素,拍出来的图片都是非常大的。因此,我们不能像对待相册截图一样使用Bitmap小图,无论大图小图都统一使用Uri进行操作。

    一、首先准备好需要使用到的Uri:

private static final String IMAGE_FILE_LOCATION = "file:///sdcard/temp.jpg";//temp file
Uri imageUri = Uri.parse(IMAGE_FILE_LOCATION);//The Uri to store the big bitmap

    二、使用MediaStore.ACTION_IMAGE_CAPTURE可以轻松调用Camera程序进行拍照:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//action is capture

intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);startActivityForResult(intent, TAKE_BIG_PICTURE);//or TAKE_SMALL_PICTURE

    三、接下来就可以在 onActivityResult中拿到返回的数据(Uri),并将Uri传递给截图的程序。

switch (requestCode) {case TAKE_BIG_PICTURE:Log.d(TAG, "TAKE_BIG_PICTURE: data = " + data);//it seems to be null//TODO sent to crop
cropImageUri(imageUri, 800, 400, CROP_BIG_PICTURE);break;case TAKE_SMALL_PICTURE:Log.i(TAG, "TAKE_SMALL_PICTURE: data = " + data);//TODO sent to crop
cropImageUri(imageUri, 300, 150, CROP_SMALL_PICTURE);break;default:break;}

    可以看到,无论是拍大图片还是小图片,都是使用的Uri,只是尺寸不同而已。我们将这个操作封装在一个方法里面。

private void cropImageUri(Uri uri, int outputX, int outputY, int requestCode){Intent intent = new Intent("com.android.camera.action.CROP");intent.setDataAndType(uri, "image/*");intent.putExtra("crop", "true");intent.putExtra("aspectX", 2);intent.putExtra("aspectY", 1);intent.putExtra("outputX", outputX);intent.putExtra("outputY", outputY);intent.putExtra("scale", true);intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);intent.putExtra("return-data", false);intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());intent.putExtra("noFaceDetection", true); // no face detection
startActivityForResult(intent, requestCode);}

    四、最后一步,我们已经将数据传入裁剪图片程序,接下来要做的就是处理返回的数据了:

    switch (requestCode) {case CROP_BIG_PICTURE://from crop_big_picture
Log.d(TAG, "CROP_BIG_PICTURE: data = " + data);//it seems to be nullif(imageUri != null){Bitmap bitmap = decodeUriAsBitmap(imageUri);imageView.setImageBitmap(bitmap);}break;case CROP_SMALL_PICTURE:if(imageUri != null){Bitmap bitmap = decodeUriAsBitmap(imageUri);imageView.setImageBitmap(bitmap);}else{Log.e(TAG, "CROP_SMALL_PICTURE: data = " + data);}break;default:break;}

这篇关于Android 拍照或从相册取图片并裁剪的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1081579

相关文章

基于Python实现高效PPT转图片工具

《基于Python实现高效PPT转图片工具》在日常工作中,PPT是我们常用的演示工具,但有时候我们需要将PPT的内容提取为图片格式以便于展示或保存,所以本文将用Python实现PPT转PNG工具,希望... 目录1. 概述2. 功能使用2.1 安装依赖2.2 使用步骤2.3 代码实现2.4 GUI界面3.效

在Android平台上实现消息推送功能

《在Android平台上实现消息推送功能》随着移动互联网应用的飞速发展,消息推送已成为移动应用中不可或缺的功能,在Android平台上,实现消息推送涉及到服务端的消息发送、客户端的消息接收、通知渠道(... 目录一、项目概述二、相关知识介绍2.1 消息推送的基本原理2.2 Firebase Cloud Me

Python实现AVIF图片与其他图片格式间的批量转换

《Python实现AVIF图片与其他图片格式间的批量转换》这篇文章主要为大家详细介绍了如何使用Pillow库实现AVIF与其他格式的相互转换,即将AVIF转换为常见的格式,比如JPG或PNG,需要的小... 目录环境配置1.将单个 AVIF 图片转换为 JPG 和 PNG2.批量转换目录下所有 AVIF 图

详解如何通过Python批量转换图片为PDF

《详解如何通过Python批量转换图片为PDF》:本文主要介绍如何基于Python+Tkinter开发的图片批量转PDF工具,可以支持批量添加图片,拖拽等操作,感兴趣的小伙伴可以参考一下... 目录1. 概述2. 功能亮点2.1 主要功能2.2 界面设计3. 使用指南3.1 运行环境3.2 使用步骤4. 核

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(