为什么这个图像在Java中按比例缩小后看起来这么糟糕?

发布于 2024-10-17 04:47:20 字数 1492 浏览 5 评论 0原文

这是原始图像: 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;
}

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

Here is the original image: http://rank.my/public/images/uploaded/orig-4193395691714613396.png

And here it is scaled down to 300x225:

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

And here it is scaled down to 150x112:

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

As you can see, 300x225 looks pretty bad, and 150x112 looks awful. Here is the code I'm using to scale down the image:

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

What am I doing wrong here? The image scaling doesn't have to be especially fast, quality is definitely a priority over speed. Am I using the wrong technique?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

£冰雨忧蓝° 2024-10-24 04:47:20

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

There are three ways to fix the downscaling problem. First is to do it in multiple steps, with no more than a 75% reduction in each step. The second is to blur the image before resizing; the more it shrinks, the more you'll have to blur. The third way is to use a method that filters using more than the 2x2 to 4x4 pixel blocks used by a naive bilinear or bicubic interpolation method. As the shrink factor grows larger, so should the pixel block used by the filter, otherwise you get aliasing artifacts as you've seen here.

心凉怎暖 2024-10-24 04:47:20

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

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

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

I've never used these libraries so I feel unqualified to answer, but I can't help but pass along these links I found that I think may be useful. Hopefully this will help.

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

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

迷荒 2024-10-24 04:47: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());

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

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

JAI is pretty frustrating. I still wonder why, no matter what settings you do, it never matches the speed, quality and simplicity of ImageMagick. I prefer to use ImageMagick wherever I can.

The code below is what gives me best result for image scaling. Please note that I have used RenderingHints.VALUE_RENDER_QUALITY and SubsampleAverage and not RenderingHints.VALUE_INTERPOLATION_BICUBIC.

I have wrapped up JAI processing in a small block and always use it to scale down. The same code does not give good result when you scale-up -- a different setting applies for that. I have not tried with PNG, JPEG is what I worked with.

Hope this helps

//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());

Also, the articles that helped me are.

(The links above are from my bookmark, edit them if you find they are dead)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文