一、简介:

在开发过程中,我们或多或少的都会接触到Bitmap这个东西,用的不好的话就会出现OOM问题,同时,也会有压缩的需求,可能有人会说,向Glide不是已经对图片压缩了么,但有时向图片上传到服务器功能,还得需要我们手动处理,去压缩图片后,再上传,否则,会造成上传很慢,尤其是用户网速不好的时候,还会浪费用户流量,甚至上传失败。

二、首先了解一下关于Bitmap的Config的理解

1、)A:透明度 R:红色 G:绿 B:蓝

public enum Config {

ALPHA_8 (1),

RGB_565 (3),

@Deprecated

ARGB_4444 (4),

ARGB_8888 (5);

}

Bitmap.Config ARGB_4444:每个像素占四位,即A=4,R=4,G=4,B=4,那么一个像素点占4+4+4+4=16位

Bitmap.Config ARGB_8888:每个像素占四位,即A=8,R=8,G=8,B=8,那么一个像素点占8+8+8+8=32位

Bitmap.Config RGB_565:每个像素占四位,即R=5,G=6,B=5,没有透明度,那么一个像素点占5+6+5=16位

Bitmap.Config ALPHA_8:每个像素占四位,只有透明度,没有颜色。

2、)内存计算

一张 1024 * 1024 像素,采用ARGB8888格式,一个像素32位,每个像素就是4字节,占有内存就是4M若采用RGB565,一个像素16位,每个像素就是2字节,占有内存就是2M。

Glide加载图片默认格式RGB565,Picasso为ARGB8888,默认情况下,Glide占用内存会比Picasso低,色彩不如Picasso鲜艳,自然清晰度就低。

通常我们优化Bitmap时,当需要做性能优化或者防止OOM(Out Of Memory),我们通常会使用Bitmap.Config.RGB_565这个配置,因为Bitmap.Config.ALPHA_8只有透明度,显示一般图片没有意义,Bitmap.Config.ARGB_4444显示图片不清楚,Bitmap.Config.ARGB_8888占用内存最多。

图片加载

如果我们想要加载一张大图到内存中,如果不进行压缩的话,那么很显然就会出现OOM的崩溃,

譬如我们加载一张5440*3000的大图到手机上面,如果不进行压缩处理的话,那么就会出现OOM。

错误日志如下

java.lang.OutOfMemoryErrorandroid.graphics.BitmapFactory.nativeDe

codeStream(Native

Method)android.graphics.BitmapFactory.decodeStreamInternal(Bitmap

Factory.java:703)android.graphics.BitmapFactory.decodeStream(Bitm

apFactory.java:679)android.graphics.BitmapFactory.decodeFile(Bitma

pFactory.java:446)android.graphics.BitmapFactory.decodeFile(Bitmap

Factory.java:480)com.example.ly.bitmapdemo.MainActivity.onCreate(M

ainActivity.java:21)

导致这种情况的发生的根据原因就是内存溢出,Android给每个APP的内存都是有限的,所以不能容忍这种情况的发生,所以我们就必须进行压缩一下。

压缩后的效果如下:

图片压缩

我们在上传一张图片到服务器时一般都会先进行压缩一下,这样不仅可以节省流量同时也可以节约上传的时间。最近碰到项目里碰到一个问题:图片上传时,有时会出现超时的问题,客户那边出现的频率非常高,而我的手机却基本没出现过,检查了一下原因,大概有两个:

客户的网速不是太好,3G速度不够,上传图片需要很长时间导致超时产生。图片很大,占了3、4M,没经过压缩直接上传,导致超时产生。

针对以上两种情况,主要对于第二种原因进行优化。总结来说就是将图片进行压缩再上传,经过一系列的操作,发现超时现象基本不会出现了,原先2M的图片,经过压缩只有50Kb不到,压缩率达到60%,效果很明显。

原理分析

如何将一张大图压缩到100kb以下并且保持不失真的特性?这就需要用到下面这个类了BitmapFactory.Options

BitmapFactory.Options缩放图片主要用到inSample采样率,

inSample = 1,采样后图片的宽高为原始宽高

inSample > 1,例如2,宽高均为原图的宽高的1/2

一个采用ARGB8888的1024 *1024 的图片

inSample = 1,占用内存就 1024 *1024 *4 = 4M

inSample = 2,占用内存就 512 *512 * 4 = 1M

BitmapFactory 给我们提供了一个解析图片大小的参数类 BitmapFactory.Options ,把这个类的对象的 inJustDecodeBounds 参数设置为 true,这样解析出来的 Bitmap 虽然是个 null,但是 options 中可以得到图片的宽和高以及图片的类型。得到了图片实际的宽和高之后我们就可以进行压缩设置了,主要是计算图片的采样率。

//第一次采样

BitmapFactory.Options options = new BitmapFactory.Options();

//该属性设置为true只会加载图片的边框进来,并不会加载图片具体的像素点,也就是说不会把图片加载到内存中

options.inJustDecodeBounds = true;

//第一次加载图片,这时只会加载图片的边框进来,并不会加载图片中的像素点

BitmapFactory.decodeFile(filePath, options);

//获得原图的宽和高

int outWidth = options.outWidth;

int outHeight = options.outHeight;

接下来就需要进行选定压缩的采样率了。目前市场上的主流手机分辨率一般最低是720-1280了所以就按照此分辨率进行压缩

//原始图片的宽度与720的比值,然后向上取整这里为8

int wRatio = (int) Math.ceil(options.outWidth / (float) 720);

//原始图片的高度与1280的比值,然后向上取整这里为3

int hRatio = (int) Math.ceil(options.outHeight / (float) 1280); //获取采样率

if (wRatio > 1 && hRatio > 1) {

if (wRatio > hRatio) {

options.inSampleSize = wRatio;

} else {

options.inSampleSize = hRatio;

}

}

经过上面这个采样率进行压缩后的宽和高肯定是小于720-1270的,我们计算的结果是:680-375

我们来实际比较一下压缩结果:

原先:54403000*如果采用ARGB_8888模式的话,那么如果不压缩直接加载到内存的话,那么它将占:

5440/1024 *3000/1024 *4 = 62.25M,不崩溃才怪呢~

那么现在:680375*见证奇迹的时候,680/1024 *375/1024 *4=0.9M

两者一比较的话,那么效果还是比较明显的,相差大约64倍,所以还是可以的。当然了经过上面的压缩方法,我们将压缩后的图片上传到服务器的话,那么将会大大的减少流量同时也会减少上传超时的几率的。

当然了,如果还嫌大的话,我们可以进一步增加压缩的比例,可以设置成480800*,那么这样的话,质量肯定是有所下降的。

这里是图片二次采样的代码

public class BitmapUtils {

/**

* @param filePath 要加载的图片路径

* @param destWidth 显示图片的控件宽度

* @param destHeight 显示图片的控件的高度

* @return

*/

public static Bitmap getBitmap(String filePath, int destWidth, int destHeight) {

//第一次采样

BitmapFactory.Options options = new BitmapFactory.Options();

//该属性设置为true只会加载图片的边框进来,并不会加载图片具体的像素点

options.inJustDecodeBounds = true;

//第一次加载图片,这时只会加载图片的边框进来,并不会加载图片中的像素点

BitmapFactory.decodeFile(filePath, options);

//获得原图的宽和高

int outWidth = options.outWidth;

int outHeight = options.outHeight;

//定义缩放比例

int sampleSize = 1;

while (outHeight / sampleSize > destHeight || outWidth / sampleSize > destWidth) {

//如果宽高的任意一方的缩放比例没有达到要求,都继续增大缩放比例

//sampleSize应该为2的n次幂,如果给sampleSize设置的数字不是2的n次幂,那么系统会就近取值

sampleSize *= 2;

}

/********************************************************************************************/

//至此,第一次采样已经结束,我们已经成功的计算出了sampleSize的大小

/********************************************************************************************/

//二次采样开始

//二次采样时我需要将图片加载出来显示,不能只加载图片的框架,因此inJustDecodeBounds属性要设置为false

options.inJustDecodeBounds = false;

//设置缩放比例

options.inSampleSize = sampleSize;

options.inPreferredConfig = Bitmap.Config.ARGB_8888;

//加载图片并返回

return BitmapFactory.decodeFile(filePath, options);

}

}

glide 压缩图拍呢_Android图片压缩(二次采样)相关推荐

  1. 如何压缩jpg大小?jpg图片压缩的简单方法

    我们日常的学习.工作中,经常需要收发很多jpg图片.当这些jpg图片体积过大的时候,不仅会减缓我们传输的速度,还会占用大量的电脑储存空间.那么如何将图片压缩(https://www.yasuotu.c ...

  2. 怎么把图片压缩100k?如果将图片压缩指定大小?

    很多时候想要把图片压缩大小到固定数值,这时候用压缩图的图片压缩到指定大小(图片压缩到指定大小 图片压缩大小至指定kb以下-压缩图)就非常方便,下面以图片压缩到100k以内为例子来讲解一下具体步骤. 1 ...

  3. Android_Bitmap_图片的二次采样并生成缩略图

    首先尝试通过字节数组或者流,只去加载图片的外边缘,此时必须指定BitmapFactory.Options 的inJustDecodeBounds成员名,将其只为true,一旦设置为true,Bitma ...

  4. glide 压缩图拍呢_用Glide-图片的压缩-图片压缩原理

    前言: 这一节里面我们将介绍Glide如何对图片进行压缩,这一点在加载图片较多或者加载的图片像素很高的程序里面至关重要 Glide 系列目录 1.Glide-入门教程 2.Glide-占位图以及加载动 ...

  5. [android图片压缩]一款不错的图片压缩,值得学习!

    前言:大家都做过类似图片上传的app,也不免涉及到处理图片问题,在处理图片的时候就可能出现失真的效果,比如在网络不好的情况下大图上传导致的网络卡顿造成体验效果差,还有本身处理图片就要处理IO异常,在开 ...

  6. 如何压缩照片不失真?图片压缩不模糊的方法

    经常拍照的小伙伴们应该都知道,现在的数码设备的像素越来越高,所以拍摄出来的照片也就越来越大,一般照片都在几M到十几M之间,这些图片虽然非常清楚,但是同样的也非常占空间,平时在使用或者发送.上传的时候非 ...

  7. 图片怎么压缩到200k以内?图片压缩怎么指定大小?

    ​在某些情况下,我们需要将图片压缩到指定(https://www.yasuotu.com/imagesize)的大小,例如200k以内,在本文中,我们将用一个特别简单的方法来将图片压缩到200k以内的 ...

  8. okhttp3图片压缩上传_支持 图片压缩、PDF压缩 合并 分割的网址、极力推荐、超奈斯...

    今天给大家分享的是一个可以进行图片压缩,PDF文件编辑的好用网址. 名称:docsmall 大家有没有那种因为上传图片时体积过大,需要缩小,但找半天也找不到压缩工具的时候. 这个网址小编用了很长时间了 ...

  9. python图像文件压缩_python中如何实现图片压缩

    python实现图片压缩的方法:1.导入Image包:2.使用get_size(file)命令获取图片文件的大小:3.使用[os.path.splitext()]方式拼接文件地址:然后压缩文件到指定大 ...

最新文章

  1. Linux内核网络栈1.2.13-socket.c函数概述
  2. Ajax---根据id从数据库查找对应的省份名称
  3. (七)日志采集工具sleuth--分布式链路跟踪(zipkin)
  4. corosync+pacemaker+crmsh配置高可用集群。
  5. layer.open子页面调用父页面的方法_记好这 24 个 ES6 方法,用来解决实际开发的 JS 问题...
  6. angularjs directive 实例 详解
  7. 教你简单理解分布式与传统单体架构的区别
  8. SPI 读取不同长度 寄存器_[读书笔记]《计算机科学速成课》—6 寄存器和内存
  9. 浏览器专属 CSS Hack:区分 Firefox / Opera / Safari / Internet Explorer
  10. File对象的深度遍历以及删除练习。
  11. java实现订单物品计算佣金,java三角形、NextDay、佣金问题代码
  12. 自己编写错误代码的规范
  13. 开源 java CMS - FreeCMS2.3会员我的简历
  14. echart保存图片的两种实现方式
  15. 服务器密码忘记处理之二:重置密码
  16. MySQL--binlog--介绍/用法
  17. 2022年安全员-C证上岗证题目及在线模拟考试
  18. *.dfm resource kept;file *.dfm resource discarded
  19. 设置Notes暗黑模式
  20. killer queen ctf

热门文章

  1. 一个误操作导致 5.4 万 Star 全部归零,10年的心血...
  2. Protege新手入门(基础篇)
  3. 计算两坐标点球面距离、两向量夹角及多边形面积
  4. 计算机基础优质课教案,计算机基础公开课教案
  5. 华为称鸿蒙系统支持第三方手机,“开源开放毫无保留”,欢迎厂商使用
  6. RT-Thread Studio 使用笔记(九)| 开启OLED显示(使用 u8g2 软件包 c-latest 版本)
  7. 淘宝评价计分规则,店铺信用评价如何累计
  8. C语言输入一个字符,完成大小写转换
  9. 搜狗输入法 状态栏 自带的好用工具
  10. 大暑节气海报图片|大暑节气海报文案