图片加载<第二篇>:BitmapFactory.Options详解

(1)常用属性
BitmapFactory.Options options = new BitmapFactory.Options();

//默认值为false,如果设置成true,那么在解码的时候就不会返回bitmap,即bitmap = null。
options.inJustDecodeBounds = false;

//可以复用之前用过的bitmap
options.inBitmap = null;

//是该bitmap缓存是否可变,如果设置为true,将可被inBitmap复用
options.inMutable = true;


DisplayMetrics dm = getResources().getDisplayMetrics();
//表示这个bitmap的像素密度,当inDensity为0时,系统默认赋值为屏幕当前像素密度
options.inDensity = dm.densityDpi;

//表示要被画出来时的目标像素密度,当inTargetDensity为0时,系统默认赋值为屏幕当前像素密度
options.inTargetDensity = options.inDensity;

//表示实际设备的像素密度
options.inScreenDensity = 0;

//这个参数可以改变bitmap分辨率大小,inSampleSize >= 1。
//当inSampleSize < 1时,inSampleSize就默认是1。
//假如:图片的宽和高分别是width、height,那么图片解码生成的bitmap的宽度是:width / inSampleSize,高度是:height / inSampleSize
//inSampleSize影响bitmap的分辨率,从而影响bitmap占用内存的大小。
options.inSampleSize = 1;

//设置这个Bitmap是否可以被缩放,默认值是true,表示可以被缩放。
options.inScaled = true;
(2)图片加载之前先计算图片大小
Bitmap bitmap = BitmapFactory.decodeFile(FileDirUtil.getInstance().getExternalStorageDirectory() + File.separator + "temp.jpg");

我们看一下上面的代码,那是解码一张本地图片,解码之后bitmap将占用内存空间,如果bitmap太大导致app性能降低,甚至导致OOM发生,为了防止这种现象,我们可以先计算本地图片的分辨率:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(FileDirUtil.getInstance().getExternalStorageDirectory() + File.separator + "temp.jpg", options );
int imageHeight = options.outHeight;
Log.d("aaa", "图片的高度:"+imageHeight);
int imageWidth = options.outWidth;
Log.d("aaa", "图片的宽度:"+imageWidth);

inJustDecodeBounds设置true时,本地图片解码之后bitmap为null,只计算图片的宽度和高度。拿到图片宽度和高度之后可以根据我们自己的策略是否放大或缩小图片分辨率。

(3)使用inBitmap复用bitmap

inMutable设置成true,可以使当前bitmap对空间可被复用。

(4)像素密度分析

BitmapFactory.Options中与像素密度有关的主要有三个参数:inDensityinTargetDensityinScreenDensity

配合inScaled参数可以控制图像缩放。

我们先看一下源码

/**
 * Set the newly decoded bitmap's density based on the Options.
 */
private static void setDensityFromOptions(Bitmap outputBitmap, Options opts) {
    if (outputBitmap == null || opts == null) return;

    final int density = opts.inDensity;
    if (density != 0) {
        outputBitmap.setDensity(density);
        final int targetDensity = opts.inTargetDensity;
        if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
            return;
        }

        byte[] np = outputBitmap.getNinePatchChunk();
        final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
        if (opts.inScaled || isNinePatch) {
            outputBitmap.setDensity(targetDensity);
        }
    } else if (opts.inBitmap != null) {
        // bitmap was reused, ensure density is reset
        outputBitmap.setDensity(Bitmap.getDefaultDensity());
    }
}

inDensity的默认值为0,会执行

outputBitmap.setDensity(Bitmap.getDefaultDensity());

bitmap的像素密度为屏幕默认像素密度,相当于

DisplayMetrics dm = getResources().getDisplayMetrics();
//表示这个bitmap的像素密度,当inDensity为0时,系统默认赋值为屏幕当前像素密度
options.inDensity = dm.densityDpi;

当我们给inDensity取值时,就会走另一个分支,接下来才是重点

当inTargetDensity=0或者inDensity=inTargetDensity或者inDensity=inScreenDensity时,图像的像素密度是inDensity,否则,当inScaled = true或者图像为9Path图片时,最终图像的像素密度为inTargetDensity。

inDensityinTargetDensityinScreenDensityinScaled配合使用可以对图片进行缩放,缩放的比例是targetDensity / density

(5)inSampleSize

修改像素密度只能修改图像的分辨率,但不能改变bitmap大小。
而inSampleSize不仅可以修改分辨率,而且bitmap的大小也随便变化。

假如默认情况(inSampleSize = 1)下,图像的分辨率是205x205,占用内存0.16031265M,那么如果将inSampleSize 设置成2,那么分辨率的宽和高分别除以2,占用的内存也会变小,最终图像的分辨率是103x103,占用内存为0.040470123M,bitmap大小整整缩小了4倍。

(6)设置彩色模式
options.inPreferredConfig = Bitmap.Config.ARGB_8888;

比较简单,只有一句话。

图片.png

ARGB_8888: 图像默认模式,有ARGB四个颜色通道,每个通道占8位。

ARGB_4444: 已被弃用,有ARGB四个颜色通道,每个通道占4位。

RGB_565: 屏幕默认颜色模式,有RGB三个颜色通道。

ALPHA_8: 单通道,只有透明度通道。

RGBA_F16HARDWARE是Android 8.0新增的,目前用的比较少。

(7)获取图像的Mime类型
options.outMimeType
(8)设置缓冲区大小
//设置缓存区,如果不设置默认为16M
options.inTempStorage = new byte[1024 * 1024 * 16];

如果不设置,那么默认为16M。

(9)其他方法
//这个值和抖动解码有关,默认值为false,表示不采用抖动解码。在Android N 之后已被废弃。
options.inDither = true;

//这个值表示是否在解码时图片有更高的品质,仅用于JPEG格式。如果设置为true,则图片会有更高的品质,但是会解码速度会很慢。
//在Android N 之后已被废弃。
options.inPreferQualityOverSpeed = true;

//设置为true时,表示空间不够是否可以被释放。和inInputShareable一起使用。在Android5.0后被弃用。
options.inPurgeable = false;

//设置为true时,后者表示是否可以共享引用。和inPurgeable一起使用。在Android5.0后被弃用。
options.inInputShareable = false;

//在Android N 之后已被废弃
options.mCancel = false;

以上这些方法在高版本API上已被弃用,所以就不用研究了。

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

推荐阅读更多精彩内容

  • 先发一张昨天去看我雷哥演唱会的皂片然后再说正文哈哈。 简介 由于工作原因,boss下达的任务就大概说了对图片进行压...
    我叫王菜鸟阅读 5,218评论 2 16
  • 7.1 压缩图片 一、基础知识 1、图片的格式 jpg:最常见的图片格式。色彩还原度比较好,可以支持适当压缩后保持...
    AndroidMaster阅读 2,499评论 0 13
  • 摘要:对android 上图片压缩,其实总结起来基本可以分为两类压缩:尺寸压缩和质量压缩, 尺寸压缩其实也可以理解...
    男爵是只猫丶阅读 8,774评论 2 14
  • 今天去学校一趟,跟以前比,给人的感觉是不一样的。 在学校两年半,直至拍毕业照时都没有一种“要毕业了”的感觉...
    柳璐樱阅读 1,385评论 1 1
  • 第一次知道 “端午节”是从祖母口中听说的。她当时正绘声绘色地给我讲“白娘子与许仙”的故事,说到白娘子与许仙自西湖边...
    浪里黑条条阅读 448评论 0 0