圖片加載OOM

今天給大家分享的是解決解析圖片的出現oom的問題,我們可以用BitmapFactory這裏的各種Decode方法,如果圖片很小的話,不會出現oom,但是當圖片很大的時候就要用BitmapFactory.Options這個東東了,Options裏主要有兩個參數比較重要.

options.inJustDecodeBounds = false/true;  
options.inSampleSize = ssize;  //圖片壓縮比例.  


我們去解析一個圖片,如果太大,就會OOM,我們可以設置壓縮比例inSampleSize,但是這個壓縮比例設置多少就是個問題,所以我們解析圖片可以分爲倆個步驟,第一步就是獲取圖片的寬高,這裏要設置Options.inJustDecodeBounds=true,這時候decode的bitmap爲null,只是把圖片的寬高放在Options裏,然後第二步就是設置合適的壓縮比例inSampleSize,這時候獲得合適的Bitmap.


主要是通過BitmapFactory.Options 來實現。
Options中有個屬性inJustDecodeBounds。我們可以充分利用它,來避免大圖片的溢出問題。他是什麼原理呢?
API這樣說:如果該 值設爲true那麼將不返回實際的bitmap,也不給其分配內存空間這樣就避免內存溢出了。但是允許我們查詢圖片的信息這其中就包括圖片大小信息(options.outHeight (圖片原始高度)和option.outWidth(圖片原始寬度))。


Options中有個屬性inSampleSize。我們可以充分利用它,實現縮放。
如果被設置爲一個值> 1,要求解碼器解碼出原始圖像的一個子樣本,返回一個較小的bitmap,以節省存儲空間。
例如,inSampleSize = = 2,則取出的縮略圖的寬和高都是原始圖片的1/2,圖片大小就爲原始大小的1/4。
對於任何值< = 1的同樣處置爲1。


那麼相應的方法也就出來了,通過設置 inJustDecodeBounds爲true,獲取到outHeight(圖片原始高度)和 outWidth(圖片的原始寬度),然後計算一個inSampleSize(縮放值),然後就可以取圖片了,這裏要注意的是,inSampleSize 可能小於0,必須做判斷。


實現步驟:


第一步:BitmapFactory.Option
設置 inJustDecodeBounds爲true


第二步:BitmapFactory.decodeFile(path,option)方法
解碼圖片路徑爲一個位圖。如果指定的文件名是空的,或者不能解碼到一個位圖,函數將返回null[空值]。
獲取到outHeight(圖片原始高度)和 outWidth(圖片的原始寬度)


第三步:計算縮放比例,也可以不計算,直接給它設定一個值。
options.inSampleSize = "你的縮放倍數";
如果是2就是高度和寬度都是原始的一半。


第四步:設置options.inJustDecodeBounds = false;
重新讀出圖片
bitmap = BitmapFactory.decodeFile(path, options);


具體實現:

package xiaosi.compress;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;

public class Compress extends Activity
{
    /** Called when the activity is first created. */
    private ImageView    image    = null;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        image = (ImageView) findViewById(R.id.image);
        image.setImageBitmap(decodeBitmap());
    }

    public Bitmap decodeBitmap()
    {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 通過這個bitmap獲取圖片的寬和高
        Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/MTXX/3.jpg", options);
        if (bitmap == null)
        {
            System.out.println("bitmap爲空");
        }
        float realWidth = options.outWidth;
        float realHeight = options.outHeight;
        System.out.println("真實圖片高度:" + realHeight + "寬度:" + realWidth);
        // 計算縮放比
        int scale = (int) ((realHeight > realWidth ? realHeight : realWidth) / 100);
        if (scale <= 0)
        {
            scale = 1;
        }
        options.inSampleSize = scale;
        options.inJustDecodeBounds = false;
        // 注意這次要把options.inJustDecodeBounds 設爲 false,這次圖片是要讀取出來的。
        bitmap = BitmapFactory.decodeFile("/sdcard/MTXX/3.jpg", options);
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        System.out.println("縮略圖高度:" + h + "寬度:" + w);
        return bitmap;
    }
}


自己項目資料:

public class MainActivity extends Activity {
	private ImageView imageview;
	private int width;
	private int heigh;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initData();
		initView();
	}

	@SuppressLint("NewApi")
	private void initData() {
		WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
		Log.v("data", "wm.getDefaultDisplay().getHeight()-->>"
				+ wm.getDefaultDisplay().getHeight()
				+ "wm.getDefaultDisplay().getWidth()-->>"
				+ wm.getDefaultDisplay().getWidth());
//		Point outSize = new Point();
//		wm.getDefaultDisplay().getSize(outSize);
//		width = outSize.x;
//		heigh = outSize.y;
		width=wm.getDefaultDisplay().getWidth();
		heigh=wm.getDefaultDisplay().getHeight();
	}

	private void initView() {
		imageview = (ImageView) findViewById(R.id.imageview);
		showBitmap();
	}

	private void showBitmap() {
		BitmapFactory.Options opts = new Options();
		opts.inJustDecodeBounds = true;
		BitmapFactory.decodeFile("/sdcard/c.jpg", opts);//文件不加載
		int imageHeight = opts.outHeight;
		int imageWidth = opts.outWidth;
		Log.v("data", "imageHeight-->>" + imageHeight + "imageWidth-->>"
				+ imageWidth);
		int caclY = imageHeight / heigh;
		int caclX = imageWidth / width;
		int cacl = 1;
		if (caclY > caclX & caclX > 1) {
			cacl = caclY;
		}
		if (caclX > caclY & caclY > 1) {
			cacl = caclX;
		}
		opts.inJustDecodeBounds = false;
		opts.inSampleSize = cacl;
		Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/c.jpg", opts);//文件加載
		imageview.setImageBitmap(bitmap);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
}

XML文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scaleType="fitXY"/>

</RelativeLayout>




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章