详解Bitmap之ARGB_8888/RGB_565/ALPHA_8/ARGB_4444
前言
有時會看到別人使用bitmap是用到ARGB_8888/RGB_565這類參數(shù),那么這些參數(shù)是什么?對bitmap有什么影響?
Bitmap.Config
他們是Bitmap.Config的四種枚舉類型。ARGB分別是alpha透明度和red、green、blue三色
- ARGB_8888:分別用8位來記錄4個值,所以每個像素會占用32位。
- ARGB_4444:分別用4位來記錄4個值,所以每個像素會占用16位。
- RGB_565:分別用5位、6位和5位來記錄RGB三色值,所以每個像素會占用16位。
- ALPHA_8:根據(jù)注釋應(yīng)該是不保存顏色值,只保存透明度(8位),每個像素會占用8位。
內(nèi)存大小
那么對bitmap有何影響?
這里都以ARGB_8888為基準來進行對比。
- ARGB_4444:內(nèi)存占用減少一半,但是每個值圖片失真度很嚴重,這個參數(shù)本身已經(jīng)不推薦使用了。
- RGB_565:內(nèi)存占用減少一半,舍棄了透明度,同時三色值也有部分損失,但是圖片失真度很小。
- ALPHA_8:內(nèi)存占用減少3/4,沒有顏色,只有透明度,即黑白。
測試代碼
try {URL url = new URL("http://h.hiphotos.baidu.com/image/pic/item/b21c8701a18b87d6b025e513040828381f30fd53.jpg");HttpURLConnection connection = (HttpURLConnection)url.openConnection();InputStream in = connection.getInputStream();ByteArrayOutputStream content = new ByteArrayOutputStream();byte[] buffer = new byte[10 * 1024];int count;while((count = in.read(buffer)) > 0){content.write(buffer, 0, count);}byte[] data = content.toByteArray();BitmapFactory.Options options1 = new BitmapFactory.Options();options1.inPreferredConfig = Bitmap.Config.ARGB_8888;Bitmap bitmap1 = BitmapFactory.decodeByteArray(data, 0 , data.length, options1);//System.out.println("bitmap ARGB_8888 length " + bitmap1.getByteCount());System.out.println("bitmap ARGB_8888 length " + bitmap1.getRowBytes() * bitmap1.getHeight());BitmapFactory.Options options2 = new BitmapFactory.Options();options2.inPreferredConfig = Bitmap.Config.RGB_565;Bitmap bitmap2 = BitmapFactory.decodeByteArray(data, 0 , data.length, options2);//System.out.println("bitmap RGB_565 length " + bitmap2.getByteCount());System.out.println("bitmap RGB_565 length " + bitmap2.getRowBytes() * bitmap2.getHeight());BitmapFactory.Options options3 = new BitmapFactory.Options();options3.inPreferredConfig = Bitmap.Config.ALPHA_8;Bitmap bitmap3 = BitmapFactory.decodeByteArray(data, 0 , data.length, options3);//System.out.println("bitmap ALPHA_8 length " + bitmap3.getByteCount());System.out.println("bitmap ALPHA_8 length " + bitmap3.getRowBytes() * bitmap3.getHeight());BitmapFactory.Options options4 = new BitmapFactory.Options();options4.inPreferredConfig = Bitmap.Config.ARGB_4444;Bitmap bitmap4 = BitmapFactory.decodeByteArray(data, 0 , data.length, options4);//System.out.println("bitmap ARGB_4444 length " + bitmap4.getByteCount());System.out.println("bitmap ARGB_4444 length " + bitmap4.getRowBytes() * bitmap4.getHeight());} catch (Exception e) {e.printStackTrace(); }但是實際測試中發(fā)現(xiàn)內(nèi)存的大小與預(yù)期并不一樣,那么是為什么?
ARGB_4444
首先,使用ARGB_4444發(fā)現(xiàn)內(nèi)存沒有變化,看看官方的解釋
/** Each pixel is stored on 2 bytes. The three RGB color channels and the alpha channel (translucency) are stored with a 4 bits precision (16 possible values.) This configuration is mostly useful if the application needs to store translucency information but also needs to save memory. It is recommended to use ARGB_8888 instead of this configuration. Note: as of Build.VERSION_CODES.KITKAT, any bitmap created with this configuration will be created using ARGB_8888 instead.Deprecated Because of the poor quality of this configuration, it is advised to use ARGB_8888 instead. **/ @Deprecated ARGB_4444 (4),原來在KITKAT,即Android 19之后,這個參數(shù)就徹底無效了,只用這個參數(shù)會被默認替換為ARGB_8888,所以內(nèi)存大小沒有變化。
ALPHA_8
測試的時候,發(fā)現(xiàn)ALPHA_8也無效,不僅內(nèi)存大小沒變化,圖片也還是原圖,沒有失去色彩。
我們來看看官方對inPreferredConfig的注釋:
/* If this is non-null, the decoder will try to decode into this internal configuration. If it is null, or the request cannot be met, the decoder will try to pick the best matching config based on the system's screen depth, and characteristics of the original image such as if it has per-pixel alpha (requiring a config that also does). Image are loaded with the Bitmap.Config.ARGB_8888 config by default. */ public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;翻譯過來就是如果inPreferredConfig不為null,那么解碼器回嘗試使用此參數(shù)指定的顏色模式來對圖片進行解碼,如果解碼時發(fā)現(xiàn)不能滿足這個模式,那么解碼器回根據(jù)原圖的特征及當(dāng)前設(shè)備的屏幕位深,自動選擇合適的顏色模式來解碼。
簡單說就是inPreferredConfig只是一個建議選項,最終使用的模式不一定是它指定的,這個要跟原圖特征和當(dāng)前設(shè)備的屏幕位深有關(guān)。
這就是當(dāng)我么使用ALPHA_8無線的原因。另外根據(jù)上面的描述,RGB_565也可能無效,比如講圖片換成下面這個
https://pngimg.com/uploads/cocktail/cocktail_PNG51.png
總結(jié)
由于ARGB_4444已廢除,而ALPHA_8需要在特殊條件下使用,一般用來做特殊需求的,所以我們大多數(shù)是用的還是ARGB_8888和RGB_565。
RGB_565能夠在保證圖片質(zhì)量的情況下大大減少內(nèi)存的開銷,是解決oom的一種方法。但是一定要注意RGB_565是沒有透明度的,如果圖片本身需要保留透明度,那么就不能使用RGB_565。
同時也要注意,inPreferredConfig設(shè)置的模式并不一定會生效。
總結(jié)
以上是生活随笔為你收集整理的详解Bitmap之ARGB_8888/RGB_565/ALPHA_8/ARGB_4444的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 批量改文件后缀
- 下一篇: Acticity切换时ScrollVie