使用Java JAI缩放图像

时间:2010-11-18 23:11:35

标签: java image scaling jai

我必须使用Java JAI缩放图像。现在,我使用以下代码:

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);
}

不幸的是,这会导致非常糟糕的结果,特别是因为我经常需要缩放比例因子小于0.5的图像......

有什么建议吗?

3 个答案:

答案 0 :(得分:15)

我猜您是想尝试将较大的图像缩放到缩略图大小或从原始图像到缩放图像的某些大小差异?

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

事实证明,旧的Java 1.1 Image.getScaledInstance方法中的SCALE_AREA_AVERAGING或SCALE_SMOOTH方法是一个相当昂贵的多步骤操作,它在后台进行了大量工作以生成漂亮的图像。 / p>

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

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

几个月前我在编写图像托管服务时实际上是在寻找这个答案,并且惊讶于“如何在Java中创建漂亮的缩略图这个简单的问题”有多么复杂。成了。

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

该库名为imgscalr。您可以像下载一样简单地下载和使用它:

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

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

我已经制作了一些图书馆的版本,如果您只是想撕掉“好东西”并自己做一些事情,那就去吧。这一切都在GitHub,并没有一个是绝密,只是为了让人们的生活更轻松。

希望有所帮助。

答案 1 :(得分:3)

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

答案 2 :(得分:1)

如果你很幸运,你只有Black&白色图像,然后您可以使用非常快速和高质量的操作:SubsampleBinaryToGray