[小笔记] Android 中 Bitmap 的放缩配置
本篇文章中主要讨论 Android
中 Bitmap
中的放缩有关的 BitmapFactory#Options
设置的配置。
inJustDecodeBounds
这个参数非常有用,在解析编码后的图片文件(PNG
,JPEG
等等)时,如果添加了这个参数那么就只会解析图片的尺寸,而不会真正的解码图片到 Bitmap
,这在对加载优化大图片时非常有用。
只加载图片尺寸可以参考以下代码:
Kotlin
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile("./test.png", options)
val with = options.outWidth
val height = options.outHeight
inDensity、inTargetDensity 与 inScaled
只有当 inScaled
设置为 true
时(默认就是为 true
),inDesity
与 inTargetDesity
才会生效。
inDesity
表示输入的图片的像素密度,inTargetDesity
表示渲染时的像素密度,当他们的值不一样时,就需要重新计算输入图片的放缩值,计算方式放缩的方式是 scale
= inTargetDesity
/ inDesity
。
这里就不得不再提到不同 dpi
目录下的 drawable
的资源文件,当 dpi
越高的目录下的资源文件的 inDesity
值就越大。可以参照以下的表:
一模一样的图片存放在不同 dpi
的 drawable
目录下,当在程序运行时加载他们获取到的 Bitmap
是不一样的。
我这里测试了 ldpi
和 xxxhdpi
的情况。最后得到的测试截图是:
上面的图片是 ldpi
,而下面的图片是 xxxhdpi
。根据上面的表得知 ldpi
的 inDesity
是 0.75
,而 xxxhdpi
的 inDesity
是 3.5
,代入上面的公式就得出 ldpi
的放缩值要比 xxxhdpi
要大。其中 inTargetDesity
是根据 屏幕像素密度inScreenDensity
计算的,同一台设备是固定的。
对于上面的测试结果我的理解是:Android
认为 ldpi
中的资源文件本来的像素密度就低,但是屏幕的像素密度比较大,所以就有必要将 ldpi
中的资源文件进行放大,这样才能使高屏幕密度的设备有更好的体验;相反如果是 xxxhdpi
目录下就认为是其中的资源文件像素密度高,和屏幕的像素密度对比相差就比较小,所以放缩小一点就能够有较好的体验,而且更加节省内存。
如果是不同的设备,他们的屏幕的像素密度也不一样,代入上面的公式也就是,同一个目录下的资源文件,高屏幕密度的设备加载的资源占用的内存就更大,分辨率就更高(但是不同的设备使用的资源目录可能不一样,取决于系统的判断,所以为了更好的体验,我们应用的资源文件尽可能的覆盖多的屏幕像素密度设备)。
当然这是系统加载资源文件时 inDensity
与 inTargetDensity
的处理逻辑,我们在加载本地的图片时,我们可以自己来控制 inDensity
与 inTargetDensity
这两个参数以达到放缩图片的目的。
inSampleSize
更加直接的图片加载时的放缩配置,它的值必须是 2
的幂,1 表示不放缩,2
就表示长宽变成原来的 1 / 2
,内存的占用就变成原来的 1 / 4
。