android开发

Bitmap系列-Options

2018-03-28  本文已影响0人  sjandroid

这是我的第一篇关于Bitmap的文章,如有理解错误之处,烦请大家能及时留言提出,我会及时纠正,谢谢。

今天主要和大家探讨的是BitmapFactory.Options的使用.

目录:

第一部分:BitmapFactory.Options属性的理解

第二部分:从源码角度查看Options是如何工作的


BitmapFactory.Options

接下来分析一下Options中一些重要属性.

先放类图


BitmapFactory.Options

inDither(***)

1:定义:是否对位图抖动处理

2:作用:会让图片的显示效果更平滑一些,提高显现效果.

3:使用场景:颜色模式高的图片(例如ARGB_8888)采用低颜色模式(例如:RGB_565)去解码的时候,需要把此值设置为true.

4:原理:https://blog.csdn.net/haozipi/article/details/47185535(这个说的比较清楚)

inPreferQualityOverSpeed(**)

1:API解析:如果inPreferQualityOverSpeed设置为true,则解码器将尝试将重建图像解码为更高质量,即使牺牲解码速度.目前该领域只影响JPEG解码,在这种情况下,将使用更精确但速度稍慢的IDCT方法.

inPremultiplied(***)

1:API解释:如果为true(这是默认值),则生成的位图的颜色通道将由Alpha通道预先倍增。

对于由视图系统或Canvas直接绘制的图像,这不应设置为false。 视图系统和Canvas假定所有绘制的图像都被预乘以简化绘制时间混合,并且在绘制未预乘积时会抛出RuntimeException。

这可能仅在您想操纵原始编码图像数据时才有用,例如, 使用RenderScript或自定义OpenGL。

这不会影响没有Alpha通道的位图。

将inScaled设置为true时将此标志设置为false可能会导致不正确的颜色。

2:注意:inScaled设置为true,inPremultiplied设置为false,并且图像具有alpha通道(例如加载png图片),则会出错"java.lang.RuntimeException: Canvas: trying to use a non-premultiplied bitmap"

inPreferredConfig(*****)

1:定义:解码图片生成Bitmap时的颜色模式.

2:作用:标记每个像素点占的内存大小(单位是字节)

3:疑问:目前从api说明来看,不同的Config对应的每个像素点占的内存是不一样的,但是测试时发现,ALPHA_8,RGB_565,ARGB_8888占用的内存一样大,目前还不知道原因??

inSampleSize(*****)

1:采样率

2:取值:2的整数幂(小于1则取值为1,任何其他值将向下舍入到最接近的2的幂)

3:作用:对图片进行二次采样,使Bitmap占用的内存大小降低,使Bitmap的宽和高减小(宽高变为原图的1/sampleSize,进而Bitmap占用的内存变小为1/sampleSize^2)

4:场景:大图加载,缩略图

inJustDecodeBounds(*****)

1:是否仅仅测量Bitmap的边界

2:取值:true,只测量Bitmap的宽高等属性,并且解码返回的Bitmap为null. 这些属性值从outWitdh,outHeight,outMimeType(图片类型)获取.

inMutable(*****Mutable:易变的,可变的)

1:作用:标记位图是否可变,是否可以对该位图做修改.

2:取值:true:可变,false:不可变

3:注意点:如果用Options加载的Bitmap的话,那么此值对应的是Bitmap的mIsMutable属性.

如果是不可变的话,例如调用setPixel()修改位图中像素点的颜色会抛出"IllegalStateException(非法状态异常)"

inBitmap(*****)

1:作用:指示解码器重复使用已经加载的Bitmap的内存空间去加载新位图从而达到节省内存的目的.

2:注意点:1:重用位图的mIsMutable的值为false,那么新加载Bitmap就不能用重用位图的内存空间解码图片。此时新加载的Bitmap与重用的Bitmap不是同一个。

2:重用位图的mIsMutable的值为true,如果要加载位图的getByteCount()字节数大于重用位图的Bitmap.getAllocationByteCount()分配的字节数,

那么调用BitmapFactory.decode()会返回 null 并将抛出IllegalArgumentException。

3:重用位图的mIsMutable的值为true,如果要加载位图的getByteCount()字节数小于或等于重用位图的Bitmap.getAllocationByteCount()分配的字节数,

BitmapFactory就可以重复使用可变位图来解码任何其他位图.

此时:1:重用位图与新加在位图是同一个对象

2:重用位图的尺寸变成了新加载位图的尺寸

3:重用位图的内存大小与新加载位图的位图内存大小一样,且都为重用位图的大小

4:重用位图的内容变成了新加载位图的内容(从源码来看也确实是这样,因为重用位图像素信息存储的是新加载位图的像素信息)

inScaled(*****)

1:定义:是否缩放,而API解释则更清楚一些:设置此标志时,如果inDensity和inTargetDensity不为0,则位图将在加载时缩放以匹配inTargetDensity,而不是每次绘图到Canvas时都依靠图形系统进行缩放。

BitmapRegionDecoder将忽略此标志,并且不会根据密度缩放输出。 (尽管支持inSampleSize)默认情况下,此标志处于打开状态,如果需要位图的非缩放版本,应将其关闭。 九个补丁位图忽略这个标志并且总是缩放。

如果inPremultiplied设置为false,并且图像具有alpha,则将此标志设置为true可能会导致不正确的颜色。

2:作用:缩放Bitmap

inDensity(*****)

1:定义:该位图是在哪种像素密度下创建的(这个理解的可能不对,如果理解不对的话,希望大神们多多指出).

2:取值:DisplayMetrics中的值.

3:作用:与inScaled,inTargetDensity,inScreenDensity一起使用,决定最终Bitmap的宽高

4:note:当Options.inDensity不为0的话则把该值设置到Bitmap的mDensity(see BitmapFactory.setDensityFromOptions()).

inTargetDensity(*****)

1:定义:该位图要加载并显示到的目标设备上的像素密度。

2:取值:DisplayMetrics中的值.

3:作用:与inScaled,inTargetDensity,inScreenDensity一起使用,决定最终Bitmap的宽高

4:note:当Options.inScaled或isNinePatch一项为真则把该值设置到Bitmap的mDensity(see BitmapFactory.setDensityFromOptions()).

inScreenDensity(*****)

1:定义:这个不知道怎么理解,希望打什么能指出

2:取值:DisplayMetrics中的值.

3:作用:1:与inScaled,inTargetDensity,inScreenDensity一起使用,决定最终Bitmap的宽高.

          2:通过与inDensity比较是否相等来确认是否需要缩放位图(相等不缩放,不相等则缩放)

inPurgeable与inInputShareable

inPurgeable与inInputShareable联合使用,从Build.VERSION_CODES.LOLLIPOP(21)开始,可以采用inBitmap替换.

网上找的解释:inPurgeable与inInputShareable 二个是并列使用,如果设置了inPurgeable = false,则inInputShareable的值会被忽略;

这二个选项的作用主要是便于系统及时回收bitmap占用的内存;

inPurgeable:设置为True,则使用BitmapFactory创建的Bitmap用于存储Pixel的内存空间,在系统内存不足时可以被回收,当应用需要再次访问

该Bitmap的Pixel时,系统会再次调用BitmapFactory 的decode方法重新生成Bitmap的Pixel数组。 设置为False时,表示不能被回收。

inInputShareable:设置是否深拷贝,与inPurgeable结合使用,inPurgeable为false时,该参数无意义.


从源码层分析Options是如何工作的

下面简单从BitmapFactory.cpp中分析各属性的作用(分析的很简单,几乎每个开发同学拿到这个源码都能看懂,所以就稍微梳理下加深下印象就行了)。

•inSampleSize:这里不做深究底层是如何实现的,有兴趣的小伙伴可以自行研究下

•inJustDecodeBounds:

•inSacled与inDensity与nTargetDensity与inScreenDensity

这几个属性共同决定了最终要显示的Bitmap的宽/高。

•inBitmap:

好了,今天的分享就到这里了,有什么理解错误的地方,欢迎大家积极指出,我会尽快改正的,谢谢。

上一篇下一篇

猜你喜欢

热点阅读