1. 學習Bitmap之前的先需概念:
- 屏幕像素:屏幕上像素點數,單位是px, 1px爲1個像素點。
- 屏幕尺寸:屏幕的對角線長度,單位是英寸,1英寸=2.54cm。
- 屏幕分辨率:屏幕縱橫向上的像素點數,單位是px,格式:縱向像素*橫向像素 如1960*1080。
- 屏幕像素密度:每英寸上面的像素點個數,單位是dpi,是“dot per inch”的縮寫。
補充:
- 相同尺寸情況下,分辨率越高,屏幕越清新,即屏幕像素密度越大。
- 屏幕密度計算方式:Density = 對角線上像素點/對角線尺寸。
2. drawable不同目錄分辨率及系統dpi、基準比例
ldpi | mdpi | hdpi | xhdpi | xxhdpi | xxxhdpi | |
---|---|---|---|---|---|---|
分辨率 | 240*320 | 320*480 | 480*800 | 720*1280 | 1080*1920 | 2160*3840 |
系統dpi | 120 | 160 | 240 | 320 | 480 | 640 |
基準比例 | 0.75 | 1 | 1.5 | 2 | 3 | 4 |
- 上表中系統dpi也是Density,對應着bitmap中bitmap.inDensity
- 這裏的基準比例是用於dp和px的換算
3. dp與px之間換算
首先需要理解三個概念:
名稱 | 含義 |
---|---|
dp | 安卓佈局中相對大小 |
dpi | 像素密度 |
px | 像素點 |
dp的計算公式:
控件顯示像素(px) = 控件相對尺寸(dp) * 設備像素密度(dpi)/基準像素密度(dpi)
這裏基準像素密度選擇160dpi。
我們看下下面這段代碼:
<ImageView
android:id="@+id/imageView"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:contentDescription="@string/app_name"
android:scaleType="fitCenter" />
這裏我們對此ImageView要求顯示尺寸:200dp * 200dp,那我們先看下真正的顯示尺寸是多少?
1534497327(1).png
上圖中可以看到:
- targetWidth = 800,targetHeight = 800, 單位是px; 此參數表示真正顯示的尺寸。
- toTargetDensity = 640,單位是dpi; 此參數表示設備的dpi。
回頭我們去驗證一下公式:
- ImageView尺寸相對大小 = 200dp
- 當前設備像素密度 = 640dpi
- 基準像素密度 = 160dpi
- 顯示像素 = 800 px
驗證:800(px) = 200(dp) * 640(dpi) / 160 (dpi)
舉一反三:
在320x480分辨率,像素密度爲160,1dp=1px
在480x800分辨率,像素密度爲240,1dp=1.5px
4. Bitmap顯示尺寸
Android 設備比較多,而且圖片分辨率比較多。這裏爲了統一顯示,Android系統做了一些處理,這裏介紹一下使用Bitmap將圖片進行映射不同設備上顯示。步驟如下:
- drawable不同目錄下的分辨率不一樣,屏幕密度也不一樣,將圖片放到不同目錄中。
- 各個設備的分辨率不一樣,屏幕密度也不一樣。
- 使用Bitmap可以將不同分辨率的圖片映射到相應的設備上。
計算公式:
width = pixWidth / inDensity * inTargetDensity
height = pixHeight / inDensity * inTargetDensity
注意:上述公式中/爲“除”
名稱 | 含義 |
---|---|
width/height | 設備屏幕上寬度/高度 |
pixWidth/pixHeight | 圖片實際寬度/高度 |
inDensity | 圖片存放目錄下的像素密度 |
inTargetDensity | 設備像素密度 |
注意:上表格中/爲“或者”的意思
5. Bitmap內存大小
Bitmap的內存大小計算公式:
Bitmap的Memorysize = (pixWidth / inDensity * inTargetDensity) * (pixHeight / inDensity * inTargetDensity) * 一個像素的內存大小。
注意:
- pixWidth/pixHeight:實際像素的寬度/高度。
- 一個像素的內存大小和Bitmap的存儲的方式有關。
- 存儲方式有五種,分別是ALPHA_8,RGB_565,ARGB_4444,ARGB_8888,RGBA_F16;
- 枚舉定義在Bitmap.Config類中。
不同存儲類型和內存大小的關係如下圖:
存儲方式 | 內存大小 |
---|---|
ALPHA_8 | 1byte |
RGB_565 | 2byte |
ARGB_4444 | 4byte |
ARGB_8888 | 4byte |
RGBA_F16 | 4byte |
下面是這四種類型的詳細解釋:
-
ALPHA_8:每個像素都需要1(8位)個字節的內存,只存儲位圖的透明度,沒有顏色信息
-
RGB_565:同理,R佔5位精度,G佔6位精度,B佔5位精度,一共是16位精度,摺合兩個字節。這裏注意的時,這個類型存儲的只是顏色信息,沒有透明度信息
-
ARGB_4444:A(Alpha)佔4位的精度,R(Red)佔4位的精度,G(Green)佔4位的精度,B(Blue)佔4位的精度,加起來一共是16位的精度,摺合是2個字節,也就是一個像素佔兩個字節的內存,同時存儲位圖的透明度和顏色信息。不過由於該精度的位圖質量較差,官方不推薦使用
-
ARGB_8888:這個類型的跟ARGB_4444的原理是一樣的,只是A,R,G,B各佔8個位的精度,所以一個像素佔4個字節的內存。由於該類型的位圖質量較好,官方特別推薦使用。但是,如果一個480*800的位圖設置了此類型,那個它佔用的內存空間是:480*800*4/(1024*1024)=1.5M
-
RGBA_F16:每個像素用8位存儲,每個通道(RGBA)使用半精度(16位)存儲,此類型適用於寬色域和HDR內容