SpringBoot压缩png, jpg, jpeg, webp类型图片的实现代码

 更新时间:2024年08月26日 09:22:54   作者:三过食堂而不入  
这篇文章主要介绍了SpringBoot压缩png, jpg, jpeg, webp类型图片的实现,文中通过代码示例和图文结合的方式给大家讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下

1.需求

业务要求对png, jpg, jpeg, webp 格式图片进行等比例压缩

2.开发中遇到的问题

使用 Thumbnails 包, 发现只能压缩 jpg 和 jpeg , 不能压缩webp
接着找到了 webp-imageio 解决webp , 又发现 这俩都不支持 png ,
接着找到了 OpenViewerFX 去处理png…

3. 实现代码

3.1 pom 引用

  <!--压缩png-->
        <dependency>
            <groupId>org.jpedal</groupId>
            <artifactId>OpenViewerFX</artifactId>
            <version>6.6.14</version>
        </dependency>

        <!-- Thumbnailator: 图片缩放和压缩工具 -->
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.14</version>
        </dependency>

        <!-- TwelveMonkeys: 支持更多图片格式 -->
        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-core</artifactId>
            <version>3.9.4</version>
        </dependency>
        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-jpeg</artifactId>
            <version>3.9.4</version>
        </dependency>
        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-webp</artifactId>
            <version>3.9.4</version>
        </dependency>

        <!--压缩webp-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-imaging</artifactId>
            <version>1.0-alpha1</version>
        </dependency>
        <dependency>
            <groupId>org.sejda.imageio</groupId>
            <artifactId>webp-imageio</artifactId>
            <version>0.1.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.imgscalr/imgscalr-lib -->
        <dependency>
            <groupId>org.imgscalr</groupId>
            <artifactId>imgscalr-lib</artifactId>
            <version>4.2</version>
        </dependency>

3.2 controller 代码

我这里自己定死了生产图片文件夹的路径 , 各位大神按照自己实际的需求改动

package com.example.controller;

import com.example.service.ImageCompressionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;

/**
 * @ClassName: ImageCompressionController
 * @Description: TODO
 * @Author: 赵狗
 * @Date: 2024/8/23 15:04
 */
@RequestMapping("/imageApi")
@RestController
public class ImageCompressionController {
    @Autowired
    private ImageCompressionService imageCompressionService;

    /**
     * 图片压缩方法
     * @param file
     * @param quality
     * @return
     * @throws IOException
     */
    @PostMapping("/compressBySize")
    public String compressImageBySize(@RequestParam("file") MultipartFile file,
                                      @RequestParam("quality") String quality
                                      ) throws IOException {

        String outputPath = "F:\\images\\" + "compressed_size_" + file.getOriginalFilename();

        File outputFile = new File(outputPath);
        prepareOutputDirectory(outputFile);
        File inputFile = convertMultipartFileToFile(file);
        // 将quality转为 float
        float qualityFloat = Float.parseFloat(quality);

        imageCompressionService.compressImageBySize(inputFile, outputFile,qualityFloat);

        inputFile.delete();

        return "File compressed successfully by size: " + outputFile.getAbsolutePath();
    }

    /**
     * 判断文件夹是否存在, 如果没有则创建
     * @param outputFile
     */
    private void prepareOutputDirectory(File outputFile) {
        if (!outputFile.getParentFile().exists()) {
            outputFile.getParentFile().mkdirs();
        }
    }

    /**
     * 将MultipartFile转换为File
     * @param file
     * @return
     * @throws IOException
     */
    private File convertMultipartFileToFile(MultipartFile file) throws IOException {
        File convFile = new File(System.getProperty("java.io.tmpdir") + "/" + file.getOriginalFilename());
        file.transferTo(convFile);
        return convFile;
    }

    public boolean isWebPSupported() {
        Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("webp");
        return readers.hasNext();
    }

}

3.3 Service 代码

package com.example.service;

import com.idrsolutions.image.png.PngCompressor;
import com.luciad.imageio.webp.WebPWriteParam;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.stereotype.Service;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;

/**
 * @ClassName: ImageCompressionService
 * @Description: TODO
 * @Author: 赵狗
 * @Date: 2024/8/23 15:03
 */
@Service
public class ImageCompressionService {

    private static final int DEFAULT_QUALITY = 80; // 默认压缩质量为 80

    /**
     * 压缩图片方法
     * @param inputFile
     * @param outputFile
     * @param quality
     * @throws IOException
     */
    public void compressImageBySize(File inputFile, File outputFile, float quality) throws IOException {

        // 根据输入文件的后缀名获取文件格式
        String formatName = getFileExtension(inputFile);

        // 根据不同的文件格式,调用相应的压缩方法
        if ("webp".equalsIgnoreCase(formatName)) {
            // 对webp格式的图片进行压缩
            compressWebpImage(inputFile,outputFile,quality);
        } else if("png".equalsIgnoreCase(formatName)){
            // 对png格式的图片进行压缩
            compressPngImage(inputFile, outputFile);
        } else {
            // 对jpg或其他格式的图片进行压缩,这里假设jpg的压缩方法与其他格式不同
            compressJpgImage(inputFile, outputFile, quality, formatName);
        }
    }

    /**
     * 压缩jpg 以及 jpeg 格式的图片方法
     * @param inputFile
     * @param outputFile
     * @param quality
     * @param formatName
     * @throws IOException
     */
    private void compressJpgImage(File inputFile, File outputFile, float quality, String formatName) throws IOException {
        // 压缩jpg 以及 jpeg 格式的图片
        Thumbnails.of(inputFile)
                .scale(1) // 明确告诉库不需要改变图片尺寸
                .outputQuality(quality) // 设置输出图片的质量
                .outputFormat(formatName) // 保持原有格式
                .toFile(outputFile);
    }

    /**
     * 压缩png格式图片方法
     * @param inputFile
     * @param outputFile
     * @throws IOException
     */
    private void compressPngImage(File inputFile, File outputFile) throws IOException {
        PngCompressor.compress(inputFile, outputFile);
    }

    /**
     * 压缩webp格式图片方法
     * @param inputFile
     * @param outputFile
     * @param quality
     * @throws IOException
     */
    public  void compressWebpImage(File inputFile, File outputFile, float quality) throws IOException {
        // 读取输入的WebP图像
        BufferedImage image = ImageIO.read(inputFile);

        // 获取WebP格式的ImageWriter
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("webp");
        if (!writers.hasNext()) {
            throw new IllegalStateException("No WebP writer found");
        }
        ImageWriter writer = writers.next();

        // 设置输出流
        try (ImageOutputStream ios = ImageIO.createImageOutputStream(outputFile)) {
            writer.setOutput(ios);

            // 设置压缩参数
            WebPWriteParam writeParam = (WebPWriteParam) writer.getDefaultWriteParam();
            writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            writeParam.setCompressionType("Lossy");
            writeParam.setCompressionQuality(quality); // 设置压缩质量,值范围 0.0 ~ 1.0
            // 写出压缩后的WebP图像
            writer.write(null, new IIOImage(image, null, null), writeParam);
        } finally {
            writer.dispose();
        }
    }

    /**
     * 获取图片类型方法
     * @param file
     * @return
     */
    private String getFileExtension(File file) {
        String name = file.getName();
        return name.substring(name.lastIndexOf('.') + 1).toLowerCase();
    }
}

3.4 apifox 调用

在这里插入图片描述

3.5 效果图

3.5.1 压缩前:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.5.2 压缩后

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

以上就是SpringBoot压缩png, jpg, jpeg, webp类型图片的实现代码的详细内容,更多关于SpringBoot压缩图片的资料请关注脚本之家其它相关文章!

相关文章

  • 手把手带你分析SpringBoot自动装配完成了Ribbon哪些核心操作

    手把手带你分析SpringBoot自动装配完成了Ribbon哪些核心操作

    这篇文章主要介绍了详解Spring Boot自动装配Ribbon哪些核心操作的哪些操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-08-08
  • SpringBoot中获取配置文件的注解详解

    SpringBoot中获取配置文件的注解详解

    这篇文章主要介绍了SpringBoot中获取配置文件的注解详解, 一般情况下:如果我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value,如果我们使用JavaBean来与配置文件进行映射,我们直接使用@ConfigurationProperties,需要的朋友可以参考下
    2023-10-10
  • 详解Java sort()数组排序(升序和降序)

    详解Java sort()数组排序(升序和降序)

    这篇文章主要介绍了详解Java sort()数组排序(升序和降序),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • java高并发写入用户信息到数据库的几种方法

    java高并发写入用户信息到数据库的几种方法

    本文主要介绍了java高并发写入用户信息到数据库的几种方法,具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • Quartz之Job与JobDetail深入解析

    Quartz之Job与JobDetail深入解析

    下面小编就为大家带来一篇Quartz之Job与JobDetail深入解析。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • java实现简易版图形界面计算器

    java实现简易版图形界面计算器

    这篇文章主要为大家详细介绍了java实现简易版图形界面计算器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • Java中常用的设计模式之建造者模式详解

    Java中常用的设计模式之建造者模式详解

    这篇文章主要为大家详细介绍了Java中常用的设计模式之建造者模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • spring异步service中处理线程数限制详解

    spring异步service中处理线程数限制详解

    这篇文章主要给大家介绍了关于spring异步service中处理线程数限制的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用spring具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • 关于spring依赖注入的方式以及优缺点

    关于spring依赖注入的方式以及优缺点

    这篇文章主要介绍了关于spring依赖注入的方式以及优缺点,依赖注入,是IOC的一个方面,是个通常的概念,它有多种解释,这概念是说你不用创建对象,而只需要描述它如何被创建,需要的朋友可以参考下
    2023-07-07
  • Springboot线程池并发处理数据优化方式

    Springboot线程池并发处理数据优化方式

    这篇文章主要介绍了Springboot线程池并发处理数据优化方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12

最新评论