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压缩图片的资料请关注脚本之家其它相关文章!

相关文章

  • Spring Cloud Gateway组件的三种使用方式实例详解

    Spring Cloud Gateway组件的三种使用方式实例详解

    Spring Cloud Gateway是 Spring 官方基于 Spring5.0 、 SpringBoot2.0 和 Project Reactor 等技术开发的网关旨在为微服务框架提供一种简单而有效的统一的API 路由管理方式,统一访问接口,这篇文章主要介绍了Spring Cloud Gateway组件的三种使用方式,需要的朋友可以参考下
    2024-01-01
  • Java泛型的简单实例

    Java泛型的简单实例

    这篇文章介绍了Java泛型的简单实例,有需要的朋友可以参考一下
    2013-10-10
  • MyBatis-Plus输出完整SQL(带参数)的三种方案

    MyBatis-Plus输出完整SQL(带参数)的三种方案

    当我们使用 mybatis-plus 时,可能会遇到SQL 不能直接执行,调试也不方便的情况,那么,如何打印完整 SQL(带参数)呢?本篇文章将介绍 3 种实现方式,并对比它们的优缺点,需要的朋友可以参考下
    2025-02-02
  • Java使用I/O流读取文件内容的方法详解

    Java使用I/O流读取文件内容的方法详解

    这篇文章主要介绍了Java使用I/O流读取文件内容的方法,结合实例形式详细分析了java使用I/O流读取文件常见操作技巧,需要的朋友可以参考下
    2019-11-11
  • 浅谈java实现背包算法(0-1背包问题)

    浅谈java实现背包算法(0-1背包问题)

    本篇文章主要介绍了浅谈java实现背包算法(0-1背包问题) ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • SpringBoot实现登录拦截器的方法详解

    SpringBoot实现登录拦截器的方法详解

    其实spring boot拦截器的配置方式和springMVC差不多,只有一些小的改变需要注意下就ok了。本文主要给大家介绍了关于如何在Springboot实现登陆拦截器功能,需要的朋友可以参考下
    2022-07-07
  • 浅谈java泛型的作用及其基本概念

    浅谈java泛型的作用及其基本概念

    下面小编就为大家带来一篇浅谈java泛型的作用及其基本概念。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • SpringBoot自动装配之@Import深入讲解

    SpringBoot自动装配之@Import深入讲解

    由于最近的项目需求,需要在把配置类导入到容器中,通过查询,使用@Import注解就能实现这个功能,@Import注解能够帮我们吧普通配置类(定义为Bean的类)导入到IOC容器中
    2023-01-01
  • SpringBoot中@EnableAutoConfiguration和@Configuration的区别

    SpringBoot中@EnableAutoConfiguration和@Configuration的区别

    这篇文章主要介绍了SpringBoot中@EnableAutoConfiguration和@Configuration的区别,@SpringBootApplication相当于@EnableAutoConfiguration,@ComponentScan,@Configuration三者的集合,需要的朋友可以参考下
    2023-08-08
  • 浅析Java进制转换、输入、命名问题

    浅析Java进制转换、输入、命名问题

    这篇文章主要介绍了Java进制转换、输入、命名问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07

最新评论