1. 程式人生 > >載入大圖片到記憶體的合理方法

載入大圖片到記憶體的合理方法

圖形影象處理

先明確幾個概念。
1.關於單位:計算機中最小單位是位元bit,即一個0或者一個1,計
算機儲存檔案是以byte為單位,byte是位元組等於8個位元。
1M=1024kb;1kb=1024byte;1byte=8bit;

2.計算機如何表示圖形:以畫素為單位,組合成一張圖片,影象的解析度就是畫素的個數。比如一張圖片的解析度是1028*720,這張圖片就由1028*720個畫素點組成。組成圖片的畫素點越多,對圖片細節的描繪就越精確,表現出來的就是更加清晰。照相機的畫素越高(應該說解析度越高)拍出的照片越清晰就是這個道理,500萬畫素就表示拍出的一張照片由500w個畫素組成。

3.計算機儲存影象:儲存每個畫素的顏色,假如以32位點陣圖的格式儲存,每個畫素需要32bit也就是4個byte,計算一下,1028*720*4/1024/1024=2.82M 需要2.82M的空間儲存這張圖片。不過計算機中有很多的圖片壓縮方式,比如黑白照片一個bit就可以表示一個畫素,相當而言佔用空間是非常小的。
android下使用的是RGB表示顏色。RGB:red green blue,#ff ff ff .#FF FF FF表示白色,#000000表示黑色。

4.Android系統在記憶體中表示一個畫素的顏色需要32位,以16進製表示:0x FF FF FF FF ,第一個FF代表透明度,依次為,紅色,綠色,藍色。一個int的值時32位,一個int值可以代表計算機中一個畫素的顏色。

5.大部分Android手機系統給每個應用程式分配的記憶體大小為16M,當應用程式申請的記憶體超過這個值時,會報OOM(out of memory)記憶體溢位,應用會崩潰。android載入圖片需要的記憶體跟圖片佔用空間的大小沒有一點關係,而是由圖片的解析度決定,比如解析度是1028*720,需要申請的記憶體是1028*720個畫素,如果以32位的點陣圖格式載入圖片,每個畫素需要32bit也就是4個byte,計算一下,1028*720*4/1024/1024=2.82M。需要申請2.82M的記憶體。即使是一張黑白照片,它的解析度是1028*720那麼所要申請的記憶體空間也是2.8M。

載入大圖片到記憶體中

手機螢幕都是有既定的解析度的,一個螢幕最多有多少個畫素點是固定的,解析度很大的圖片即使載入進記憶體中也有可能不能完全顯示出來,所以我們在Android中載入大圖片時候要先將圖片縮放,縮放的原理簡單說就是將周圍數十個畫素點用一個畫素點來表示,以人眼的分別能力感覺不出來太明顯的變化。根據圖片實際大小和手機螢幕解析度大小的比例進行縮放。程式碼如下:

public void click(View view){
        //相當消耗記憶體資源 根據圖片的解析度而定
        // Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/photo.jpg");
// iv.setImageBitmap(bitmap); //1.得到螢幕的寬高資訊 WindowManager wm = getWindowManager(); int screenWidth = wm.getDefaultDisplay().getWidth(); int screenHeight = wm.getDefaultDisplay().getHeight(); System.out.println("螢幕寬高:"+screenWidth+"-"+screenHeight); //2.得到圖片的寬高。 BitmapFactory.Options opts = new Options();//解析點陣圖的附加條件 opts.inJustDecodeBounds = true;//不去解析真實的點陣圖,只是獲取這個點陣圖的標頭檔案資訊 Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/photo.jpg", opts); int bitmapWidth = opts.outWidth; int bitmapHeight = opts.outHeight; System.out.println("圖片寬高: "+bitmapWidth+"-"+bitmapHeight); //3.計算縮放比例 int dx = bitmapWidth/screenWidth; int dy = bitmapHeight/screenHeight; int scale = 1; if(dx>dy&&dy>1){ System.out.println("按照水平方法縮放,縮放比例:"+dx); scale = dx; } if(dy>dx&&dx>1){ System.out.println("按照垂直方法縮放,縮放比例:"+dy); scale = dy; } //4.縮放載入圖片到記憶體。 opts.inSampleSize = scale; opts.inJustDecodeBounds = false;//真正的去解析這個點陣圖。 bitmap = BitmapFactory.decodeFile("/mnt/sdcard/photo.jpg", opts); iv.setImageBitmap(bitmap); }