“This is my fourth day of participating in the First Challenge 2022. For more details: First Challenge 2022.”

The article brief introduction

Sometimes, our project needs to generate small thumbnails of business pictures, or transcode the picture format, what method will we use?

Use object storage directly and hand over business requirements to third parties? Or do you use javaScript to manipulate images?

Have you tried back-end direct processing?

In this article, you will learn how to use Java to gracefully process images. Including: mainstream image format transcoding, image compression (thumbnail generation), image attached watermark, etc. Main external toolkits used:

  • Thumbnailator: The old thumbnail generating tool.
  • Webp-imageio-core: Enables Java to support webP reading and writing.

If you want to support more images, you can extend the Java Image IO stream, but more on that later…

Video tutorial

I simply recorded a video, which can be transferred to station B if necessary:

6 minutes Learn how to use Java “hardcore” compression and Transcoding of images – image transcoding and thumbnail generation

Image transcoding/generate thumbnail

The principle of

The Thumbnailator package used this time is actually a encapsulated class and method, which is implemented based on Java Image I/O API, Java 2D API and other API interfaces.

So, based on the Java Image I/O API, the supported Image formats are limited, but they are sufficient for most cases. The supported formats are as follows:

  • Read: JPEG 2000, JPG, tiff, bmp, PCX, gif, WBMP, PNG, RAW, JPEG, PNM, tif, TIFF, wbmp, jpeg, jbig2, jpg, JPEG2000, BMP, pcx, GIF, png, raw, JBIG2, pnm, TIF, jpeg2000, jpeg 2000
  • Write: JPEG 2000, JPG, tiff, bmp, PCX, gif, WBMP, PNG, RAW, JPEG, PNM, tif, TIFF, wbmp, jpeg, jpg, JPEG2000, BMP, pcx, GIF, png, raw, pnm, TIF, jpeg2000, jpeg 2000

Many of the authors of this article introduced the package and said it supports Apple’s HEIC format, which definitely does not support Thumbnailator processing. Unless you can write a transcoder directly. But in this case, I think it’s better to call ImageMagick. I’ll have a chance to share that later.

How to install

If you are a Maven-managed project, or use Maven-managed projects, add dependencies:

< the dependency > < groupId > net. Coobird < / groupId > < artifactId > thumbnailator < / artifactId > < version > [0.4, < / version 0.5) > < / dependency >Copy the code

The dependency definition above is in the range of getting version 0.4.xThumbnailatorThe latest available version of. If you need a specific version of the Thumbnailator, replace [0.4, 0.5) with a specific version number, such as 0.4.13Alternatively, if the download is too slow, you can switch from Maven to a domestic download source (e.g.Ali Maven mirror source)

If you are not a Maven project, you can download the latest version of Thumbnailator. How to manually add a lib package to the latest version of Thumbnailator: github.com/coobird/thu…

How to use

Thumbnailator is easy to use. You need to use Java’s Image I/O API, BufferedImages, and Graphics2D to process images. Simple usage demo:

Thumbnails.of(new File("path/to/directory").listFiles())
    .size(640, 480)
    .outputFormat("jpg")
    .toFiles(Rename.PREFIX_DOT_THUMBNAIL);
Copy the code
  • Original picture address:path/to/directory
  • Output image size:640 * 480
  • Output picture format:jpg
  • IO stream output address (output picture) :Rename.PREFIX_DOT_THUMBNAIL

Pictures of transcoding

Demo code:

Thumbnails.of(originalImage).scale(scale)
        .outputFormat("jpg")
        .outputQuality(compression)
        .toFile(thumbnailImage);
Copy the code

Among them:

  • scaleIs the picture size equal scale, isfloatType.
  • outputFormatIs the type of output image. Note: This is not supported by defaultwebp, if requiredwebp, need to be installed in advancewebp-imageio-core, you can see below how to make Java supportWebp.
  • outputQualityIs the quality of the output picture, i. e. sharpness/resolution.

Use the original image to generate thumbnails

Demo code:

Thumbnails.of(new File("original.jpg"))
        .size(160, 160)
        .toFile(new File("thumbnail.jpg"));
Copy the code

Where, the original image file, can use the String String instead of the address:

Thumbnails.of("original.jpg")
        .size(160, 160)
        .toFile("thumbnail.jpg");
Copy the code

Usually, thumbnail output is already small, but you can still use.outputQualit to reduce image quality (resolution).

Rotating images

Very simple; Add.rotate. Such as:

Thumbnails.of(new File("original.jpg"))
        .rotate(90)
        .toFile(new File("image-with-watermark.jpg"));
Copy the code

Add a watermark

Adding a watermark is also very easy. Add.watermark.

Thumbnails.of(new File("original.jpg")) .watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File("watermark.png")), 0.5 f). ToFile (new File (" image - with - watermark. JPG "));Copy the code

Field demonstration

I use on my website the above packages, set up an online demo address: tool. Mintimate. Cn/processIMG

Function: after the user uploads the picture, the system has the user’s choice of output format, transcoding the picture.

Extension judgment

The front end sends the picture to the background, and the background can judge the file extension:

String thumbnailImageName=originalImage.getName(); // Thumbnail output name String thumbnailImagePath; Switch (format){case "JPG": thumbnailImagePath=System.getProperty("user.dir") + "/file/Output/" + thumbnailImageName.substring(0,thumbnailImageName.lastIndexOf("."))+".jpg"; break; case "PNG": thumbnailImagePath=System.getProperty("user.dir") + "/file/Output/" + thumbnailImageName.substring(0,thumbnailImageName.lastIndexOf("."))+".png"; break; case "WEBP": thumbnailImagePath=System.getProperty("user.dir") + "/file/Output/" + thumbnailImageName.substring(0,thumbnailImageName.lastIndexOf("."))+".webp"; break; case "BMP": thumbnailImagePath=System.getProperty("user.dir") + "/file/Output/" + thumbnailImageName.substring(0,thumbnailImageName.lastIndexOf("."))+".bmp"; break; default: thumbnailImagePath=System.getProperty("user.dir") + "/file/Output/" + thumbnailImageName; break; }Copy the code

Create a blank thumbnail file

Thumbnailator can create file objects directly from String automatically, but for our own control we’ll create them manually:

File thumbnailImage = new File(thumbnailImagePath);
        // Check whether the path exists and create it if it does not
        if(! thumbnailImage.getParentFile().exists()) { thumbnailImage.getParentFile().mkdirs(); }Copy the code

Transcoding pictures

try {
            switch (format){
                case "JPG":
                    Thumbnails.of(originalImage).scale(scale)
                            .addFilter(new ThumbnailsImgFilter())
                            .outputFormat("jpg")
                            .outputQuality(compression)
                            .toFile(thumbnailImage);
                    break;
                case "PNG":
                    Thumbnails.of(originalImage).scale(scale)
                            .outputFormat("png")
                            .outputQuality(compression)
                            .toFile(thumbnailImage);
                    break;
                case "WEBP":
                    Thumbnails.of(originalImage).scale(scale)
                            .imageType(ThumbnailParameter.DEFAULT_IMAGE_TYPE)
                            .outputFormat("webp")
                            .outputQuality(compression)
                            .toFile(thumbnailImage);
                    break;
                case "BMP":
                    Thumbnails.of(originalImage).scale(scale)
                            .addFilter(new ThumbnailsImgFilter())
                            .outputFormat("bmp")
                            .outputQuality(compression)
                            .toFile(thumbnailImage);
                    break;
                default:
                    Thumbnails.of(originalImage).scale(scale)
                            .imageType(ThumbnailParameter.DEFAULT_IMAGE_TYPE)
                            .outputQuality(compression)
                            .toFile(thumbnailImage);
                    break; }}catch (IOException e) {
            e.printStackTrace();
        }
Copy the code

Since I was using Springboot for a quick build, I actually created a configuration rule called addFilter that renders a transparent PNG image white when it turns into a JPG. (Just to look good…) . Implementation details:

import net.coobird.thumbnailator.filters.ImageFilter;

import java.awt.*;
import java.awt.image.BufferedImage;

public class ThumbnailsImgFilter implements ImageFilter {
    @Override
    public BufferedImage apply(BufferedImage bufferedImage) {
        int w = bufferedImage.getWidth();
        int h = bufferedImage.getHeight();
        BufferedImage newImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphic = newImage.createGraphics();
        graphic.setColor(Color.white);// Set the background to white
        graphic.fillRect(0.0, w, h);
        graphic.drawRenderedImage(bufferedImage, null);
        graphic.dispose();
        returnnewImage; }}Copy the code

In this way, you can successfully transcode the image (properly, can also compress the image (; ´ Д `)) :The left is the original picture, and the right is the transcoding picture. This is the size of the case, the picture quality becomes 80% of the original; The main file size is smaller, brought about by the Webp format. Below we introduce Java transcoding Webp format.

Java handles the Webp format

What is Webp format

According to Wikipedia: WebP (pronounced: Weppy] is a kind of image file format that provides lossless compression and lossless compression (reversible compression) at the same time, derived from image encoding format, is considered to be the sister project of WebM multimedia format, is developed by Google in the purchase of On2 Technologies, released under the TERMS of BSD license. The advantages of Webp are obvious:

  • Better image data compression algorithm
  • Smaller picture volume
  • Naked eye recognition of undifferentiated image quality
  • Lossless and lossy compression modes
  • Alpha transparency and animation features

Simply put, it can be like PNG format, preserve lossless image quality, and keep the image transparent characteristics; At the same time, the image can be compressed like JPG. Webp, in the same case, has a smaller file size than PNG, and even smaller than JPG.

Webp format is supported

Because Webp was actually developed by Google, Java IO streams were not designed to support the Webp format.

There are many ways for Java IO streams to support Webp, but here is one that has the opportunity to accept more

Depending on the system, you need to install the following dependency packages:

/natives /linux_32 libxxx[-vvv].so /linux_64 libxxx[-vvv].so /osx_32 libxxx[-vvv].dylib /osx_64 libxxx[-vvv].dylib /osx_arm64 libxxx[-vvv].dylib /windows_32 xxx[-vvv].dll /windows_64 xxx[-vvv].dll /aix_32 libxxx[-vvv].so libxxx[-vvv].a  /aix_64 libxxx[-vvv].so libxxx[-vvv].aCopy the code

For reference: github.com/scijava/nat… You can also use webp-imageio-core. Here’s how to use it.

Webp imageio – core is used

Since webp-Imageio-core is not published in the Maven central repository, you need to add your own lib dependencies to the webp-Imageio-core jar package. The jar package can be downloaded at github.com/nintha/webp… Next add a custom

:

<dependency>  
    <groupId>com.github.nintha</groupId>  
    <artifactId>webp-imageio-core</artifactId>  
    <version>{version}</version>  
    <scope>system</scope>  
    <systemPath>${pom.basedir}/libs/webp-imageio-core-{version}.jar</systemPath>  
</dependency>
Copy the code

For example: my project, add locallib: At this point, Java already supports processingWebpFormat the picture.

Field use

The simplest use… By adding the Thumbnailator dependencies mentioned above, you can use the Thumbnailator to process the IMAGE IO stream directly. Used alone, we can handle it in the most traditional way: image to WEBP:

public static void main(String args[]){
        String srcFile = System.getProperty("user.dir") + "/file/Input/"+"Input.png" // The original address
        String webpFile = System.getProperty("user.dir") + "/file/Output/"+"Output.png" // Output address
        encodingToWebp(srcFile, webpFile);
    }
    
    public static void encodingToWebp(String srcFile, String webpFile) {
        encodingToWebp(new File(srcFile),new File(webpFile) );
    }
 
    / * * *@param: srcFile
     * @param: webpFile
     * @description: Encode the file in WEBP format *@author: Mintimate
     */
    public static void encodingToWebp(File srcFile, File webpFile) {
 
        try {
 
            // Obtain an image to encode from somewhere
            BufferedImage image = ImageIO.read(srcFile);
 
            // Obtain a WebP ImageWriter instance
            ImageWriter writer = ImageIO.getImageWritersByMIMEType("image/webp").next();
 
            // Configure encoding parameters
            WebPWriteParam writeParam = new WebPWriteParam(writer.getLocale());
            writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            writeParam.setCompressionType(writeParam.getCompressionTypes()[WebPWriteParam.LOSSLESS_COMPRESSION]);
 
            // Configure the output on the ImageWriter
            writer.setOutput(new FileImageOutputStream(webpFile));
 
            // Encode
            writer.write(null.new IIOImage(image, null.null), writeParam);
 
 
            / / release of the reader
            writer.dispose();
 
            // Close the file stream
            fileImageOutputStream.close();
        } catch(IOException e) { e.printStackTrace(); }}Copy the code

The last

At this point, you can use your Thumbnailator to gracefully process your image.

However, you will find that in some cases the image processing (jpeg image processing) will be red, the processing method is very simple, you can use BufferedImage to write and read the image, so that the image will not be red or pink distortion.

There is an opportunity to accept other Java Image IO extensions to allow Java projects to support more image formats.