5

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

似乎生成缩略图的代码绝对正确地将插值渲染提示设置为“双三次”,但它在我们的开发环境(OS X)或生产网络服务器(Linux)上没有兑现它们.

我已经提取了生成缩略图的代码,将其重写为一个直接的 Java 应用程序(即从 main() 方法启动),插值渲染提示明确设置为“双三次”,并重现了(缺少)双三次和双线性调整大小。

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

我是否缺少任何 JVM 环境设置和/或其他库以使其正常工作?我为此做了很多头撞墙。

4

4 回答 4

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

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

Scalar 类上还有许多其他方法(都是静态的且易于使用),可让您控制一切。

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

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 为您完成所有这些工作,而不必担心任何事情”,这真的是一段很长的路要走。

于 2011-07-05T16:18:16.530 回答
1

也许这是您的解决方案:

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;
}
于 2009-09-09T11:28:07.737 回答
0

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

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

仍然不如 ImageMagick,但比它好。

于 2009-11-17T00:07:14.180 回答
0

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

于 2012-07-03T02:49:39.570 回答