• 保存到桌面  加入收藏  设为首页
安卓应用

安卓图片加载工具类,避免读取大图片出现OOM内存溢出

时间:2016-10-15 13:37:52   作者:胜行天下   来源:胜行天下   阅读:510   评论:0

要给自己相亲了,安徽的单身女生看过来,有认识的朋友也麻烦介绍一下,十分感谢!我的微信:596957738 ,我的相关简介:http://xiangqin.jiangjiesheng.cn ,静候佳音!



package com.aotu.jianantong.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

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

/**
 
 * @author 作者 江节胜 E-mail:jiangjsheng@qq.com
 * @version 创建时间:2016年7月14日 下午1:45:06
 *
 */
public class ImageResizer {
 private static final String TAG = "ImageResizer";

 public ImageResizer() {
 }

 // 传入资源文件,计算合适的大小,返回一个Bitmap对象
 public Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
   int reqWidth, int reqHeight) {
  // First decode with inJustDecodeBounds=true to check dimensions
  final BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = true;
  BitmapFactory.decodeResource(res, resId, options);

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

  // Decode bitmap with inSampleSize set
  options.inJustDecodeBounds = false;
  return BitmapFactory.decodeResource(res, resId, options);// 或者其他方式

 }

 /**
  * 为了加载文件系统的文件避免二次decodeStream返回null而专门调整的方法decode方法 解释:
  * FileInputStream是一种有序的文件流,而两次的decodeStream调用影响了文件流的位置属性,
  * 导致了第二次decodeStream时得到的是null,为了解决这个问题,可以通过文件流来得到他所对应的文件描述符, 然后在通过
  * BitmapFactory.decodeFileDescriptor方法来加载一张缩放过的图片
  */
 public Bitmap decodeSampledBitmapFromFileDescriptor(FileDescriptor fd,
   int reqWidth, int reqHeight) {
  // First decode with inJustDecodeBounds=true to check dimensions
  final BitmapFactory.Options options = new BitmapFactory.Options();

  options.inJustDecodeBounds = true;
  BitmapFactory.decodeFileDescriptor(fd, null, options);

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

  // Decode bitmap with inSampleSize set
  options.inJustDecodeBounds = false;
  return BitmapFactory.decodeFileDescriptor(fd, null, options);
 }

 /**
  * 方法说明:可能还是解决不了内存溢出,最多捕获内存溢出。使用decodeSampledBitmapFromPathMoreSafe处理
  */
 @Deprecated
 public Bitmap decodeSampledBitmapFromPath(String path, int reqWidth,
   int reqHeight) {
  // First decode with inJustDecodeBounds=true to check dimensions
  final BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = true;
  BitmapFactory.decodeFile(path, options);

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

  // Decode bitmap with inSampleSize set
  options.inJustDecodeBounds = false;
  try {
   return BitmapFactory.decodeFile(path, options);
  } catch (OutOfMemoryError e) {
   e.printStackTrace();
  }
  return null;
 }

 /**
  * 20160918新增:inSampleSize 重新计算(之前的方法计算的值不够精确),并捕获异常。
  * 方法说明:http://www.cnblogs.com/zgz345/archive/2013/01/08/2851204.html 使用中要
  * if(!bmp.isRecycle() ){ bmp.recycle() //回收图片所占的内存 system.gc() //提醒系统及时回收 }
  * 从ImageView中获取
  * bitmaphttp://blog.csdn.net/a907763895/article/details/11905699
  */
 public Bitmap decodeSampledBitmapFromPathMoreSafe(String path,
   int reqWidth, int reqHeight) {
  final BitmapFactory.Options options = new BitmapFactory.Options();
  options.inDither = false;
  options.inPurgeable = true;
  options.inTempStorage = new byte[12 * 1024];// 创建一个12kb的临时空间
  options.inJustDecodeBounds = true;

  File file = new File(path);
  FileInputStream fs = null;
  try {
   fs = new FileInputStream(file);

   BitmapFactory.decodeFileDescriptor(fs.getFD(), null, options);
  } catch (Exception e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  }
  // Calculate inSampleSize
  // options.inSampleSize = calculateInSampleSize(options, reqWidth,
  // reqHeight);
  /**
   * 使用此方法计算inSampleSize值 20160918新增
   */
  final int minSideLength = Math.min(reqWidth, reqHeight);
  options.inSampleSize = computeSampleSize(options, minSideLength,
    reqWidth * reqHeight);
  // Decode bitmap with inSampleSize set
  options.inJustDecodeBounds = false;

  Bitmap bmp = null;
  try {
   fs = new FileInputStream(file);
   if (fs != null)
    bmp = BitmapFactory.decodeFileDescriptor(fs.getFD(), null,
      options);
   if (fs != null) {
    fs.close();
    fs = null;
   }
   return bmp;

  } catch (Exception e) {

   try {
    if (fs != null) {
     fs.close();
     fs = null;
    }
   } catch (IOException e1) {
    e1.printStackTrace();
   }
   Log.i("test",
     "ImageResizer(图片压缩) decodeSampledBitmapFromPathMoreSafe 出现内存溢出 并返回null对象");
   e.printStackTrace();
  }
  return null;
 }

 /**
  * 方法说明: 直接使用 BitmapFactory.decodeStream(is) 返回空
  *
  * @author Aotu-JS ,email:jiangjsheng@qq.com
  * @version 创建时间:2016年8月16日 下午6:14:26
  *
  * @param is
  * @param reqWidth
  * @param reqHeight
  * @return
  */
 public Bitmap decodeSampledBitmapFromInputStream(InputStream is,
   int reqWidth, int reqHeight) {
  // First decode with inJustDecodeBounds=true to check dimensions
  Log.i("test", "decodeStream is0 == null " + String.valueOf(is == null));
  byte[] data = null;
  try {
   data = readStream(is);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

  final BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = true;
  BitmapFactory.decodeByteArray(data, 0, data.length, options);
  // Calculate inSampleSize
  options.inSampleSize = calculateInSampleSize(options, reqWidth,
    reqHeight);

  // Decode bitmap with inSampleSize set
  options.inJustDecodeBounds = false;

  Bitmap decodeStream = BitmapFactory.decodeByteArray(data, 0,
    data.length, options);
  Log.i("test",
    "decodeStream Bitmap == null "
      + String.valueOf(decodeStream == null));
  Log.i("test", "decodeStream is1 == null " + String.valueOf(is == null));
  Log.i("test", "decodeStream Bitmap size " + decodeStream.getByteCount());
  Log.i("test", "decodeStream options.inSampleSize = "
    + options.inSampleSize);

  return decodeStream;

 }

 /**
  * 原始方法计算的inSampleSize值不够精确,容易导致oom
  */
 public int calculateInSampleSize(BitmapFactory.Options options,
   int reqWidth, int reqHeight) {
  if (reqWidth == 0 || reqHeight == 0) {
   return 1;
  }

  // Raw height and width of image
  final int height = options.outHeight;
  final int width = options.outWidth;
  Log.d(TAG, "origin, w= " + width + " h=" + height);
  int inSampleSize = 1;

  if (height > reqHeight || width > reqWidth) {
   final int halfHeight = height / 2;
   final int halfWidth = width / 2;

   // Calculate the largest inSampleSize value that is a power of 2 and
   // keeps both
   // height and width larger than the requested height and width.
   while ((halfHeight / inSampleSize) >= reqHeight
     && (halfWidth / inSampleSize) >= reqWidth) {
    inSampleSize *= 2;
   }
  }

  Log.d(TAG, "sampleSize:" + inSampleSize);
  return inSampleSize;
 }

 public static int computeSampleSize(BitmapFactory.Options options,
   int minSideLength, int maxNumOfPixels) {
  int initialSize = computeInitialSampleSize(options, minSideLength,
    maxNumOfPixels);
  int roundedSize;
  if (initialSize <= 8) {
   roundedSize = 1;
   while (roundedSize < initialSize) {
    roundedSize <<= 1;
   }
  } else {
   roundedSize = (initialSize + 7) / 8 * 8;
  }

  return roundedSize;
 }

 private static int computeInitialSampleSize(BitmapFactory.Options options,
   int minSideLength, int maxNumOfPixels) {
  double w = options.outWidth;
  double h = options.outHeight;

  int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
    .sqrt(w * h / maxNumOfPixels));
  int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
    Math.floor(w / minSideLength), Math.floor(h / minSideLength));

  if (upperBound < lowerBound) {
   // return the larger one when there is no overlapping zone.
   return lowerBound;
  }

  if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
   return 1;
  } else if (minSideLength == -1) {
   return lowerBound;
  } else {
   return upperBound;
  }
 }

 /*
  * 得到图片字节流 数组大小
  */
 public static byte[] readStream(InputStream inStream) throws Exception {
  ByteArrayOutputStream outStream = new ByteArrayOutputStream();
  byte[] buffer = new byte[1024];
  int len = 0;
  while ((len = inStream.read(buffer)) != -1) {
   outStream.write(buffer, 0, len);
  }
  outStream.close();
  inStream.close();
  return outStream.toByteArray();
 }
}

有任何疑问或技术合作都可联系我

微信:767000122 【推荐】

QQ:596957738


上一篇:安卓-代码--PopUpWindow
下一篇:没有了
相关评论

加我微信 596957738 (QQ同号)加我微信   QQ联系:596957738   地址:江苏省南京市雨花台区

苏公网安备32011402010305号

皖ICP备16019989号

江节胜的Gitee,江节胜的Git地址