Android bitmap config你理解對了嗎?

在寫本文之前,我還以為自己對android的bitmap很熟悉,直到自己親手寫代碼實踐,才發(fā)現(xiàn)自己錯了很多年。真是汗顏??!

Bitmap Config

首先,根據(jù)Android API 25的文檔簡要說明一下Android的Bitmap.Config以下4個選項

  • ALPHA_8: 每個像素占用1字節(jié)(8位),存儲的是透明度信息。
  • ARGB_4444: 每個像素占用2字節(jié)(4+4+4+4=16位),ARGB分別占用4位,支持alpha通道。
    注:從API 13開始不推薦使用,在android 4.4上面,設(shè)置的ARGB_4444會被系統(tǒng)使用ARGB_8888替換
  • ARGB_8888: 默認的選項,每像素占用4字節(jié),ARGB分別占8位,支持1600萬種顏色,質(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 格式

其次,簡要說一下png格式

  • png 8: 支持不透明,索引色透明,alpha透明,最大支持256種顏色
  • png 24: 不支持透明,支持1600萬種顏色
  • png 32: 支持透明,其它同png 24,支持1600萬種顏色

bitmap內(nèi)存占用計算

第三,簡要說一下bitmap占用的內(nèi)存

Android中bitmap的內(nèi)存占用是跟圖片的尺寸(高和寬)相關(guān)。一張圖片的內(nèi)存占用大致的計算公式如下:

占用內(nèi)存 = 圖像像素總和(width x height)再 x 每像素(bitmap config)占用的字節(jié)數(shù)

以下是通過代碼準確計算

    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)在的手機攝像頭動不動就是上千萬像素,拍出來的照片如果按默認的ARGB_8888 config加載,則至少是幾十M的內(nèi)存占用。

Android的圖片資源主要分兩部分:

  1. 一種是apk中自帶的,多為png格式,由系統(tǒng)加載,支持縮放,代碼中通過R.xxx引用,decode時使用的是默認的ARGB_8888選項,圖像質(zhì)量高;
  2. 另一種是網(wǎng)絡(luò)圖片或本地圖片,多為jpg格式,加載時一般使用第三方的圖片加載庫,為節(jié)省內(nèi)存decode時多為RGB_565選項。

平時都是這么用,也沒發(fā)現(xiàn)問題,優(yōu)化內(nèi)存占用時,一般也是從圖片的尺寸方面入手。不過最近優(yōu)化一個跟圖片相關(guān)的功能,在圖片尺寸無法縮放的條件下,只能通過更改bitmap config來降低內(nèi)存的占用。然后意外的發(fā)現(xiàn),導(dǎo)致顛覆了我的三觀。為此我特地寫了一個測試sample,代碼詳見github,特地創(chuàng)建了一張背景色透明,圖片內(nèi)容為A(黑色50%透明度)R(紅色)G(綠色)B(藍色)圖片,然后分別導(dǎo)出為:png8(alpha透明)、png24(不透明)、png32和jpeg(不透明)格式的圖,分別使用ALPHA_8, ARGB_4444, ARGB_8888, RGB_565四種config加載圖片,得到的實際結(jié)果如下(假設(shè)圖像總像素為X)。

實踐結(jié)果

運行截圖

screenshot
screenshot

結(jié)果統(tǒng)計

bitmap.config ALPHA_8 ARGB_4444 ARGB_8888 RGB_565
png8
41 X 2 X 4 X 42 X A 透明
png24
41 X 2 X 4 X 2 X
png32
41 X 2 X 4 X 42 X A 透明
jpeg
41 X 2 X 4 X 2 X

請注意表格中帶刪除線的部分

  1. ALPHA_8:config占用的內(nèi)存竟然和ARGB_8888一樣,不是說每個像素占用1字節(jié)的么?
  2. RGB_565:在png8和png32中,圖片中的A都保持了50%的透明度,而且占用的內(nèi)存也和ARGB_8888一樣,不是說RGB_565不包含alpha么?不是說占用的內(nèi)存是ARGB_8888的一半么?
  3. ARGB_4444:在android 6.0上面,png8和png32看不見(全透明),png24和jpeg顯示為一塊黑色區(qū)域,在android 4.2上則顯示正常。

帶著上面的疑問,在網(wǎng)上進行了相關(guān)的搜索,也沒有找到答案。好吧,我是懵了,不知道各位看客如何?附上github上的示例工程:https://github.com/Jamling/BitmapConfig

本文永久鏈接: http://www.ieclipse.cn/2017/06/14/Android/Android-bitmap-config/ 未經(jīng)允許,禁止轉(zhuǎn)載,如有問題,請在我的博客原始頁面提交評論。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 2021期待與你一起共事,點擊查看崗位[http://www.itdecent.cn/p/6f4d67fa406...
    閑庭閱讀 17,069評論 0 75
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,180評論 25 708
  • 一直以來Bitmap都是開發(fā)中很棘手的問題,這個問題就是傳說中的OOM(java.lang.OutofMemory...
    M悇芐冋憶閱讀 5,066評論 0 11
  • 寫一句話要有一句話的作用,不矯情,不做無病呻吟;干脆利落,不拖泥帶水。 寫作水平不高,自己不熟的詞匯,一定弄清含義...
    帥氣的小恒閱讀 243評論 2 3
  • 那天,去探望剛生下寶寶的玨。到了醫(yī)院,上了樓,進入產(chǎn)科。 這絕對是每個醫(yī)院最有人情味的地方,也是醫(yī)院里能讓人快樂、...
    粉妖閱讀 426評論 0 1

友情鏈接更多精彩內(nèi)容