引用鏈接
關(guān)于Android中圖片大小毫缆、內(nèi)存占用與drawable文件夾關(guān)系的研究與分析
結(jié)果分析
- 同一張圖片,放在不同目錄下乐导,會(huì)生成不同大小的Bitmap
- Bitmap的長(zhǎng)度和寬度越大苦丁,占用的內(nèi)存就越大
- 圖片在硬盤(pán)上占用的大小,與在內(nèi)存中占用的大小完全不一樣
下面我會(huì)對(duì)上面幾個(gè)問(wèn)題一一解釋物臂。
我們以放在drawable文件夾下面的圖片為例旺拉,加載到內(nèi)存之后,2160*3840大小的Bitmap占用的內(nèi)存為
2160 * 3840 * 4 = 3317,7600 byte = 3,2400kb = 31.640625 M
所以drawable文件夾下的App內(nèi)存占用 = 原始內(nèi)存8.31M+圖片內(nèi)存31.64M= 39.95M 鹦聪,與實(shí)際內(nèi)存占用39.88M存在0.1755%的誤差账阻,在誤差范圍之內(nèi)。
先簡(jiǎn)單解釋一下上面的計(jì)算公式泽本,長(zhǎng)*寬是圖片的像素總數(shù)淘太,乘以4則是因?yàn)橐粋€(gè)像素占用A、R规丽、G蒲牧、B四個(gè)通道,每個(gè)通道占用8位赌莺,所以描述一個(gè)像素需要32位即4個(gè)字節(jié)冰抢。
一個(gè)顏色通道需要8位描述,2^8=256艘狭,所以每個(gè)顏色通道就有256種狀態(tài)挎扰。如果把彩色圖轉(zhuǎn)化成灰階圖的話翠订,也有256種狀態(tài)分割從白色到黑色之間的過(guò)渡顏色。
當(dāng)然遵倦,也并不是所有格式的圖片每個(gè)像素占用4字節(jié)尽超,這和圖片在加載時(shí)設(shè)置的Bitmap.Config有關(guān),默認(rèn)的是Bitmap.Config.ARGB_8888梧躺,其他類型如下:
Bitmap.Config.ALPHA_8
此時(shí)圖片只有alpha值似谁,沒(méi)有RGB值
A 占 8bit = 1字節(jié) = 1像素
Bitmap.Config.ARGB_4444
一個(gè)像素占用2個(gè)字節(jié),alpha(A)值掠哥,Red(R)值巩踏,Green(G)值,Blue(B)值各占4個(gè)bites共16bites,即2個(gè)字節(jié)
ARGB各占8bit(4 * 4)= 16bit = 2字節(jié) = 1像素
Bitmap.Config.ARGB_8888
一個(gè)像素占用4個(gè)字節(jié)续搀,alpha(A)值塞琼,Red(R)值,Green(G)值目代,Blue(B)值各占8個(gè)bites屈梁,共32bites,即4個(gè)字節(jié)。這是一種高質(zhì)量的圖片格式榛了,在電腦上普通采用。它也是Android手機(jī)上一個(gè)Bitmap的默認(rèn)格式煞抬。
ARGB各占8bit(4 * 8)= 32bit = 4字節(jié) = 1像素
Bitmap.Config.RGB_565
一個(gè)像素占用2個(gè)字節(jié)霜大,沒(méi)有alpha(A)值,即不支持透明和半透明革答,Red(R)值占5個(gè)bites 战坤,Green(G)值占6個(gè)bites ,Blue(B)值占5個(gè)bites,共16bites,即2個(gè)字節(jié)残拐。對(duì)于沒(méi)有透明和半透明顏色的圖片來(lái)說(shuō)途茫,該格式的圖片能夠達(dá)到比較的呈現(xiàn)效果,相對(duì)于ARGB_8888來(lái)說(shuō)也能減少一半的內(nèi)存開(kāi)銷(xiāo)溪食。因此它是一個(gè)不錯(cuò)的選擇囊卜。
R(5bit)+G(6bit)+B(5bit) = 16bit = 2字節(jié) = 1像素
那么為啥在硬盤(pán)上存儲(chǔ)只需要77.11k,放到內(nèi)存里面就需要30多M呢错沃?
因?yàn)檫@根本不是一回事呀~
存放在硬盤(pán)上的圖片文件栅组,會(huì)根據(jù)各自的壓縮規(guī)則進(jìn)行壓縮,比如Jpeg這種有損壓縮的圖片格式枢析,最常使用可變字長(zhǎng)編碼的哈弗曼編碼玉掸,會(huì)使用哈弗曼樹(shù),也就是最優(yōu)二叉樹(shù)醒叁,根據(jù)某些數(shù)據(jù)出現(xiàn)的頻率對(duì)數(shù)據(jù)段編碼司浪,從而減少占用的硬盤(pán)大小泊业。
比如說(shuō)“10111”這個(gè)序列在圖片的二進(jìn)制數(shù)據(jù)中出現(xiàn)的概率最大,那我們可以用“01”來(lái)代替這一段數(shù)據(jù)啊易,原來(lái)5位的數(shù)據(jù)脱吱,用2位就可以表示了,這就是壓縮率60%认罩。當(dāng)然這只是打個(gè)比方箱蝠,在實(shí)際操作中需要考慮“異前綴原則”等編碼的基本原則。
而如果把圖像讀取到內(nèi)存中就不一樣了垦垂,因?yàn)槲覀冃枰恳粋€(gè)像素都能在屏幕上顯示宦搬,所以會(huì)把每個(gè)像素點(diǎn)都加載至內(nèi)存中,不會(huì)對(duì)相同像素進(jìn)行壓縮或者是替換劫拗,所以你也應(yīng)該能明白前面提到的Bitmap占用內(nèi)存大小的計(jì)算公式的由來(lái)了间校。
說(shuō)到這里,其實(shí)后兩個(gè)結(jié)論已經(jīng)解釋清楚了页慷,那么為什么“同一張圖片憔足,放在不同目錄下,會(huì)生成不同大小的Bitmap”呢酒繁?
放置不同drawable文件夾的區(qū)別
配置:
- 模擬機(jī)(1080*1920 xxhdpi )
- 圖片(720 * 1280)
當(dāng)圖片放置在drawable-ldpi中時(shí) (4倍關(guān)系)
圖片長(zhǎng) = 720 *(16/4)= 2880
圖片寬 = 1280 *(16/4) = 5120
當(dāng)圖片放置在drawable-mdpi中時(shí) (3倍關(guān)系)
圖片長(zhǎng) = 720 *(12/4)= 2160
圖片寬 = 1280 *(12/4) = 3840
當(dāng)圖片放置在drawable-hdpi中時(shí) (2倍關(guān)系)
圖片長(zhǎng) = 720 *(8/4)= 1440
圖片寬 = 1280 *(8/4) = 2560
當(dāng)圖片放置在drawable-xhdpi中時(shí) (1.5倍關(guān)系)
圖片長(zhǎng) = 720 *(6/4)= 1080
圖片寬 = 1280 *(6/4) = 1920
當(dāng)圖片放置在drawable-xxhdpi中時(shí) (無(wú)倍數(shù)關(guān)系滓彰,不會(huì)對(duì)圖像進(jìn)行放縮,保持原始大小 )
圖片長(zhǎng) = 720 *(4/4)= 720
圖片寬 = 1280 *(4/4) = 1280
當(dāng)圖片放置在drawable-xxxhdpi中時(shí) (0.75倍數(shù)關(guān)系)
圖片長(zhǎng) = 720 *(3/4)=540
圖片寬 = 1280 *(3/4)= 960
drawable和drawable-mdpi是一樣的大小州袒,是因?yàn)閐rawable-mdpi是系統(tǒng)默認(rèn)的像素密度揭绑,其他像素密度都以它為基數(shù),當(dāng)只在drawable中存在圖片時(shí)郎哭,如果使用該圖片他匪,那么將按照drawable-mdpi的放縮比例進(jìn)行放縮。
Android分辨率及對(duì)應(yīng)密度 如圖:
例如夸研,當(dāng)前設(shè)備的dpi是480(即xxhdpi)邦蜜,那么對(duì)于存放于mdpi目錄中的圖片會(huì)被放大三倍。對(duì)于很多設(shè)備亥至,其dpi并不剛好是六種通用密度最大dpi悼沈,這種情況下,圖片的縮放倍數(shù)如何計(jì)算呢抬闯?
稍微思考一下井辆,我們就可以得到通用的縮放倍數(shù)(縮放因子)計(jì)算方法:對(duì)于任意設(shè)備,各drawable-[density]目錄下的圖片放大倍數(shù)的計(jì)算公式
公式:scale=設(shè)備dpi/圖片所在Drawable目錄對(duì)應(yīng)最大dpi
那么溶握,圖片的實(shí)現(xiàn)顯示尺寸通過(guò)圖片尺寸乘以縮放倍數(shù)就可以得到了杯缺。
其實(shí)這里有些繞~我自己也總是混淆 要注意兩種概念:
- 圖片和手機(jī)配置都固定的情況下 圖片放置到不同文件夾(上面介紹的這種);
- 圖片放置固定文件夾 多分辨率的手機(jī)加載(常用場(chǎng)景)睡榆;
簡(jiǎn)述第2中概念:假如 圖片固定放到xxhdp文件夾下
1萍肆、你的手機(jī)分辨率是1920 * 1080那么圖片保持原始大小加載袍榆;
2、手機(jī)分辨率是大于1920 * 1080塘揣,則會(huì)將圖片等比放大 加載包雀;
3、手機(jī)分辨率是大于1920 * 1080亲铡,則會(huì)將圖片等比縮小 加載才写;
結(jié)論
從上面的測(cè)試我們可以得出以下幾個(gè)結(jié)論:
- 當(dāng)圖片放置在不同drawable文件夾中,且只有這一張圖片時(shí)奖蔓,運(yùn)行設(shè)備會(huì)根據(jù)自身的屏幕密度赞草,對(duì)圖片進(jìn)行放縮,放縮比例符合前面圖上的規(guī)則
- 圖片文件的大小與在內(nèi)存中占用的大小沒(méi)關(guān)系吆鹤,內(nèi)存中實(shí)際占用大小與圖片分辨率厨疙、像素顯示參數(shù)有關(guān)
所以,在一個(gè)App里面使用一套UI理論上應(yīng)該是沒(méi)有問(wèn)題的疑务,但是要注意
- 最好使用較高分辨率的切圖沾凄,并且放置在正確的drawable文件夾中,比如按照xxhdpi的分辨率進(jìn)行切圖知允,放置在drawable-xxhdpi中
- 對(duì)于可以使用.9格式的圖片撒蟀,最好使用.9,減少資源大小
- 如果有條件廊镜,最好提供多套UI切圖牙肝。如果只有一套切圖,系統(tǒng)需要對(duì)圖片進(jìn)行壓縮嗤朴,會(huì)進(jìn)行大量運(yùn)算,影響設(shè)備性能虫溜。同時(shí)雹姊,在某些情況下,系統(tǒng)對(duì)圖片的壓縮會(huì)可能會(huì)出現(xiàn)鋸齒衡楞,造成信息的丟失
- 如果是多套切圖的話吱雏,最好不要直接用工具按照比例放縮,這樣小圖標(biāo)會(huì)丟失一些細(xì)節(jié)瘾境。當(dāng)然歧杏,這部分是美工來(lái)做的,可以讓她參考這篇文章利用PS CS6的新功能保持ICON細(xì)節(jié)飽滿完美
思考一下迷守,如果把一個(gè)本來(lái)應(yīng)該放在drawable-xxhdpi里面的圖片放在了drawable文件夾中會(huì)出現(xiàn)什么問(wèn)題呢犬绒?
明明是(4/4)變成了(12/4) 導(dǎo)致 在xxhdpi設(shè)備上,圖片會(huì)被放大3倍兑凿,圖片內(nèi)存占用就會(huì)變?yōu)樵瓉?lái)的9倍凯力!
如果你要把一個(gè)高2px的分割線做成9.png圖片茵瘾,想讓細(xì)線在不同密度中都是2px,而不是被安卓根據(jù)密度進(jìn)行縮放咐鹤,可以放到drawable-nopdi拗秘,這個(gè)資源文件夾中的圖片,將按照實(shí)際像素顯示祈惶,不會(huì)被安卓根據(jù)密度進(jìn)行縮放雕旨。