我意识到这个问题是不久前提出的,但如果其他人仍然遇到这个问题。
缩略图看起来像屁股的原因是由两件事引起的(主要是第一个):
- 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 为您完成所有这些工作,而不必担心任何事情”,这真的是一段很长的路要走。