android图片压缩总结
一、bitmap 图片格式介绍
android中图片是以bitmap形式存在的,那么bitmap所占内存,直接影响到了应用所占内存大小,首先要知道bitmap所占内存大小计算方式:
bitmap内存大小 = 图片长度 x 图片宽度 x 一个像素点占用的字节数
以下是图片的压缩格式:

其中,A代表透明度;R代表红色;G代表绿色;B代表蓝色。
- ALPHA_8 表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度
- ARGB_4444 表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节
- ARGB_8888 表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节
- RGB_565 表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节
内部相关函数介绍:http://blog.csdn.net/xxxzhi/article/details/51607765
显示bitmap: http://blog.csdn.net/ymangu666/article/details/37729109
二、生成Bitmap对象:
1. 从drawable资源文件中生成Bitmap对象:可以通过Option设置生成bitmap的属性
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.kb455,options);
注: 如果资源只放在drawable目录下,没有在hdpi等文件夹中,获取的bitmap文件会非常大,超过原始图片的大小,很可能出现OOM。
一种办法是将资源文件放在各个 dpi目录下 二、可以设置为options.inscaled = false,生成的bitmap与图片大小一致。
还可以通过其它渠道生成bitmap如inputstream,代码见“四”中的例子。
这里需要注意的是 Option.inJustDecodeBounds 这个变量,官方的解释:
If set to true, the decoder will return null (no bitmap), but the out… fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.
当只是需要来获取图片的宽高而不创建一个 bitmap对象时需要设置为 true,这时系统不会分配 bitmap的内存。如下是官方的例子:
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;
三、图片压缩(不改变图片宽高)
下面代码通过while循环将图片压缩到topLimit(KB)之下,但是该种方法有个缺点,如果topLimit很小,但是原始的Bitmap
又很大,当options减小到负值时任然不能达到目标大小之下。(http://www.jianshu.com/p/0ab8fde08bcf)
public static byte[] compressQualityBitmap(Bitmap bitmap, int topLimit) {
if(bitmap != null && topLimit > 0) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int options = 100;
bitmap.compress(CompressFormat.JPEG, options, baos);
while(baos.toByteArray().length > topLimit * 1024) {
baos.reset();
options -= 5;
bitmap.compress(CompressFormat.JPEG, options, baos);
}
byte[] bitmapArray = baos.toByteArray();
try {
baos.close();
baos = null;
} catch (IOException var14) {
;
} finally {
if(baos != null) {
try {
baos.close();
baos = null;
} catch (IOException var13) {
;
}
}
return bitmapArray;
}
} else {
return null;
}
}
1、下面函数是在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的,这也是为什么该方法叫质量压缩方法。图片的长,宽,像素都不变,bitmap所占内存大小是不会变的,但是压缩到byte数组baos的长度会逐渐的变小。
bitmap.compress(CompressFormat.JPEG, options, baos);
2、需要如果是bit.compress(CompressFormat.PNG, quality, baos);这样的png格式,quality就没有作用了,bytes.length不会变化,因为png图片是无损的,不能进行压缩。
3、该方法压缩并不能无限制的压缩,当压缩到一定程度后,baos的长度变不再变化。
改变图片的格式:
第一章中列出了四种格式的Config,可以将ARGB_8888格式转换为 RGB_565存储空间可以减少为原来的一半,而不改变图片的宽高。
四、图片缩放(改变图片宽高)
1、bitmap采样率压缩:在BitmapFactory.decodexxxx() 设置 options.inSampleSize 大小来缩放图片例如: 为2时,缩放为原来宽高的一半。
public static Bitmap compressBoundsBitmap(Context context, Uri uri, int targetWidth, int targetHeight) {
InputStream input = null;
Bitmap bitmap = null;
try {
input = context.getContentResolver().openInputStream(uri);
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(input, (Rect)null, options);
input.close();
int originalWidth = options.outWidth;
int originalHeight = options.outHeight;
if(originalWidth != -1 && originalHeight != -1) {
boolean be1 = true;
int widthBe = 1;
if(originalWidth > targetWidth) {
widthBe = originalWidth / targetWidth;
}
int heightBe = 1;
if(originalHeight > targetHeight) {
heightBe = originalHeight / targetHeight;
}
int be2 = widthBe > heightBe?heightBe:widthBe;
if(be2 <= 0) {
be2 = 1;
}
options.inJustDecodeBounds = false;
options.inSampleSize = be2;
input = context.getContentResolver().openInputStream(uri);
bitmap = BitmapFactory.decodeStream(input, (Rect)null, options);
input.close();
input = null;
} else {
Object be = null;
}
} catch (FileNotFoundException var23) {
;
} catch (IOException var24) {
;
} finally {
if(input != null) {
try {
input.close();
} catch (IOException var22) {
;
}
}
return bitmap;
}
}
优点:效率较高,解析速度快
缺点:采样率inSampleSize的取值只能是2的次方数(例如:inSampleSize=15,实际取值为8;inSampleSize=17,实际取值为16;实际取值会往2的次方结算),因此该方法不能精确的指定图片的大小
2.通过Matrix缩放图片(不推荐)
/**
* 图片的缩放方法
*
* @param bitmap :源图片资源
* @param maxSize :图片允许最大空间 单位:KB
* @return
*/
public static Bitmap getZoomImage(Bitmap bitmap, double maxSize) {
if (null == bitmap) {
return null;
}
if (bitmap.isRecycled()) {
return null;
} // 单位:从 Byte 换算成 KB
double currentSize = bitmapToByteArray(bitmap, false).length / 1024;
// 判断bitmap占用空间是否大于允许最大空间,如果大于则压缩,小于则不压缩
while (currentSize > maxSize) {
// 计算bitmap的大小是maxSize的多少倍
double multiple = currentSize / maxSize;
// 开始压缩:将宽带和高度压缩掉对应的平方根倍
// 1.保持新的宽度和高度,与bitmap原来的宽高比率一致
// 2.压缩后达到了最大大小对应的新bitmap,显示效果最好
bitmap = getZoomImage(bitmap, bitmap.getWidth() / Math.sqrt(multiple), bitmap.getHeight() / Math.sqrt(multiple));
currentSize = bitmapToByteArray(bitmap, false).length / 1024;
}
return bitmap;
} /**
* 图片的缩放方法
*
* @param orgBitmap :源图片资源
* @param newWidth :缩放后宽度
* @param newHeight :缩放后高度
* @return
*/
public static Bitmap getZoomImage(Bitmap orgBitmap, double newWidth, double newHeight) {
if (null == orgBitmap) {
return null;
}
if (orgBitmap.isRecycled()) {
return null;
}
if (newWidth <= 0 || newHeight <= 0) {
return null;
} // 获取图片的宽和高
float width = orgBitmap.getWidth();
float height = orgBitmap.getHeight();
// 创建操作图片的matrix对象
Matrix matrix = new Matrix();
// 计算宽高缩放率
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 缩放图片动作
matrix.postScale(scaleWidth, scaleHeight);
Bitmap bitmap = Bitmap.createBitmap(orgBitmap, 0, 0, (int) width, (int) height, matrix, true);
return bitmap;
} /**
* bitmap转换成byte数组
*
* @param bitmap
* @param needRecycle
* @return
*/
public static byte[] bitmapToByteArray(Bitmap bitmap, boolean needRecycle) {
if (null == bitmap) {
return null;
}
if (bitmap.isRecycled()) {
return null;
} ByteArrayOutputStream output = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
if (needRecycle) {
bitmap.recycle();
} byte[] result = output.toByteArray();
try {
output.close();
} catch (Exception e) {
Log.e(TAG, e.toString());
}
return result;
}
优点:可以精确地指定图片的缩放大小
缺点:是在原bitmap的基础之上生成的,占内存,效率低.
3/ThumbnailUtils 类进行
将bitmap转换为byte方法:
public static byte[] BitmapToByte(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 80, baos);//其中80参数表示要压缩的比例
return baos.toByteArray();
}
参考:http://blog.csdn.net/harryweasley/article/details/51955467
android图片压缩总结的更多相关文章
- Android 图片压缩、照片选择、裁剪,上传、一整套图片解决方案
1.Android一整套图片解决方案 http://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650820998&idx=1& ...
- android图片压缩方法
android 图片压缩方法: 第一:质量压缩法: private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = ...
- android图片压缩的3种方法实例
android 图片压缩方法: 第一:质量压缩法: private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = ...
- Android 图片压缩器
概述 Android 图片压缩器:一款高效的图片压缩器库,支持批量压缩,异步压缩.多线程多任务压缩,压缩比设置等特性. 详细 代码下载:http://www.demodashi.com/demo/12 ...
- Android 图片压缩各种方式
前言:由于公司项目当中需要用到压缩这块的相应技术,之前也做过的图片压缩都不是特别的理想, 所以这次花了很多心思,仔细研究和在网上找到了很多相对应的资料.为了就是 以后再做的时候直接拿来用就可以了 ...
- Android图片压缩上传(二)
之前有用到libjpeg,还是有一定的局限性,最近用了一个新的方式,效果还是挺不错,随着作者的版本更新,Bug也随之变少,目前项目中运用已上线. 1.之前的方式Android图片压缩,不失真,上线项目 ...
- Android图片压缩方法总结
本文总结Android应用开发中三种常见的图片压缩方法,分别是:质量压缩法.比例压缩法(根据路径获取图片并压缩)和比例压缩法(根据Bitmap图片压缩). 第一:质量压缩方法: ? 1 2 3 ...
- Android图片压缩
import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java ...
- 性能优化——Android图片压缩与优化的几种方式
图片优化压缩方式大概可以分为以下几类:更换图片格式,质量压缩,采样率压缩,缩放压缩,调用jpeg压缩等1.设置图片格式Android目前常用的图片格式有png,jpeg和webp,png:无损压缩图片 ...
随机推荐
- jedis 链接池使用(转)
Jedis作为redis的最佳客户端,它提供了连接池的特性,“连接池”在通常情况下可以有效的提高应用的通信能力,并且这是一种良好的设计模式.Jedis的连接池设计基于apache commons-po ...
- Spring3.x错误--Pointcut is not well-formed:expecting 'name pattern' at...
Spring3.x错误: 解决方法: (*com.dayang.service..*(..)) *和com.dayang.之间有空格
- 整理iOS9适配中出现的坑
一.NSAppTransportSecurity iOS9让所有的HTTP默认使用了HTTPS,原来的HTTP协议传输都改成TLS1.2协议进行传输.直接造成的情况就是App发请求的时候弹出网络无法连 ...
- 设置p标签可编辑
一,只可编辑,粘贴复制字段长度不正常 <p contenteditable="true" >这是一个可编辑内容的p标签啦啦~</p> 二,可编辑,可粘贴复制 ...
- Win7_Ultimate + VS2010 + openGL_MFC单文档应用开发框架搭建步骤
Win7_Ultimate + VS2010 + openGL单文档应用开发框架搭建步骤 上一个配置是基于OpenGL的开发工具配置的,下面就是基于Vs2010的MFC单文档应用开发. 通过网上查找资 ...
- Windows Server 2008 R2远程桌面服务配置和授权激活
远程桌面服务安装好之后使用的是120天临时授权,所以会跳出以下提示,我们介绍远程桌面授权的激活. 现在我们使用命令 mstsc /admin 强制登录服务器 需要在“远程桌面服务”--安装“远程桌面授 ...
- spring mvc配置ObjectMapper忽略无法识别的字段,以及一些博客推荐
通过Spring的MethodInvokingFactoryBean类实现的调用configure方法,此方法返回调用该方法的本身实例. 配置完毕后,可以在spring mvc的消息处理器中使用,为了 ...
- 数据库选项--ALTER DATABASE WITH 选项
指定当数据库从一种状态转换到另一种状态时,何时回滚未完成的事务. 如果终止子句被忽略,则当数据库中存在任何锁时,ALTER DATABASE 语句将无限期等待. 只能指定一条终止子句,而且该子句应跟在 ...
- Oracle数据库中 to_date()与24小时制表示法及mm分钟的显示
一.在使用Oracle的to_date函数来做日期转换时,时候也许会直接的采用“yyyy-MM-dd HH:mm:ss”的格式作为格式进行转换,但是在Oracle中会引起错误:“ORA 01810 ...
- 理解go语言 协程之间的通讯
go已经越来越被重视了,特别适合大型互联网公司基础服务的编写,高效,高并发,可以同时允许多个明星出轨,多个明星结婚 都不在话下,下面介绍下GO协程通讯的过程 直接上代码 package main im ...