今天介紹一些關於Bitmap
的基礎知識:bash
Bitmap
是什麼drawable
文件夾Bitmap.Options
Bitmap
所佔內存Bitmap
官方的說法是:Bitmap
是對位圖的抽象。 形象地來講,咱們在手機屏幕上所看到的圖片就是由一個個像素點拼接而成的,每一個像素點的都是用不一樣數量的二進制位來表示,而Bitmap
就是用來保存這些二進制位。app
Bitmap
佔用內存分析前面咱們說到,Bitmap
的最終目的是爲了在屏幕上顯示圖片,因此首先咱們須要瞭解關於屏幕密度的相關知識:ui
px
:若是咱們近距離地看手機屏幕,就能夠發現它有一個個小點,每個小點就表示一個像素,咱們一般稱它爲px
。1920 * 1080
,也就是說它的高有1920px
,寬爲1080px
,像素點總和就是1920 * 1080px
。px
爲單位,而是用英寸爲單位的,它和咱們平時說的米、釐米是一個概念。ppi
:英文名爲pixel per inch
,中文全稱爲每英寸屏幕上的像素數,它決定了屏幕的質量,一般是按手機的對角線來計算的,也就是說,它等於對象線的像素個數除以對角線的長度(單位爲英寸)。dp/dip
:英文名爲density-independent pixel
,這是安卓特有的概念,它和px
的做用相同,都是用來表示長度。可是它和硬件屏幕無關,若是須要轉換爲px
,那麼1dp
在屏幕上最終會顯示爲(ppi / 160)
個px
。dpi
:英文名爲dot per inch
,中文全稱爲每英寸圖片上點的個數,它決定了圖片的質量,好比dpi
爲320
,那麼最終在手機上一張320 * 320
的圖片就會用320 * 320 * (dpi / 160)
個像素點來表示。在Android
中,經過DisplayMetrics
能夠得到上述的信息:spa
public static void logDensityInfo(Activity activity) {
DisplayMetrics displayMetrics = new DisplayMetrics();
//將信息保存到displayMetrics中.
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
//1.x軸和y軸的dpi.
Log.d("logDensityInfo", "ydpi=" + displayMetrics.ydpi);
Log.d("logDensityInfo", "xdpi=" + displayMetrics.xdpi);
//2.x軸和y軸的像素個數.
Log.d("logDensityInfo", "heightPixels=" + displayMetrics.heightPixels);
Log.d("logDensityInfo", "widthPixels=" + displayMetrics.widthPixels);
//3.dpi
Log.d("logDensityInfo", "densityDpi=" + displayMetrics.densityDpi);
//4.dpi/160.
Log.d("logDensityInfo", "density=" + displayMetrics.density);
//5.一般狀況下和density相同.
Log.d("logDensityInfo", "scaledDensity=" + displayMetrics.scaledDensity);
}
複製代碼
在個人手機上,最終的結果是: code
dpi
相關的值是怎麼得到的:
public void setToDefaults() {
density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
densityDpi = DENSITY_DEVICE;
scaledDensity = density;
xdpi = DENSITY_DEVICE;
ydpi = DENSITY_DEVICE;
}
複製代碼
其中DENSITY_DEFAULT
爲160
,而DENSITY_DEVICE
則是經過下面方式獲得的:對象
private static int getDeviceDensity() {
return SystemProperties.getInt("qemu.sf.lcd_density", SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
}
複製代碼
drawable
文件夾內的圖片提及dpi
,天然就會想到res
文件夾下的drawable-?
文件夾,咱們在平時開發中會發現,若是將同一大小的圖片,放在不一樣的drawable
文件夾下,最終在屏幕上展示的大小是不同的。 這實際上是Android
在讀取資源的時候,會根據文件夾的不一樣,給每一個文件夾定義一個叫作density
的屬性,根據最終找到的資源所在的文件夾位置,會有如下幾種狀況:圖片
dpi
文件夾:不進行縮放。drawable-nodpi
其它的dpi
文件夾:那麼最終的長度變爲(原始長度 / 所在文件夾density) * 匹配文件夾density
drawable-nodpi
:不進行縮放。而每一個ARBG
位的二進制個數相乘,就是圖片所佔內存的大小,對應的density
以下:ip
drawable-nodpi
:不縮放drawable-ldpi
:0.75
drawable
:1
drawable-mdpi
:1
drawable-hdpi
:1.5
drawable-xhdpi
:2
drawable-xxhdpi
:3
drawable-xxhdpi
:4
若是某個資源存在於上面的多個文件夾下,它的匹配優先級以下:內存
dpi
匹配的dpi
文件夾dpi
高的dpi
文件夾drawable-nodpi
dpi
低,但大於等於1
的dpi
文件夾drawable
drawable-ldpi
Bitmap.Config
這是一個枚舉類型,它用來描述每一個像素是如何被保存的,它會影響圖片的質量並決定可否表示透明/半透明顏色。資源
ALPHA_8
:每一個像素點僅表示alpha
的值,它不會存儲任何顏色信息,佔8位
。RGB_565
:每一個像素用5位R/6位G/5位G
來表示,佔16位
。ARGB_8888
:每一個像素分別用8位
存儲ARGB
,佔32位
。ARGB_4444
:和8888
相似,只不過對於每一個通道是使用4位
表示,所以它的圖片質量比較低,已經不推薦使用了。已經介紹完所須要掌握的基礎知識,總結下來,Bitmap
所佔內存大小其實由兩個因素決定:
ARGB
所佔位寬第一點的影響因素有:原始圖片的寬高、手機內置的dpi
、圖片所放位置。 第二點的影響因素有:Bitmap
所對應的Bitmap.Config
配置。
下面咱們幾個例子,驗證前面說的三種狀況:
720 * 1280
,它所匹配到的文件夾爲drawable-xhdpi
,咱們先將一個原始大小爲48 * 48
的圖片方在drawable-xhdpi
文件夾中,並配置Option
爲Bitmap.Config.RGB_565
:private void logWrapperImageView() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.drawable_test, options);
Log.d("logWrapperImageView", "width=" + bitmap.getWidth() + ",height=" + bitmap.getHeight() + ",size=" + bitmap.getByteCount());
}
複製代碼
這種狀況下最終的結果爲,雖然咱們指出了須要用RGB_565
,可是系統每一個像素仍是隻用了一位:
width=48,height=48,size=2304 //RGB_565
width=48,height=48,size=9216 //ARGB_8888
width=48,height=48,size=2304 //ALPHA_8
複製代碼
1080 * 1920
,它所匹配到的文件夾爲drawable-xxhdpi
,咱們先將一個原始大小爲48 * 48
的圖片方在drawable-xxhdpi
文件夾中,並配置Option
爲Bitmap.Config.RGB_565
,運行和上面同樣的程序,獲得的結果爲:width=48,height=48,size=2304 //RGB_565
複製代碼
接着改變它的Options
:
width=48,height=48,size=9216 //ARGB_8888
width=48,height=48,size=2304 //ALPHA_8
複製代碼
drawable-nodpi
的文件夾中720 * 1280
,把圖片放在drawable-xxhdpi
文件夾中:width=32,height=32,size=4096 //RGB_565
複製代碼
改變它的Options
:
width=32,height=32,size=4096 //ALPHA_8
width=32,height=32,size=4096 //ARGB_8888
複製代碼
1080 * 1960
,把圖片放在drawable-xhdpi
文件夾中:width=72,height=72,size=20736
複製代碼
改變它的Options
width=72,height=72,size=20736 //ALPHA_8
width=72,height=72,size=20736 //ARGB_8888
複製代碼
drawable-nodpi
文件夾中720 * 1280
:width=48,height=48,size=2304 //RGB_565
width=48,height=48,size=9216 //ARGB_8888
width=48,height=48,size=2304 //ALPHA_8
複製代碼
1080 * 1960
:width=48,height=48,size=2304 //RGB_565
width=48,height=48,size=9216 //ARGB_8888
width=48,height=48,size=2304 //ALPHA_8
複製代碼
從上面的例子中,總結出幾點:
dpi
文件夾,和放在drawable-nodpi
文件夾是相同的。RGB_565
時,實際佔用的是一個字節。Options
,都是採用佔用4字節
的方式。dpi
文件夾下和drawable-nodpi
文件夾下時,長寬不進行縮放。匹配文件夾density/所在文件夾density
,以上面3.5.2
的720 * 1280
手機爲例,原始的圖片的長寬爲48
,其匹配文件夾的density
爲2
,所在文件夾的density
爲3
,因此縮放倍數爲2/3
,所以,最後的長寬爲32
。Bitmap
所佔內存大小就等於它的長寬乘以每一個像素所佔位數。