前些天参加面试时,被问到的一个问题是: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. OSError: [WinError 126] 找不到指定的模块————Shapely
  2. Luogu P5244 [USACO2019Feb Platinum] Mowing Mischief (动态规划、决策单调性)
  3. 开年赢好运!程序员加油包等你免费拿
  4. JavaScript 中的闭包和作用域链(读书笔记)
  5. layer 线上_LAYER
  6. 校验插入指定结点是否导致编码循环的示例函数
  7. 【LeetCode】【字符串】题号:*299. 猜数字游戏
  8. Linux系统调用怎么和内核或底层驱动交互的 inode struct file
  9. 软考下午c语言真题,软考程序员下午试题分析和备考建议
  10. 【C语言】标准内容介绍(C99)
  11. 启科量子在2022全球数字经济大会量子信息技术与应用论坛公布量子计算机工程化进展
  12. A Deep Journey into Super-resolution: A Survey阅读
  13. jQuery菜鸟学习实例
  14. 做了三年数据分析,给你的几点建议
  15. concat特征融合_小目标检测文献相关(特征融合)
  16. 【信号与系统】(二十)傅里叶变换与频域分析——取样定理
  17. [go学习笔记.第一章] go可以做什么
  18. 设变量n为float类型,m为int类型,则以下能实现将n中的数值保留小数点后两位,第三位进行四舍五人运算的表达式是: A) n=(n*100+0.5)/100.0 B)m=n*100+0.5
  19. 魔术师usm安装服务器系统,U盘魔术师V3(USMv3)
  20. HTML第二天学习总结—— 表格

热门文章

  1. Android代码模拟物理、屏幕点击事件 、APP内部自动点击
  2. Unity ~2D精灵动画制作
  3. 员工类为抽象父类,包括属性:姓名、职位、基本工资、应发工资、实发工资、应缴税;
  4. 直通车运营,直通车养分计划,直通车养分需注意的点,直通车怎样上分
  5. 如何用大数据解读流浪汉的生活
  6. Python Docker 镜像使用yum命令报错 except KeyboardInterrupt, e: SyntaxError: invalid syntax
  7. Redis源码详解 - Replication(主备)流程
  8. Windows10配置JAVA环境变量(图文教程)
  9. 网站绑定域名如何操作呢
  10. Python 龙贝格/Romberg算法