Home > Java > javaTutorial > body text

Java example analysis of 1M image compression and optimization to 100kb

WBOY
Release: 2022-07-27 21:17:47
forward
2852 people have browsed it

本篇文章给大家带来了关于java的相关知识,主要为大家介绍了java实现1M图片压缩优化到100kb示例详解,图像压缩是数据压缩技术在数字图像上的应用,有需要的朋友可以借鉴参考下,希望能够有所帮助。

Java example analysis of 1M image compression and optimization to 100kb

推荐学习:《java视频教程

一、图像压缩

图像压缩是数据压缩技术在数字图像上的应用,目的是减少图像数据中的冗余信息,从而用更加高效的格式存储和传输数据。

图像压缩可以是有损数据压缩,也可以是无损数据压缩。

怎么样?

是不是感觉图像压缩技术没有想象中那么简单了?

二、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);
Copy after login

比如说通过 ImageIO.getImageWritersByFormatName() 可以返回一个Iterator,其中包含了通过命名格式对图像进行编码的 ImageWriter。

Iterator<ImageWriter> writers =  ImageIO.getImageWritersByFormatName("jpg");
ImageWriter writer = (ImageWriter) writers.next();
Copy after login

比如说通过 ImageIO.createImageOutputStream() 可以创建一个图像的输出流对象,有了该对象后就可以通过 ImageWriter.setOutput() 将其设置为输出流。

File compressedImageFile = new File("bbcompress.jpg");
OutputStream os =new FileOutputStream(compressedImageFile);
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
writer.setOutput(ios);
Copy after login

紧接着,可以对 ImageWriter 进行一些参数配置,比如说压缩模式,压缩质量等等。

ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.01f);
Copy after login

压缩模式一共有四种,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();
        }
    }
}
Copy after login

执行压缩后,可以看到图片的大小压缩到了 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>
Copy after login

第二步,要想使用 OpenCV,需要先初始化。

OpenCV.loadShared();
Copy after login

第三步,使用 OpenCV 读取图片。

Mat src = Imgcodecs.imread(imagePath);
Copy after login

第四步,使用 OpenCV 压缩图片。

MatOfInt dstImage = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 1);
Imgcodecs.imwrite("resized_image.jpg", sourceImage, dstImage);
Copy after login

MatOfInt 的构造参数是一个可变参数,第一个参数 IMWRITE_JPEG_QUALITY 表示对图片的质量进行改变,第二个是质量因子,1-100,值越大表示质量越高。

执行代码后得到的图片如下所示:

借这个机会,来对比下 OpenCV 和 JDK 原生 API 在压缩图像时所使用的时间。

这是我本机的配置情况,早年买的顶配 iMac,也是我的主力机。一开始只有 16 G 内存,后来加了一个 16 G 内存条,不过最近半年电脑突然死机重启的频率明显提高了,不知道是不是 Big Sur 这个操作系统的问题还是电脑硬件老了。

结果如下所示:

opencvCompress压缩完成,所花时间:1070
jdkCompress压缩完成,所花时间:322

压缩后的图片大小差不多,都是 19 KB,并且质量因子都是最低值。

推荐学习:《java视频教程

The above is the detailed content of Java example analysis of 1M image compression and optimization to 100kb. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:jb51.net
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template