To be frank, I am the guy who spent two days and nights optimizing 1M images to 100KB – Wang Xiaoer!

Ever since I was trending for an article, I’ve been so depressed that I need 50 sleeping pills a day to fall asleep.

The network exposure of those information about one code, some true or false, I will not clarify here. Let’s talk about how I optimized the image from 1M to 100KB.

Yes, every line of code, every picture and every technical document has been repeatedly approved, optimized and optimized for perfection due to the particularity of the group size and access scale of the system. To make the system run more efficiently, we compressed an image from 1MB to 500KB and optimized it from 500KB to 100KB.

This kind of work seems to be as simple as slipping a love letter to my schoolgirl and asking her to be my girlfriend.

But little do they know, which contains a very high technical content!

Don’t believe me, LET me tell you something.

First, image compression

Image compression is the application of data compression technology in digital image, which aims to reduce the redundant information in image data and store and transmit data in a more efficient format.

Image compression can be lossy or lossless.

How’s that?

Do you feel that image compression technology is not as easy as you imagined?

More information on image compression can be found in the following links.

The heart of the machine: www.jiqizhixin.com/graph/techn…

Second, Java digital image processing

As this “more than 200,000 outsourcing project” “main developer”, I will introduce you to Java digital image processing technology, I used it to process pictures at the beginning.

Digital Image Processing (Digital Image Processing) is a method and technology to remove noise, enhance, restore, segment and extract features of images by computer.

The input is image signal, and then after effective algorithm processing by DIP, the output is digital signal.

To compress the Image, we need to read the Image and convert it to a BufferedImage object. BufferedImage is a subclass of the Image class that describes a buffer with accessible Image data, consisting of the Image data of ColorModel and Raster.

Nonsense I don’t say more, directly into the actual combat!

Three, image compression actual combat

It just so happens that I have a local cover image that I’ve used before, 236 kilobytes away from 1M, which I can use as a test.

This is done using the ImageIO class, a static class that provides a set of methods for reading and writing images, as well as simple encoding and decoding of images.

For example, imageio.read () reads an image into a BufferedImage object:

File input = new File("ceshi.jpg");
BufferedImage image = ImageIO.read(input);
Copy the code

For instance by ImageIO. GetImageWritersByFormatName () returns an Iterator, which contains the ImageWriter by naming format for image coding.

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

For instance by ImageIO. CreateImageOutputStream () can create an image of an output stream object, with the object after can through ImageWriter. SetOutput () will be set to the output stream.

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

Next, you can configure ImageWriter parameters such as compression mode, compression quality, and so on.

ImageWriteParam param = writer.getDefaultWriteParam();

param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.01 f);
Copy the code

There are four compression modes. MODE_EXPLICIT is one of them, which means that ImageWriter can tiled and compress based on additional information from subsequent sets, such as the setCompressionQuality() method that follows.

The setCompressionQuality() method takes a number between 0 and 1, with 0.0 indicating maximum compression and 1.0 indicating that image quality is important. For lossy compression schemes, compression quality should control the tradeoff between file size and image quality (for example, by selecting a quantization table when writing a JPEG image). For lossless scenarios, compression quality can be used to control the tradeoff between file size and the time required to perform compression (for example, by optimizing the line filter and setting the ZLIB compression level when writing PNG images).

The overall code is as follows:

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.01 f);

            writer.write(null.new IIOImage(image, null.null), param);

            os.close();
            ios.close();
            writer.dispose();

        } catch(IOException e) { e.printStackTrace(); }}}Copy the code

After compression, you can see that the size of the image is reduced to 19 KB:

It can be seen that the image is already distorted when the quality factor is 0.01F. You can increase the quality factor appropriately, such as 0.5F. Let’s see again.

Image quality has improved significantly, but the size is still only 64 KB and the compression is still reliable.

Other open source libraries

Next, let’s recommend some image processing libraries that can be easily integrated into a project, all of which are free.

1) ImageJ, written in Java, can edit, analyze, process, save and print images.

2) Apache Commons Imaging, a library for reading and writing various image formats, including fast parsing of image information (such as size, color, space, ICC profile, etc.) and metadata.

3) ImageMagick, can read and write images in over 100 formats including DPX, EXR, GIF, JPEG, JPEG-2000, PDF, PNG, Postscript, SVG and TIFF. You can also resize, flip, mirror, rotate, twist, cut and transform images, adjust image colors and apply a variety of special effects, including drawing text, lines, polygons, ellipses and Bezier curves.

4) OpenCV, released under the BSD license, is free to learn and commercially available and provides interfaces to major programming languages including C/C++, Python and Java. OpenCV is designed for computational efficiency with an emphasis on real-time applications that can take full advantage of multi-core processors.

Here to OpenCV as an example, to demonstrate the image compression. Of course, OpenCV is a classic overachiever for compressing images.

The first step is to add OpenCV dependencies to our project, using Maven as an example.

<dependency> <groupId>org. openPNP </groupId> <artifactId>opencv</artifactId> <version>4.5.1-2</version> </dependency>Copy the code

Second, to use OpenCV, you need to initialize it.

OpenCV.loadShared();
Copy the code

Third, use OpenCV to read the image.

Mat src = Imgcodecs.imread(imagePath);
Copy the code

Step 4, use OpenCV to compress the image.

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

The construction parameter of MatOfInt is a variable parameter. The first parameter IMWRITE_JPEG_QUALITY indicates the quality of the image to be changed. The second parameter is the quality factor, 1-100.

After executing the code, the resulting image looks like this:

This is an opportunity to compare the amount of time OpenCV takes to compress images with the JDK’s native APIS.

This is the configuration of my machine. I bought an iMac in the early years and it is also my main machine. I started with 16 GB of ram, and then a 16 GB ram was added, but the frequency of sudden crashes and reboots has increased significantly in the last six months. I don’t know if it’s the Big Sur operating system or the old hardware.

The result is as follows:

OpencvCompress compression completed, runtime: 1070 jdkCompress compression completed, runtime: 322Copy the code

The compressed images are about the same size, all 19 KB, with the lowest quality factor.

Four, a little heart

After the above technical analysis, I’m sure you can see that optimizing from 1M images to 100KB is a “not easy” task…

Isn’t 100 kilobytes small? It’s only 1/10 of what it was.

You know, I worked two days and nights in a row.

Finally, I fell asleep on my computer.

Did not think of the saliva directly to the computer whole short circuit, I this just be from the dream inside frighten wake up!

😔, life is not easy, and line and cherish it ~


This article has been published on GitHub’s 1.6K + Star. It is said that every good Java programmer likes her. It is humorous and easy to understand. The content includes Java foundation, Java concurrent programming, Java virtual machine, Java enterprise development, Java interview and other core knowledge points. Learn Java, look for Java programmers to advance the road 😄.

Github.com/itwanger/to…

Star the repository and you have the potential to become a good Java engineer. Click the link below to jump to the Java Programmer’s Path to Progress website and start your fun learning journey.

tobebetterjavaer.com/

Nothing keeps me here but purpose, and though there are roses by the shore, and trees by the shore, and still harbours, I am not tied.