Android內存中的圖片

www345 9年前發布 | 10K 次閱讀 Android Android開發 移動開發


public static final Bitmap.Config ALPHA_8
public static final Bitmap.Config ARGB_4444
public static final Bitmap.Config ARGB_8888
public static final Bitmap.Config RGB_565

說白了就ALPHA_8就是Alpha由8位組成
ARGB_4444就是由4個4位組成即16位,
ARGB_8888就是由4個8位組成即32位,
RGB_565就是R為5位,G為6位,B為5位共16位

由此可見:
ALPHA_8 代表8位Alpha位圖
ARGB_4444 代表16位ARGB位圖
ARGB_8888 代表32位ARGB位圖
RGB_565 代表8位RGB位圖

位圖位數越高代表其可以存儲的顏色信息越多,當然圖像也就越逼真。

 

圖片的分辨率是3776 * 2520,每一點又是由ARGB色組成,每個色素占4個Byte,所以這張圖片加載到內存中需要消耗的內存為:
3776 * 2520 * 4byte = 38062080byte,會造成內存溢出,那么如何加載大圖片呢?

如何加載大分辨率圖片

有時候我們確實會需要加載一些大分辨率的圖片,但是對于移動設備而言,哪怕加載能成功那么大的內存也是一種浪費(屏幕分辨率限制),所以就需要想辦法把圖片按照一定比率壓縮,使分辨率降低,以至于又不需要耗費很大的堆內存空間,又可以最大的利用設備屏幕的分辨率來顯示圖片。這里就用到一個 BitmapFactory.Options對象,下面來介紹它。
BitmapFactory.Options為BitmapFactory的一個內部類,它主要用于設定與存儲BitmapFactory加載圖片的一些信息。下面是Options中需要用到的屬性:
inJustDecodeBounds:如果設置為true,將不把圖片的像素數組加載到內存中,僅加載一些額外的數據到Options中。
outHeight:圖片的高度。
outWidth:圖片的寬度。
inSampleSize:如果設置,圖片將依據此采樣率進行加載,不能設置為小于1的數。例如設置為4,分辨率寬和高將為原來的1/4,這個時候整體所占內存將是原來的1/16。

 

示例代碼:

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.view.Menu;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView; 
public class MainActivity extends Activity {
    private Button btn_loadimage;
    private ImageView iv_bigimage; 
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); 
         btn_loadimage = (Button) findViewById(R.id.btn_loadimage);
        iv_bigimage = (ImageView) findViewById(R.id.iv_bigimage); 
         btn_loadimage.setOnClickListener(new View.OnClickListener() { 
             @Override
            public void onClick(View v) {
                // Bitmap bitmap=BitmapFactory.decodeFile("/sdcard/a.jpg");
                // iv_bigimage.setImageBitmap(bitmap); 
                 BitmapFactory.Options opts = new Options();
                // 不讀取像素數組到內存中,僅讀取圖片的信息
                opts.inJustDecodeBounds = true;
                BitmapFactory.decodeFile("/sdcard/a.jpg", opts);
                // 從Options中獲取圖片的分辨率
                int imageHeight = opts.outHeight;
                int imageWidth = opts.outWidth; 
                 // 獲取Android屏幕的服務
                WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
                // 獲取屏幕的分辨率,getHeight()、getWidth已經被廢棄掉了
                // 應該使用getSize(),但是這里為了向下兼容所以依然使用它們
                int windowHeight = wm.getDefaultDisplay().getHeight();
                int windowWidth = wm.getDefaultDisplay().getWidth(); 
                 // 計算采樣率
                int scaleX = imageWidth / windowWidth;
                int scaleY = imageHeight / windowHeight;
                int scale = 1;
                // 采樣率依照最大的方向為準
                if (scaleX > scaleY && scaleY >= 1) {
                    scale = scaleX;
                }
                if (scaleX < scaleY && scaleX >= 1) {
                    scale = scaleY;
                } 
                 // false表示讀取圖片像素數組到內存中,依照設定的采樣率
                opts.inJustDecodeBounds = false;
                // 采樣率
                opts.inSampleSize = scale;
                Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/a.jpg", opts);
                iv_bigimage.setImageBitmap(bitmap); 
             }
        });
    }
}

加載縮略圖

1. 使用inJustDecodeBounds,讀bitmap的長和寬。

  1. 根據bitmap的長款和目標縮略圖的長和寬,計算出inSampleSize的大小。
  2. 使用inSampleSize,載入一個大一點的縮略圖A
  3. 使用createScaseBitmap,將縮略圖A,生成我們需要的縮略圖B。
  4. 回收縮略圖A。</span> </p>

    需要注意的事情

     createScaseBitmap如果原圖和目標縮略圖大小一致,那么不會生成一個新的bitmap直接返回bitmap,因此,回收的時候,要判斷縮略圖A是否就是縮略圖B,如果說是的話,不要回收。

    /**

    • http://developer.android.com/training/displaying-bitmaps/load-bitmap.html */ public class BitmapUtils { private static int calculateInSampleSize(BitmapFactory.Options options,

         int reqWidth, int reqHeight) {
      

      final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) {

         final int halfHeight = height / 2;
         final int halfWidth = width / 2;
         while ((halfHeight / inSampleSize) > reqHeight
                 && (halfWidth / inSampleSize) > reqWidth) {
             inSampleSize *= 2;
         }
      

      } return inSampleSize; }

      // 如果是放大圖片,filter決定是否平滑,如果是縮小圖片,filter無影響 private static Bitmap createScaleBitmap(Bitmap src, int dstWidth,

         int dstHeight) {
      

      Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false); if (src != dst) { // 如果沒有縮放,那么不回收

         src.recycle(); // 釋放Bitmap的native像素數組
      

      } return dst; }

      // 從Resources中加載圖片 public static Bitmap decodeSampledBitmapFromResource(Resources res,

         int resId, int reqWidth, int reqHeight) {
      

      final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // 讀取圖片長款 options.inSampleSize = calculateInSampleSize(options, reqWidth,

             reqHeight); // 計算inSampleSize
      

      options.inJustDecodeBounds = false; Bitmap src = BitmapFactory.decodeResource(res, resId, options); // 載入一個稍大的縮略圖 return createScaleBitmap(src, reqWidth, reqHeight); // 進一步得到目標大小的縮略圖 }

      // 從sd卡上加載圖片 public static Bitmap decodeSampledBitmapFromFd(String pathName,

         int reqWidth, int reqHeight) {
      

      final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(pathName, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; Bitmap src = BitmapFactory.decodeFile(pathName, options); return createScaleBitmap(src, reqWidth, reqHeight); } }</pre>
      來自:http://www.cnblogs.com/huozhong/p/4968410.html

 本文由用戶 www345 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!