android图片的打开和缩放时出现oom处理过程

标签: android 图片 缩放 | 发表时间:2013-06-20 15:59 | 作者:yehui18sui
出处:http://blog.csdn.net

内容如题:

以前对于图片缩放时出现oom,也是束手无策。昨天看了 Android_Tutor对于图片处理的文章,今天就斗胆将这部分的内容演习下。

首先创建一个布局文件:用imageview控件加载图片

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

    <Button
        android:id="@+id/show"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scaleType="matrix"
        android:src="@drawable/ic_launcher" />

</LinearLayout>

其次:用公共类ImageCacheUtil对图片进行压缩处理:这样可以保证图片太大的时候不会出现oom

/**
 * @FILE:ImageCacheUtil.java
 * @AUTHOR:hui-ye
 * @DATE:2013-6-19 下午2:23:56
 **/
package com.view.imagecachedemo;

import java.io.InputStream;

import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.net.Uri;

/*******************************************
 * 
 * @CLASS:ImageCacheUtil
 * @DESCRIPTION:获得经过缩放处理的bitmap,以保证不会出现oom
 * @AUTHOR:hui-ye
 * @VERSION:v1.0
 * @DATE:2013-6-19 下午2:23:56
 *******************************************/
public class ImageCacheUtil {
	/**
	 * @description:获取bitmap	
	 * @author:hui-ye
	 * @param path 图片文件的路径
	 * @param data	图片的文件的数据
	 * @param context 上下文对象
	 * @param uri 资源
	 * @param target 模板宽或者高的大小
	 * @param width 是否是宽度
	 * @return:
	 */

	public static Bitmap getResizedBitmap(String path, byte[] data,
			Context context, Uri uri, int target, boolean width)
			throws Exception {
		// android api
		// BitmapFactory.Options options = new BitmapFactory.Options();
		// options.inJustDecodeBounds = true;
		// BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
		// int imageHeight = options.outHeight;
		// int imageWidth = options.outWidth;
		// String imageType = options.outMimeType;
		Bitmap bitmap = null;
		// 添加一个Options对象
		Options options = null;
		if (target > 0) {
			options = new Options();
			// 设置options的属性:inJustDecodeBounds=true的时候读取图片的时候,bitmap为null,将图片宽和高放到options中
			options.inJustDecodeBounds = true;
			// 获得图片(这样会将图片的宽和高放入到options中)
			decode(path, data, context, uri, options);
			// 获得压缩的比例
			int outWidth = options.outWidth;
			// 这样做宽和高就是相等了
			if (!width) {
				outWidth = Math.max(outWidth, options.outHeight);
			}
			// 计算压缩比例
			int ssize = sampleSize(outWidth, target);
			options.inSampleSize = ssize;
			// 设置inJustDecodeBounds = false,从新构建bitmap
			options.inJustDecodeBounds = false;
			bitmap = decode(path, data, context, uri, options);
		}
		return bitmap;
	}

	/**
	 * @description:解析Bitmap的公用方法.注意各个方法的参数必须要有options
	 * @author:hui-ye
	 * @param path
	 * @param data
	 * @param context
	 * @param uri
	 * @param options
	 * @return:
	 */

	public static Bitmap decode(String path, byte[] data, Context context,
			Uri uri, BitmapFactory.Options options) throws Exception {
		Bitmap bitmap = null;
		if (path != null) {
			bitmap = BitmapFactory.decodeFile(path, options);
		} else if (data != null) {
			BitmapFactory.decodeByteArray(data, 0, data.length, options);
		} else if (uri != null) {
			// uri不为空的时候context也不要为空.:ContentResolver;Uri内容解析器
			ContentResolver resolver = context.getContentResolver();
			InputStream is;
			is = resolver.openInputStream(uri);
			bitmap = BitmapFactory.decodeStream(is, null, options);
		}
		return bitmap;
	}

	/**
	* @description:获取samplesize图片的压缩比例	(这里就简单实现都是2的倍数啦.也就是說看width会是target的倍数)
	* @author:hui-ye
	* @param width
	* @param target
	* @return:
	*/

	private static int sampleSize(int width, int target) {
		int result = 1;
		for (int i = 0; i < 10; i++) {
			if (width < target * 2) {
				break;
			}
			width = width / 2;
			result = result * 2;
		}
		return result;
	}
}

计算好了压缩比例,返回一个被压缩处理过的图片。

再次。打开相册,从中选择图片,进行压缩处理,将处理过的图片放到imageview中:

对于各个属性的说明:

/** 
	 * 打开本地相册的requestcode. 
	 */
	public static final int OPEN_PHOTO_REQUESTCODE = 0x1;
	/** 
	* 图片的target大小. 
	*/
	private static final int target = 400;
	private ImageView image;
	/**   
	 * matrix:这是一个图片的变化矩阵(提供记录图片位置、记录图片缩放比例、实现图片移动等 ) 
	 */
	private Matrix matrix;
	/**   
	 * curmatrix:记录图片当前位置的变换矩阵  
	 */
	private Matrix curmatrix;
	// 初始化模式参数
	private int mode = 0;
	// 无模式
	private static final int NONE = 0;
	// 拖拉模式
	private static final int DRAG = 1;
	// 缩放模式
	private static final int ZOOM = 2;
	/**   
	 * startPoint:第一个点的坐标  
	 */
	private PointF startPoint = new PointF();;
	/**   
	 * startDistance:缩放前两个点之间的距离  
	 */
	private float startDistance;
	/**   
	 * endDistance:缩放后两个点之间的距离  
	 */
	private float endDistance;
	/**   
	 * middlePoint:两个点之间的中点  
	 */
	private PointF middlePoint;
	/**   
	 * ZOOM_THRESHOLD:当两点的  startDistance距离大于ZOOM_THRESHOLD的时候才缩放
	 */
	private static final float ZOOM_THRESHOLD = 10.0f;
	private Button show;


/**
	 * @description:打开相册	
	 * @author:hui-ye:
	 */

	private void setupViews() {
		Intent intent = new Intent();
		intent.setAction(Intent.ACTION_PICK);
		intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
				"image/jpeg");
		startActivityForResult(intent, OPEN_PHOTO_REQUESTCODE);
	}


从相册中选择图片后,进行压缩处理,并将图片显示在imageview中

// 对startActivityForResult(intent,OPEN_PHOTO_REQUESTCODE );启动后的返回结果处理
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
		case OPEN_PHOTO_REQUESTCODE:
			if (resultCode == RESULT_OK) {
				Bitmap bitmap = null;
				// 将返回的数据构建成bitmap
				try {
					bitmap = ImageCacheUtil.getResizedBitmap(null, null, this,
							data.getData(), target, false);
				} catch (Exception e) {
					e.printStackTrace();
					Toast.makeText(this, "生成图片失败", 1).show();
				}
				if (bitmap != null) {
					// 为imageview设置图片
					image.setImageBitmap(bitmap);
				}
			}
			break;

		default:
			break;
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

最后处理图片的缩放:

// 这里对图片的缩放处理
		image.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction() & MotionEvent.ACTION_MASK) {
				// 取得第一个触控点的坐标
				case MotionEvent.ACTION_DOWN:
					// 设置当前的模式为拖拉模式
					mode = DRAG;
					// 记录图片当前的移动位置
					curmatrix.set(image.getImageMatrix());
					// 记录当前的坐标
					startPoint.set(event.getX(), event.getY());
					break;
				// 屏幕上已经有触控点了
				case MotionEvent.ACTION_POINTER_DOWN:
					// 如果是两点触控,则将mode设置为缩放模式
					mode = ZOOM;
					// 获取当前坐标和第一个坐标之间的距离
					startDistance = spacing(event);
					if (startDistance > ZOOM_THRESHOLD) {
						// 获取两点之间的中点
						middlePoint = getMiddlePoint(event);
						// 记录图片当前的缩放比例
						curmatrix.set(image.getImageMatrix());
					}
					break;
				// 判断触控点的移动(一个点移动还是多点移动 )
				case MotionEvent.ACTION_MOVE:
					// 一个点的移动为拖拉模式
					if (mode == DRAG) {
						// 获取x轴的移动距离
						float distanceX = event.getX() - startPoint.x;
						// 获取y轴的移动距离
						float distanceY = event.getY() - startPoint.y;
						// 设置 移动变换
						curmatrix.set(image.getImageMatrix());
						// 设置图片的移动
						matrix.postTranslate(distanceX, distanceY);
					} else if (mode == ZOOM) {
						// 结束距离
						endDistance = spacing(event);
						if (endDistance > ZOOM_THRESHOLD) {
							// 缩放比例
							float scale = endDistance / startDistance;
							matrix.set(curmatrix);
							matrix.postScale(scale, scale, middlePoint.x,
									middlePoint.y);
						}
					}
				case MotionEvent.ACTION_UP:
					// 当手指离开屏幕,但屏幕上仍有其他触点(手指)时触发该事件
				case MotionEvent.ACTION_POINTER_UP:
					mode = NONE;
					break;

				default:
					break;
				}
				image.setImageMatrix(matrix);
				return true;
			}
		});

// 计算移动距离
	private float spacing(MotionEvent event) {
		// event.getX(0)第一个点坐标,event.getX(1)为第二个点的坐标
		float x = event.getX(0) - event.getX(1);
		float y = event.getY(0) - event.getY(1);
		return FloatMath.sqrt(x * x + y * y);
	}

	/**
	* @description:获得两个点的中点坐标	
	* @author:hui-ye
	* @param event
	* @return:
	*/

	public static PointF getMiddlePoint(MotionEvent event) {
		float x = (event.getX(0) + event.getX(1)) / 2;
		float y = (event.getY(0) + event.getY(1)) / 2;
		return new PointF(x, y);
	}

好了,介绍就到此为止,其他的希望大家去研究 android API   http://developer.android.com/training/displaying-bitmaps/index.html

附件是完整的程序代码

作者:yehui18sui 发表于2013-6-20 15:59:58 原文链接
阅读:4 评论:0 查看评论

相关 [android 图片 缩放] 推荐:

android图片的打开和缩放时出现oom处理过程

- - CSDN博客移动开发推荐文章
以前对于图片缩放时出现oom,也是束手无策. 昨天看了 Android_Tutor对于图片处理的文章,今天就斗胆将这部分的内容演习下. 首先创建一个布局文件:用imageview控件加载图片. 其次:用公共类ImageCacheUtil对图片进行压缩处理:这样可以保证图片太大的时候不会出现oom.

[原]Android多点触控技术实战,自由地对图片进行缩放和移动

- - guolin的专栏
转载请注明出处: http://blog.csdn.net/guolin_blog/article/details/11100327. 在上一篇文章中我带着大家一起实现了Android瀑布流照片墙的效果,虽然这种效果很炫很酷,但其实还只能算是一个半成品,因为照片墙中所有的图片都是只能看不能点的. 因此本篇文章中,我们就来对这一功能进行完善,加入点击图片就能浏览大图的功能,并且在浏览大图的时候还可以通过多点触控的方式对图片进行缩放.

JAVA上传图片的缩放处理

- - CSDN博客推荐文章
  图片上传到服务器后,会根据情况将图片缩小成一个图标,我们可以利用java强大的图形处理功能,对上传的图片进行缩放处理.   下面的程序使用jdk1.4中最新的ImageIO对图片进行读写. 使用AffineTransform对图片进行缩放.   * @param fromdir 图片的原始目录.

android截取屏幕图片

- - BlogJava-首页技术区
                mButton.setText("截屏次数:"+mPrintNum);.         //1.构建Bitmap   .         //2.获取屏幕   .         //3.保存Bitmap    .             //文件   .                 Toast.makeText(this, "截屏文件已保存至SDCard/PrintScreenDemo/ScreenImage/下", Toast.LENGTH_LONG).show();   .

android图片压缩方法

- - CSDN博客移动开发推荐文章
第一:我们先看下质量压缩方法.         image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中  .         while ( baos.toByteArray().length / 1024>100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩         .

iPhone/android的viewport 解决网页自动缩放的问题

- - 快乐无极的博客
viewport有如下几个属性:. width设置viewport的宽度,即iphone最初模拟PC浏览器的宽度,之后iphone会这个宽度展现的页面同比缩放到iphone屏幕上. 设置width=device-width后就不会再进行缩放了,因为宽度正好和iphone的宽度相同(前提是没有设置缩放比例).

Android动画处理缩放,平移,旋转

- - 移动开发 - ITeye博客
     建立三个Activity分别实现缩放,平移,旋转. 这里为了显示清楚,小编采取了分页模式中的ActivityGroup,来使得页面分别显示三个Activity,感兴趣的可以在我博客里找有讲述,觉得实现麻烦的可以利用跳转功能,如果连跳转都觉得麻烦的建议使用方法直接按钮定义也可以. 首先布局文件定义,因为三个xml异曲同工,这里就只列出一个例子:.

android 比较靠谱的图片压缩

- - ITeye博客
第一:我们先看下质量压缩方法:. image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中. //循环判断如果压缩后图片是否大于100kb,大于继续压缩. baos.reset();//重置baos即清空baos.

AndroidのBitmap之大图片优化

- - 博客园_首页
不解释大家懂得,在listview 或grid或viewpager等大量大尺寸图片时,会造成OOM. 这里是优化图片内存的一个方法,注释写的很 明确... public Bitmap getBitmapFromNet(final String url,final int width,final int height){//从网络下载图片.

android回收图片使用内存

- - 移动开发 - ITeye博客
在android开发过程当中,如果要用到大量图片而你又没有做好图片内存的回收,很容易就会造成OOM内存溢出的问题. 下面介绍一种图片内存回收的方法,就是将图片从添加到的ViewGroup中一张一张拿出来回收,具体代码如下:. 其中的ViewGroup可以是ViewFlipper、ViewPager等等继承自ViewGroup的子类.