前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何使用Java快速地给图片转码和生成缩略图(Thumbnailator和webp-imageio-core的使用)

如何使用Java快速地给图片转码和生成缩略图(Thumbnailator和webp-imageio-core的使用)

原创
作者头像
Mintimate
修改2021-07-06 12:07:55
7.6K1
修改2021-07-06 12:07:55
举报
文章被收录于专栏:Mintimate's Blog

文章简介

本文中介绍,如何使用Java优雅处理图片;包括:主流图片格式转码、图片压缩(缩略图生成)等。主要用到的外部工具包:

本文对应博客图文( ´▽`):https://www.mintimate.cn/2021/01/19/JavaDealWithImage

在线演示

搭建了一个在线演示地址:https://image.mintimate.cn/

视频教程

和以前一样,我们觉得有用、有必要录个视频的内容,我们还是会花时间做个视频:

B站视频:视频原链接,望投币嗷:https://www.bilibili.com/video/BV1nT4y1K7E6

腾讯云社区视频:视频链接地址,望点赞嗷:https://cloud.tencent.com/developer/video/10496

图片转码/生成缩略图

原理

本次博客使用的Thumbnailator包,实际上是封装好的类和方法,基于Java的Image I/O APIJava 2D API等API接口实现。所以,因为基于Java Image I/O API,所以支持的图片格式有限,但是已经满足绝大多数情况。

一般支持的格式如下:

  • 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

所以,像Apple的HEIC格式,是不支持使用Thumbnailator进行处理的。

如何安装

首先添加lib包,如果你是Maven工程,或者使用Maven管理的项目,添加依赖:

代码语言:txt
复制
<dependency>
  <groupId>net.coobird</groupId>
  <artifactId>thumbnailator</artifactId>
  <version>[0.4, 0.5)</version>
</dependency>

上面的依赖项定义是获取0.4.x版本范围内的Thumbnailator的最新可用版本。如果需要特定版本的Thumbnailator,则将[0.4,0.5)替换为特定版本号,例如0.4.13

Maven内添加依赖
Maven内添加依赖

另外,如果下载太慢,可以把Maven换成国内下载源(比如:阿里Maven镜像源

如果你不是Maven工程,可以下载Thumbnailator的最新版本,如何手动添加lib包,最新版本Thumbnailator下载:https://github.com/coobird/thumbnailator/releases/latest

如何使用

Thumbnailator的使用十分简单,原本你需要使用Java的Image I/O APIBufferedImagesGraphics2D来处理图片,Thumbnailator直接封装上述操作。简单的使用演示:

代码语言:txt
复制
Thumbnails.of(new File("path/to/directory").listFiles())
    .size(640, 480)
    .outputFormat("jpg")
    .toFiles(Rename.PREFIX_DOT_THUMBNAIL);
  • 原图片地址:path/to/directory
  • 输出图片大小:640*480
  • 输出图片格式:jpg
  • IO流输出地址(输出图片):Rename.PREFIX_DOT_THUMBNAIL

图片转码

演示代码:

代码语言:txt
复制
Thumbnails.of(originalImage).scale(scale)
        .outputFormat("jpg")
        .outputQuality(compression)
        .toFile(thumbnailImage);

其中:

  • scale是图片尺寸等比缩放,为float类型。
  • outputFormat是输出图片的类型,注意:默认不支持webp,如果需要使用webp,需要提前安装webp-imageio-core,可以看看下文如何使Java支持Webp
  • outputQuality是输出图片的质量,即:清晰度/分辨率。

使用原图片生成缩略图

演示代码:

代码语言:txt
复制
Thumbnails.of(new File("original.jpg"))
        .size(160, 160)
        .toFile(new File("thumbnail.jpg"));

其中,原图片文件,可以使用字符串String来代替地址:

代码语言:txt
复制
Thumbnails.of("original.jpg")
        .size(160, 160)
        .toFile("thumbnail.jpg");

通常,缩略图输出体积已经很小,但是还是可以使用.outputQualit来降低图片质量(分辨率)。

旋转图片

很简单;添加.rotate即可。如:

代码语言:txt
复制
Thumbnails.of(new File("original.jpg"))
        .rotate(90)
        .toFile(new File("image-with-watermark.jpg"));

添加水印

添加水印也十分简单,添加.watermark即可:

代码语言:txt
复制
Thumbnails.of(new File("original.jpg"))
        .watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File("watermark.png")), 0.5f)
        .toFile(new File("image-with-watermark.jpg"));

实操演示

我在我网站上使用上述包,搭建了一个在线演示地址:https://image.mintimate.cn/

效果图(˶‾᷄ ⁻̫ ‾᷅˵)
效果图(˶‾᷄ ⁻̫ ‾᷅˵)

功能:用户上传图片后,系统更具用户的选择的输出格式,转码图片。

扩展名判断

前端传送图片到后台,我们后台可以对文件扩展名进行判断:

代码语言:txt
复制
String thumbnailImageName=originalImage.getName(); //缩略图输出名
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;
       }

创建空白缩略图文件

虽然Thumbnailator可以直接自动根据String创建对应文件对象,但是为了更方便我们自己控制,我们手动创建:

代码语言:txt
复制
File thumbnailImage = new File(thumbnailImagePath);
        // 判断路径是否存在,如果不存在则创建
        if (!thumbnailImage.getParentFile().exists()) {
            thumbnailImage.getParentFile().mkdirs();
        }

转码图片

代码语言:txt
复制
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();
        }

因为,我是使用Springboot快速构建,我其实是创建了一个配置规则addFilter,可以使PNG透明图片转为JPG时,透明背景渲染为白色。(单纯为了好看……)。实现细节:

代码语言:txt
复制
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);//背景设置为白色
        graphic.fillRect(0, 0, w, h);
        graphic.drawRenderedImage(bufferedImage, null);
        graphic.dispose();
        return newImage;
    }
}

这样,就可以成功转码图片了(运用恰当,还可以压缩图片( ;´Д`)):

主要压缩效果,是Webp格式带来的
主要压缩效果,是Webp格式带来的

左边为原图,右边为转码后图片。这个是大小不变情况下,图片质量变为原来80%;主要文件大小变小,是Webp格式带来的。下文我们介绍一下Java转码Webp格式。

Java处理Webp格式

什么是Webp格式

根据Wiki百科:WebP(发音:weppy])是一种同时提供了有损压缩与无损压缩(可逆压缩)的图片文件格式,派生自影像编码格式,被认为是WebM多媒体格式的姊妹项目,是由Google在购买On2 Technologies后发展出来,以BSD授权条款发布。

而Webp具有的优势,显而易见:

  • 更优的图像数据压缩算法
  • 更小的图片体积
  • 肉眼识别无差异的图像质量
  • 无损和有损的压缩模式
  • Alpha 透明以及动画的特性 简单地说,它可以像PNG格式一样,保存无损画质,并保持图片透明特性;同时,可以像JPG一样,压缩图片。Webp在同等情况下,文件体积比PNG小,甚至比JPG还小。

Java如何支持Webp格式

因为Webp,实际上是Google开发的,所以Java IO流设计之初就不支持Webp格式。所以根据系统的不同,需要安装对应的依赖包:

代码语言:txt
复制
/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].a

可以参考项目:https://github.com/scijava/native-lib-loader

当然,你也可以直接用大神整合好的lib包,比如:webp-imageio-core;下文就详解如何使用。

webp-imageio-core使用

因为webp-imageio-core并没有发布到Maven中央仓库,所以使用Maven骨架用户需要自己添加lib依赖

首先下载webp-imageio-core的jar发布包,下载地址:https://github.com/nintha/webp-imageio-core/releases

之后添加自定义<dependency>:

代码语言:txt
复制
<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>

比如:我的项目,添加本地lib:

添加自定义lib到Maven
添加自定义lib到Maven

这个时候,Java就已经支持处理Webp格式图片了。

实操使用

最简单的使用……其实是再加入上文所提到的Thumbnailator依赖包,便可以使用Thumbnailator直接处理图片IO流。

单独使用,我们可以用最传统的方法处理:

图片转WEBP:

代码语言:txt
复制
public static void main(String args[]){
        String srcFile = System.getProperty("user.dir") + "/file/Input/"+"Input.png" //原图地址
        String webpFile = System.getProperty("user.dir") + "/file/Output/"+"Output.png" //输出地址
        encodingToWebp(srcFile, webpFile);
    }
    
    public static void encodingToWebp(String srcFile, String webpFile) {
        encodingToWebp(new File(srcFile),new File(webpFile) );
    }
 
    /**
     * @param: srcFile
     * @param: webpFile
     * @description: 将文件编码为WEBP格式
     * @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);
 
 
            //释放reader
            writer.dispose();
 
            //关闭文件流
            fileImageOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
}

最后

感兴趣可以关注B站:Mintimate

如果想进一步处理图片,需要基于系统工具包了:

比如:ImageMagick

ImageMagick其实是真正全功能图片处理,但是Java调用前,系统需要预先安装ImageMagick,且Mac、Linux和Windows上调用方法有差异,有机会给大家介绍( ̀⌄ ́)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章简介
  • 在线演示
  • 视频教程
  • 图片转码/生成缩略图
    • 原理
      • 如何安装
        • 如何使用
          • 图片转码
          • 使用原图片生成缩略图
          • 旋转图片
          • 添加水印
        • 实操演示
          • 扩展名判断
          • 创建空白缩略图文件
          • 转码图片
      • Java处理Webp格式
        • 什么是Webp格式
          • Java如何支持Webp格式
            • webp-imageio-core使用
              • 实操使用
              • 最后
              相关产品与服务
              图片处理
              图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档