图片加载OOM

来源:互联网 发布:阿里云开网站 编辑:程序博客网 时间:2024/06/05 04:56
今天给大家分享的是解决解析图片的出现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;@Overrideprotected 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);}@Overridepublic 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>