一、bitmap 图片格式介绍

android中图片是以bitmap形式存在的,那么bitmap所占内存,直接影响到了应用所占内存大小,首先要知道bitmap所占内存大小计算方式:

  bitmap内存大小 =  图片长度 x 图片宽度 x 一个像素点占用的字节数

以下是图片的压缩格式:

其中,A代表透明度;R代表红色;G代表绿色;B代表蓝色。  

  1. ALPHA_8         表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度
  2. ARGB_4444    表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节
  3. ARGB_8888    表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节
  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图片压缩总结的更多相关文章

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

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

  2. android图片压缩方法

    android 图片压缩方法: 第一:质量压缩法: private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = ...

  3. android图片压缩的3种方法实例

    android 图片压缩方法: 第一:质量压缩法: private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = ...

  4. Android 图片压缩器

    概述 Android 图片压缩器:一款高效的图片压缩器库,支持批量压缩,异步压缩.多线程多任务压缩,压缩比设置等特性. 详细 代码下载:http://www.demodashi.com/demo/12 ...

  5. Android 图片压缩各种方式

       前言:由于公司项目当中需要用到压缩这块的相应技术,之前也做过的图片压缩都不是特别的理想, 所以这次花了很多心思,仔细研究和在网上找到了很多相对应的资料.为了就是 以后再做的时候直接拿来用就可以了 ...

  6. Android图片压缩上传(二)

    之前有用到libjpeg,还是有一定的局限性,最近用了一个新的方式,效果还是挺不错,随着作者的版本更新,Bug也随之变少,目前项目中运用已上线. 1.之前的方式Android图片压缩,不失真,上线项目 ...

  7. Android图片压缩方法总结

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

  8. Android图片压缩

    import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java ...

  9. 性能优化——Android图片压缩与优化的几种方式

    图片优化压缩方式大概可以分为以下几类:更换图片格式,质量压缩,采样率压缩,缩放压缩,调用jpeg压缩等1.设置图片格式Android目前常用的图片格式有png,jpeg和webp,png:无损压缩图片 ...

随机推荐

  1. Linux IPC 之信号量

    信号量(也叫信号灯)是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语. 信号量是进程/线程同步的一种方式,有时候我们需要保护一段代码,使它每次只能被一个执行进程/线程运行,这种工作就需 ...

  2. C++/C头文件 .h和 .c

    在C语言家族程序中,头文件被大量使用.一般而言,每个C++/C程序通常由头文件(header files)和定义文件(definition files)组成.头文件作为一种包含功能函数.数据接口声明的 ...

  3. 红楼梦3d游戏

    1. 红楼梦大观园2d图 2. 红楼梦3d图 潇湘馆 注册机:根据电脑名和时间生成一个id,然后根据注册机生成注册码.

  4. MFC中不同对话框间使用SendMessage发送自定义消息的具体实现

    1. 基本知识 SendMessage的基本结构如下: SendMessage(     HWND hWnd,  //消息传递的目标窗口或线程的句柄.     UINT Msg, //消息类别(这里可 ...

  5. java线程一

    我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread).线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源,比 ...

  6. 搜狗Q3业绩迅猛增长,战略整合稳步推进

        继9月16日腾讯与搜狗战略结盟之后,最近搜狗再次吸引了业界关注的目光,10月29日,搜狗公布了截至2013年9月30日的第三季度未经审计的财务报告.财报显示,新搜狗Q3营收达5700万美元,同 ...

  7. 【转】【译】【Win10】在你的程序标题栏中显示后退按钮

    原文地址:http://www.sharpgis.net/post/2015/05/21/Displaying-a-backbutton-in-your-app-window 免责声明:这篇文章基于 ...

  8. Spring Boot 应用系列 4 -- Spring Boot 2 整合log4j2

    一.背景 1. log4j2传承于log4j和logback,它是目前性能最好的日志处理工具,有关它们的性能对比请看: 2. 除了性能好之外,log4j2有这么几个重要的新features: (1) ...

  9. Alwayson--与复制的影响

    在主副本上建立复制后,复制的事务日志读取代理(log reader)不会读取尚未同步到辅助副本的日志,因为辅助副本可能在下一时刻转化成为主副本,变为新的复制发布服务器,为此需要保证复制处理的日志总慢于 ...

  10. echarts呈现数据表图形

    讲一下echarts的用法,列举了两个图表,一个是单柱图,一个是多柱图,至于饼状图,只许更改echarts的类型就好了 一.首先是要两个div,用来存放两个图表 <div class=" ...