在寫本文之前剩愧,我還以為自己對(duì)android的bitmap很熟悉猪叙,直到自己親手寫代碼實(shí)踐,才發(fā)現(xiàn)自己錯(cuò)了很多年。真是汗顏把妗犬第!
Bitmap Config
首先,根據(jù)Android API 25的文檔簡(jiǎn)要說(shuō)明一下Android的Bitmap.Config以下4個(gè)選項(xiàng)
- ALPHA_8: 每個(gè)像素占用1字節(jié)(8位)芒帕,存儲(chǔ)的是透明度信息歉嗓。
- ARGB_4444: 每個(gè)像素占用2字節(jié)(4+4+4+4=16位),ARGB分別占用4位背蟆,支持alpha通道鉴分。
注:從API 13開始不推薦使用,在android 4.4上面带膀,設(shè)置的ARGB_4444會(huì)被系統(tǒng)使用ARGB_8888替換 - ARGB_8888: 默認(rèn)的選項(xiàng)志珍,每像素占用4字節(jié),ARGB分別占8位垛叨,支持1600萬(wàn)種顏色伦糯,質(zhì)量最高,當(dāng)然內(nèi)存占用也高嗽元。
- RGB_565: 每像素占用2字節(jié)敛纲,RGB分別占5,6剂癌,5位淤翔。支持65535種顏色,不支持alpha珍手。
bitmap.config | ALPHA_8 | ARGB_4444 | ARGB_8888 | RGB_565 |
---|---|---|---|---|
bytes/pixel | 1 byte | 2 byte | 4 byte | 2 byte |
alpha channel | 8 bit | 4 bit | 8 bit | not support |
PNG 格式
其次办铡,簡(jiǎn)要說(shuō)一下png格式
- png 8: 支持不透明,索引色透明琳要,alpha透明寡具,最大支持256種顏色
- png 24: 不支持透明,支持1600萬(wàn)種顏色
- png 32: 支持透明稚补,其它同png 24童叠,支持1600萬(wàn)種顏色
bitmap內(nèi)存占用計(jì)算
第三,簡(jiǎn)要說(shuō)一下bitmap占用的內(nèi)存
Android中bitmap的內(nèi)存占用是跟圖片的尺寸(高和寬)相關(guān)课幕。一張圖片的內(nèi)存占用大致的計(jì)算公式如下:
占用內(nèi)存 = 圖像像素總和(width x height)再 x 每像素(bitmap config)占用的字節(jié)數(shù)
以下是通過(guò)代碼準(zhǔn)確計(jì)算
public static int getSizeInBytes(@Nullable Bitmap bitmap) {
if (bitmap == null) {
return 0;
}
// There's a known issue in KitKat where getAllocationByteCount() can throw an NPE. This was
// apparently fixed in MR1: http://bit.ly/1IvdRpd. So we do a version check here, and
// catch any potential NPEs just to be safe.
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
try {
return bitmap.getAllocationByteCount();
} catch (NullPointerException npe) {
// Swallow exception and try fallbacks.
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
return bitmap.getByteCount();
}
// Estimate for earlier platforms.
return bitmap.getWidth() * bitmap.getRowBytes();
}
以一張10241024的圖片為例厦坛,使用ARGB_8888,占用的內(nèi)存為10241024*4=4M乍惊。像現(xiàn)在的手機(jī)攝像頭動(dòng)不動(dòng)就是上千萬(wàn)像素杜秸,拍出來(lái)的照片如果按默認(rèn)的ARGB_8888 config加載,則至少是幾十M的內(nèi)存占用润绎。
Android的圖片資源主要分兩部分:
- 一種是apk中自帶的撬碟,多為png格式诞挨,由系統(tǒng)加載,支持縮放呢蛤,代碼中通過(guò)R.xxx引用惶傻,decode時(shí)使用的是默認(rèn)的ARGB_8888選項(xiàng),圖像質(zhì)量高其障;
- 另一種是網(wǎng)絡(luò)圖片或本地圖片银室,多為jpg格式,加載時(shí)一般使用第三方的圖片加載庫(kù)励翼,為節(jié)省內(nèi)存decode時(shí)多為RGB_565選項(xiàng)蜈敢。
平時(shí)都是這么用,也沒發(fā)現(xiàn)問(wèn)題抚笔,優(yōu)化內(nèi)存占用時(shí)扶认,一般也是從圖片的尺寸方面入手。不過(guò)最近優(yōu)化一個(gè)跟圖片相關(guān)的功能殊橙,在圖片尺寸無(wú)法縮放的條件下辐宾,只能通過(guò)更改bitmap config來(lái)降低內(nèi)存的占用。然后意外的發(fā)現(xiàn)膨蛮,導(dǎo)致顛覆了我的三觀叠纹。為此我特地寫了一個(gè)測(cè)試sample,代碼詳見github敞葛,特地創(chuàng)建了一張背景色透明誉察,圖片內(nèi)容為A(黑色50%透明度)R(紅色)G(綠色)B(藍(lán)色)圖片,然后分別導(dǎo)出為:png8(alpha透明)惹谐、png24(不透明)持偏、png32和jpeg(不透明)格式的圖,分別使用ALPHA_8, ARGB_4444, ARGB_8888, RGB_565四種config加載圖片氨肌,得到的實(shí)際結(jié)果如下(假設(shè)圖像總像素為X)鸿秆。
實(shí)踐結(jié)果
運(yùn)行截圖
![screenshot](https://raw.githubusercontent.com/Jamling/BitmapConfig/master/screenshot.jpg)
結(jié)果統(tǒng)計(jì)
bitmap.config | ALPHA_8 | ARGB_4444 | ARGB_8888 | RGB_565 |
---|---|---|---|---|
![]() |
41 |
2 X | 4 X |
42 不 |
![]() |
41 |
2 X | 4 X | 2 X |
![]() |
41 |
2 X | 4 X |
42 不 |
![]() |
41 |
2 X | 4 X | 2 X |
請(qǐng)注意表格中帶刪除線的部分
- ALPHA_8:config占用的內(nèi)存竟然和ARGB_8888一樣,不是說(shuō)每個(gè)像素占用1字節(jié)的么怎囚?
- RGB_565:在png8和png32中卿叽,圖片中的A都保持了50%的透明度,而且占用的內(nèi)存也和ARGB_8888一樣恳守,不是說(shuō)RGB_565不包含alpha么考婴?不是說(shuō)占用的內(nèi)存是ARGB_8888的一半么?
- ARGB_4444:在android 6.0上面催烘,png8和png32看不見(全透明)沥阱,png24和jpeg顯示為一塊黑色區(qū)域,在android 4.2上則顯示正常伊群。
帶著上面的疑問(wèn)考杉,在網(wǎng)上進(jìn)行了相關(guān)的搜索屁使,也沒有找到答案。好吧奔则,我是懵了,不知道各位看客如何蔽午?附上github上的示例工程:https://github.com/Jamling/BitmapConfig
本文永久鏈接: http://www.ieclipse.cn/2017/06/14/Android/Android-bitmap-config/ 未經(jīng)允許易茬,禁止轉(zhuǎn)載,如有問(wèn)題及老,請(qǐng)?jiān)谖业牟┛驮柬?yè)面提交評(píng)論抽莱。