为什么这个图像在Java缩小后看起来如此糟糕?

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

在这里,它缩小到300×225:

http://sofzh.miximages.com/java/norm-4193395691714613396.png

在这里,它缩小到150×112:

http://sofzh.miximages.com/java/small-4193395691714613396.png

正如你所看到的,300×225看起来非常糟糕,150×112看起来很糟糕。 这是我用来缩小图像的代码:

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

我在这做错了什么? 图像缩放不一定非常快,质量绝对优先于速度。 我使用了错误的技术吗?

有三种方法可以解决降尺度问题。 首先是分多步完成,每步减少不超过75%。 第二种是在resize之前模糊图像; 它越萎缩,你就越需要模糊。 第三种方法是使用一种方法,该方法使用超过2×2到4×4像素块的filter,使用的是天真的双线性或双三次插值方法。 随着收缩因子变大,滤波器使用的像素块也应该变大,否则您会看到如此处所见的锯齿伪像。

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

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

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

JAI非常令人沮丧。 我仍然想知道为什么,无论你做什么设置,它永远不会匹配ImageMagick的速度,质量和简单性。 我更喜欢在任何地方使用ImageMagick。

下面的代码为我提供了最佳的图像缩放结果。 请注意,我使用了RenderingHints.VALUE_RENDER_QUALITYSubsampleAverage不是 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()); 

另外,帮助我的文章是。

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