本文主要講解Bitmap.Config以及其中RGB_565使用和問題。
先看看Bitmap.Config枚舉:

其中RGBA_F16和HARDWARE都是 api 26(8.0)之后才有的,ARGB_4444因為顯示效果差,在api 13之后都會失效強(qiáng)制轉(zhuǎn)成使用ARGB_8888模式。所以正常使用模式有ARGB_8888和RGB_565。
ARGB_8888模式所占內(nèi)存是RGB_565的兩倍,在一個華為高配手機(jī)上,一個圖片50007000很正常,計算內(nèi)存:50007000*4 = 133.5M,這時候調(diào)用Canvas.drawBitmap會直接報 oom。
很自然地,我們想到使用RGB_565加載,內(nèi)存可以減小一半。但是要注意:
1、RGB_565沒有透明通道,如果上層需要用到透明通道,就不能使用RGB_565。
2、在顯示效果上,加載Bitmap時可以使用Options.inDither = true (抖動解碼)來優(yōu)化顯示效果。
Paint也有一個setDither方法,效果應(yīng)該類似類似
3、使用RGB_565加載出來的Bitmap再次保存到文件后,會變得偏綠。起始這點在上面枚舉的圖片中已經(jīng)說得很清楚。如果一個需求是同一個文件要反復(fù)讀寫,最后發(fā)現(xiàn)圖片會變得銅綠色,簡直不可饒恕。
不過有兩個策略可以緩解這種情況 (為了節(jié)省內(nèi)存真是拼了 =_= ):
1、減少存儲次數(shù),怎么說?比如沒有修改過,保存的時候就不必存啦,因為Bitmap拿到的本身就已經(jīng)是失真的啦,反復(fù)儲存會導(dǎo)致失真累加,最后沒法看。所以需要邏輯上控制好策略咯,真的需要存儲才去寫。
2、真的要寫咋辦?有個同事提醒我,可不可以轉(zhuǎn)成有透明度的圖?雖然他不是Android的,但是感覺很有道理的樣子,于是我們寫下了如下類似的代碼:
if( !destBitmap.getConfig().equals(Bitmap.Config.ARGB_8888)) {
//保存時拷貝成8888模式防止圖片變色
destBitmap= BitmapUtil.copyBitmap(destBitmap, Bitmap.Config.ARGB_8888);
}
...省略寫入文件的代碼
如果需要的圖片配置不是ARGB_8888則先使用ARGB_8888配置拷貝一份,再寫入文件!驗證效果后發(fā)現(xiàn),大差不差,哈哈。問題是保存時內(nèi)存會暴漲一下啦~ 不管,崩了再來╭(╯^╰)╮