我意识到这个问题不久前就被问过,但以防万一其他人仍然遇到这个问题。
缩略图看起来像屁股的原因有两个原因(主要是第一个):
- Java 中的非增量图像缩放非常粗糙,会丢弃大量像素数据,并且无论渲染提示如何,都会对结果进行一次平均。
- 在 Java2D 中处理支持不佳的 BufferedImage 类型(通常是 GIF)可能会导致外观非常差/抖动的结果。
事实证明老面积平均比例过滤器 http://download.oracle.com/javase/6/docs/api/java/awt/image/AreaAveragingScaleFilter.html在制作漂亮的缩略图方面做得不错,但它速度很慢并且被 Java2D 团队弃用了——不幸的是他们没有用任何漂亮的开箱即用的替代方案来取代它,让我们有点靠自己了。
Chris Campbell(来自 Java2D 团队)几年前用增量缩放的概念解决了这个问题——不是在一次操作中从起始分辨率到目标分辨率,而是分步骤进行,结果看起来要好得多。
鉴于此代码相当大,我将所有最佳实践写入一个名为的库imgscalr http://www.thebuzzmedia.com/software/imgscalr-java-image-scaling-library/并在 Apache 2 许可证下发布。
最基本的用法如下所示:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 640);
在此用例中,库使用所谓的“自动”缩放模式,并将生成的图像(尊重其比例)调整到 640x640 的边界框内。因此,如果图像不是正方形而是标准 4:3 图像,它会将其大小调整为 640x480 —— 参数只是它的最大尺寸。
网上还有很多其他方法标量类 http://www.thebuzzmedia.com/downloads/software/imgscalr/javadoc/org/imgscalr/Scalr.html(全静态且易于使用)让您可以控制一切。
为了获得尽可能最好看的缩略图,命令如下所示:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY,
150, 100, Scalr.OP_ANTIALIAS);
Scalr.OP_ANTIALIAS 是可选的,但很多用户觉得当你在 Java 中缩小到足够小的缩略图时,像素值之间的一些过渡有点过于离散,使图像看起来“锐利”,所以很多的用户请求一种稍微软化缩略图的方法。
这是通过一个卷积运算 http://download.oracle.com/javase/6/docs/api/java/awt/image/ConvolveOp.html如果您以前从未使用过它们,那么尝试找出要使用的正确“内核”......是一件痛苦的事情。在类上定义的 OP_ANTIALIAS 常量是我在与另一位将 imgscalr 部署到巴西社交网络(用于缩放个人资料照片)的用户进行一周测试后发现的最好看的抗锯齿操作。我把它包括在内是为了让每个人的生活更轻松一些。
此外,除了所有这些示例之外,您可能已经注意到,当您缩放 GIF 和某些其他类型的图像 (BMP) 时,有时缩放后的结果与原始图像相比看起来很糟糕……这是因为图像的支持很差。 BufferedImage 类型和 Java2D 回退到使用其软件渲染管道而不是硬件加速管道以获得更好的支持图像类型。
imgscalr 将为您处理所有这些问题,并将图像保留为最受支持的图像类型,以避免这种情况。
不管怎样,这确实是一个很长的说法,“你可以使用 imgscalr 为你做这一切,而不必担心任何事情”。