Thumbnailator处理图片尺寸时如何只缩小不放大

Resize Only if Larger with Thumbnailator

用Java处理图片,少不了使用Thumbnailator这个优秀、简洁的开源库。最近在使用这个库为前端上传的图片生成缩略图,发现在某种场景下,生成的缩略图尺寸会比原始图片尺寸还大,这显然不符合我们的预期。

为小尺寸图片生成缩略图

我们用一张图来演示:

原始图片180*180

这张原始图片的尺寸为180*180,而我们的后端服务会为所有图片生成一个300*300以内的缩略图,使用的是以下代码:

int maxWidth = 300; int maxHeight = 300; Thumbnails.of(inputFile) .size(maxWidth, maxHeight) .outputQuality(0.5) .toFile(outputFile);

以上代码生成的缩略图为:

默认生成的缩略图300*300

可以发现原本180*180的图片被放大到了300*300,同时缩略图的体积反而比原始图片大了不少,这不符合我们生成缩略图的要求。通过跟踪查看Thumbnailator的源码(具体在 FixedSizeThumbnailMaker.make(BufferedImage img) 方法中),发现图片resize的逻辑是:

  • 当原始图片的宽大于指定的width(原始图片的高大于指定的height时),图片会被缩小到width*height的框内
  • 当原始图片的宽小于指定的width(原始图片的高小于指定的height时),图片会被放大到width*height的框内

总之,生成的图片是贴合width*height这个框的。通过翻阅Github Issues,也没有找到这个问题的解决办法,甚至官方表示这个问题目前也不会解决:https://github.com/coobird/thumbnailator/issues/152#issuecomment-636476388

经过一番折腾,我找到了一个相对简单的解决办法,首先需要定义这样一个类:

import java.awt.image.BufferedImage; import java.io.IOException; import net.coobird.thumbnailator.Thumbnails; import net.coobird.thumbnailator.filters.ImageFilter; public class NoScaleUpResizer implements ImageFilter { private final int maxWidth; private final int maxHeight; public NoScaleUpResizer(int maxWidth, int maxHeight) { this.maxWidth = maxWidth; this.maxHeight = maxHeight; } @Override public BufferedImage apply(BufferedImage img) { if (img.getWidth() <= maxWidth && img.getHeight() <= maxHeight) { // 当图片宽高不超过最大宽高时,不处理,直接返回原始图片 return img; } try { // 否则,将图片缩小到最大宽高 return Thumbnails.of(img).size(maxWidth, maxHeight).asBufferedImage(); } catch (IOException e) { throw new RuntimeException(e); } } }

这个类实现了Thumbnailator中的 ImageFilter 类,可以在图片处理过程中进行相应操作。接下来我们就可以使用这个类来生成缩略图:

Thumbnails.of(inputFile) .scale(1) // 先不缩放 .addFilter(new NoScaleUpResizer(maxWidth, maxHeight)) // 然后使用NoScaleUpResizer将图片缩小到指定尺寸 .outputQuality(0.5) .toFile(outputFile);

运行一下看看生成后的缩略图:

使用NoScaleUpResizer生成的缩略图180*180

该缩略图保持了原图尺寸180*180,因此我们实现了resize图片时只缩小不放大的需求,只有当图片尺寸大于指定尺寸时,才调整图片大小。

 

======== 2022.11.12更新

😂直到最近再次关注该问题时,发现官方还是没有支持该功能(最新版本为0.4.18)。

于是特意在Issue下留下了我之前的解决方案:https://github.com/coobird/thumbnailator/issues/152#issuecomment-1311733987,希望能帮助更多关注该问题的人~

 

文章评论
${fromAuthor ? '郄正元' : '游客'} 作者 ${gmtCreate}
${content}
${subList.length}
发表评论
${commentToArticle ? '' : parentContent}
字数:0/${maxCommentLength}
该邮箱地址仅用于接收其他用户的回复提醒,不会泄露