三天两夜,1M图片优化到100kb/肝都熬爆了
坦白从宽吧,我就是那个花了两天两夜才把 1M 图片优化到 100kb 的家伙——王小二!
自从因为一篇报道登上热搜后,我差点抑郁,每天要靠 50 片安眠药才能入睡。
网络上曝光的那些关于一码通的消息,有真有假,我这里就不再澄清了。就说说我是怎么把图片从 1M 优化到 100kb 的故事吧。
是的,由于系统群体规模和访问规模的特殊性,每一行代码、每一张图片、每一个技术文档都反复核准,优化再优化,精益求精。为确保系统运行得更高效,我们将一张图片从1MB压缩到500KB,再从500KB优化到100KB。
这样的工作在外人看起来,简单到就好像悄悄给学妹塞一张情书就能让她做我女朋友一样简单。
但殊不知,这其中蕴含着极高的技术含量!
不信,我给你们普及下。
一、图像压缩
图像压缩是数据压缩技术在数字图像上的应用,目的是减少图像数据中的冗余信息,从而用更加高效的格式存储和传输数据。
图像压缩可以是有损数据压缩,也可以是无损数据压缩。
怎么样?
是不是感觉图像压缩技术没有想象中那么简单了?
二、Java数字图像处理
作为这次“20 多万外包项目”的“主力开发人员”,我这里就给大家介绍下 Java 数字图像处理技术吧,一开始我就是用它来处理图片的。
数字图像处理(Digital Image Processing)是通过计算机对图像进行去除噪声、增强、复原、分割、提取特征等处理的方法和技术。
输入的是图像信号,然后经过 DIP 进行有效的算法处理后,输出为数字信号。
为了压缩图像,我们需要读取图像并将其转换成 BufferedImage 对象,BufferedImage 是 Image 类的一个子类,描述了一个具有可访问的图像数据缓冲区,由 ColorModel 和 Raster 的图像数据组成。
废话我就不多说了,直接进入实战吧!
三、图像压缩实战
刚好我本地有一张之前用过的封面图,离 1M 只差 236 KB,可以拿来作为测试用。
这其中要用到 ImageIO 类,这是一个静态类,提供了一系列方法用来读和写图像,同时还可以对图像进行简单的编码和解码。
比如说通过 ImageIO.read() 可以将图像读取到 BufferedImage 对象:
File input = new File("ceshi.jpg");
BufferedImage image = ImageIO.read(input);
比如说通过 ImageIO.getImageWritersByFormatName() 可以返回一个Iterator,其中包含了通过命名格式对图像进行编码的 ImageWriter。
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
ImageWriter writer = (ImageWriter) writers.next();
比如说通过 ImageIO.createImageOutputStream() 可以创建一个图像的输出流对象,有了该对象后就可以通过 ImageWriter.setOutput() 将其设置为输出流。
File compressedImageFile = new File("bbcompress.jpg");
OutputStream os =new FileOutputStream(compressedImageFile);
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
writer.setOutput(ios);
紧接着,可以对 ImageWriter 进行一些参数配置,比如说压缩模式,压缩质量等等。
ImageWriteParam param = writer.getDefaultWriteParam();param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.01f);
压缩模式一共有四种,MODE_EXPLICIT 是其中一种,表示 ImageWriter 可以根据后续的 set 的附加信息进行平铺和压缩,比如说接下来的 setCompressionQuality() 方法。
setCompressionQuality() 方法的参数是一个 0-1 之间的数,0.0 表示尽最大程度压缩,1.0 表示保证图像质量很重要。对于有损压缩方案,压缩质量应该控制文件大小和图像质量之间的权衡(例如,通过在写入 JPEG 图像时选择量化表)。 对于无损方案,压缩质量可用于控制文件大小和执行压缩所需的时间之间的权衡(例如,通过优化行过滤器并在写入 PNG 图像时设置 ZLIB 压缩级别)。
整体代码如下所示:
public class Demo {public static void main(String[] args) {try {File input = new File("ceshi.jpg");BufferedImage image = ImageIO.read(input);Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");ImageWriter writer = (ImageWriter) writers.next();File compressedImageFile = new File("bbcompress.jpg");OutputStream os = new FileOutputStream(compressedImageFile);ImageOutputStream ios = ImageIO.createImageOutputStream(os);writer.setOutput(ios);ImageWriteParam param = writer.getDefaultWriteParam();param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);param.setCompressionQuality(0.01f);writer.write(null, new IIOImage(image, null, null), param);os.close();ios.close();writer.dispose();} catch (IOException e) {e.printStackTrace();}}
}
执行压缩后,可以看到图片的大小压缩到了 19 KB:
可以看得出,质量因子为 0.01f 的时候图片已经有些失真了,可以适当提高质量因子比如说 0.5f,再来看一下。
图片质量明显提高了,但大小依然只有 64 KB,压缩效果还是值得信赖的。
四、其他开源库
接下来,推荐一些可以轻松集成到项目中的图像处理库吧,它们全都是免费的。
1)ImageJ,用 Java 编写的,可以编辑、分析、处理、保存和打印图像。
2)Apache Commons Imaging,一个读取和写入各种图像格式的库,包括快速解析图像信息(如大小,颜色,空间,ICC配置文件等)和元数据。
3)ImageMagick,可以读取和写入超过100种格式的图像,包括DPX、EXR、GIF、JPEG、JPEG-2000、PDF、PNG、Postscript、SVG和TIFF。还可以调整大小、翻转、镜像、旋转、扭曲、剪切和变换图像,调整图像颜色,应用各种特殊效果,包括绘制文本、线条、多边形、椭圆和贝塞尔曲线。
4)OpenCV,由BSD许可证发布,可以免费学习和商业使用,提供了包括 C/C++、Python 和 Java 等主流编程语言在内的接口。OpenCV 专为计算效率而设计,强调实时应用,可以充分发挥多核处理器的优势。
这里就以 OpenCV 为例,来演示一下图像压缩。当然了,OpenCV 用来压缩图像属于典型的大材小用。
第一步,添加 OpenCV 依赖到我们的项目当中,以 Maven 为例。
<dependency><groupId>org.openpnp</groupId><artifactId>opencv</artifactId><version>4.5.1-2</version>
</dependency>
第二步,要想使用 OpenCV,需要先初始化。
OpenCV.loadShared();
第三步,使用 OpenCV 读取图片。
Mat src = Imgcodecs.imread(imagePath);
第四步,使用 OpenCV 压缩图片。
MatOfInt dstImage = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 1);
Imgcodecs.imwrite("resized_image.jpg", sourceImage, dstImage);
MatOfInt 的构造参数是一个可变参数,第一个参数 IMWRITE_JPEG_QUALITY 表示对图片的质量进行改变,第二个是质量因子,1-100,值越大表示质量越高。
执行代码后得到的图片如下所示:
借这个机会,来对比下 OpenCV 和 JDK 原生 API 在压缩图像时所使用的时间。
这是我本机的配置情况,早年买的顶配 iMac,也是我的主力机。一开始只有 16 G 内存,后来加了一个 16 G 内存条,不过最近半年电脑突然死机重启的频率明显提高了,不知道是不是 Big Sur 这个操作系统的问题还是电脑硬件老了。
结果如下所示:
opencvCompress压缩完成,所花时间:1070
jdkCompress压缩完成,所花时间:322
压缩后的图片大小差不多,都是 19 KB,并且质量因子都是最低值。
四、一点点心声
经过上面的技术分析后,相信你们都明白了,把1M图片优化到100kb实在是一件“不太容易”的事情。。。。
100KB 很小了吧?只有原来的 1/10。
要知道,我可是连续加班了两天两夜,不眠不休。
累到最后,我趴在电脑上都睡着了。
没想到哈喇子直接给电脑整短路了,我这才算是从梦里面吓醒来了!
三天两夜,1M图片优化到100kb/肝都熬爆了相关推荐
- Python小技巧:将 1M 图片优化压缩到 1024kb,简单到手到擒来
知乎热搜有一篇帖子,某省会城市健康码连续两次崩溃,相关公司在之前的报道中还声称:用两天两夜,将 1M 图片优化到 100kb. 报道中提到:"为了确保系统运行更高效,他们将一张图片从 1MB ...
- 永坤电机SEO三天两夜课程学习总结
通过这次的学习.我在以前的基础上进一步巩固了互联网上的很多知识并运用到我们产品上.例如我们公司的产品:电机,通过互联网这一渠道来推广.目的是为了提高网站收录,提高网站权重,提高精准流量. 对于如何是着 ...
- 我与前端之间不得不说的三天两夜之javaScript
前端基础之JavaScript JavaScript概述 JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后 ...
- 三天两夜肝完这篇万字长文,终于拿下了TCP/IP
前言 计算机网络是一门基础课程,但是老师所讲的东西无非起到一个抛砖引玉的作用.然而对于需要自学的人来说,无疑是更难的.前路漫漫-- 计算机网络本来就是比较枯燥的,文章内容较多,建议读者耐心看完这篇文章 ...
- 【158期】三天两夜肝完这篇万字长文,看完它,面试再也不用怕被问到 TCP/IP 了...
程序员的成长之路 互联网/程序员/技术/资料共享 关注 阅读本文大概需要 28 分钟. 来自:juejin.im/post/6850037269244575757 前言 计算机网络是一门基础课程,但是 ...
- 理论 | 三天两夜,万字长文,吃透TCP/IP
这是小小的本周第二篇,在本周的第二篇里,将会用长文讲解TCP和IP的理论相关知识.用于进行详解. 这是小小本周的第二篇 思维导图 思维导图如下 计算机体系网络结构分层 概述 这里进行概述如下 物理层 ...
- 我与前端之间不得不说的三天两夜之html基础
HTML 初识 分类 cs模式 client-server bs模式 Browser-server web服务本质 from socket import *def main():service=soc ...
- 宁波之行三天两夜回顾
和姐妹们聊天聊着就突发奇想:我们去宁波玩吧! 然后就定下来去宁波玩. 19号考完试,20号中午我从杭州去金华,21号晚上坐K846,23:13-05:11的车到宁波(很奇怪金华到宁波的高铁都只有下午的 ...
- 两阶段鲁棒优化程序 采用微网为模型,主要将安装成本、运营成本以及综合效益三个方面纳入考虑范围
两阶段鲁棒优化程序 采用微网为模型,主要将安装成本.运营成本以及综合效益三个方面纳入考虑范围,建立两阶段鲁棒优化模型,采用的是CCG方法,本程序为matlab编制,有售后,可以进行!另外本程序考虑发电 ...
- 每个网站SEO优化人员都要熟知的三大图片优化技巧
在网站优化中,优化人员往往会更加重视关键词优化.网站结构等优化,对于图片的优化也更是作为网站优化的重点,在网站设计以及文章内容更新时都会用到图片,想要搜索引擎能够对图片进行良好的抓取和收录,就要让搜索 ...
最新文章
- 教育部办公厅关于2020-2021学年面向中小学生的全国性竞赛活动名单的公示
- recyclerview 滚动冲突_如何处理手势冲突 | 手势导航连载 (三)
- 【错误记录】FFmpeg 推流报错 ( FLV does not support sample rate 8000, choose from (44100, 22050, 11025) )
- vivo android8公测,vivo 开启安卓P公测不限人数!这四款机型用户别错过了
- Linux 环境下的抓包工具 - tcpdump
- java正则匹配英文句号_「正则表达式」王国奇遇记
- 互联网企业安全之端口监控
- ROS配置分布式通信
- c语言通讯录程序设计个人感言,C语言学习感悟(1)
- GIT 密钥生成工具puttygen使用技巧
- Python实现简易语音转文字功能模块
- Windows 自带的 UTF8 字符 颜文字表情符号
- 双向迁移图协同过滤GCF的跨域推荐
- How to hide the New! icon or control how long the icon is displayed.
- 凸函数(convex)
- Nginx访问控制,限速limit_conn, limit_req
- inet_aton和inet_ntoa
- 1:基本初等函数的性质
- 【CSS笔记】CSS选择器的优先级(权重)
- 百度的广告金主需要MarTech产品不?
热门文章
- QQ 第三方登录知识点总结
- Goole Tag Manager 介绍
- c++中类的private的static变量实现类对象的数据共享
- it行业se是_计算机行业SSE、SE、BSE、PE、PL各自是什么职位意思?
- Leetcode︱448. Find All Numbers Disappeared in an Array找到所有数组中消失的数字.java
- 例题 2-1 aabb 2-2 3n+1问题
- java中gc是什么_java什么是gc
- java 金额数字转换大写算法
- Excel格式的SNP数据怎么变为plink格式
- Java for循环和foreach循环区别