1.    图片压缩相关概念

在android开发中,图片加载到内存中通常需要占用大量的内存,导致app性能过度消耗,严重的话可能会导致OOM异常,所以对图片进行优化就尤为重要。
android图片压缩的格式可以通过以下一张图进行概括,这张图摘自官方API文档:
 
对于各个参数的含义,通过以下一张表格总结一下

ALPHA_8 每个像素存储为单个半透明(alpha)通道,占用1字节内存,用来存储遮罩非常有用
ARGB_4444  每个像素占用2字节存储空间,由于在这个配置下的图片质量比较差,官方建议使用ARGB_8888,官方已提示ARGB_4444不推荐使用
ARGB_8888   每个像素占用4字节存储空间,每个通道(A,R,G,B)都以8位精度进行存储,这种格式下图片质量最佳,官方推荐尽可能使用这种格式存储
HARDWARE     一种特殊的存储格式,当位图仅仅存储在图形内存中时,位图始终保持不变
RGBA_F16    每个像素存储在8个字节上,很少用
RGB_565   每个像素存储在2个字节上,没有透明度,只包括了红,绿,蓝三个通道,当使用不需要透明度图片时,可以使用该格式存储

android图片加载到内存,bitmap所占内存的大小可以由下列公式进行计算:
bitmap所占内存 = 图片分辨率 * 一个像素所占的字节数
上述公式其实是不严谨的,对于从SD卡,assests目录或者网络中加载图片所占用的内存,是可以通过上述的公式计算出来的。但是如果图片存储在res目录中,当图片加载进内存时,会经过一次分辨率的转换,然后在计算内存占用多少,这时图片的分辨率应该是转换之后的分辨率,而不是原图的分辨率。
这里只讨论常规图片压缩方式,图片都是存储在SD卡或者assests目录中,对于存储在res目录下的情况忽略。
bitmap的压缩方式主要有:
1.    采样率压缩
2.    缩放压缩
3.    质量压缩
4.    设置RGB_565
5.    使用createScaledBitmap
下面简单讨论下各种压缩方式

2. 采样率压缩

通过设置BitmapFactory.Options的inSampleSize参数,达到压缩图片的目的。该参数表示压缩为原图的几分之一,必须大于1,小于1按照1处理。
下面通过加载原图和设置inSampleSize来对比设置inSampleSize加载图片之后的效果。
把一张原图不经过压缩直接加载到内存中:

Bitmap bitmap =
BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png");
if(bitmap != null) {String info = "原始图片大小: " + (bitmap.getByteCount()) + " 宽度: " + bitmap.getWidth() + " 高度: " + bitmap.getHeight();Log.v("sample", info);tvOrgin.setText(info);imgvOrgin.setImageBitmap(bitmap);
}

设置inSampleSize参数,加载一张图片到内存中:

BitmapFactory.Options options = new BitmapFactory.Options();
String str = edtvSample.getText().toString();
int sample = 2;
try {sample = Integer.parseInt(str);
} catch (Exception e) {Toast.makeText(this, "请输入有效数字内容", Toast.LENGTH_SHORT).show();e.printStackTrace();return ;
}
options.inSampleSize = sample;Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png", options);
if(bitmap != null) {String info = "压缩图片大小: " + (bitmap.getByteCount()) + " 宽度: " + bitmap.getWidth() + " 高度: " + bitmap.getHeight();Log.v("sample", info);tvCompress.setText(info);imgvCompress.setImageBitmap(bitmap);
}

其中inSampleSize通过界面动态设置,以此来查看不同inSampleSize加载图片的具体效果。
例如把inSampleSize设置成4,宽度和高度都变为了原来的1/4,图片内存整整缩小为原来的1/16。
 
下面是我测试的一张效果:

3. 缩放压缩

通过Martix变换,设置缩放值以此来达到图片压缩的目的。

Bitmap bitmap =
BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png");
String strx = edtvSx.getText().toString();
String stry = edtvSy.getText().toString();float sx = 0.5f;
float sy = 0.5f;
try {sx = Float.parseFloat(strx);sy = Float.parseFloat(stry);
} catch (Exception e) {Toast.makeText(this, "请输入有效数字内容", Toast.LENGTH_SHORT).show();e.printStackTrace();return ;
}
if(bitmap != null) {Matrix matrix = new Matrix();matrix.setScale(sx, sy);Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);String info = " sx: " + sx + " sy: " + sy + " 压缩图片大小: " + (newBitmap.getByteCount()) + " 宽度为: " + newBitmap.getWidth() + " 高度为: " + newBitmap.getHeight();Log.v("martix", info);tvCompress.setText(info);imgvCompress.setImageBitmap(newBitmap);
}

把x,y缩放值分别设置成0.5f,可以看到压缩后的图片宽,高都是原图宽高的1/2,图片整体大小是原图的1/4.
 
效果图:

4. 质量压缩

质量压缩并不会减少bitmap占用的内存,bitmap的分辨率会和原图保持一致。质量压缩的原理是通过算法扣掉(同化)了 图片中的一些某个点附近相近的像素,以此介绍图片中的颜色数量,达到减少文件大小的目的。
质量压缩测试代码:

        Bitmap bitmap =
BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png");ByteArrayOutputStream baos = new ByteArrayOutputStream();String str = edtvQuality.getText().toString();int quality = 100;try {quality = Integer.parseInt(str);} catch (Exception e) {Toast.makeText(this, "请输入有效数字内容", Toast.LENGTH_SHORT).show();e.printStackTrace();return ;}if(bitmap != null) {
//            bitmap.compress(Bitmap.CompressFormat.PNG, quality, baos); // 设置Bitmap.CompressFormat.PNG,quality将不起作用,PNG是无损压缩bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);byte[] bytes = baos.toByteArray();Bitmap newBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);String info = " quality: " + quality + " 压缩图片大小: " + (newBitmap.getByteCount()) + " 压缩后文件大小: " + (bytes.length) + " 宽度为: " + newBitmap.getWidth() + " 高度为: " + newBitmap.getHeight();Log.v("quality", info);tvCompress.setText(info);imgvCompress.setImageBitmap(newBitmap);}
关键代

码是:

bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);

其中quality是压缩质量,100表示保持最佳质量压缩效果,值越小表示压缩效果越差。
如果上述方法的CompressFormat参数设置成Bitmap.CompressFormat.PNG,那么后面的quality参数将会失效,无论怎样改变quality的值,压缩后的文件都不会改变这是因为PNG是无损压缩。
把quality设置成5,可以看下压缩效果:
 
效果图:
 

5. 设置RGB_565

设置RGB_565相比ARGB_8888减少了一半内存,这是因为RGB_565每个像素是2个字节存储的,但是bitmap的宽和高并不会改变。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = config;
Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png", options);
if(bitmap != null) {String info = " 压缩图片大小: " + (bitmap.getByteCount()) + " 宽度为: " + bitmap.getWidth() + " 高度为: " + bitmap.getHeight();Log.v("rgb", info);tvCompress.setText(info);imgvCompress.setImageBitmap(bitmap);
}

以下是使用RGB_565压缩的输出:

 效果图:

6. 使用createScaledBitmap

使用createScaledBitmap()方法可以把图片压缩成用户期望任意尺寸的图片,如果期望尺寸和图片相差太大,会导致图片失真。

Bitmap bitmap =
BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png");
String strx = edtvWidth.getText().toString();
String stry = edtvHeight.getText().toString();int width = 200;
int height = 200;
try {width = Integer.parseInt(strx);height = Integer.parseInt(stry);
} catch (Exception e) {Toast.makeText(this, "请输入有效数字内容", Toast.LENGTH_SHORT).show();e.printStackTrace();return ;
}
if(bitmap != null) {Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);String info = " width: " + width + " height: " + height + " 压缩图片大小: " + (newBitmap.getByteCount()) + " 宽度为: " + newBitmap.getWidth() + " 高度为: " + newBitmap.getHeight();Log.v("scale", info);tvCompress.setText(info);imgvCompress.setImageBitmap(newBitmap);
}

把宽高设置成200之后的效果:
 
 
可以看到,如果不按比例进行缩放设置,图片是会拉伸,失真的。

本文的源码比较简单,就不上传了,需要的留下邮箱私发。

android 图片压缩,bitmap压缩总结相关推荐

  1. 图片上传压缩android,android 图片上传压缩常见问题分析

    图片的上传与压缩是android经常需要用到的步骤,那么,如何解决上传图片oom问题呢?android 图片上传压缩常见问题分析,希望可以帮助大家更加的了解android 图片方面的困惑. 下面,是我 ...

  2. android 图片过滤,android 图片转为bitmap,黑白镜过滤

    图片转bitmap 1.获取图片资源 Bitmap bitmap= BlackWhite(BitmapFactory.decodeResource(getResources(), R.mipmap.t ...

  3. bitmap的六种压缩方式,Android图片压缩(转)

    转载请注明出处,谢谢:http://blog.csdn.net/harryweasley/article/details/51955467 android中图片是以bitmap形式存在的,那么bitm ...

  4. bitmap的六种压缩方式,Android图片压缩

    转载请注明出处,谢谢:http://blog.csdn.net/harryweasley/article/details/51955467 android中图片是以bitmap形式存在的,那么bitm ...

  5. Android图片压缩(质量压缩和尺寸压缩)Bitmap转成字符串上传

    在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...

  6. Android 超清大尺寸图片压缩转Base64中卡顿/速度优化问题整理(在子线程压缩Bitmap卡的主线程进度条走不动了。。。)

    最近遇到需求是前后端传输图片使用的是Base64,但是前端(Android 端)图片很大(尺寸很大4480 × 2520,质量也很大7-10M),需要压缩到一定尺寸(1280 × 960,当然还可以压 ...

  7. Android图片压缩(质量压缩和尺寸压缩)

    在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...

  8. android使用的图片压缩格式,Android 之使用libjpeg压缩图片

    一.环境 Android Studio 4.0.1 NDK R15c so包是2.0.6生成的 libturbojpeg.so 二.准备 1.编写native方法并用javah命令生成头文件 obje ...

  9. Android仿微信高效压缩图片(libjpeg)

    用过ios手机的同学应该很明显感觉到,ios拍照1M的图片要比安卓拍照排出来的5M的图片还要清晰.这是为什么呢? 这得了解android底层是如何对图片进行处理的. 当时谷歌开发Android的时候, ...

最新文章

  1. 全国首个5G+AI的智慧交通管理示范应用成功开通!
  2. 计算机视觉成安防“显学”落地仍需解决这些难题
  3. Spring可扩展Schema标签
  4. js cookies 存数组_用一个例子理解JS函数的底层处理机制
  5. java并发之线程封闭(二)
  6. NSString的各种用法总结(创建、截取、判断比较、转化数据类型、拼接、替换、添加、追加、读取、写入、删去、改变)
  7. Python - 排序( 插入, 冒泡, 快速, 二分 )
  8. MySQL二进制版本的安装及卸载
  9. eclipse配置java开发环境_Java中Eclipse开发环境配置
  10. 详解BILSTM-CRF模型结构进行命名实体识别
  11. 研究方法|用CiteSpace进行科学文献可视化分析
  12. 手机的RFID射频技术应用
  13. 【目标跟踪系列】SiamRpn卷积流程以及代码
  14. Qt::WA_QuitOnClose
  15. Raul的新机器学习书!
  16. 剪辑器更新-去水印详解
  17. 大会详细日程:O'Reilly AI Conference 北京站
  18. 南师大考研632c语言,2019南京师范大学外国语言学及应用语言学考研623外国语言文学基础知识与汉语写作与830英语语言学基础知识与翻译考试真题试卷...
  19. VMware12+Ubuntu16.04 安装 以及全屏的实现
  20. 电信版系统可随时升级支持4G网络

热门文章

  1. ros1-gazebo创建世界和机器人模型(单线雷达、多线雷达、相机)
  2. Python学习指南(看完不迷路)
  3. 小猪的Android入门之路 Day 8 part 3
  4. 使用docker快速安装Oracle11gR2
  5. 栅格布局一般怎么用_Bootstrap每天必学之栅格系统(布局)
  6. 使用echarts中国地图添加气泡时使用接口访问的数据不显示
  7. 舒亦梵:4.24非农周即将来临,作为投资者的你做好准备了吗
  8. 一次应用访问数据库 IP 配成外网 IP 引发的血案
  9. pyplot 画多个图时搅合到了一起_家里来了好些小朋友,什么游戏可以让孩子们玩到一起?...
  10. Codeforces Round #406 (Div. 1) A. Berzerk 记忆化搜索