共计 4116 个字符,预计需要花费 11 分钟才能阅读完成。
坦白从宽吧,我就是那个花了两天两夜把 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。要晓得,我可是间断加班了两天两夜,不眠不休。
累到最初,我趴在电脑上都睡着了。没想到哈喇子间接给电脑整短路了,我这才算是从梦外面吓醒来了!😔,生存不易,且行且珍惜吧~