Java实现把图片处理到指定大小的操作方法

 更新时间:2025年03月11日 09:47:29   作者:laizhenghua  
项目开发中,经常遇到图片上传功能,发现如果图片比较大时,在查看、预览、下载速度会特别慢,考虑到浪费流量以及文件服务器的存储空间,决定在后端优化处理完再上传,所以本文给大家介绍了使用Java把图片处理到指定大小的操作方法,需要的朋友可以参考下

引言

项目开发中,经常遇到图片上传功能,发现如果图片比较大时,在查看、预览、下载速度会特别慢,考虑到浪费流量以及文件服务器的存储空间,决定在后端优化处理完再上传,以减少存储空间与优化传输速率。这里使用Java自带的ImageIO进行处理分享给大家。

1、Java常见的图像处理插件

  • Java自带的ImageIO
  • Google的Thumbnails(实现也相对于比较简单,功能也更加丰富)-- 可自行了解

本文将使用两种工具实现图片的压缩,在保持清晰度的前提下,去减少图片的大小,以达到减少存储空间与提高文件传输速率的目的。

2、图片压缩优化实战

以压缩JPG文件为例,详见下图现有接近40MB的jpg文件。

Google的Thumbnails

1.先引入依赖

<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.20</version>
</dependency>

代码实现

@Test
public void test4() {
    String filePath = "/static/dist.jpg"; // 文件路径
    ClassPathResource resource = new ClassPathResource(filePath);
    InputStream inputStream = null;
    try {
        inputStream = resource.getInputStream();
        int i = 0;
        for (float quality = 0.9f; quality > 0.0f; quality -= 0.1f) {
            String path = StrUtil.format("src/main/resources/static/compression_dist_{}.jpg", ++i);
            File distFile = new File(path);
            Thumbnails.of(inputStream)
                    .scale(quality)
                    .outputQuality(1) // 输出的图片质量
                    .toFile(distFile);
            long length = distFile.length();
            if (length / 1024 <= 5120) { // 压缩至5MB左右
                System.out.println(length / (1024 * 1024) + "MB");
                break;
            }
            if (ObjectUtil.isNull(inputStream) || inputStream.available() == 0) {
                inputStream = new FileInputStream(distFile);
            }
            distFile.delete();
        }
    } catch (IOException ex) {
        log.error(ex.getMessage());
        ex.printStackTrace();
    } finally {
        IoUtil.close(inputStream);
    }
}

Java自带的ImageIO

@Test
public void test() {
    // 1.准备jpg图像编写器
    Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
    ImageWriter writer = writers.next();

    ImageWriteParam writeParam = writer.getDefaultWriteParam();
    writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // 设置压缩模式

    // 2.准备源文件(要压缩的文件)
    String filePath = "/static/dist.jpg"; // 文件路径
    ClassPathResource resource = new ClassPathResource(filePath);

    // 3.指定目标压缩文件大小(这里按KB计算)
    int targetSize = 5120; // 5MB
    try (InputStream inputStream = resource.getInputStream()) {
        int available = inputStream.available();
        // 4.判断源文件大小是否小于目标压缩大小
        if ((available / 1000) <= targetSize) {
            log.error(StrUtil.format("[{}] 文件小于 {}KB 无需压缩!", resource.getFilename(), targetSize));
            return;
        }
        BufferedImage inputImage = ImageIO.read(inputStream);
        // 设定压缩比例(接近目标文件大小)
        for (float quality = 0.95f; quality > 0.0f; quality -= 0.05f) {
            String path = StrUtil.format("src/main/resources/static/compression_dist_{}.jpg", quality);
            File distFile = new File(path);
            // 输出参数
            ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(distFile);
            writer.setOutput(imageOutputStream);

            writeParam.setCompressionQuality(quality); // 设置压缩比例(0-1之间)
            writer.write(null, new IIOImage(inputImage, null, null), writeParam);

            // 是否接近于目标大小
            if (distFile.length() / 1024 <= targetSize) {
                IoUtil.close(imageOutputStream);
                break;
            }
            distFile.delete();
        }
    } catch (IOException ex) {
        log.error(ex.getMessage());
        ex.printStackTrace();
    }

    // IoUtil.close(imageOutputStream);
    writer.dispose();
}

再来看压缩效果(dist.jpg为原文件),可以打开文件进行对比(清晰度基本没啥变化)

到此这篇关于Java实现把图片处理到指定大小的操作方法的文章就介绍到这了,更多相关Java图片指定大小内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中增强for循环代码示例

    Java中增强for循环代码示例

    这篇文章主要给大家介绍了Java中增强for循环的相关资料,for/in循环就是JDK5.0中所谓的增强For循环,它能对数组和集合进行遍历,使用它会使用你的代码短小而精炼的多,需要的朋友可以参考下
    2023-10-10
  • java基于dom4j包实现对XML解析的方法

    java基于dom4j包实现对XML解析的方法

    这篇文章主要介绍了java基于dom4j包实现对XML解析的方法,结合实例形式分析了java针对xml格式数据的相关解析操作实现技巧,需要的朋友可以参考下
    2017-05-05
  • springboot3.x中Jakarta包无法引入的问题

    springboot3.x中Jakarta包无法引入的问题

    最近想将一些项目升级到springboot3.x和java17的时候,发现项目依赖中有Jakarta的包,但是代码标红提示没有相关的类,本文就来介绍一下解决方法,感兴趣的可以了解一下
    2024-02-02
  • 浅谈使用java实现阿里云消息队列简单封装

    浅谈使用java实现阿里云消息队列简单封装

    这篇文章主要介绍了浅谈使用java实现阿里云消息队列简单封装,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • Java BigDecimal类用法详解

    Java BigDecimal类用法详解

    BigDecimal 由任意精度的整数非标度值 和32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负scale 次幂。
    2016-06-06
  • Java中正则表达式的使用和详解(上)

    Java中正则表达式的使用和详解(上)

    这篇文章主要介绍了Java中正则表达式的使用和详解,包括匹配验证验证email是否正确,在字符串中查询字符或者字符串的代码实例,需要的朋友可以参考下
    2017-04-04
  • Springboot整合knife4j与shiro的操作

    Springboot整合knife4j与shiro的操作

    这篇文章主要介绍了Springboot整合knife4j与shiro的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Spring Boot整合mybatis并自动生成mapper和实体实例解析

    Spring Boot整合mybatis并自动生成mapper和实体实例解析

    本文是小编给大家总结的关于Spring Boot整合mybatis并自动生成mapper和实体的内容,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-05-05
  • Mybatis中typeAliases的使用

    Mybatis中typeAliases的使用

    这篇文章主要介绍了Mybatis中typeAliases的使用,需要的朋友可以参考下
    2017-08-08
  • springbean的加载过程及应用场景分析

    springbean的加载过程及应用场景分析

    Bean已经被实例化、属性注入、初始化,并且注册到容器中,可以被其他Bean或应用程序使用,这篇文章主要介绍了springbean的加载过程以及应用场景,需要的朋友可以参考下
    2024-04-04

最新评论