Bitmap()

BitmapFactory.Options 加载图片时的一些静态参数类(大概20个值)

这些参数的讲解api有时候说明的 不够细致,可以建议去看当前参数对应的源码注释,这 些注释说的细致些

  • Bitmap inBitmap

复用位图分配的内存,常规加载图片时每加载一张内存就要为这张图片分配相应的内存空间。但是使用了此参数,当我们加载1张图片后,把此图片赋值给inBitmap,以后再此加载其他图片时可以使用inBitmap复用以前的内存,而不再开辟新的内存空间

  • int inDensity:用于设置位图密度(就是图片本身的密度)
  • int inScreenDensity:屏幕实际密度(无用,随便更改不影响结果)
  • int inTargetDensity:位图最终显示到屏幕上的密度

这三个密度到底是什么关系呢?系统最终显示位图用的什么密度比呢?

假设一张图1920*1080 ,手机的设备密度比densityDpi:480dpi,density:3

当我们把图片存储在sdcard或者是raw,assert目录下时,不设置inDensity和inTargetDensity参数

加载一张图片到内存中换算:1920 * 3=5760 1080*3=2250
不设置任何参数我们加载图片进入内存就使用实际的设备密度比

当我们把图片放在xxxhdpi文件夹下,不设置inDensity和inTargetDensity参数

加载一张图片到内存中换算:1920 * 480/640=1440 1080*480/640=563
因为加载到xxxhdpi文件夹他的密度比是640,我们手机本身是480,系统会自己做换算480/640
同理加载到xxhdpi :480/480

当inDensity不设置参数或者是inDensity=0(如果设置0或者不设置取设备密度或者是默认160,见源码),
且显示设置inTargetDensity=960(如果设置0就默认去设备密度)**

sdcard或者是raw等目录时:1920 * 3*(inTargetDensity/inDensity)=1920*3*(960/480)
xxxhdpi:1920 * (480/640)*(inTargetDensity/inDensity)

当inDensity和inTargetDensity都设置且大于0时

不论文件存储在哪里:1920 *(inTargetDensity/inDensity)

总结:

1:当我们不使用inDensity、inTargetDensity任何参数时,图片加载到内存都会经过换算,
如果是xxxhdpi这种文件夹的图片都会使用设备密度比/文件夹密度 来换算图片,这也是官方适配图片的方式
如果是外部加载的图片则直接乘以当前密度比来换算图片
2:当我们一旦使用inDensity、inTargetDensity这两个任何一个参数时,如果只使用了inTargetDensity,而不设置inDensity,或者是使用了inDensity参数但是值是0,这个时候不但要先把图片按照(1)方式先进行换算,然后再使用(inTargetDensity/inDensity)进行二次换算,
3:当我们使用inDensity、inTargetDensity参数时,只要inDensity>0,则不再会进行(1)的换算,直接图片的宽高分辨了乘以(inTargetDensity/inDensity)即可
4:当inDensity、inTargetDensity不设置或者=0时,inTargetDensity一定取设备密度,而inDensity可能换算出来是设备密度也可能是一个默认值160

ps:图片进入内存计算的关键就是设置了inDensity、inTargetDensity参数没有

ps:追加一个图片内存大小计算:

我们图片再实际磁盘中保存时可能只有几十kb,但是加载到内存中时就会变成几十兆,这是因为保存到磁盘这些地方时图片进行过压缩处理,而加载到内存中,程序不知道我们要干什么他只能把图片所有信息全部在内存表示出来,所以很大,
但是这个大小不是他的真实内存占有大小,尽管不是真实的大小,如果我们动态改变密度比让图片无限制增大,他还是会出现OOM

1920 *1080 :一张图片从sdcard加载到内存的大小计算(xhdpi按照上面的方式换算一样的): 1920 *3=5760
1080*3=2250 ,5760 *2250*4=51840000;(看加载到内存好大)
这里计算没有设置任何密度参数,上面的3就是手机的density,宽高像素换算后*4是因为占4字节

ps:为什么说BitmapFactory.decodeResource(…)加载图片比

BitmapFactory.decodeStream(…)更加费内存

就是因为decodeResource加载图片时会按照我们上面说的那样对图片进行一个密度换算,在java层进行处理图片就已经变大了,而decodeStream直接入nativeDecodeAsset

  • boolean inScaled

这个标志默认是true ,他的用法要和上面的几个密度关联起来说 inScaled =true,inTargetDensity 和
inDensity都有值的时候,会默认选择inTargetDensity 密度来缩放图片,如果inScaled
=false,那么系统就不会再去缩放位图了而永远采用inDensity的值

  • boolean inDither设置图片是否进行抖动处理

true是进行抖动处理(就是获取更好的效果) 抖动处理是表示在4个颜色通道每位低于8位值时,对图片进行处理获取更好的显示效果

  • boolean inJustDecodeBounds

这个设置为true表示加载时没有真正把位图加载到内存中,但是我们可以查看位图的相关信息如宽、高等,这样用来处理大图防止OOM非常有效,这个参数一般要结合设置宽、高、缩放等参数结合使用来处理图片,但是记住在给参数在开始时设置为true,相关处理结束后要设置为false,这样系统才会真正加载图片进入内存。

  • int outWidth、int outHeight:获取位图的宽、高信息
  • int inSampleSize:缩放图片==1补缩放,如==2把原图缩放1/2
  • Bitmap.Config inPreferredConfig:设置图片像素的颜色值参数

如inPreferredConfig=null表示系统将会用最佳方式设置参数,默认是inPreferredConfig=ARGB_8888

  • boolean inPremultiplied:是否预乘alpha通道,和isPremultiplied()方法同理(见上)

如果把inPremultiplied=false,inScaled=true,那么缩放位图时可能造成颜色差异

  • boolean inMutable:表示位图是否可变,同isMutable()方法(见上)
  • boolean inPurgeable:表示内存不足时是否可以回收该图片(true:可回收)

另外当这图片回收后须再再此使用时系统将会自定decode解码此位图

  • boolean inInputShareable:

必须结合inPurgeable使用,如果inPurgeable=false,那么此属性使用无效。inInputShareable为true表示一个深度赋值,但是更耗性能

  • boolean inPreferQualityOverSpeed:把重新解码图片到更高的质量,只对jpeg图片有效

影响jpeg图片解码速度最重要的是在idct

  • byte[] inTempStorage:图片解码时临时存储数组,大小建议16KB
  • boolean mCancel:不知道怎么用,貌似是个标志位用来检查图片在解码边界和解码图像时!
  • String outMimeType:设置输出的MimeType类型,如果不设置或设置错误将忽略

mimetype类型格式有很多种(如application/ogg、application/rar………)不知道咋用

总结:以上就是BitmapFactory.Options 的参数,其实总结下来大部分优化是对图片加载时防 止OOM。

你可能感兴趣的:(Android)