android 图片压缩,bitmap压缩总结
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压缩的输出:
![](/assets/blank.gif)
效果图:
![](/assets/blank.gif)
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压缩总结相关推荐
- 图片上传压缩android,android 图片上传压缩常见问题分析
图片的上传与压缩是android经常需要用到的步骤,那么,如何解决上传图片oom问题呢?android 图片上传压缩常见问题分析,希望可以帮助大家更加的了解android 图片方面的困惑. 下面,是我 ...
- android 图片过滤,android 图片转为bitmap,黑白镜过滤
图片转bitmap 1.获取图片资源 Bitmap bitmap= BlackWhite(BitmapFactory.decodeResource(getResources(), R.mipmap.t ...
- bitmap的六种压缩方式,Android图片压缩(转)
转载请注明出处,谢谢:http://blog.csdn.net/harryweasley/article/details/51955467 android中图片是以bitmap形式存在的,那么bitm ...
- bitmap的六种压缩方式,Android图片压缩
转载请注明出处,谢谢:http://blog.csdn.net/harryweasley/article/details/51955467 android中图片是以bitmap形式存在的,那么bitm ...
- Android图片压缩(质量压缩和尺寸压缩)Bitmap转成字符串上传
在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...
- Android 超清大尺寸图片压缩转Base64中卡顿/速度优化问题整理(在子线程压缩Bitmap卡的主线程进度条走不动了。。。)
最近遇到需求是前后端传输图片使用的是Base64,但是前端(Android 端)图片很大(尺寸很大4480 × 2520,质量也很大7-10M),需要压缩到一定尺寸(1280 × 960,当然还可以压 ...
- Android图片压缩(质量压缩和尺寸压缩)
在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...
- android使用的图片压缩格式,Android 之使用libjpeg压缩图片
一.环境 Android Studio 4.0.1 NDK R15c so包是2.0.6生成的 libturbojpeg.so 二.准备 1.编写native方法并用javah命令生成头文件 obje ...
- Android仿微信高效压缩图片(libjpeg)
用过ios手机的同学应该很明显感觉到,ios拍照1M的图片要比安卓拍照排出来的5M的图片还要清晰.这是为什么呢? 这得了解android底层是如何对图片进行处理的. 当时谷歌开发Android的时候, ...
最新文章
- 全国首个5G+AI的智慧交通管理示范应用成功开通!
- 计算机视觉成安防“显学”落地仍需解决这些难题
- Spring可扩展Schema标签
- js cookies 存数组_用一个例子理解JS函数的底层处理机制
- java并发之线程封闭(二)
- NSString的各种用法总结(创建、截取、判断比较、转化数据类型、拼接、替换、添加、追加、读取、写入、删去、改变)
- Python - 排序( 插入, 冒泡, 快速, 二分 )
- MySQL二进制版本的安装及卸载
- eclipse配置java开发环境_Java中Eclipse开发环境配置
- 详解BILSTM-CRF模型结构进行命名实体识别
- 研究方法|用CiteSpace进行科学文献可视化分析
- 手机的RFID射频技术应用
- 【目标跟踪系列】SiamRpn卷积流程以及代码
- Qt::WA_QuitOnClose
- Raul的新机器学习书!
- 剪辑器更新-去水印详解
- 大会详细日程:O'Reilly AI Conference 北京站
- 南师大考研632c语言,2019南京师范大学外国语言学及应用语言学考研623外国语言文学基础知识与汉语写作与830英语语言学基础知识与翻译考试真题试卷...
- VMware12+Ubuntu16.04 安装 以及全屏的实现
- 电信版系统可随时升级支持4G网络
热门文章
- ros1-gazebo创建世界和机器人模型(单线雷达、多线雷达、相机)
- Python学习指南(看完不迷路)
- 小猪的Android入门之路 Day 8 part 3
- 使用docker快速安装Oracle11gR2
- 栅格布局一般怎么用_Bootstrap每天必学之栅格系统(布局)
- 使用echarts中国地图添加气泡时使用接口访问的数据不显示
- 舒亦梵:4.24非农周即将来临,作为投资者的你做好准备了吗
- 一次应用访问数据库 IP 配成外网 IP 引发的血案
- pyplot 画多个图时搅合到了一起_家里来了好些小朋友,什么游戏可以让孩子们玩到一起?...
- Codeforces Round #406 (Div. 1) A. Berzerk 记忆化搜索