【问题标题】:Why does this image look so bad after being scaled down in Java?为什么这个图像在 Java 中按比例缩小后看起来如此糟糕?
【发布时间】:2011-06-25 07:10:01
【问题描述】:

这是原图:http://rank.my/public/images/uploaded/orig-4193395691714613396.png

在这里它被缩小到 300x225:

http://rank.my/public/images/uploaded/norm-4193395691714613396.png

在这里它被缩小到 150x112:

http://rank.my/public/images/uploaded/small-4193395691714613396.png

如您所见,300x225 看起来很糟糕,而 150x112 看起来很糟糕。这是我用来缩小图像的代码:

private static BufferedImage createResizedCopy(final BufferedImage source, final int destWidth,
        final int destHeight) {
    final BufferedImage resized = new BufferedImage(destWidth, destHeight, source.getType());
    final Graphics2D bg = resized.createGraphics();
    bg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    bg.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    final float sx = (float) destWidth / source.getWidth();
    final float sy = (float) destHeight / source.getHeight();
    bg.scale(sx, sy);
    bg.drawImage(source, 0, 0, null);
    bg.dispose();
    return resized;
}

我在这里做错了什么?图像缩放不必特别快,质量绝对比速度更重要。我是否使用了错误的技术?

【问题讨论】:

  • @MusiGenesis:我认为你删除的答案非常好,我希望你能取消删除它。
  • 链接已失效,请使用 imgur 或类似内容托管 :)
  • 链接现已备份 - 抱歉
  • 又是死链接。请直接将它们添加到帖子中,或使用 imgur。谢谢!

标签: java graphics image-processing graphics2d


【解决方案1】:

我从来没有使用过这些库,所以我觉得没有资格回答,但我忍不住传递了这些我认为可能有用的链接。希望这会有所帮助。

http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html

http://www.componenthouse.com/article-20

【讨论】:

  • today.java.net 链接对我来说看起来不错,尤其是标题为“创建缩放实例”的部分和示例getScaledInstance(...) 实现。
【解决方案2】:

有三种方法可以解决缩小问题。首先是分多步进行,每步减少不超过75%。二是在调整大小之前对图像进行模糊处理;它缩小得越多,你就越需要模糊。第三种方法是使用一种方法,该方法使用多于 2x2 到 4x4 像素块的过滤器,这些像素块由朴素的双线性或双三次插值方法使用。随着收缩因子变大,过滤器使用的像素块也应该变大,否则会出现如您在此处看到的锯齿伪影。

【讨论】:

    【解决方案3】:

    JAI 非常令人沮丧。我仍然想知道为什么无论你做什么设置,它都无法与ImageMagick 的速度、质量和简单性相提并论。我更喜欢尽可能使用 ImageMagick。

    下面的代码为我提供了图像缩放的最佳结果。请注意,我使用了 RenderingHints.VALUE_RENDER_QUALITYSubsampleAveragenot RenderingHints.VALUE_INTERPOLATION_BICUBIC

    我已将 JAI 处理封装在一个小块中,并始终使用它来缩减规模。当您扩大规模时,相同的代码不会产生良好的结果——不同的设置适用于此。我没有尝试过使用 PNG,我使用的是 JPEG。

    希望对你有帮助

    //Set-up and load file
    PlanarImage image = JAI.create("fileload", absPath);
    RenderingHints quality = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    Properties p = new Properties(System.getProperties());
    p.put("com.sun.media.jai.disableMediaLib", "true");
    System.setProperties(p);
    
    //Setup the processes
    ParameterBlock pb = new ParameterBlock()
        .addSource(image)
        .add(scaleX)     //scaleX = (double)1.0*finalX/origX
        .add(scaleY);    //scaleY = (double)1.0*finalY/origY
    RenderedOp tempProcessingFile = JAI.create("SubsampleAverage", pb, quality);
    
    //Save the file
    FileOutputStream fout = new FileOutputStream(file);
    JPEGEncodeParam encodeParam = new JPEGEncodeParam();
    encodeParam.setQuality(0.92f); //My experience is anything below 0.92f gives bad result
    ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", fout, encodeParam);
    encoder.encode(tempProcessingFile.getAsBufferedImage());
    

    另外,对我有帮助的文章也是。

    (上面的链接来自我的书签,如果你发现它们已经死了,请编辑它们)

    【讨论】:

    • 我相信 SubsampleAverage 遵循我的第三个建议,为每个像素输出使用更大的像素块输入。
    • 失去了到 Sun 论坛的链接,可能是这个:forums.oracle.com/forums/thread.jspa?threadID=1270119?该线程以 开头“这似乎是 JAI(或任何图像 API)中最容易做的事情,但让我头疼。任务是:缩小质量最好的图像。结果:JAI 很差与 GIMP 等标准应用程序相比的性能..." 然后继续使用 RenderingHints KEY_RENDERING, VALUE_RENDER_QUALITYMemoryCacheSeekableStream,最后建议使用 ImageReadParam setSourceRegion, setSourceSubsampling
    猜你喜欢
    • 1970-01-01
    • 2011-04-28
    • 2013-08-25
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    • 2015-09-25
    • 1970-01-01
    相关资源
    最近更新 更多