前些天参加面试时,被问到的一个问题是:Android里面压缩图片有什么方法。当时只用了瀑布流照片墙的一些方法来回答,还是不够清楚,答得不太满意。现在就来总结一下Android中压缩图片的一些基本知识和流程。

一、引言

在移动开发中,图片压缩是一个非常重要的方面,因为设备内存有限,如果不对图片进行处理的话,可能会引起OOM;在瀑布流等图片经典demo中也使用了相应的处理,压缩图片等等。

现在先来了解一下Android图片的存在方式:
1.文件形式(即以二进制形式存在于硬盘上)
2.流的形式(即以二进制形式存在于内存中)
3.Bitmap形式
这三种形式的区别: 文件形式和流的形式对图片体积大小并没有影响,也就是说,如果你手机SD卡上的如果是100K,那么通过流的形式读到内存中,也一定是占100K的内存,注意是流的形式,不是Bitmap的形式,当图片以Bitmap的形式存在时,其占用的内存会瞬间变大, 增大的倍数是很可观的

检测图片三种形式大小的方法:
文件形式: file.length()
流的形式: 讲图片文件读到内存输入流中,看它的byte数
Bitmap: bitmap.getByteCount()

二、常用的图片压缩方法

**

1. BitmapFactory的decodeFile方法

**

特点: 通过设置采样率, 减少图片的像素, 达到对内存中的Bitmap进行压缩

首先,在处理图片的方法中,官方demo中推荐的也是这种方法。
结合现实场景来看,我们通常会将图片固定大小成缩略图,使用的就是decodeFile方法,然后通过传递进去 BitmapFactory.Option类型的参数取缩略图。

Option类在百度地图sdk或者其它地方中也看到过,可以说是参数或者限定的集和吧。在Option中,有两个重要的地方,一是inSampleSize表示采样率长宽压缩的比例,另外的就是inJustDecodeBounds,就是表示只包括一些解码边界信息即图片大小信息等等。举个具体的例子来说,还是以官方demo为主来讲吧:
inSampleSize表示缩略图大小为原始图片大小的几分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。
而inJustDecodeBounds设置为true的时候,就是提取图片大小信息,不返回实际的bitmap也不给其分配内存空间,但记得用完后就要把它设为false;

/**
* 计算压缩比率
*/public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth) {// 源图片的宽度final int width = options.outWidth;int inSampleSize = 1;if (width > reqWidth) {// 计算出实际宽度和目标宽度的比率final int widthRatio = Math.round((float) width / (float) reqWidth);inSampleSize = widthRatio;}return inSampleSize;}/*** 官方文档的用法改写,这是一个系列的* http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html* @param pathName* @param reqWidth* @return*/public static Bitmap decodeSampledBitmapFromResource(String pathName,int reqWidth) {// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小final BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(pathName, options);// 调用上面定义的方法计算inSampleSize值options.inSampleSize = calculateInSampleSize(options, reqWidth);// 使用获取到的inSampleSize值再次解析图片options.inJustDecodeBounds = false;return BitmapFactory.decodeFile(pathName, options);}

简要总结:
该方法就是对Bitmap形式的图片进行压缩, 也就是通过设置采样率, 减少Bitmap的像素, 从而减少了它所占用的内存。一般过程就是:
使用2的次幂来设置inSampleSize值可以使解码器执行地更加迅速、更加高效。但是,如果你想在内存或者硬盘上缓存一个调整过大小的图片,通常还是解码到合适的图片尺寸更加节省空间。

要使用这个方法,首先要使用inJustDecodeBounds为true来解码尺寸信息,将options传递过去使用新的inSampleSize值再次解码并且要将inJustDecodeBounds值设置为false。最后通过BitmapFactory.decode**的方法压缩。

2. 将图片保存到本地时进行压缩, 即将图片从Bitmap形式变为File形式时进行压缩,

特点是: File形式的图片确实被压缩了, 只对File格式进行质量压缩。注意:如果读取压缩后的file为Bitmap时,它占用的内存并没有改变

public static void compressBmpToFile(Bitmap bmp,File file){ByteArrayOutputStream baos = new ByteArrayOutputStream();int options = 80;//设置开始的compress系数bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);while (baos.toByteArray().length / 1024 > 100) { baos.reset();options -= 10;bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);}try {FileOutputStream fos = new FileOutputStream(file);fos.write(baos.toByteArray());fos.flush();fos.close();} catch (Exception e) {e.printStackTrace();}}

方法说明: 该方法是压缩图片的质量, 注意它不会减少图片的像素,比方说, 你的图片是300K的, 1280*700像素的, 经过该方法压缩后, File形式的图片是在100K以下, 以方便上传服务器, 但是你BitmapFactory.decodeFile到内存中,变成Bitmap时,它的像素仍然是1280*700, 计算图片像素的方法是 bitmap.getWidth()和bitmap.getHeight(), 图片是由像素组成的, 每个像素又包含什么呢? 熟悉PS的人知道, 图片是有色相,明度和饱和度构成的.

该方法的官方文档也解释说, 它会让图片重新构造, 但是有可能图像的位深(即色深)和每个像素的透明度会变化,JPEG only supports opaque(不透明), 也就是说以jpeg格式压缩后, 原来图片中透明的元素将消失.所以这种格式很可能造成失真

既然它是改变了图片的显示质量, 达到了对File形式的图片进行压缩, 图片的像素没有改变的话, 那重新读取经过压缩的file为Bitmap时, 它占用的内存并不会少.

所以呢,这种方法比较适用上传服务器时的图片压缩

Android图片压缩浅谈相关推荐

  1. Android图片压缩(质量压缩和尺寸压缩)

    在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...

  2. gif透明背景动画_前端基础系列之bmp、jpg、png、gif、svg常用图片格式浅谈(二)...

    IT客栈 作者:大腰子 bmp.jpg.png.gif.svg常用图片格式 之前为大家介绍了几种WEB前端常用的图片格式,对比了它们的特点,参见<前端基础系列之bmp.jpg.png.gif.s ...

  3. Android 图片压缩、照片选择、裁剪,上传、一整套图片解决方案

    1.Android一整套图片解决方案 http://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650820998&idx=1& ...

  4. Android 图片压缩器

    概述 Android 图片压缩器:一款高效的图片压缩器库,支持批量压缩,异步压缩.多线程多任务压缩,压缩比设置等特性. 详细 代码下载:http://www.demodashi.com/demo/12 ...

  5. Android图片压缩尺寸和质量

    Android在处理图片时,如果不进行压缩处理,很容易就出现OOM内存溢出(OutOfMemory)问题,所以无论是第三方图片加载还是自己在处理图片时,都要进行压缩处理. Android系统中,一张图 ...

  6. android 图片压缩总结1

    在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...

  7. Android图片压缩库——libjpeg-turbo

    为何Android图片压缩效率比IOS低质量差 为什么Android的图片压缩质量要比iPhone的压缩质量差很多,这是因为Android底层犯的一个小错误:libjpeg.并且这个错误一直持续到了今 ...

  8. 最详细的Android图片压缩攻略

    Mr.Louis的博客地址: https://blog.csdn.net/weixin_44005563 最近在研究图片压缩原理,看了大量资料,从上层尺寸压缩.质量压缩原理到下层的哈夫曼压缩,走成华大 ...

  9. android 图片压缩,bitmap压缩总结

    1.    图片压缩相关概念 在android开发中,图片加载到内存中通常需要占用大量的内存,导致app性能过度消耗,严重的话可能会导致OOM异常,所以对图片进行优化就尤为重要. android图片压 ...

最新文章

  1. 自己写的一个tomcat发布脚本
  2. java javac javap 命令使用简介
  3. 静态程序分析chapter4 - 基于格(Lattice)理论的数据流分析
  4. Web.py Cookbook 简体中文版 - Hello World!
  5. 小程序云开发搜索功能的实现正则_几行代码实现小程序云开发提现功能
  6. 小程序左右标签滑块排行榜
  7. ulimit限制 新系统_Linux查看及修改系统的资源限制命令ulimit
  8. java中readline函数_自定义BufferedReader中read和readLine方法
  9. C语言数据结构各种排序算法(选择,直接,希尔,起泡等排序)
  10. WORD2010每次启动都要配置
  11. python将excel导入生成矩阵_Python导入数值型Excel数据并生成矩阵操作
  12. 通才还是专才——由摩托裁员引发的讨论
  13. 基本数据结构----顺序表
  14. 单服务器部署rancher_基于CentOS 7部署Rancher 2.0
  15. Redis雪崩和Redis穿透
  16. 请问苹果x是如何建文件夹_苹果手机怎么建文件夹
  17. 旁路电容、滤波电容、去耦电容的作用与应用原理详解
  18. MapReduce 与 Database 的乌龙战
  19. 腾讯互娱AMS | 我的打包我做主——浅析前端构建
  20. Android-简单单词书app

热门文章

  1. npm 使用淘宝镜像
  2. 属牛的女孩起名:高贵有气质的女孩名字怎么取
  3. delta机器人 寸拳_阅读小说 第四十四章 连环寸拳-重生之功夫机器人内容-我就去小说网...
  4. 算法笔记---最大公约数和最小公倍数
  5. Linux如何用find命令查找文件
  6. oracle创建dml触发器,Oracle数据库创建DML触发器
  7. scratch练习之渣男
  8. 上周五NYMEX原油期货0810合约下跌6.59美元/桶,国际油价创17年来最大单日跌幅
  9. Webpack前端打包工具
  10. 香肠派对显示服务器断开怎么解决,香肠派对匹配自动取消什么情况?大家不要慌服务器异常马上解决[多图]...