一、圖像的存儲形式——Bitmap
數字圖像在計算機上以位圖(bitmap)的形式存在。位圖是一個矩形點陣,其中每一點稱為像素(pixel),像素是數字圖像中的基本單位。一幅m×n大小的圖像,是由m×n個明暗度不等的像素組成的。
數字圖像中各個像素所具有的明暗程度由灰度值(gray level)所標識。一般將白色的灰度值定義為255,黑色灰度值定義為0,而由黑到白之間的明暗度均勻地劃分為256個等級。
對于黑白圖像,每個像素用一個字節數據來表示;
對于彩色圖像,每個像素需用三個字節數據來表述。彩色圖像可以分解成紅(R)、綠(G)、藍(B)三個單色圖像,任何一種顏色都可以由這三種顏色混合構成。在圖像處理中,彩色圖像的處理通常是通過對其三個單色圖像分別處理而得到的。
二、 ARGB_8888、ALPHA_8、ARGB_4444、RGB_565的區別
這些都是色彩的存儲模式。
A:alpha(透明度)
R:red(紅色)
G:green(綠色)
B:blue(藍色)
Bitmap.Config ARGB_4444:
A=4,R=4,G=4,B=4,那么一個像素點占4+4+4+4=16位,2字節;
Bitmap.Config ARGB_8888:
A=8,R=8,G=8,B=8,那么一個像素點占8+8+8+8=32位, 4字節;
Bitmap.Config RGB_565:
R=5,G=6,B=5,沒有透明度,那么一個像素點占5+6+5=16位, 2字節;
Bitmap.Config ALPHA_8:
A=8 只有透明度,沒有顏色。1字節;
位圖位數越高代表其可以存儲的顏色信息越多,圖像也就越逼真。ARGB_8888是最逼真的,但同樣也是最占用內存的。
三、 如何計算一張圖片所占用的內存?
假設圖片尺寸為1920x1200(像素),格式為ARGB_8888,內存如何計算?
如上面所述,圖像格式為ARGB_8888, 8+8+8+8=32位= 4字節,也就是一個像素占4字節
而這張圖片有1920x1200個像素點,所以它占用內存為:1920x1200x4(字節)/ 1024 = 9000KB 約為 8.79MB
總結來說,一張圖片占用內存為:
長 x 寬 x 每個像素點占用的內存
備注:
1 byte = 8 bit位
1 KB = 1024 bytes =2^10 bytes 字節
1 MB = 1024 KB = 2^20 bytes
1 GB = 1024 MB = 2^30 bytes
四、Android使用BitmapFactory獲取Bitmap的幾種方法
1、decodeFile(String path)獲取SD卡中的圖片:根據圖片路徑從指定的文件中創建解析Bitmap對象:
String path = "/storage/emulated/0/test.jpg";
Bitmap bitmap = BitmapFactory.decodeFile(path);
2、decodeResource(Resource res, int id) 根據資源ID從指定的資源文件中解析創建Bitmap對象:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.my_photo);
3、decodeStream(InputStream is):用于從指定輸入流中介解析、創建Bitmap對象。例如從服務器上獲取一個圖片:
String image_url = "xxxxx"; // 圖片url
Bitmap bitmap = null;
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
URL url = new URL(image_url);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(5000);
urlConnection.setRequestMethod("GET");
inputStream = urlConnection.getInputStream();
bitmap = BitmapFactory.decodeStream(inputStream);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4、decodeByteArray(byte[] data, int offset,int length):從指定字節數組的offset位置開始,將長度為length的字節數據解析成Bitmap對象。
5、decodeFileDescriptor(FileDescriptor fd):用于從FileDescriptor對應的文件中解析、創建Bitmap對象。
注意:
以上decode方法都有對應的帶BitmapFactory.options參數的方法。
**五、Bitmap解碼參數——BitmapFactory.options **
之所以把BitmapFactory.options單獨列出來,是因為它對于減少圖片內存占用等具有重要意義。詳細用法參見:http://www.lxweimin.com/p/88d86240db48
來看一下主要用到的幾個吧:
1、inJustDecodeBounds:
當設為true時,decode方法會返回null(Bitmap為空),但是Options的outWidth/outHeight/outMimeType屬性會被設置上。因此通過這種方式可以讓我們獲取Bitmap的信息同時,免去了為Bitmap的像素數據分配內存。
(其實從名字上就可以看出來,just decode bounds——只解析邊,即寬高等)
這個可以用來提前判斷我們要加載的圖片的尺寸是否太大,是否需要壓縮。
2、inSampleSize:圖片尺寸被壓縮的比例
如果將inSampleSize設為 >1 的值,那么就會返回壓縮過的圖片。例如: inSampleSize == 4,返回的圖片的寬高將是原來的1/4;
如果inSampleSize設為 <= 1,那么圖片不做變化;
同時注意,最終壓縮的比例必須是2的倍數。不是2的倍數的,需要向下取到2的倍數值。
很明顯,使用這個參數可以在解碼時幫我們壓縮圖片的尺寸。
3、inPreferredConfig,默認值為Bitmap.Config.ARGB_8888;
圖片的色彩配置信息:ARGB_8888、RGB_565等
4、outWidth/outHeight
要生成的Bitmap的寬度和高度;如果inJustDecodeBounds設為true了,那么這個就是未經壓縮過的原圖片的寬高;如果inJustDecodeBounds設為false了,那么這個就是輸出的Bitmap的寬高(有可能被壓縮過的);
六、Bitmap到底要不要Recycle?
Android 3.0
(to be continue...)