Android大图片裁剪终极解决方案(上:原理分析)
转载声明:Ryan的博客文章欢迎您的转载,但在转载的同时,请注明文章的来源出处,不胜感激! :-)
http://my.oschina.net/ryanhoo/blog/86842
约几个月前,我正为公司的APP在Android手机上实现拍照截图而烦恼不已。
上网搜索,确实有不少的例子,大多都是抄来抄去,而且水平多半处于demo的样子,可以用来讲解知识点,但是一碰到实际项目,就漏洞百出。
当时我用大众化的解决方案,暂时性的做了一个拍照截图的功能,似乎看起来很不错。可是问题随之而来,我用的是小米手机,在别的手机上都运行正常,在小米这里却总是碰钉子。虽然我是个理性的米粉,但是也暗地里把小米的工程师问候了个遍。真是惭愧!
翻文档也找不出个答案来,我一直对com.android.camera.action.CROP持有大大的疑问,它是从哪里来,它能干什么,它接收处理什么类型的数据?Google对此却讳莫如深,在官方文档中只有Intent中有只言片语言及,却不甚详尽。
随着项目的驱动,我不能抱着不了解原理就不往前走的心态,唯一要做的,是解决问题。最后在德问上找到一条解决方案,说是哪怕是大米也没问题。当时乐呵呵将代码改了改,确实在所有的手机上跑起来了,一时如释重负,对这个的疑问也抛诸脑后了。
直到月前,BOSS要求将拍照上传到服务器的图片分辨率加倍。OK,加倍简单,增加outputX以及outputY不就得了?
|
1
2
|
intent.putExtra("outputX", outputX);intent.putExtra("outputY", outputY); |
这一增加,吓了我一跳。BOSS的手机拍到的照片几乎就是个缩略图,但是被我问候了全体工程师的小米在这个时候就体现出国产神机的范儿了,小米上的尺寸一切正常。这个为什么呢?我大致了解原因,却不知道如何解决。
在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
2
|
Mobile devices typically have constrained system resources. Android devices can have as little as 16MB of memory available to a single application. |
这是Android Doc的原文,虽然不同手机系统的厂商可能围绕16M这个数字有微微的上调,但是这30M,一般的手机还真挥霍不起。也只有小米这种牛机,内存堪比个人PC,本着土财主般挥金如土的霸气才能做到。
OK,说了这么多,无非是吐吐苦水,爆爆个人经历而已,实际的解决方案在哪里呢?
我也是Google到的,话说一般百度不了的问题,那就Google或者直接StackOverFlow,只不过得看英文罢了。
最后翻来覆去,我在国外的一个Android团队的博客中找到了相应的方案,印证了我的猜想同时也给出了实际的代码。
我将这篇文章翻译成了中文,作为本博客的基础,建议详细看看。
【译】如何使用Android MediaStore裁剪大图片
这篇博客了不起的地方在于解决了Android对返回图片的大小限制,并且详细解释了裁剪图片的Intent附加数据的具体含义。OK,我只是站在巨人的肩膀上,改善方案,适应更广泛需求而已。
拿图说事儿:

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 MediaStore裁剪大图片
中篇:
Android大图片裁剪终极解决方案(中:从相册截图)
下篇:
Android大图片裁剪终极解决方案(下:拍照截图)
Android大图片裁剪终极解决方案(上:原理分析)的更多相关文章
- Android大图片裁剪终极解决方案 原理分析
约几个月前,我正为公司的APP在Android手机上实现拍照截图而烦恼不已. 上网搜索,确实有不少的例子,大多都是抄来抄去,而且水平多半处于demo的样子,可以用来讲解知识点,但是一碰到实际项目,就漏 ...
- Android大图片裁剪终极解决方案(下:拍照截图)
http://blog.csdn.net/floodingfire/article/details/8144617 http://mzh3344258.blog.51cto.com/1823534/8 ...
- Android大图片之缩略图,以及对原图依照指定宽高裁剪成缩略图
<Android大图片之变换缩略图,以及对原始大图片依照指定宽.高裁剪成缩略图> 在Android的ImageView载入图像资源过程中,出于性能和内存开销的须要.有时候须要把一个原 ...
- Android大图片导致内存问题小结
在网上看了部分Android中OOM的问题,现在根据理解,做一下笔记. Android OOM 产生的几种原因 1. 程序中使用了太多自己创建的Bitmap. 这种情况通常是最好解决的. 因为你明白你 ...
- 图片裁剪 cropper.js 上传组件封装 vue
//HTML cropper.js 文档地址: https://github.com/fengyuanchen/cropperjs/blob/master/README.md <template ...
- [原创]Android Studio的Instant Run(即时安装)原理分析和源码浅析
Android Studio升级到2.0之后,新增了Instant Run功能,该功能可以热替换apk中的部分代码,大幅提高测试安装的效率. 但是,由于我的项目中自定义了一些ClassLoader,当 ...
- Android实现图片裁剪
MainActivity.java package com.kale.imagetailor; import java.io.File; import java.io.FileNotFoundExce ...
- 【Android】图片(文件)上传的请求分析结构
怎么在android中上传文件,即怎么用Java向服务器上传文件.上传图片,这是个老问题了,在网上能搜到现成的代码,很多朋友用起来也比较熟了,但是为什么这么写,可能很多朋友并不清楚,这篇文章就来分析一 ...
- 适应各浏览器图片裁剪无刷新上传jQuery插件(转)
看到一篇兼容性很强的图片无刷新裁剪上传的帖子,感觉很棒.分享下!~ 废话不多说,上效果图. 一.首先建立如下的一个page <!DOCTYPE html> <html xmlns=& ...
随机推荐
- 网易前端JavaScript编码规范【转】
1. 变量命名规范 变量名包括全局变量,局部变量,类变量,函数参数等等,他们都属于这一类. 基本规范 变量命名都以类型前缀+有意义的单词组成,单词首字母都需要大写.例如:sUserName,nCoun ...
- CSS3:过渡大全
代码 地址:http://jsbin.com/moquyesumi/edit?html,output <!DOCTYPE HTML> <html> <head> & ...
- panel,dialog,window组件越界问题汇总
之前分别写过panel,dialog,window三个组件因为拖曳或者reSize造成组件越界而无法还原的问题,两篇文章分别针对拖曳和reSize给出了解决方案.不过根据朋友的反馈,reSize的解决 ...
- [英语学习]国外的在线广播网站,类似喜马拉雅和荔枝FM
今天在Seattle Art Museum 网站上看东西,发现了这个好网站. 主要是外文资料,可以练听力,也可以找到<我爱吕西安>的英文版本. https://soundcloud.co ...
- [项目机会]citrix 虚拟桌面对于java等高CPU占用率如何解决
citrix 虚拟桌面对于java等高CPU占用率如何解决 问题1:java等客户端对于虚拟桌面cpu影响较大,但是有些用户的确需要使用java支持的程序,是否可以通过其他途径来解决? 问题2:对于其 ...
- Web 在线文件管理器学习笔记与总结(11)获取文件夹信息 (12)返回上一级操作
(11)获取文件夹信息 文件夹没有修改操作. index.php: <?php require 'dir.func.php'; require 'file.func.php'; require ...
- [SHELL实例] (转)最牛B的 Linux Shell 命令 (一)
本文编译自commandlinefu.com ( 应该是 Catonmat ) 的系列文章 Top Ten One-Liners from CommandLineFu Explained .作为一个由 ...
- CSS Questions:Front-end Developer Interview Questions
Describe what a "reset" CSS file does and how it's useful. What Is A CSS Reset? A CSS Rese ...
- jQuery 利用 $.getJson() 实现跨域
数据量不大时,跨域的不二之选,而且操作简单,易上手. a.com/test.html //这里我假定有一些数据: var formData = form.serialize(); //这里的jsonc ...
- TCPdump抓包命令详解--摘
http://blog.csdn.net/s_k_yliu/article/details/6665673/ http://starsliao.blog.163.com/blog/static/890 ...