Android图片压缩以及优化实例
发布时间 - 2026-01-11 01:45:00 点击率:次前言

图片压缩在Android技术中已经属于烂大街,上周看了2个开源库然后对自己项目的压缩做了对比,发现一些新东西,记录与此。
为何要压缩
1、体积的原因
如果你的图片是要准备上传的,那动辄几M的大小肯定不行的,况且图片分辨率大于设备分辨率的话毫无意义。
2、内存原因
如果图片要显示下Android设备上,ImageView最终是要加载Bitmap对象的,就要考虑单个Bitmap对象的内存占用了,如何计算一张图片的加载到内存的占用呢?其实就是所有像素的内存占用总和:
bitmap内存大小 = 图片长度 x 图片宽度 x 单位像素占用的字节数
起决定因素就是最后那个参数了,Bitmap'常见有2种编码方式:ARGB_8888和RGB_565,ARGB_8888每个像素点4个byte,RGB_565是2个byte,一般都采用ARGB_8888这种。那么常见的1080*1920的图片内存占用就是:
1920 x 1080 x 4 = 7.9M
压缩原理
从上面可以总结出,图片压缩应该从两个方面入手同时进行:先是降低分辨率,然后降低每个像素的质量也就是内存占用。
分辨率压缩
假设有张原图是3840x2400,我想压缩成1920x1080,实际是不可能100%能压缩这个值的。因为图片压缩要保证宽高比,试想一下800x100的横向图可能压成20x200竖向图吗? 不可能的.。这里常见的算法就是在1920x1080的范围内保证较短边,然后按照比例压缩整个图:
这里原图的宽高比是 3840/2400 = 1.6,目标图的宽高比是1920/1080 = 1.78>1.6,较短边是高。所以就应该按照高的比例来压缩。
2400/1080=2.22,这样真实目标值就是:1728x1080,压缩比四舍五入是:2,然后通过下面代码进行压缩:
private Bitmap compressPixel(String filePath){
Bitmap bmp = null;
BitmapFactory.Options options = new BitmapFactory.Options();
//setting inSampleSize value allows to load a scaled down version of the original image
options.inSampleSize = 2;
//inJustDecodeBounds set to false to load the actual bitmap
options.inJustDecodeBounds = false;
options.inTempStorage = new byte[16 * 1024];
try {
//load the bitmap from its path
bmp = BitmapFactory.decodeFile(filePath, options);
if (bmp == null) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(filePath);
BitmapFactory.decodeStream(inputStream, null, options);
inputStream.close();
} catch (FileNotFoundException exception) {
exception.printStackTrace();
} catch (IOException exception) {
exception.printStackTrace();
}
}
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}finally {
return bmp;
}
}
看起来没什么问题,看看实测结果,原图 3840*2400,大小2.2M,我选4个分辨率当做目标值来压缩:
可以看出压缩后的4张图没有一张达到目标值,而且偏差较大,原因就是options.inSampleSize这个属性,他只能是2的N次方,如果算出来是7,Android会取近似值8,以此类推导致这个值不能压缩到目标值。看了一下Compressor这个开源库他对此做了处理,把压缩后的图片在Canvas上面按照目标尺寸重绘,得到一个新的bitmap:
核心代码:
Matrix scaleMatrix = new Matrix(); scaleMatrix.setScale(ratioX, ratioY, 0, 0); Canvas canvas = new Canvas(scaledBitmap); canvas.setMatrix(scaleMatrix); canvas.drawBitmap(bmp, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));
用Compressor开源库压缩的图片对比下:
可以看出每次都能压缩到真实目标值。(注意不是目标值,注意区分目标值和真实目标值)
质量压缩
Bitmap有个方法 compress(CompressFormat format, int quality, OutputStream stream),quality就是压缩质量传入0-100,数值越小压缩的越厉害。
不过我们一般不直接设置这个数值,而是自定义一个压缩后大小比如300KB,然后动态计算这个quality,核心代码:
//进行有损压缩
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int options_ = 100;
actualOutBitmap.compress(Bitmap.CompressFormat.JPEG, options_, baos);
//质量压缩方法,把压缩后的数据存放到baos中 (100表示不压缩,0表示压缩到最小)
int baosLength = baos.toByteArray().length;
while (baosLength / 1024 > maxFileSize)
{
//循环判断如果压缩后图片是否大于maxMemmorrySize,大于继续压缩
baos.reset();
//重置baos即让下一次的写入覆盖之前的内容
options_ = Math.max(0, options_ - 10);//图片质量每次减少10
actualOutBitmap.compress(Bitmap.CompressFormat.JPEG, options_, baos);
//将压缩后的图片保存到baos中
baosLength = baos.toByteArray().length;
if (options_ == 0)//如果图片的质量已降到最低则,不再进行压缩
break;
}
压缩实践
目前成熟的开源库有Luban:https://github.com/Curzibn/Luban
这个开源库算法比较复杂,根据效果图前后对比逆向推算了微信朋友圈的压缩,最后效果和微信差不多,如果你对压缩要求很高可以使用这个。不过方法调用是异步的,回调形式反馈结果,这个不太好。。
Compressor:https://github.com/zetbaitsu/Compressor
这个开源库就是在普通的压缩算法上做了优化改进,源码很容易看懂,推荐!下面是用Compressor对三张大图不同目标值做的压缩测试(BV是我们项目的压缩,忽略就好),质量参数设的是80%
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Android图片压缩
# Android图片压缩优化
# 开源
# 看了
# 可以看出
# 较短
# 的是
# 加载
# 我想
# 就是在
# 不可能
# 有个
# 都能
# 就好
# 不多
# 以此类推
# 很容易
# 很高
# 用了
# 与此
# 你对
# 自定义
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用
网站制作软件有哪些,制图软件有哪些?
如何在HTML表单中获取用户输入并用JavaScript动态控制复利计算循环
Python高阶函数应用_函数作为参数说明【指导】
进行网站优化必须要坚持的四大原则
Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】
深圳网站制作的公司有哪些,dido官方网站?
Laravel模型事件有哪些_Laravel Model Event生命周期详解
敲碗10年!Mac系列传将迎来「触控与联网」双革新
Laravel distinct去重查询_Laravel Eloquent去重方法
JavaScript中的标签模板是什么_它如何扩展字符串功能
实例解析Array和String方法
网站制作报价单模板图片,小松挖机官方网站报价?
HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】
如何快速生成可下载的建站源码工具?
Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法
怎样使用JSON进行数据交换_它有什么限制
高端企业智能建站程序:SEO优化与响应式模板定制开发
Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性
如何快速上传建站程序避免常见错误?
如何在阿里云域名上完成建站全流程?
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
Thinkphp 中 distinct 的用法解析
Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能
Win11应用商店下载慢怎么办 Win11更改DNS提速下载【修复】
轻松掌握MySQL函数中的last_insert_id()
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
如何基于云服务器快速搭建网站及云盘系统?
JavaScript数据类型有哪些_如何准确判断一个变量的类型
Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理
html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】
node.js报错:Cannot find module 'ejs'的解决办法
Laravel如何连接多个数据库_Laravel多数据库连接配置与切换教程
东莞专业网站制作公司有哪些,东莞招聘网站哪个好?
如何用搬瓦工VPS快速搭建个人网站?
Swift开发中switch语句值绑定模式
网站制作大概多少钱一个,做一个平台网站大概多少钱?
如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程
郑州企业网站制作公司,郑州招聘网站有哪些?
香港服务器网站推广:SEO优化与外贸独立站搭建策略
新三国志曹操传主线渭水交兵攻略
如何在阿里云通过域名搭建网站?
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
Android仿QQ列表左滑删除操作
千库网官网入口推荐 千库网设计创意平台入口
JavaScript如何实现类型判断_typeof和instanceof有什么区别
Linux安全能力提升路径_长期防护思维说明【指导】
如何用景安虚拟主机手机版绑定域名建站?

