运用BitmapFactory.Options来改善程序加载图片效率和避免内存溢出

android BitmapFactory.Options使用方法详解 BitmapFactory.Options的使用是在加载图片时,就从图片的加载和使用说起  怎样获取图片的大小? 首先我们把这个图片转成Bitmap,然后再利用Bitmap的getWidth()和getHeight()方法就可以取到图片的宽高了。 新问题又来了,在通过BitmapFactory.decodeFile(String path)方法将突破转成Bitmap时,遇到大一些的图片,我们经常会遇到OOM(Out Of Memory)的问题。怎么避免它呢? 这就用到了我们上面提到的BitmapFactory.Options这个类。 BitmapFactory.Options这个类,有一个字 立即下载
Fields
public  Bitmap inBitmap If set, decode methods that take the Options object will attempt to reuse this bitmap when loading content.
public int inDensity The pixel density to use for the bitmap.
public boolean inDither If dither is true, the decoder will attempt to dither the decoded image.
public boolean inInputShareable This field works in conjuction with inPurgeable.
public boolean inJustDecodeBounds If set to true, the decoder will return null (no bitmap), but the out...
public boolean inMutable If set, decode methods will always return a mutable Bitmap instead of an immutable one.
public boolean inPreferQualityOverSpeed If inPreferQualityOverSpeed is set to true, the decoder will try to decode the reconstructed image to a higher quality even at the expense of the decoding speed.
public  Bitmap.Config inPreferredConfig If this is non-null, the decoder will try to decode into this internal configuration.
public boolean inPurgeable If this is set to true, then the resulting bitmap will allocate its pixels such that they can be purged if the system needs to reclaim memory.
public int inSampleSize If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory.
public boolean inScaled When this flag is set, if inDensity and inTargetDensity are not 0, the bitmap will be scaled to matchinTargetDensity when loaded, rather than relying on the graphics system scaling it each time it is drawn to a Canvas.
public int inScreenDensity The pixel density of the actual screen that is being used.
public int inTargetDensity The pixel density of the destination this bitmap will be drawn to.
public byte[] inTempStorage Temp storage to use for decoding.
public boolean mCancel Flag to indicate that cancel has been called on this object.
public int outHeight The resulting height of the bitmap, set independent of the state of inJustDecodeBounds.
public  String outMimeType If known, this string is set to the mimetype of the decoded image.
public int outWidth The resulting width of the bitmap, set independent of the state of inJustDecodeBounds.

上表是BitmapFactory.Options的字段,现在详细介绍各个字段的作用:

1.inBitmap 这个一般用在Android3.0或者更高版本中,用来管理Bitmap的内存用的。如果设置了这个字段,那么解码图片的时候通过Option类去重用inBitmap这个已经存在的Bitmap的内存去加载新的Bitmap。这意味着,内存的重用从而改进性能,避免重新分配内存。但是运用inBitmap时必须确保一下三点:

  • 重用的Bitmap必须和即将解码的Bitmap的尺寸相同,且是JPEG或者PNG格式。(PS,另外还需要设置options.inMutable = true)
  • BitmapFactory.Options.inPreferredConfig字段设置无效,因为会被重用的Bitmap的configuration所覆盖。
  • 一定要使用解码方法返回的Bitmap,因为重用可能会失败(例如:尺寸不匹配)。
以下是代码示例:

首先需要声明来保持Bitmap(已经用过的Bitmap)

HashSet<SoftReference<Bitmap>> mReusableBitmaps;
private LruCache<String, BitmapDrawable> mMemoryCache;

// 如果是3.0或者以上版本,注意这里必须使用软引用或者弱引用,从Android2.3(API 9)开始系统会更积极的回收被弱引用或者软引用所应用的///资源,在这里只是为了重用Bitmap内存来进一步提高性能,这里必须用软引用或者弱引用。至于图片的复用则用LruCache来实现(是强引用)。
if (Utils.hasHoneycomb()) {
    mReusableBitmaps = new HashSet<SoftReference<Bitmap>>();
}
mMemoryCache = new LruCache<String, BitmapDrawable>(mCacheParams.memCacheSize) {

    // 通知释放不需要的缓存,这个方法在每次add新的缓存时调用
    @Override
    protected void entryRemoved(boolean evicted, String key,
            BitmapDrawable oldValue, BitmapDrawable newValue) {
        if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {
            //自定义的BitmapDrawable,来降低它里面的引用计数
            ((RecyclingBitmapDrawable) oldValue).setIsCached(false);
        } else {
            // 标准BitmapDrawable.在这里注意,是把已经不用的Bitmap保存起来,这个方法是内存缓存的图片的大小超过了指定的大小,需要抛弃不需要的图片,就是说能够被垃圾回收的Bitmap,不是缓存的Bitmap(在LruCache中的Bitmap)
            if (Utils.hasHoneycomb()) {
                // We're running on Honeycomb or later, so add the bitmap
                // to a SoftReference set for possible use with inBitmap later.
                mReusableBitmaps.add
                        (new SoftReference<Bitmap>(oldValue.getBitmap()));
            }
        }
    }
....
}

复用已经存在的Bitmap的内存空间:

public static Bitmap decodeSampledBitmapFromFile(String filename,
        int reqWidth, int reqHeight, ImageCache cache) {

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(filename, options);
    ...

    // 如果运行在Android3.0或者更高的版本,就重用intBitmap的内存空间
    if (Utils.hasHoneycomb()) {
        addInBitmapOptions(options, cache);
    }
    ... //解码方法中的options的inBitmap的值有可能被设置过了,(就是重用Bitmap内存空间成功后会设置)
    return BitmapFactory.decodeFile(filename, options);
}
addInBitmapOptions()方法对options进行了设置,给options的inBitmap设置了在HasSet中保存的Bitmap,这样就重用了已经存在的Bitmap的内存空间。一下是方法的代码:

private static void addInBitmapOptions(BitmapFactory.Options options,
        ImageCache cache) {
    // inBitmap只有和inMutable一块使用才起作用,所以
    options.inMutable = true;

    if (cache != null) {
        //  尝试寻找可重用内存空间的Bitmap
        Bitmap inBitmap = cache.getBitmapFromReusableSet(options);

        if (inBitmap != null) {
            // 如果找到了,就给inBitmap设置值,这样就能用这个Bitmap的内存空间来生成新的Bitmap
            options.inBitmap = inBitmap;
        }
    }
}

// 这个方法是在HasMap中寻找可重用内存空间的Bitmap
protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {
        Bitmap bitmap = null;

    if (mReusableBitmaps != null && !mReusableBitmaps.isEmpty()) {
        final Iterator<SoftReference<Bitmap>> iterator
                = mReusableBitmaps.iterator();
        Bitmap item;
	//遍历HasMap中的Bitmap寻找尺寸和要生成的Bitmap尺寸相同的Bitmap
        while (iterator.hasNext()) {
            item = iterator.next().get();

            if (null != item && item.isMutable()) {
                // 检测是否可被重用,就是检测其尺寸(长和宽)是否和要新生成的Bitmap的尺寸(长和宽)相同,
                if (canUseForInBitmap(item, options)) {
                    bitmap = item;

                    // 把这个能被重用内存空间的Bitmap从HashMap中删除,防止被两个以上重用导致的问题。
                    iterator.remove();
                    break;
                }
            } else {
                // Remove from the set if the reference has been cleared.
                iterator.remove();
            }
        }
    }
    return bitmap;
}
canUseForInBitmap()这个方法就是检测options中目标Bitmap的尺寸(是原始尺寸通过和inSampleSize计算能够得到要显示的Bitmap的尺寸)和HashMap中Bitmap的尺寸(由于是以前生成过的Bitmap所以一定是缩放过的)是否相同。一下是代码实现:

private static boolean canUseForInBitmap(
        Bitmap candidate, BitmapFactory.Options targetOptions) {
    int width = targetOptions.outWidth / targetOptions.inSampleSize;
    int height = targetOptions.outHeight / targetOptions.inSampleSize;

    // 如果尺寸(长和宽)相同,就返回true
    return candidate.getWidth() == width && candidate.getHeight() == height;
}


PS:在这里补充一点,使用 BitmapFactory.decode* 方法解码生成图片,除了加载app自带的图片外,其他的都需要在非主线程中进行。

先写到这里,还用工作啊。。。。

MST-GAT: Enhancing Anomaly Detection in Multimodal Time Series with Intra- and Inter-Modal Attention 本文深入解析了MST-GAT模型,这是一种通过模态内与模态间注意力机制增强多模态时间序列异常检测的新方法。它通过构建图结构显式建模传感器间的复杂时空依赖,并结合时间卷积网络与联合优化策略,有效降低了传统方法中常见的误报与漏报问题,在工业监控等场景中展现出卓越性能。 阅读详情

相关推荐

gRPC之gRPC开发流程与入门案例

gRPC之gRPC开发流程与入门案例

YIYIYI 3759

BitmapFactory.Options中参数使用

文章目录使用场景使用方式代码 使用场景 android开发的过程中,很多时候我们所需要的图片大小比原图小,这时候我们就没有必要加载原图进行显示毕竟大图占用的内存要大。 使用方式 使用BitmapFactory.Options的inSampleSize来调整图片的尺寸, 查看inSampleSize的官方注解,inSampleSize 当采样率大于一的时候 ,长和宽对应变为原来的 1/inSampleSize,对应的像素数量减少 1/(inSampleSize^2),bitmap的大小相应的也缩小为 1/(i

liu_12345_liu的博客 3671

蓝牙6.0的‘新雷达’:Channel Sounding信道探测,真能比UWB更香吗?

本文探讨了蓝牙6.0的Channel Sounding信道探测技术在室内定位领域的应用潜力。通过与UWB技术的对比分析,揭示了其在成本、功耗和兼容性方面的优势,特别是在智能门锁、物品追踪等场景中的商业价值。Channel Sounding技术不仅具备亚米级精度,还能通过现有蓝牙设备实现零边际成本部署,为物联网应用提供了新的解决方案。

weixin_29288313的博客 332

BitmapFactory.Options

转载:http://blog.csdn.net/guolin_blog/article/details/9316683

学习点滴的专栏 1234

从零构建物联网监控系统:STM32+迪文屏+WiFi模组的实战解析

本文详细解析了基于STM32微控制器、迪文串口屏和WiFi模组构建物联网监控系统的完整方案。从硬件选型、系统架构设计到数据交互实现,提供了包括迪文屏GUI开发、STM32通信协议、低功耗优化等实战经验,帮助开发者快速掌握物联网监控系统的核心技术。

docker7nomad的博客 728

Comsol固体力学仿真﹣﹣受均匀内压的厚壁球壳弹塑性分析(加载卸载全流程)

COMSOL固体力学及结构力学仿真较少,故而查询了有关资料,才建立了如下模型。图4 加载卸载全历程中的冯米塞斯应力变化。该有限元模型是通过扫掠而得的结构化网格。图2 加载卸载全历程中的塑型区域变化。图3 加载卸载全历程中的位移应力变化。图6 关键节点第一,第三主应力分布。图5 关键节点应力场与塑性区分布。《弹塑性力学》大作业,记录一下。图1 球体的有限元网格模型。

weixin_62236383的博客 1484

Android 图片压缩也即生成缩略图方法

Android 图片压缩也即生成缩略图方法   Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像文件信息,进行图像剪切、旋转、缩放等操作,并可以指定格式保存图像文件。本文从应用的角度,着重介绍怎么用Bitmap来实现这些功能。   一、Bitmap的生成 1.1 BitmapFactory decode出Bitmap     Bitm

glen1943的专栏 1034

【锂离子电池力学耦合及相场法模拟技术与应用】

8. 电化学仿真软件的使用与案例分析 (1) 各向异性纳米线锂化应力分析(实例讲解1) (2) 化学反应及死锂现象研究(案例分析2)(3) 锂化循环损伤计算(案例分析3)6. 4. 电池材料的力学与电化学耦合性能分析(1) 耦合效应对电池性能的影响(2) 耦合模型的验证与应。5. 5. 电池颗粒、极片、电芯尺度力-电-化-热多场耦合模型概述力学-7. 颗粒尺度耦合模型在电池失效分析中的应用。2. 2. 电池电极材料的分类与特性。5. (2) 耦合模型的验证与应用。电化学耦合模型与仿真。

weixin_51101456的博客 521

图片加载2:BitmapFactory.Options详解

(1)常用属性 BitmapFactory.Options options = new BitmapFactory.Options(); //默认值为false,如果设置成true,那么在解码的时候就不会返回bitmap,即bitmap = null。 options.inJustDecodeBounds = false; //可以复用之前用过的bitmap options.inBitma...

qijingwang的博客 668

即梦(Dreamina)技术浅析(六):多模态生成模型

多模态生成模型的目标是结合不同模态的数据(如文本和图像),生成新的视觉内容。其核心思想是利用文本描述引导图像或视频的生成过程,使得生成结果能够准确反映用户的意图。

m0_75253143的博客 1335

Android SurfaceFlinger——概述(一)

对于系统渲染流程的理解是指导 SurfaceFlinger 设计的核心思想,从 Android 4.1 一直到 Android 9.0 都没有太大的变化。只要抓住这五个核心思想,我们阅读 SurfaceFlinger 的难度就会下降不少。下面看一下 SurfaceFlinger 的体系和 Skia 以及 View的绘制流程的关系。framework 面向开发者所有的 View 是便于开发的控件,里面仅仅只是提供了当前 View 各种属性以及功能。

小旭的专栏 2584

Android使用BitmapFactory高效加载大图,防止OOM

基于以上,当我们决定是把原图加载进内存还是压缩图加载进内存的时候,有几点是需要考虑的: 大概的估算一下这张图片占用多少内存。 展示图片的控件的实际像素大小。 考虑一下当前设备的屏幕尺寸和屏幕分辨率。 这里我简单的说一下第二点和第三点。假设使用ImageView进行加载图片,很多时候ImageView没有图片的尺寸那么大,这个时候你把原始图片加载进来再设置给ImageV...

一抹离愁 948

IEC61850规约客户端软件开发实战(第六章)

IEC 61850标准中的GOOSE(Generic Object Oriented Substation Event,面向通用对象的变电站事件)功能是变电站自动化系统的核心通信机制,主要用于实现智能电子设备(IED)间高可靠性、低延时的实时信号传输。本章简述其核心功能与技术特点。

半青年的博客 1778

BitmapFactory.Options避免 内存溢出 OutOfMemoryError的优化方法

尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source...

weixin_33937499的博客 100

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

图片压缩和缓存高效加载规避oom总结

高效加载大图片查看每个应用程序最高可用内存是多少:int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); Log.d("TAG", "Max memory is " + maxMemory + "KB"); BitmapFactory这个类提供了多个解析方法(decodeByteArray, decodeFile, de

微凉一季的专栏 3331

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

android 解决图片加载内存溢出

尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图, 因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。 因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 sou

1428

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

解决Android加载大图片时内存溢出的问题

BitmapRegionDecoder 尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。 因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitma...

augfun的博客 989

android地图图片加载,Android 图片加载(一)高效加载Bitmap 基础篇

由于Bitmap的特殊性以及Android对单个应用所规定的最大内存限制,我们在同时加载大量Bitmap时很容易发生内存溢出,即我们通常所说的OutOfMemoryError(OOM),因此高效加载Bitmap就成为了每个Android开发者的必备技能。在学习如何高效地加载Bitmap之前,首先介绍一下如何加载一个Bitmap。我们都知道,Bitmap在Android中通常指的是一张图片,那么如何...

weixin_42510924的博客 748

Android使用BitmapFactory.Options解决加载大图片内存溢出问题

转载至 http://blog.163.com/gobby_1110/blog/static/292817152012111424410578/ 由于Android对图片使用内存有限制,若是加载几兆的大图片便内存溢出。Bitmap会将图片的所有像素(即长x宽)加载到内存中,如果图片分辨率过大,会直接导致内存溢出(java.lang.OutOfMemoryError),只有在BitmapFac

Justin Harmon 406

android图片加载

图片占内存容量计算公式为: 图片所占内存大小 = 图片长度(像素) * 图片宽度(像素) * 一个像素所占内存空间(单位:字节) 一般地,一个象素所占内存空间根据机器颜色数(专业词汇叫色深Color Depth)来决定:(1)Nokia 老S40机器 颜色数为4096色,就是2^12, 一个象素所占内存空间为1.5个字节;(2)Nokia S40新版 机器和 S60机器 颜色数为65536...

乌龟赛跑 660

Android图片的高效加载与缓存策略

一、简介 Bitmap在Android中指的是一张图片。 BitmapFactory提供了四种方法来加载图片: decodeFile----------从文件加载一个Bitmap对象 decodeResource --从资源加载一个Bitmap对象 decodeStream -----从输入流加载一个Bitmap对象 decodeByteArray--从字节数组加载一个Bitmap对象 ...

u013087553的博客 900

bitmapfactory.options 优化内存小问题

尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图, 因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。 因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的

zj的博客 422
上一篇: dp和px,那些不得不吐槽的故事——Android平台图片文字元素单位浅析
下一篇: Android Bitmap内存管理,解决内存溢出问题(1)之自定义BitmapDrawable
恶魔果实
博客等级 码龄15年 6粉丝 13原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值