• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • Android加載大圖片內存溢出

    發表于:2012-11-29來源:開源中國社區作者:蝸牛TT點擊數: 標簽:Android
    首先解析一下基本的知識: 位圖模式,bitmap顏色位數是1位 灰度模式,bitmap顏色位數是8位,和256色一樣

      首先解析一下基本的知識:

      位圖模式,bitmap顏色位數是1位

      灰度模式,bitmap顏色位數是8位,和256色一樣

      RGB模式,bitmap顏色位數是24位 在RGB模式下,一個像素對應的是紅、綠、藍三個字節

      CMYK模式,bitmap顏色位數是32位 在CMYK模式下,一個像素對應的是青、品、黃、黑四個字節

      圖像文件的字節數(Byte) = 圖像分辨率*顏色深度/8(bit/8)

      例如:一幅640*480圖像分辨率、RGB色一般為24位真彩色,圖像未經壓縮的數據容量為:640X480X24/8=921600字節=900KB(1KB=l千字節=1024字節)。

      注:一個圖像文件占的磁盤空間大小還和磁盤的文件格式有關。如:NTFS最小單位為4KB 所以圖像文件大小肯定是4KB的倍數。但是有圖圖片壓縮算法的存在,圖片文件在保存時,體積要比在內存的大小小得多,如640x480的圖片文件大小一般只在200K~300K。這也是為什么,加載幾MB的圖片文件,會導致JVM內存溢出,導致OutofMemoryException的原因。

      由上面的公式,我們可以得出,加載的圖片所占的內存大小,取決于其分辨率和顏色數。

      我們再來看看Google官方的介紹:

      這個已經非常的明白了,我們VM的app進程所獲得的內存只有區區的16MB,普普通通的5MP攝像頭拍出來的圖片,直接加載,將占用接近19MB的內存??梢?,不進行壓縮,內存將會直接溢出。

      再了解一下,android讀取解析圖片的方式,基本與Java的方式類型,通過文件輸入流,然后進行解碼,再轉成圖片格式;

      當然google的android也為我們封裝好了若干方法,來方便快捷地完成這項工作,如ImageView的setImageBitmap,setImageResource,BitmapFactory的decodeResource等,但是盡量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource來設置一張大圖,因為這些函數在完成decode后,最終都是通過java層的createBitmap來完成的,需要消耗更多內存;

      因此,改用先通過BitmapFactory.decodeStream方法,創建出一個bitmap,再將其設為ImageView的source,加載顯示。decodeStream最大的秘密在于其直接調用JNI>>nativeDecodeAsset()來完成decode,無需再使用java層的createBitmap,從而節省了java層的空間。

      在使用 decodeStream 讀取圖片時,再加上Config參數,就可以更有效地控制加載目標的內存大小,從而更有效阻止拋 OutofMemoryException異常,下面用一段代碼說明:

    Java代碼
    收藏代碼

      public static Bitmap readBitmapAutoSize(String filePath, int outWidth, int outHeight) {

      //outWidth和outHeight是目標圖片的最大寬度和高度,用作限制

      FileInputStream fs = null;

      BufferedInputStream bs = null;

      try {

      fs = new FileInputStream(filePath);

      bs = new BufferedInputStream(fs);

      BitmapFactory.Options options = setBitmapOption(filePath, outWidth, outHeight);

      return BitmapFactory.decodeStream(bs, null, options);

      } catch (Exception e) {

      e.printStackTrace();

      } finally {

      try {

      bs.close();

      fs.close();

      } catch (Exception e) {

      e.printStackTrace();

      }

      }

      return null;

      }

      private static BitmapFactory.Options setBitmapOption(String file, int width, int height) {

      BitmapFactory.Options opt = new BitmapFactory.Options();

      opt.inJustDecodeBounds = true;

      //設置只是解碼圖片的邊距,此操作目的是度量圖片的實際寬度和高度

      BitmapFactory.decodeFile(file, opt);

      int outWidth = opt.outWidth; //獲得圖片的實際高和寬

      int outHeight = opt.outHeight;

      opt.inDither = false;

      opt.inPreferredConfig = Bitmap.Config.RGB_565;

      //設置加載圖片的顏色數為16bit,默認是RGB_8888,表示24bit顏色和透明通道,但一般用不上

      opt.inSampleSize = 1;

      //設置縮放比,1表示原比例,2表示原來的四分之一....

      //計算縮放比

      if (outWidth != 0 && outHeight != 0 && width != 0 && height != 0) {

      int sampleSize = (outWidth / width + outHeight / height) / 2;

      opt.inSampleSize = sampleSize;

      }

      opt.inJustDecodeBounds = false;//最后把標志復原

      return opt;

      }

      另外,decodeStream直接拿的圖片來讀取字節碼了, 不會根據機器的各種分辨率來自動適應, 使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相應的圖片資源, 否則在不同分辨率機器上都是同樣大小(像素點數量),顯示出來的大小就不對了。 可參考下面的代碼:

    Java代碼
    收藏代碼

      BitmapFactory.Options opts = new BitmapFactory.Options();

      //設置圖片的DPI為當前手機的屏幕dpi

      opts.inTargetDensity = ctx.getResources().getDisplayMetrics().densityDpi;

      opts.inScaled = true;

      另外,圖片的bitmap對象為大對象,不用了要注意主動回收,

    Java代碼
    收藏代碼

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>