Bitmap的decode底层源码流程分析。
研究c++源码之前要先细读一下BitmapFactory.Options的几个关键属性的注释。
核心:其实这个类就是BitmapFactory加载bitmap的一个配置(没看到可以自己去研读注释)。
inDensity:;当前配置中设置的密度大小;decodeResource方法下默认取图片所在目录的密度大小。
inTargetDensity:预期加载一个inTargetDensity密度大小的bitmap,这个bitmap按理是会被绘制在同样密度的Canvas上,decodeResource方法下默认取屏幕密度。
inScreenDensity:This is purely for applications running in density compatibility code(不是很好翻译)
inScaled:是否可以缩放,默认为true。
缩放逻辑:如果inDensity不等于inScreenDensity,并且inDensity和inTargetDensity不等于0,则吧inDensity放大到等于inTargetDensity(c++层源码可以查看)。
Bitmap.Config inPreferredConfig:颜色模式,其实就是颜色值的存储方式,不解释,太简单。不设置的话会自动根据图片是否包含alpha等和屏幕灰阶深度来选择。
ColorSpace inPreferredColorSpace:色彩空间,WCG广色域(android不支持)、SRGB等,源代码可以查看。不设置的话会自动根据inPreferredConfig以及图片中的颜色来选择。
**
decodeResourceStream
**
1、这里主要就是前面说的自动根据资源文件和屏幕密度设置inDensity和inTargetDensity。
2、加载bitmap和设置bitmap加载成功后的density。
3、nativeDecodeAsset
对应的c++方法:nativeDecodeAsset。
4、doDecode
方法。
初始化和校验BitmapFactory.Options的参数。
继续计算一些参数:颜色模式,ninepatch图不允许设置为rgb565,android7以前会出现抖动而ninepatch图同时会拉伸,不允许出现这种效果,对于颜色模式如果出现不明确需要矫正的话都是设为ARGB8888。
这里尝试分配内存,可能出现java堆和native堆以及javaBitmap大小的情况,然后从流中读取数据并进行图片解码保存到decodingBitmap
对象中,**注意这里只有采样率生效 **。
最后这里,进行了缩放,即实现了inDensity和inTargetDensity之间的缩放
。然后分三种情况生成java bitmap对象。第一种就是使用inBitmap属性重复利用内存的方式;第二种是使用Hardware的方式;第三种也是利用bitmap.cpp
的createBitmap
函数生成一个bitmap对象,注意这个地方的**defaultAllocator
**内存分配器,不同系统版本的默认内存分配不一样。
关键点1:整体流程分为参数的赋值校验与计算和图片的解码与缩放。
缩放有采样率的缩放和密度缩放。
解码颜色模式的校验机制。
关键点2:内存占用大小,与颜色模式以及缩放有关。