Android圖片加載系列(0) 你不得不知道的Bitmap基礎知識

一、圖像的存儲形式——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...)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容