Android 一張圖片(BitMap)佔用記憶體的計算 圖片記憶體最佳化,
在Android開發中,我現在發現很多人還不會對圖片佔用記憶體進行很好的計算。
因此撰寫該博文來做介紹,期望達到拋磚引玉的作用。
Android中一張圖片(BitMap)佔用的記憶體主要和以下幾個因數有關:圖片長度,圖片寬度,單位像素佔用的位元組數。一張圖片(BitMap)佔用的記憶體=圖片長度*圖片寬度*單位像素佔用的位元組數註:圖片長度和圖片寬度的單位是像素。圖片(BitMap)佔用的記憶體應該和螢幕密度(Density)無關,雖然我暫時還拿不出直接證據。建立一個BitMap時,其單位像素佔用的位元組數由其參數BitmapFactory.Options的inPreferredConfig變數決定。inPreferredConfig為Bitmap.Config類型,Bitmap.Config類是個枚舉類型,它可以為以下值
| Enum Values |
| Bitmap.Config |
ALPHA_8 |
Each pixel is stored as a single translucency (alpha) channel. This is very useful to efficiently store masks for instance. No color information is stored. With this configuration, each pixel requires 1 byte of memory. 此時圖片只有alpha值,沒有RGB值, 一個像素佔用一個位元組 |
| Bitmap.Config |
ARGB_4444 |
This field is deprecated. Because of the poor quality of this configuration, it is advised to use ARGB_8888instead. 這種格式的圖片,看起來品質太差,已經不推薦使用。 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. 一個像素佔用2個位元組,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各佔4個bites 共16bites,即2個位元組 |
| Bitmap.Config |
ARGB_8888 |
Each pixel is stored on 4 bytes. Each channel (RGB and alpha for translucency) is stored with 8 bits of precision (256 possible values.) This configuration is very flexible and offers the best quality. It should be used whenever possible 一個像素佔用4個位元組,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各佔8個bites 共32bites,即4個位元組 這是一種高品質的圖片格式,電腦上普通採用的格式。它也是Android手機上一個BitMap的預設格式。 |
| Bitmap.Config |
RGB_565 |
Each pixel is stored on 2 bytes and only the RGB channels are encoded: red is stored with 5 bits of precision (32 possible values), green is stored with 6 bits of precision (64 possible values) and blue is stored with 5 bits of precision. This configuration can produce slight visual artifacts depending on the configuration of the source. For instance, without dithering, the result might show a greenish tint. To get better results dithering should be applied. This configuration may be useful when using opaque bitmaps that do not require high color fidelity. 一個像素佔用2個位元組,沒有alpha(A)值,即不支援透明和半透明, Red(R)值佔5個bites ,Green(G)值佔6個bites ,Blue(B)值佔5個bites,共16bites,即2個位元組. 對於沒有透明和半透明顏色的圖片來說,該格式的圖片能夠達到比較的呈現效果, 相對於ARGB_8888來說也能減少一半的記憶體開銷。因此它是一個不錯的選擇。 另外我們通過android.content.res.Resources來取得一個張圖片時,它也是以該格式來構建BitMap的 從Android4.0開始,該選項無效。即使設定為該值,系統任然會採用 ARGB_8888來構造圖片 |
注:ARGB指的是一種色彩模式,裡面A代表Alpha,R表示red,G表示green,B表示blue,其實所有的可見色都是紅綠藍組成的,所以紅綠藍又稱為三原色。A R G B
透明度 紅色 綠色 藍色簡單點說
圖片格式(Bitmap.Config) |
佔用記憶體的計算方向 |
一張100*100的圖片佔用記憶體的大小 |
ALPHA_8 |
圖片長度*圖片寬度 |
100*100=10000位元組 |
ARGB_4444 |
圖片長度*圖片寬度*2 |
100*100*2=20000位元組 |
ARGB_8888 |
圖片長度*圖片寬度*4 |
100*100*4=40000位元組 |
RGB_565 |
圖片長度*圖片寬度*2 |
100*100*2=20000位元組 |
另外,需要注意這裡的圖片佔用記憶體是指在Navtive中佔用的記憶體,當然BitMap使用的絕大多數記憶體就是該記憶體。因為我們可以簡單的認為它就是BitMap所佔用的記憶體。Bitmap對象在不使用時,我們應該先調用recycle(),然後才它設定為null.雖然Bitmap在被回收時可以通過BitmapFinalizer來回收記憶體。但是調用recycle()是一個良好的習慣在Android4.0之前,Bitmap的記憶體是分配在Native堆中,調用recycle()可以立即釋放Native記憶體。從Android4.0開始,Bitmap的記憶體就是分配在dalvik堆中,即JAVA堆中的,調用recycle()並不能立即釋放Native記憶體。但是調用recycle()也是一個良好的習慣。
通過dumpsys meminfo命令可以查看一個進程的記憶體使用量情況,當然也可以通過它來觀察我們建立或銷毀一張BitMap圖片記憶體的變化,從而推斷出圖片佔用記憶體的大小。
樣本:adb shell "dumpsys meminfo com.lenovo.robin"運行結果。Applications Memory Usage (kB):Uptime: 18696550 Realtime: 18696541** MEMINFO in pid 7985 [com.lenovo.robin] ** native dalvik other total size: 4828 5379 N/A 10207 allocated: 4073 2852 N/A 6925 free: 10 2527 N/A 2537 (Pss): 608 317 1603 2528(shared dirty): 2240 1896 6056 10192 (priv dirty): 548 36 1276 1860
Objects Views: 0 ViewRoots: 0 AppContexts: 0 Activities: 0 Assets: 2 AssetManagers: 2 Local Binders: 5 Proxy Binders: 11 Death Recipients: 1OpenSSL Sockets: 0
SQL
heap: 0 MEMORY_USED: 0 PAGECACHE_OVERFLOW: 0 MALLOC_SIZE: 0