很多时候,如果APP需要下载和加载很多图片(尤其是大图片)的时候,就往往会报如下图所示的错误:

如上图所示,OOM(OutOfMemoryError)表示内存溢出,这是因为网络或内存中的图片被加载成Bitmap时耗费的内存超出了系统内存而造成内存溢出。解决这个问题有很多方法,这里主要介绍其中的一种方法:图片压缩。

这里贴出一个工具类:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory; /**
* 图片压缩工具类
*/
public class ImageUtil {
/**
* 从指定路径获取Bitmap图片
*
* @param imgPath 原始图片的路径
*/
public static Bitmap getBitmap(String imgPath) {
// Get bitmap through image path
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = false;
newOpts.inPurgeable = true;
newOpts.inInputShareable = true;
// Do not compress
newOpts.inSampleSize = 1;
newOpts.inPreferredConfig = Config.RGB_565;
return BitmapFactory.decodeFile(imgPath, newOpts);
} /**
* 将图片存储到指定路径的文件中
*
* @param bitmap 原始图片Bitmap
* @param outPath 目标图片路径
*/
public static void storeImage(Bitmap bitmap, String outPath) throws FileNotFoundException {
FileOutputStream os = new FileOutputStream(outPath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
} /**
* 尺寸压缩(改变图片的宽高),适合用于加载缩略图
*
* @param imgPath 图片路径
* @param pixelW 想要将图片压缩到的宽度
* @param pixelH 想要将图片压缩到的高度
*/
public Bitmap ratio(String imgPath, float pixelW, float pixelH) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 开始读入图片,此时把options.inJustDecodeBounds 设回true,即只读边不读内容
newOpts.inJustDecodeBounds = true;
newOpts.inPreferredConfig = Config.RGB_565;
// Get bitmap info, but notice that bitmap is null now
Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts); newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
// 想要缩放的目标尺寸
float hh = pixelH;// 设置高度为240f时,可以明显看到图片缩小了
float ww = pixelW;// 设置宽度为120f,可以明显看到图片缩小了
// 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;//be=1表示不缩放
if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0) be = 1;
newOpts.inSampleSize = be;//设置缩放比例
// 开始压缩图片,注意此时已经把options.inJustDecodeBounds 设回false了
bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
return bitmap;
} /**
* 尺寸压缩(改变图片的宽高),适合用于加载缩略图
*
* @param image 图片的Bitmap
* @param pixelW 想要将图片压缩到的宽度
* @param pixelH 想要将图片压缩到的高度
*/
public Bitmap ratio(Bitmap image, float pixelW, float pixelH) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, os);
if (os.toByteArray().length / 1024 > 1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
os.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, 50, os);//这里压缩50%,把压缩后的数据存放到baos中
}
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
BitmapFactory.Options newOpts = new BitmapFactory.Options();
//开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
newOpts.inPreferredConfig = Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeStream(is, null, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
float hh = pixelH;// 设置高度为240f时,可以明显看到图片缩小了
float ww = pixelW;// 设置宽度为120f,可以明显看到图片缩小了
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;//be=1表示不缩放
if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0) be = 1;
newOpts.inSampleSize = be;//设置缩放比例
//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
is = new ByteArrayInputStream(os.toByteArray());
bitmap = BitmapFactory.decodeStream(is, null, newOpts);
return bitmap;
} /**
* 质量压缩,然后存储到指定路径
*
* @param image 原始图片Bitmap
* @param outPath 目标图片路径
* @param maxSize 图片将被压缩成这么多KB
*/
public void compressAndGenImage(Bitmap image, String outPath, int maxSize) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
// scale
int options = 100;
// Store the bitmap into output stream(no compress)
image.compress(Bitmap.CompressFormat.JPEG, options, os);
// Compress by loop
while (os.toByteArray().length / 1024 > maxSize) {
// Clean up os
os.reset();
// interval 10
options -= 10;
image.compress(Bitmap.CompressFormat.JPEG, options, os);
}
// Generate compressed image file
FileOutputStream fos = new FileOutputStream(outPath);
fos.write(os.toByteArray());
fos.flush();
fos.close();
} /**
* 质量压缩并存储到指定路径
*
* @param imgPath 想要压缩的图片路径
* @param outPath 目标图片路径
* @param maxSize 图片将被压缩成这么多KB
* @param needsDelete 压缩后是否删除原始图片
*/
public void compressAndGenImage(String imgPath, String outPath, int maxSize, boolean needsDelete) throws IOException {
compressAndGenImage(getBitmap(imgPath), outPath, maxSize);
if (needsDelete) {
File file = new File(imgPath);
if (file.exists()) {
file.delete();
}
}
} /**
* 尺寸压缩后保存图片
*
* @param image 原始图片Bitmap
* @param outPath 目标图片路径
* @param pixelW 想要将图片压缩到的宽度
* @param pixelH 想要将图片压缩到的高度
*/
public void ratioAndGenThumb(Bitmap image, String outPath, float pixelW, float pixelH) throws FileNotFoundException {
Bitmap bitmap = ratio(image, pixelW, pixelH);
storeImage(bitmap, outPath);
} /**
* 尺寸压缩后保存图片,并决定是否删除原始图片
*
* @param imgPath 想要压缩的图片路径
* @param outPath 目标图片路径
* @param pixelW 想要将图片压缩到的宽度
* @param pixelH 想要将图片压缩到的高度
* @param needsDelete 是否删除原始图片
*/
public void ratioAndGenThumb(String imgPath, String outPath, float pixelW, float pixelH, boolean needsDelete) throws FileNotFoundException {
Bitmap bitmap = ratio(imgPath, pixelW, pixelH);
storeImage(bitmap, outPath);
if (needsDelete) {
File file = new File(imgPath);
if (file.exists()) {
file.delete();
}
}
}
}

【Android - 进阶】之图片压缩的更多相关文章

  1. Android中的图片压缩

    1.android中计算图片占用堆内存的kB大小跟图片本身的kB大小无关,而是根据图片的尺寸来计算的. 比如一张 480*320大小的图片占用的堆内存大小为: 480*320*4/1024=600kB ...

  2. Android笔记(七十五) Android中的图片压缩

    这几天在做图记的时候遇第一次遇到了OOM,好激动~~ 追究原因,是因为在ListView中加载的图片太大造成的,因为我使用的都是手机相机直接拍摄的照片,图片都比较大,所以在加载的时候会出现内存溢出,那 ...

  3. Android学习之图片压缩,压缩程度高且失真度小

    曾经在做手机上传图片的时候.直接获取相机拍摄的原图上传,原图大小一般1~2M.因此上传一张都比較浪费资源,有些场景还须要图片多张上传,所以近期查看了好多前辈写的关于图片处理的资料.然后试着改了一个图片 ...

  4. Android 简单介绍图片压缩和图片内存缓存

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9316683 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工, ...

  5. 【Android 进阶】图片载入框架之Glide

    简单介绍 在泰国举行的谷歌开发人员论坛上,谷歌为我们介绍了一个名叫 Glide 的图片载入库,作者是 bumptech.这个库被广泛的运用在 google 的开源项目中,包含 2014 年 googl ...

  6. Android 中图片压缩分析(上)

    作者: shawnzhao,QQ音乐技术团队一员 一.前言 在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩. 前者是在不改变图片尺寸的情 ...

  7. 每个人都要学的图片压缩终极奥义,有效解决 Android 程序 OOM

    # 由来 在我们编写 Android 程序的时候,几乎永远逃避不了图片压缩的难题.除了应用图标之外,我们所要显示的图片基本上只有两个来源: 来自网络下载 本地相册中加载 不管是网上下载下来的也好,还是 ...

  8. Android 图片压缩、照片选择、裁剪,上传、一整套图片解决方案

    1.Android一整套图片解决方案 http://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650820998&idx=1& ...

  9. Android图片压缩方法总结

    本文总结Android应用开发中三种常见的图片压缩方法,分别是:质量压缩法.比例压缩法(根据路径获取图片并压缩)和比例压缩法(根据Bitmap图片压缩).   第一:质量压缩方法:   ? 1 2 3 ...

随机推荐

  1. Microsoft Visual Studio 2010 遇到了异常,可能是由某个扩展导致的。 转载

    问题: 今天打开好久没用的Microsoft Visual Studio 2010 ,刚才创建了一个C++工程,错误就出现了. 只要在VS2010源码编辑器中输入一个字符,它就报错 ":Mi ...

  2. 使用gdb跟踪Linux内核启动过程(从start_kernel到init进程启动)

    本次实验过程如下: 1. 运行MenuOS系统 在实验楼的虚拟机环境里,打击打开shell,使用下面的命令 cd LinuxKernel/ qemu -kernel linux-/arch/x86/b ...

  3. gettid()和pthread_self()的区别

    Linux中,每个线程有一个tid,类型long,由sys_gettid()取得. Linux内核中并没有实现线程,而是由glibc线程库实现的POSIX线程.每个线程也有一个id,类型 pthrea ...

  4. gem install 出现Errno::ECONNRESET: Connection reset by peer - SSL_connect (https://ruby.taobao.org

    这几天在ubuntu14.04.1 64位上安装rails的时候,由于大天朝的原因,更换了淘宝源,然后执行 gem install rails 这个时候,总是会提示 Errno::ECONNRESET ...

  5. JavaScript学习总结【1】、初识JS

    1.什么是 JavaScript? JavaScript 是一门跨平台.面向对象的动态的弱类型的轻量级解释型语言,是一种基于对象和事件驱动并具有相对安全性的客户端脚本语言.应用于 HTML 文档能够在 ...

  6. 从文章"避免复制与粘贴"到文章"Extract Method"的反思(2)

    好了.在上一篇里面讲了讲怎么把临时变量应该从函数里面剔除去.这个过程叫做从临时变量变成查询 那么接下来我们聊聊把代码提炼成函数,有叫做用函数对象取代函数 那么,问题来了:在函数中什么样的代码是需要被提 ...

  7. HDU 5726 GCD (2016 Multi-University Training Contest 1)

      Time Limit: 5000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Description Give y ...

  8. shell抓取

    #!/bin/sh ` configDir="$dir/config" ipport="$configDir/ip_port" url="http:/ ...

  9. 根据http协议传送数据

    发送的内容: [50 4f 53 54 20 2f 64 65 78 2f 66 69 72 65 70 6f 77 65 72 20 48 54 54 50 2f 31 2e 31 0d 0a 43 ...

  10. bootcamp

    为了鄙社自主研发的html5studio和mist,我给Air划了32G装windows囧 第一要注意的是,必须使用bootcamp划分将要安装windows的分区,不要在windows安装过程中删除 ...