android图片的打开和缩放时出现oom处理过程
16lz
2021-01-26
内容如题:
以前对于图片缩放时出现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,从新构建bitmapoptions.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 );启动后的返回结果处理@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {switch (requestCode) {case OPEN_PHOTO_REQUESTCODE:if (resultCode == RESULT_OK) {Bitmap bitmap = null;// 将返回的数据构建成bitmaptry {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() {@Overridepublic 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桌面悬浮窗显示录屏时间控制效果
- 获取Android手机上的图片和视频缩略图
- Android屏幕大小自适应
- Android的百度地图开发BaiduMapApiDemo
- Android下保存简单网页到本地(包括简单图片链接转换)
- Android高效加载大图,防止OOM,以及多图解决方案
- Android中实现自动轮播的框架(Banner)的介绍以及使用
- Android异步下载网络图片(其三)