7

I have to scale an image with Java JAI. At the time now, I use the following code:

private static RenderedOp scale(RenderedOp image, float scale) {
    ParameterBlock scaleParams = new ParameterBlock();
    scaleParams.addSource(image);
    scaleParams.add(scale).add(scale).add(0.0f).add(0.0f);
    scaleParams.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC_2));

    // Quality related hints when scaling the image
    RenderingHints scalingHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    scalingHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
    scalingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    scalingHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
    scalingHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
    scalingHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    scalingHints.put(JAI.KEY_BORDER_EXTENDER, BorderExtender.createInstance(BorderExtender.BORDER_COPY));

    return JAI.create("scale", scaleParams, scalingHints);
}

Unfortunately, this leads to very bad results, especially because I often have to scale images with a scale factor less than 0.5...

Any advice?

4

3 回答 3

16

我猜您正在尝试将较大的图像缩小到缩略图大小或从原始图像到缩放图像的一些同样大的差异?

如果是这样,这个主题实际上是 Chris Campbell 在 2007 年从 Java2D 解决的(我不希望你知道这一点,只是指出这是一个常见问题),因为新的 Java2D 缩放方法 (RenderingHints.VALUE_INTERPOLATION_*) 没有提供等效于当时已弃用的Image.getScaledInstance(SCALE_AREA_AVERAGING 或 SCALE_SMOOTH)方法。

事实证明,旧 Java 1.1 Image.getScaledInstance 方法中的 SCALE_AREA_AVERAGING 或 SCALE_SMOOTH 方法是一种相当昂贵的多步骤操作,需要在后台进行大量工作才能生成漂亮的图像。

Chris 指出,使用 Java2D 获得相同结果的新的“正确”方法是不断将图像缩放一半直到达到所需图像大小的增量过程,最好使用更高质量的比例,例如RenderHints.VALUE_INTERPOLATION_BICUBIC 或 BILINEAR。

结果与人们想要的原始 Image.getScaledInstance 方法几乎相同。

实际上,几个月前,我在编写图像托管服务时就在寻找这个答案,并对“如何在 Java 中制作漂亮的缩略图”这个简单的问题感到惊讶。变成了。

我最终创建了一个小型 Java 库(Apache 2,开源),它使用“最佳实践”实现了 3 种不同的 Java 图像缩放方法,包括 Chris 建议的增量方法。

该库称为imgscalr。您可以下载并使用它,如下所示:

BufferedImage thumbnail = Scalr.resize(srcImage, 150);

有更多选项可以设置和使用(例如缩放的质量或速度),但开箱即用的智能默认设置可以为您制作漂亮的缩放图像,因此您不必担心更多不想。该库还努力处理和避免任何并非绝对必要的对象分配,并在不需要时立即处理 BufferedImage 实例——它旨在作为长时间运行的服务器应用程序的一部分的代码,所以这是批判的。

我已经发布了几个版本的库,如果你宁愿撕掉“好东西”并自己做点什么,那就去做吧。这一切都在GitHub 上,而且都不是最高机密,只是为了让人们的生活更轻松。

希望有帮助。

于 2011-02-06T17:04:42.137 回答
3

我使用Thumbnailator取得了不错的效果。我不知道 JAI.KEY_BORDER_EXTENDER 应该做什么,但我想其余的功能(抗锯齿、抖动等)都受支持。我用它来生成相当大的黑白图像的灰度缩略图

于 2011-06-29T18:05:53.037 回答
1

如果你很幸运并且你只有黑白图像,那么你可以使用非常快速和高质量的操作:SubsampleBinaryToGray

于 2012-08-29T10:26:50.187 回答