首页 > 代码库 > Android BitmapFactory图片压缩处理(大位图二次采样压缩处理)

Android BitmapFactory图片压缩处理(大位图二次采样压缩处理)

Android实际开发中,在加载大量图片的时候,比如ViewPager、GridView、ListView中,加载了大量的比较大图片就容易出现OOM(内存溢出)的异常,这是因为一个应用的最大内存使用只有16M,超过了这个值,就会出现OOM。所以我们实际开发中,要想避免OOM出现就要对相应的图片进行压缩处理。

本文即使用了BitmapFactory和BitmapFactory.Option这两个类,对图片进行相应的尺寸压缩处理。经测试,成功解决了未压缩图片之前出现的OOM异常。

实现效果图:

本Demo使用的图片大小为2M左右(压缩以前)。

我压缩图片之前:

我这里将压缩的代码注释掉了:


运行结果:


进行压缩处理后的图片:

压缩后图片大小为:


大约为98KB


运行结果:


源代码:


布局文件:

activity_main:

<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" >
    </ListView>

</RelativeLayout>

list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_marginLeft="20dp"/>

</LinearLayout>


MainActivity:

package com.android_bitmapcompressdemo;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

public class MainActivity extends Activity {
	private ListView listView;
	private MyAdapter adapter;
	private int[] items = new int[] { R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc };
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		listView = (ListView) findViewById(R.id.listView);
		adapter = new MyAdapter(this, items);
		listView.setAdapter(adapter);
		adapter.notifyDataSetChanged();
	}
}


ListView适配器:MyAdapter:

package com.android_bitmapcompressdemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyAdapter extends BaseAdapter {
	private int[] items = new int[] {};
	private Context context;
	private String TAG = "zhongyao";
	private Bitmap bitmap = null;

	public MyAdapter(Context context, int[] items) {
		this.context = context;
		this.items = items;
	}

	@Override
	public int getCount() {
		return items.length;
	}

	@Override
	public Object getItem(int position) {
		return items[position];
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder;
		if (convertView == null) {
			convertView = LayoutInflater.from(context).inflate(R.layout.list_item, null);
			holder = new ViewHolder();
			holder.imageView = (ImageView) convertView.findViewById(R.id.imageView);
			holder.textView = (TextView) convertView.findViewById(R.id.textView);
			
			convertView.setTag(holder);
		}else {
			holder = (ViewHolder) convertView.getTag();
		}
		
			bitmap = BitmapCompressTools.decodeSampledBitmapFromResource(
					context.getResources(), R.drawable.pc, 100, 100);
			Log.d(TAG, "压缩之后的图片大小为:" + bitmap.getByteCount());
		holder.imageView.setImageBitmap(bitmap);
		holder.textView.setText("图片"+position);
		
		return convertView;
	}

	class ViewHolder {
		ImageView imageView;
		TextView textView;
	}
}

BitmapCompressTools(压缩工具类):

package com.android_bitmapcompressdemo;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class BitmapCompressTools {
	public static Bitmap decodeSampledBitmapFromResource(Resources res,
			int resId, int reqWidth, int reqHeight) {

		// 给定的BitmapFactory设置解码的参数
		final BitmapFactory.Options options = new BitmapFactory.Options();
		// 从解码器中获取原始图片的宽高,这样避免了直接申请内存空间
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeResource(res, resId, options);

		// Calculate inSampleSize
		options.inSampleSize = calculateInSampleSize(options, reqWidth,
				reqHeight);

		// 压缩完后便可以将inJustDecodeBounds设置为false了。
		options.inJustDecodeBounds = false;
		return BitmapFactory.decodeResource(res, resId, options);
	}

	/**
	 * 指定图片的缩放比例
	 * 
	 * @param options
	 * @param reqWidth
	 * @param reqHeight
	 * @return
	 */

	public 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;
//			// }
//			
			/**
			 * 压缩方式一
			 */
			// 计算压缩的比例:分为宽高比例
			final int heightRatio = Math.round((float) height
					/ (float) reqHeight);
			final int widthRatio = Math.round((float) width / (float) reqWidth);
			inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
//		}

		return inSampleSize;
	}
}

达到了预期效果,但是写到这里滑动ListView的时候,还是会有些卡顿,有这方面解决经验的可以给我留言讨论。

源代码已上传到资源中,可到我的资源中下载。