图片二次采样和压缩

图片的存在形式

1.文件形式(即以二进制形式存在于硬盘上)

2.流的形式(即以二进制形式存在于内存中)

3.Bitmap形式

这三种形式的区别: 文件形式和流的形式对图片体积大小并没有影响,也就是说,如果你手机SD卡上的如果是100K,那么通过流的形式读到内存中,也一定是占100K的内存,注意是流的形式,不是Bitmap的形式,当图片以Bitmap的形式存在时,其占用的内存会瞬间变大

1,检测图片三种形式大小的方法:

文件形式: file.length()

流的形式: 讲图片文件读到内存输入流中,看它的byte数

Bitmap: bitmap.getByteCount()

二.常见的压缩方式

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

特点是: File形式的图片确实被压缩了, 但是当你重新读取压缩后的file为 Bitmap是,它占用的内存并没有改变

图片二次采样的原因

二次采样就是为了避免图片加载时的OOM异常。

1.第一次采样

第一次采样我主要是想要获得图片的压缩比例,假如说我有一张图片是200200,那么我想把这张图片的缩略图显示在一个5050的ImageView上,那我的压缩比例应该为4,接下来我应该这么做,我先加载图片的边界到内存中,这个加载操作并不会耗费多少内存,加载到内存之后,我就可以获得这张图片的宽高参数,然后根据图片的宽高,再结合控件的宽高计算出缩放比例。

2.第二次采样

在第一次采样的基础上,我来进行二次采样。二次采样的时候,我把第一次采样后算出来的结果作为一个参数传递给第BitmapFactory,这样在加载图片的时候系统就不会将整张图片加载进来了,而是只会加载该图片的一张缩略图进来,这样不仅提高了加载速率,而且也极大的节省了内存,而且对于用户来说,他也不会有视觉上的差异

BitmapFactory.Options的作用:

1.防止内存溢出;

2.节省内存开销;

3.系统更流畅;

BitmapFactory.decodeByteArray方法对压缩后的byte[]解码后,得到的Bitmap大小依然和未压缩过一样

如果你想要显示的Bitmap占用的内存少一点,还是需要去设置加载的像素长度和宽度(变成缩略图)

BitmapFactory.Options的重要属性:

1.injustDecodeBounds;

设为true,那么BitmapFactory并不会真的返回一个Bitmap给你,它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM。

设置为false,BitmapFactory返回bitmap;

2.outWidth&outHeight;

bitmap图像的宽和高;

3.inSampleSize;

获取采样率

inSampleSize大于1时,图像高、宽分别以2的inSampleSize次方分之一缩小

inSampleSize小于等于1时,图像高、宽不变;

4.inpreferredConfig:

ALPHA_8: 每个像素用占8位,存储的是图像的透明值,占1个字节;

RGB_565:每个像素用占16位,分别为5-R,6-G,5-B通道,占2个字节;

ARGB-4444:每个像素占16位,即每个通道用4位表示,占2个字节;

ARGB_8888:每个像素占32位,每个通道用8位表示,占4个字节;

5.inDither:

是否进行图像抖动处理;

6.inMutable:

如果设置为true,将返回一个mutable的bitmap,可用于修改BitmapFactory加载而来的bitmap.

7.inScale:

是否需要放缩位图

图片二次采样的Java代码的实现

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;  
inJustDecodeBounds:
如果inJustDecoedBounds设置为true的话,解码bitmap时可以只返回其高、宽和Mime类型,而不必为其申请内存,从而节省了内存空间。



        //第一次加载图片,这时只会加载图片的边框进来,并不会加载图片中的像素点  
        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;  

inPreferredConfig "
这个值是设置色彩模式,默认值是ARGB_8888,在这个模式下,一个像素点占用4bytes空间,一般对透明度不做要求的话,一般采用RGB_565模式,这个模式下一个像素点占用2bytes。
        //加载图片并返回  
        return BitmapFactory.decodeFile(filePath, options);  
    }  
}  

图片的压缩

图片压缩

Bitmap.compress方法确实可以压缩图片,但压缩的是存储大小,即你放到disk上的大小

android图片压缩总结

总结来看,图片有三种存在形式:硬盘上时是file,网络传输时是stream,内存中是stream或bitmap,所谓 的质量压缩,它其实只能实现对file的影响,你可以把一个file转成bitmap再转成file,或者直接将一个bitmap转成file时,这个最终的file是被压缩过的,但是中间的bitmap并没有被压缩(或者说几乎没有被压缩,我不确定),因为bigmap在内存中的大小是按像素计算的,也就是width * height,对于质量压缩,并不会改变图片的像素,所以就算质量被压缩了,但是bitmap在内存的占有率还是没变小,但你做成file时,它确实变小了;

而尺寸压缩由于是减小了图片的像素,所以它直接对bitmap产生了影响,当然最终的file也是相对的变小了;

图片大小的压缩

private void resizePhoto() {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    
    BitmapFactory.decodeFile(mcurrentPhotoPath, options);
    
    double ratio = Math.max(options.outWidth*1.0d/1024 , options.outHeight*1.0d/1024);
    
    options.inSampleSize = (int)Math.ceil(ratio);
    
    options.inJustDecodeBounds = false;
    
    mphotoImage = BitmapFactory.decodeFile(mcurrentPhotoPath, options);
}

图片质量的压缩

//质量压缩
public static Bitmap compressImage(Bitmap image, int size) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
    int options = 100;
    while ( baos.toByteArray().length / 1024>50) {   //循环判断如果压缩后图片是否大于50kb,大于继续压缩       
        baos.reset();//重置baos即清空baos
        image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
        options -= 10;//每次都减少10
    }
    ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
    Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
    return bitmap;
}

质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度,来达到压缩图片的目的,图片的长,宽,像素都不会改变,那么bitmap所占内存大小是不会变的。

参考链接

二次采样的代码链接:https://blog.csdn.net/qq_37548177/article/details/73920917

图片的压缩(二次采样):https://www.cnblogs.com/bimingcong/p/4943659.html

图片压缩链接:
https://www.jianshu.com/p/c117450031ff

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351

推荐阅读更多精彩内容

  • 摘要:对android 上图片压缩,其实总结起来基本可以分为两类压缩:尺寸压缩和质量压缩, 尺寸压缩其实也可以理解...
    男爵是只猫丶阅读 8,774评论 2 14
  • 图片压缩就是为了避免我们内存溢出,所有要对一系列进行压缩二次采样等 1.什么是OOM?为什么会引起OOM? out...
    lay_wn阅读 959评论 0 1
  • 7.1 压缩图片 一、基础知识 1、图片的格式 jpg:最常见的图片格式。色彩还原度比较好,可以支持适当压缩后保持...
    AndroidMaster阅读 2,499评论 0 13
  • 为何要压缩 1、体积的原因如果你的图片是要准备上传的,那动辄几M的大小肯定不行的,况且图片分辨率大于设备分辨率的话...
    mahongyin阅读 799评论 0 1
  • 一直以来Bitmap都是开发中很棘手的问题,这个问题就是传说中的OOM(java.lang.OutofMemory...
    M悇芐冋忆阅读 4,745评论 0 11