Java 2D Image调整大小忽略双三次/双线性插值渲染提示(OS X + linux)

mad*_*lep 4 java 2d resize image bicubic

我正在尝试使用Image Voodoo插件在JRuby/Rails应用程序中为上传的图像创建缩略图 - 问题是调整大小的缩略图看起来像......屁股.

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

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

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

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

Riy*_*lla 5

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

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

  • Java中的非增量图像缩放非常粗糙,无论渲染提示如何,都会抛出大量像素数据并对结果求平均值.
  • 在Java2D(通常是GIF)中处理支持不良的BufferedImage类型会导致非常糟糕的外观/抖动结果.

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

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

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

最基本的用法如下所示:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 640);
Run Code Online (Sandbox Code Playgroud)

在这个用例中,库使用所谓的"自动"缩放模式,并且在640x640的边界框内适合生成的图像(尊重它的比例).因此,如果图像不是正方形并且是标准的4:3图像,则会将其大小调整为640x480 - 参数只是它的最大尺寸.

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

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

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

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

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

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

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

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