Java 2D Imageresize忽略双三次/双线性插值渲染提示(OS X + linux)

我正在尝试使用Image Voodoo插件在JRuby / Rails应用程序中为上传的图像创建缩略图 – 问题是resize的缩略图看起来像……屁股。

生成缩略图的代码似乎绝对正确地将插值渲染提示设置为“bicubic”,但是它并没有在我们的开发环境(OS X)或生产Web服务器(Linux)上表现出来。 。

我已经提取出代码来生成缩略图,将其重写为直接的Java应用程序(即从main()方法开始),插值呈现提示明确设置为“bicubic”,并且已经复制了(缺少)双三次和双线性resize。

正如在OS X和Linux上所预期的那样,拇指按钮是丑陋且像素化的,但在Windows上,它使用双三次插值很好地调整了图像的大小。

是否有任何JVM环境设置和/或其他库我缺少使其工作? 对于这个,我正在做很多撞墙的事。

我意识到这个问题是在不久前被问到的,但是其他任何人仍然遇到这个问题。

缩略图看起来像屁股的原因是由两件事(主要是第一件)引起的:

  • Java中的非增量图像缩放非常粗糙,抛出大量像素数据并将结果平均一次,而不管渲染提示如何。
  • 在Java2D(通常是GIF)中处理支持不良的BufferedImage类型会导致非常差的外观/抖动结果。

事实certificate,旧的AreaAveragingScaleFilter在制作漂亮的缩略图方面做得不错,但是Java2D团队很慢并且不赞成 – 不幸的是他们并没有用任何漂亮的开箱即用的替代品取代它而离开了我们我们自己。

几年前,Chris Campbell(来自Java2D团队)使用增量缩放的概念解决了这个问题 – 而不是在一次操作中从您的起始分辨率转到目标分辨率,而是逐步完成,结果看起来要好得多。

鉴于此代码的代码非常大,我将所有最佳实践编写到名为imgscalr的库中,并在Apache 2许可下发布。

最基本的用法如下:

BufferedImage img = ImageIO.read(...); // load image BufferedImage scaledImg = Scalr.resize(img, 640); 

在这个用例中,库使用所谓的“自动”缩放模式,并在640×640的边界框内拟合生成的图像(遵循它的比例)。 因此,如果图像不是正方形并且是标准的4:3图像,则会将其调整为640×480 – 参数只是它的最大尺寸。

Scalr类中有许多其他方法(所有静态且易于使用),允许您控制所有内容。

为了获得最佳的缩略图,该命令将如下所示:

 BufferedImage img = ImageIO.read(...); // load image BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 150, 100, Scalr.OP_ANTIALIAS); 

Scalr.OP_ANTIALIAS是可选的,但是很多用户认为当你缩小到Java中足够小的缩略图时,像素值之间的某些过渡有点太离散并且使图像看起来“清晰”,所以很多用户要求一种软化缩略图的方法。

这是通过ConvolveOp完成的,如果你以前从未使用它们,那么试图弄清楚要使用的正确的“内核”是……痛苦的屁股。 OP_ANTIALIAS常量定义在类上它是最好看的抗锯齿操作我经过一周的测试后发现与另一个用户已经将imgscalr部署到他们在巴西的社交网络中(用于缩放配置文件照片)。 我把它包括在内让每个人的生活变得更轻松。

此外,在所有这些示例的顶部,你可能已经注意到当你缩放GIF和一些其他类型的图像(BMP)时,有时缩放的结果看起来比原始的可怕……这是因为图像支持不足BufferedImage类型和Java2D回归使用它的软件渲染管道而不是硬件加速管道,以获得更好的支持图像类型。

imgscalr将为您处理所有这些并保持图像在最佳支持的图像类型可能,以避免这种情况。

无论如何,这是一个很长的说法,“你可以使用imgscalr为你做所有这些,而不必担心任何事情”。

也许这是一个解决方案:

 public BufferedImage resizeImage(BufferedImage source, int width, int height) { BufferedImage result = new BufferedImage(widht, height, BufferedImage.TYPE_INT_ARGB); Graphics g = result.getGraphics(); g.drawImage(source, 0, 0, widht, height, null); g.dispose(); return result; } 

最后,升级到最新版本的ImageVoodoo似乎可以提高质量。

查看源代码,看起来他们正在做一些时髦的AWT渲染,然后将其拉出来。 讨厌,但它似乎工作。

仍然不如ImageMagick,但比它更好。

@Riyad,增量扩展的代码不是“相当大”,它非常小(正如你在2007年的post中看到的那样, http://today.java.net/pub/a/today/2007/04 /03/perils-of-image-getscaledinstance.html#creating-scaled-instances )拥有一个提供其他选项的库可能很有用,但使库使用库是无稽之谈。