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:无损压缩图片 ...
随机推荐
- LA 3213 Ancient Cipher (水题,转化)
题意:给定两个长度相同的字符串,判断它们之间是否存在一一对应关系,顺序不定. 析:刚开始没看到顺序不定,然后写完没胡把样例看完就交了,结果WA了一次...其实这是一个水题,既然顺序不定,那么更简单,我 ...
- cmake-mark_as_advanced
mark_as_advanced: Mark cmake cached variables as advanced. mark_as_advanced([CLEAR|FORCE] VAR VAR2 V ...
- 股票——成交量加权平均价VWAP
成交量加权平均价是将多笔交易的价格按各自的成交量加权而算出的平均价,若是计算某一证券在某交易日的VWAP,将当日成交总值除以总成交量即可.VWAP可作为交易定价的一种方法,亦可作为衡量机构投资者或交易 ...
- Android-Activity跳转时动画
Activity跳转时动画,是在跳转Activity,或者在Activity结束返回 等,用到的进入效果: 第一种效果展示: 第一个Activity的代码: package liudeli.activ ...
- Grafana展示DNS解析延时
首先一个完整的监控肯定会包含三个部分:1.数据收集部分.2.数据存储部分.3.数据展示部分,今天我也是从这三个方面来实现这个监控的. 数据收集(SHELL 脚本) 没有想到比较好的方法来采集数 ...
- LeetCode148:Sort List
题目: Sort a linked list in O(n log n) time using constant space complexity. 解题思路: 根据题目要求,可知只能用归并排序,其他 ...
- linux系统编程之文件与IO(一):文件描述符、open,close
什么是IO? 输入/输出是主存和外部设备之间拷贝数据的过程 设备->内存(输入操作) 内存->设备(输出操作) 高级I/O ANSI C提供的标准I/O库称为高级I/O,通常也称为带缓冲的 ...
- 转载:R语言Data Frame数据框常用操作
Data Frame一般被翻译为数据框,感觉就像是R中的表,由行和列组成,与Matrix不同的是,每个列可以是不同的数据类型,而Matrix是必须相同的. Data Frame每一列有列名,每一行也可 ...
- CSS/CSS3
CSS/CSS3 选择器. 选择器 例子 例子描述 CSS 说明 .class .intro 选择 class="intro" 的所有元素. 1 #id #firstname 选择 ...
- vux组件简单使用请大佬指点
一.打开vux项目 我用的是vsCode工具自己找看个人选择,第一次使用请去找vc方便开发使用的插件 二.项目目录及文件,有遮挡部分自行查看文件 三.根据官方文档实现引入插件 通过vux-loader ...