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的时候,还是会有些卡顿,有这方面解决经验的可以给我留言讨论。

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

Android BitmapFactory图片压缩处理(大位图二次采样压缩处理),布布扣,bubuko.com

时间: 2024-10-16 11:15:45

Android BitmapFactory图片压缩处理(大位图二次采样压缩处理)的相关文章

Android开发之大位图二次采样压缩处理(源代码分享)

图片有各种形状和大小.在许多情况下这些图片是远远大于我们的用户界面(UI)且占据着极大的内存空间,如果我们不对位图进行压缩处理,我们的程序会发生内存泄露的错误. MainActivity的代码 package com.example.g08_bitmap; import android.os.Bundle; import android.app.Activity; import android.content.res.Resources; import android.graphics.Bitm

Android开发之大位图压缩水印处理

我们在发微博或者csdn博文的时候都可以给图片加上一个水印,一个独立的标识,那是怎么实现的呢?先封装一个BitmapTools封装类,该类要解决的问题是一将突破存储至sdcard中,二给图片加上水印. BitmapTools package com.example.g11_bitmap04; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import android.conte

Android BitmapFactory.Options 解决大图片加载OOM问题

当我们在Android使用bitmap加载图片过程中,它会将整张图片所有像素都存在内存中,由于Android对图片内存使用的限制,很容易出现OOM(Out of Memory)问题. 为了避免此类问题我们可以采用BitmapFactory.Options或是使用第三方的图片加载库.如Fresco.Picasso等. BitmapFactory.Options 读取图片尺寸.类型 如文档所示: 如果BitmapFactory.Options中inJustDecodeBounds 字段设置为true

Android 高清加载巨图方案, 拒绝压缩图片

源地址:http://blog.csdn.net/lmj623565791/article/details/49300989 一.概述 距离上一篇博客有段时间没更新了,主要是最近有些私事导致的,那么就先来一篇简单一点的博客脉动回来. 对于加载图片,大家都不陌生,一般为了尽可能避免OOM都会按照如下做法: 对于图片显示:根据需要显示图片控件的大小对图片进行压缩显示. 如果图片数量非常多:则会使用LruCache等缓存机制,将所有图片占据的内容维持在一个范围内. 其实对于图片加载还有种情况,就是单个

图片--Android有效解决加载大图片时内存溢出的问题

Android有效解决加载大图片时内存溢出的问题 博客分类: Android Android游戏虚拟机算法JNI 尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存. 因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView

Android中图片压缩方案详解

如感觉排版不舒服,可移步至此处查看 图片的展示可以说在我们任何一个应用中都避免不了,可是大量的图片就会出现很多的问题,比如加载大图片或者多图时的OOM问题,可以移步到Android高效加载大图.多图避免程序OOM.还有一个问题就是图片的上传下载问题,往往我们都喜欢图片既清楚又占的内存小,也就是尽可能少的耗费我们的流量,这就是我今天所要讲述的问题:图片的压缩方案的详解. 1.质量压缩法 设置bitmap options属性,降低图片的质量,像素不会减少 第一个参数为需要压缩的bitmap图片对象,

Android之图片压缩

1. 引子 前几天跟服务端的一个妹子联调接口,服务器配置一张图片,几十KB就行,她问我图片从哪里找,我告诉她先随便在网上找个图片链接就行了.结果一运行程序,就崩溃了,出现了下面的异常. java.lang.OutofMemoryError 内存溢出OOM,我当时一脸懵逼. 图-1 一脸懵逼 于是拿着后台返回的链接去查看了一下图片,是一张6M的壁纸. 图-2 我内心几乎是崩溃的 这只是一个简单的联调,而在联调过程中操作不当导致出现OOM问题,大家就当是个玩笑.其实在Android中很容易出现OOM

Android 中图片压缩分析(上)

作者: shawnzhao,QQ音乐技术团队一员 一.前言 在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩. 前者是在不改变图片尺寸的情况下,改变图片的存储体积,而后者则是降低图像尺寸,达到相同目的. 由于本文的篇幅问题,分为上下两篇发布. 二.Android 质量压缩逻辑 在Android中,对图片进行质量压缩,通常我们的实现方式如下所示: ByteArrayOutputStream outputStream = new Byte

图片的压缩(二次采样)

1 package com.qianfeng.bitmapdisplay.tasks; 2 3 import android.graphics.Bitmap; 4 import android.graphics.BitmapFactory; 5 import android.graphics.drawable.Drawable; 6 import android.os.AsyncTask; 7 import android.widget.ImageView; 8 import com.qianf