后端java压缩图片超详细图文教程

 更新时间:2024年04月26日 10:56:01   作者:骑鱼过海的猫123  
这篇文章主要给大家介绍了关于后端java压缩图片的相关资料,片压缩是一种广泛采用的技术,它不仅能显著减小文件大小,释放更多存储空间,还能提升图片加载速度,避免长时间等待,需要的朋友可以参考下

1. 图片压缩原理

图片压缩主要分为两种类型:有损压缩和无损压缩

  • 有损压缩:有损压缩通过减少图片中的几余数据来减小图片文件的大小,但会损失定的图片质量。常见的有损压缩算法有JPEG、WebP等。
  • 无损压缩:无损压缩通过优化图片的编码算法来减小图片文件的大小,但不会损失任何图片质量。常见的无损压缩算法有PNG、GIF等
    对于需要压缩至指定大小的需求,我们可以使用有损压缩算法,并通过不断尝试不同的压缩质量来达到目标大小。

2. ImageIO压缩(java原生)

3.thumbnailator

官网地址

3.1引入依赖

<!--图片压缩-->
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.19</version>
        </dependency>

3.2 图片处理步骤

3.3 使用

3.3.1 构建Thumbnails.Builder

要使用thumbnailtor,主要使用Thumbnails类,该类采用建造者模式设计,类中提供了很多返回Builder的静态方法。
正如下图所示,Thumbnails提供了通过字符串图片地址、File对象、URI对象等方式创建Thumbnails对象的方式。

3.3.2 of方法

有5种重载方法

 * =============of方法=============
     * scale 代表缩放
     * toFile是输出图片的方法
     */
    @Test
    public void test() throws IOException {
        //参数是本地文件路径,支持多参数
        Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
                .scale(1D)
                .toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\3.png");
    }

    @Test
    public void test2() throws IOException {
        // File类型的参数,支持多参数
        Thumbnails.of(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png"))
                .scale(1D)
                .toFile(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\4.png"));
    }

    @Test
    public void test3() throws IOException {
        // BufferedImage类型参数
        BufferedImage bufferedImage = ImageIO.read(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png"));
        Thumbnails.of(bufferedImage)
                .scale(1D)
                .toFile(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\5.jpg"));
    }

    @Test
    public void test4() throws IOException {
        // FileInputStream类型
        InputStream inputStream = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png"));
        Thumbnails.of(inputStream)
                .scale(1D)
                .toFile(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\7.jpg"));
    }

    @Test
    public void test5() throws IOException {
        // 网络图片
        URL url = new URL("https://img1.baidu.com/it/u=1546227440,2897989905&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500");
        Thumbnails.of(url)
                .scale(1D)
                .toFile(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\8.jpg"));
    }

3.3.3 fromxxx方法

/**
     * =============fromImages方法。批量处理BufferedImage类型的图片 =============
     * scale 代表缩放
     * toFile是输出图片的方法
     */
    @Test
    public void test8() throws IOException {
        // 参数是本地文件路径,支持多参数
        URL url = new URL("https://lmg.jj20.com/up/allimg/1114/0406210Z024/2104060Z024-5-1200.jpg");
        URL url2 = new URL("https://lmg.jj20.com/up/allimg/4k/s/02/210924233115O14-0-lp.jpg");
        BufferedImage bufferedImage1 = ImageIO.read(url);
        BufferedImage bufferedImage2 = ImageIO.read(url2);

        List<BufferedImage> list = new ArrayList<>();
        list.add(bufferedImage1);
        list.add(bufferedImage2);
        File file = new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\11.png");
        File file2 = new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\22.png");
        List<File> files = new ArrayList<>();
        files.add(file);
        files.add(file2);
        Thumbnails.fromImages(list)
                .scale(1D)
                // 这里必须使用`toFiles`,因为处理的是多图
                .toFiles(files);//Rename.SUFFIX_HYPHEN_THUMBNAIL 这里用这个会报错,注意.
    }

    /**
     * =============fromInputStreams 方法。批量处理InputStream类型的图片。 =============
     * scale 代表缩放
     * toFile是输出图片的方法
     */
    @Test
    public void test9() throws IOException, URISyntaxException {
        // 参数是本地文件路径,支持多参数
        FileInputStream fileInputStream1 = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\11.png"));
        FileInputStream fileInputStream2 = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\22.png"));

        List<InputStream> list = new ArrayList<>();
        list.add(fileInputStream1);
        list.add(fileInputStream2);
        File file = new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\111.png");
        File file2 = new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\222.png");
        List<File> files = new ArrayList<>();
        files.add(file);
        files.add(file2);
        Thumbnails.fromInputStreams(list)
                .scale(1D)
                // 这里必须使用`toFiles`,因为处理的是多图
                .toFiles(files);//Rename.SUFFIX_HYPHEN_THUMBNAIL 这里用这个会报错,注意.
    }

3.3.4 图片尺寸&旋转&水印

图片尺寸控制可以通过width、height,size, forceSize,scale方法控制。

  • 处理的图片必须指定大小,size,width,height,forcesize,scale;不可重复设置同一种类型的属性;有的属性设置会互斥;
  • width、height,size方法会默认保证原始图片比例(可以通过设置keepAspectRatio(false)取消,如果取消则等价于forceSize方法。) 因为收到原始图片宽高比例的限制,即便设置了宽高可能也不会引起图片的尺寸(像素)变化 forceSize则会强制保证宽高,
  • scale是设置图片宽高比例,不大于1的数参数。
  • 有以下异常情况要注意:
    调用width和height方法后不能再使用size或者scale方法,否则会抛出异常。
    调用size方法后不能再使用size,scale方法,否则会抛出异常。
    调用scale方法后不能调用size或keepAspectRatio(boolean) 方法,否则会抛出异常。

3.3.4.1 等比例缩放,控制宽高比(以实际图 宽高相对长度长的为准)

比如原图高大于宽,则 size宽设置失效,否则相反

@Test
    //等比例缩放,
    //源:宽:681,长:563,长宽比:0.8267254038  压缩结果:宽:110,高:91,长宽比:0.8272727273
    public void test10() throws IOException {
        //参数是本地文件路径,支持多参数
        Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
                .size(110, 900)
                .toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\44.png");
    }

3.3.4.2 forceSize方法,强制控制宽高

@Test
    //forceSize方法
    //源:宽:681,长:563,长宽比:0.8267254038  压缩到:宽:50,
    public void test11() throws IOException {
        //参数是本地文件路径,支持多参数
        Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
                .forceSize(50, 50)
                .toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\test11.png");
    }

3.3.4.3 scale方法,宽高压缩比例

@Test
    //scale 方法
    //源:宽:681,长:563,长宽比:0.8267254038  压缩到:宽681/2 ,高563/2,
    public void test12() throws IOException {
        //参数是本地文件路径,支持多参数
        Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
                .scale(0.5)
                .toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\test22.png");
    }

3.3.4.4 rotate方法,控制旋转

@Test
    //rotate 方法
    //源:宽:681,长:563,长宽比:0.8267254038  压缩到:宽681/2 ,高563/2,
    public void test13() throws IOException {
        //参数是本地文件路径,支持多参数
        Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
                .rotate(30) // 旋转30度
                .scale(0.5)
                .toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\test22.png");
    }

3.3.4.5 watermark方法,添加水印

@Test
    //watermark 方法
    public void test14() throws IOException {
        //参数是本地文件路径,支持多参数
        Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
                // 水印放到右下角
                .watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\watermark.jpg")), 0.5f)
                .scale(1D)
                .toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\test14.png");
    }

3.3.5 输出格式&输出质量

outputFormat控制输出格式
outputQuality(float quality)设置输出质量,参数介于0和1之间,支持小数,数字越小质量越差

 @Test
    /**
     * outputFormat 方法
     * outputFormat(String format)方法用于设置输出文件格式。支持的格式可以通过ImageIO.getWriterFormatNames()获取。
     * 常用: JPG jpg tiff bmp BMP gif GIF WBMP png PNG JPEG tif TIF TIFF jpeg wbmp。
     *
     * outputQuality(float quality)设置输出质量,参数介于0和1之间,支持小数,数字越小质量越差。
     */
    public void test15() throws IOException {
        //参数是本地文件路径,支持多参数
        Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
                // 如果不设置默认跟原图片一致
                .outputFormat("jpg")
                // 设置质量 0.1F-1F之间
                .outputQuality(0.1F)
                .scale(1D)
                .toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\test15");
    }

3.3.6 输出

3.3.6.1 输出到文件

toFile方法,将处理后的文件输出到指定文件,参数是文件路径,不是必须要指定文件后缀。
toFile要求文件读入的时候必须是单个源,例如如果是Thumbnails.of(“input/logo.jpg”,“input/logo2.jpg”),使用toFile输出会抛出异常。

  • 输出多文件
    批量接入的文件处理完毕后,可以通过toFiles输出到指定目录下。

public void toFiles(File destinationDir, Rename rename) throws IOException // ①
public void toFiles(Rename rename) throws IOException // ②
public void toFiles(Iterable iterable) throws IOException { // ③

/**
     * public void toFiles(File destinationDir, Rename rename) throws IOException // **********只有file类型输入才可以用************
     *  第一个参数是文件夹路径,第二个参数是文件名处理类型
     *  NO_CHANGE:文件名不修改。
     *  PREFIX_DOT_THUMBNAIL:追加 thumbnail.到文件名的开头。例如,给定 picture.jpg,结果为thumbnail.picture.jpg。
     *  SUFFIX_DOT_THUMBNAIL:.thumbnail追加到文件扩展名之前的文件名。例如,给定 picture.jpg,结果为 picture.thumbnail.jpg
     *  SUFFIX_HYPHEN_THUMBNAIL:-thumbnail追加到文件扩展名之前的文件名。例如,给定 picture.jpg,结果为 picture-thumbnail.jpg。
     *
     *
     * public void toFiles(Rename rename) throws IOException // ②
     *  此方法是①的简化,等价于①中的第一个参数destinationDir为空。
     *
     * public void toFiles(Iterable<File> iterable) throws IOException { // ③
     *  参数是Iterable类型,也就是说可以给每个文件设置输出文件名。
     */

3.3.6.1 输出到单个输出流&多输出流

@Test
    //输出到多输出流
    public void toOutPUtStreamTest2() throws IOException {
        OutputStream os = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\新建文件夹\\55.png");
        OutputStream os2 = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\新建文件夹\\66.png");
        List<OutputStream> list=new ArrayList<>();
        list.add(os);
        list.add(os2);
        Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
                .scale(1D)
                .toOutputStreams(list);
    }

toFiles有三种多态方法

3.3.7 allowOverwrite 覆盖文件

默认为true,如果文件存在,则覆盖
可设置 allowOverwrite=false,文件存在,则报错

3.3.8 输出到内存输出流(操作内存)

ByteArrayOutputStream
ByteArrayInputStream

@Test
    //输出到内存输出流
    public void toOutPUtStreamTest3() throws IOException {
        ByteArrayOutputStream os = new ByteArrayOutputStream();//内存输出流
        Thumbnails.of("F:\\company2\\浙江\\02-需求开发\\23年12月\\图片附件上传问题\\2.jpg")
                .scale(1D)
                .toOutputStream(os);
//        os.writeTo(new FileOutputStream(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\66.png")));//直接输出
        ByteArrayInputStream inputStream = new ByteArrayInputStream(os.toByteArray());//转化为内存输入流
        Thumbnails.of(inputStream)
                .size(200,220)
                .outputQuality(1D)
                .toFile("F:\\company2\\浙江\\02-需求开发\\23年12月\\图片附件上传问题\\99");
    }

总结 

到此这篇关于后端java压缩图片的文章就介绍到这了,更多相关java压缩图片内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java插件扩展机制之SPI案例讲解

    Java插件扩展机制之SPI案例讲解

    这篇文章主要介绍了Java插件扩展机制之SPI案例讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • 玩转SpringBoot2快速整合拦截器的方法

    玩转SpringBoot2快速整合拦截器的方法

    这篇文章主要介绍了玩转SpringBoot2快速整合拦截器的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • java集合框架的体系结构详细说明

    java集合框架的体系结构详细说明

    最近在一本J2EE的书中看到了很不错的对集合框架的说明文章
    2012-11-11
  • Idea中Java项目如何修改项目名

    Idea中Java项目如何修改项目名

    这篇文章主要介绍了Idea中Java项目如何修改项目名问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • mybatis Invalid bound statement(not found)排坑记录

    mybatis Invalid bound statement(not foun

    这篇文章主要介绍了mybatis Invalid bound statement(not found)排坑记录,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 使用maven自定义插件开发

    使用maven自定义插件开发

    这篇文章主要介绍了使用maven自定义插件开发,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • 一文详解Java中的可变对象(Mutable)与不可变对象(Immutable)

    一文详解Java中的可变对象(Mutable)与不可变对象(Immutable)

    如何在 Java 中创建不可变对象?我以前以为所有对象都是不可变的,因为如果你改变一个 String 实例的内容,它总是会创建一个新的 String 对象并指向该对象,在本文中,我不仅将分享在 Java 中Immutable的步骤,还将讨论可变对象与不可变对象及其优缺点
    2023-11-11
  • Java获取两个集合List的交集、补集、并集(相加)和差集(相减)的不同方式

    Java获取两个集合List的交集、补集、并集(相加)和差集(相减)的不同方式

    这篇文章主要给大家介绍了关于Java获取两个集合List的交集、补集、并集(相加)和差集(相减)的不同方式,在一般操作中对于list集合取交集、差集、并集,比较简单,需要的朋友可以参考下
    2023-08-08
  • Java单例模式简单介绍

    Java单例模式简单介绍

    这篇文章主要为大家详细介绍了Java单例模式简单的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • 一文带你彻底了解Java8中的Lambda,函数式接口和Stream

    一文带你彻底了解Java8中的Lambda,函数式接口和Stream

    这篇文章主要为大家详细介绍了解Java8中的Lambda,函数式接口和Stream的用法和原理,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-08-08

最新评论