我们很多时候需要进行图片的裁剪,其实这个功能在android系统中已经有一套解决方案了,虽然界面和效果并不是很优秀但功能毫无疑问是完美实现了。至于,不用自带的方案怎么做自定义,这个就是后话了。本篇主要讲解的是裁剪的原理和流程,外带分析了大图裁剪和小图裁剪的不同之处,同时给出具体的实现方案。

一、原理+流程

andorid提供了一个action,com.android.camera.action.CROP,

是Intent intent = new Intent("com.android.camera.action.CROP");

通过这个action就可以实现图片的裁剪,具体就是实现这个intent,然后在这个intent中putExtra()中put各种参数,最后通过来启动一个startActivityForResult(intent, requestCode);,这是裁剪图片的activity,进行裁剪。

裁剪完后返回一个bitmap,交给开发者进行处理。

也就是说,我们是通过系统写好的Activity进行了主要的操作,自己只需要在activity类中的onActivityResult中根据requestCode来进行判断和处理即可。

启动系统相册的Activity:

    /**
* 从相册获取图片
*/
private void choicePicFromAlbum() {
// 来自相册
Intent albumIntent = new Intent(Intent.ACTION_PICK, null);
/**
* 下面这句话,与其它方式写是一样的效果,如果:
* intent.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
* intent.setType(""image/*");设置数据类型
* 要限制上传到服务器的图片类型时可以直接写如:"image/jpeg 、 image/png等的类型"
*/
albumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(albumIntent, ALBUM_OK);
}

启动系统照相的Activity:

    /**
* 拍照后获取图片
*/
private void choicePicFromCamera() {
// 来自相机
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 下面这句指定调用相机拍照后的照片存储的路径,这样通过这个uri就可以得到这个照片了
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(cameraIntent, CAMERA_OK);// CAMERA_OK是用作判断返回结果的标识
}

启动裁剪图片的Activity:

    /**
* 裁剪图片方法实现
* @param uri
*/
public void clipPhoto(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP");
//可以选择图片类型,如果是*表明所有类型的图片
intent.setDataAndType(uri, "image/*");
// 下面这个crop = true是设置在开启的Intent中设置显示的VIEW可裁剪
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例,这里设置的是正方形(长宽比为1:1)
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 1000);
intent.putExtra("outputY", 1000);
//裁剪时是否保留图片的比例,这里的比例是1:1
intent.putExtra("scale", true);
//是否是圆形裁剪区域,设置了也不一定有效
//intent.putExtra("circleCrop", true);
//设置输出的格式
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
//是否将数据保留在Bitmap中返回
intent.putExtra("return-data", true); startActivityForResult(intent, CUT_OK);
}

二、主要问题

如果我们截取的图片是大图,那么我们首先会想着提高输出图片的大小

// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 800);
intent.putExtra("outputY", 800);

但这样就会出现问题,由于图片过大,占用内存过多所以系统会自行将图片进行压缩,以避免出现OOM的问题。下面摘录一篇博文的部分内容来解释这个问题:

原文:http://blog.csdn.net/floodingfire/article/details/8144604

  在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。

如此惊人的数字!哪怕你愿意为一张生命周期超不过10s的位图愿意耗费这么巨大的内存,Android也不会答应的。

1 Mobile devices typically have constrained system resources.
2 Android devices can have as little as 16MB of memory available to a single application.

这是Android Doc的原文,虽然不同手机系统的厂商可能围绕16M这个数字有微微的上调,但是这30M,一般的手机还真挥霍不起。也只有小米这种牛机,内存堪比个人PC,本着土财主般挥金如土的霸气才能做到。

得出的结论是,如果你截取的是小图那么就返回一个bitmap,但如果是大图那么就返回一个uri。这样就不会出现问题啦。

三、从相册中截图

参考自:http://blog.csdn.net/floodingfire/article/details/8144615

现在原作者托管的代码已经用了lib包作为例子了,和博客中略有差异。

原作者博文中写了两种方式,我个人用的不是很习惯。通过自己的测试发现博主提供的方法在手机上也没法适用,于是贴出自己的解决方案。目前在小米2-原生4.4系统上测试通过

 具体写法参照:

http://www.cnblogs.com/tianzhijiexian/p/3989296.html

这个文章是参照博主的写的,在miui上测试通过:http://www.cnblogs.com/tianzhijiexian/p/3859480.html,但之后就出问题了。

详细解释如何通过Android自带的方式来实现图片的裁剪——原理分析+解决方案的更多相关文章

  1. android开发——从相冊中选择图片不裁剪

    转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46864777 问题: 在郭神的第一行代码中,第8章的从相冊中选择图片这块,从相冊选 ...

  2. Activity详细解释(生命周期、以各种方式启动Activity、状态保存,等完全退出)

    一.什么是Activity? 简单的说:Activity或者悬浮于其它窗体上的交互界面. 在一个应用程序中通常由多个Activity构成.都会在Manifest.xml中指定一个主的Activity, ...

  3. POI操作Excel详细解释,HSSF和XSSF两种方式

    HSSF道路: package com.tools.poi.lesson1; import java.io.FileInputStream; import java.io.FileNotFoundEx ...

  4. Android slidingmenu详细解释 滑动的优化

    Android slidingmenu 详细解释 性能优化 转载请注明:   http://blog.csdn.net/aaawqqq 简单介绍 SlidingMenu 是github 上Androi ...

  5. Android中时间戳的详细解释

    Android中时间戳的详细解释: (1).定义: 时间戳就是根据当前系统时间生成的一组随机数字. (2).作用: 作为对数据唯一性的一种判断依据.避免了重复修改数据所带来的错误! (3).应用: ( ...

  6. 记一次使用 android 自带 WebView 做富文本编辑器之API、机型的兼容及各种奇葩bug的解决

    转载请声明出处(http://www.cnblogs.com/linguanh/) 目录 1,测试设备介绍 2,开源项目richeditor及CrossWalk的选择 3,遇到的bug及其解决方法 4 ...

  7. Linux学习笔记15——GDB 命令详细解释【转】

    GDB 命令详细解释 Linux中包含有一个很有用的调试工具--gdb(GNU Debuger),它可以用来调试C和C++程序,功能不亚于Windows下的许多图形界面的调试工具. 和所有常用的调试工 ...

  8. Android 4.4 KitKat NotificationManagerService使用具体解释与原理分析(一)__使用具体解释

    概况 Android在4.3的版本号中(即API 18)增加了NotificationListenerService,依据SDK的描写叙述(AndroidDeveloper)能够知道,当系统收到新的通 ...

  9. Nginx location配置详细解释

    nginx location配置详细解释 语法规则: location [=|~|~*|^~] /uri/ { - } = 开头表示精确匹配 ^~ 开头表示uri以某个常规字符串开头,理解为匹配 ur ...

随机推荐

  1. 在k8s集群中,利用prometheus的jmx_exporter进行tomcat的JVM性能监控,并用grafana作前端展示

    查找了很多文档,没有完全达到我要求的, 于是,作了一定的调整,成现在这样. 操作步骤如下: 一,准备好两个文件. jmx_prometheus_javaagent-0.3.1.jar jmx_expo ...

  2. H5地理位置定位

    一:介绍使用的知识点 1.地理定位的原理 2.geolocation对象 3.Geolocation Api 4.getCurrentPosition的第一个参数 5.getCurrentPositi ...

  3. 几种常见类的使用(System,Runtime,Math,Date,Calendar,Random)

    一:System 1.介绍 System:类中的方法和属性都是静态的. out:标准输出,默认是控制台. in:标准输入,默认是键盘. 2.properties 获取系统属性信息:Properties ...

  4. php 会话控制(Session会话控制)

    php的session会话是通过唯一的会话ID来驱动的,会话ID是一个加密的随机数字,由php生成,在会话的生命周期中都会保存在客户端.客户端保存数据的地方只有cookie,所以php的会话ID一般保 ...

  5. 002.Rsync详细配置项

    一 相关参数 全局参数 在文件中[module]之前的所有参数都是全局参数,当然也可以在全局参数部分定义模块参数,这时候该参数的值就是所有模块的默认值. port 指定后台程序使用的端口号,默认为87 ...

  6. JAVAEE——SpringBoot入门:简介、微服务、环境准备、helloworld与探究、快速构建项目

    一.Spring Boot 入门 1.Spring Boot 简介 简化Spring应用开发的一个框架: 整个Spring技术栈的一个大整合: J2EE开发的一站式解决方案: 2.微服务 2014,m ...

  7. Eclipse设置之:代码注释/server 控制台输出乱码解决

    1           Eclipse设置 Configure clean up style The location is here: And the configuration should fo ...

  8. Orleans介绍

    一.介绍 Orleans是一个框架,提供了一个直接的方法来构建分布式高规模计算应用程序 默认可扩展 -> Orleans处理构建分布式系统的复杂性,使您的应用程序能够扩展到数百台服务器.低延迟 ...

  9. Jindent——让intellij idea 像eclipse一样生成模版化的javadoc注释

    插件地址 http://plugins.jetbrains.com/plugin/2170?pr=idea 安装方法参考 http://www.cnblogs.com/nova-/p/3535636. ...

  10. BZOJ.3698.XWW的难题(有源汇上下界最大流ISAP)

    题目链接 按套路行列作为两部分,连边 \(S->row->column->T\). S向代表行的元素连边cap(A[i][n])(容量上下界为上下取整),代表列的元素向T连边cap( ...