我知道这个问题很久以前就被提出了,但如果还有人遇到这个问题的话,请注意以下两点(主要是第一点):
- Java中的非增量图像缩放非常粗糙,会抛弃大量像素数据,并且无论渲染提示如何,都会平均处理结果。
- 在Java2D中处理支持性较差的BufferedImage类型(通常是GIF)可能会导致外观非常糟糕/抖动。
事实证明,旧的
AreaAveragingScaleFilter可以做出好看的缩略图,但速度很慢,而且已经被Java2D团队弃用了。不幸的是,他们没有用任何好的开箱即用的替代方案来取代它,让我们自己摸索。
几年前,Java2D团队的Chris Campbell提出了增量缩放的概念——不是在一个操作中从起始分辨率到目标分辨率,而是分步进行,结果看起来更好。
考虑到这段代码相当庞大,我将所有最佳实践整理成一个名为
imgscalr的库,并在Apache 2许可下发布。
最基本的使用方法如下:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 640);
在这种使用情况下,该库使用所谓的“自动”缩放模式,并将结果图像(保持其比例)适合于640x640的边界框中。因此,如果图像不是正方形而是标准的4:3图像,则会将其调整为640x480 - 参数只是它的最大尺寸。
Scalr class上有一堆其他方法(全部都是静态且易于使用),允许您控制一切。
为了获得可能的最佳缩略图,命令应如下所示:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY,
150, 100, Scalr.OP_ANTIALIAS);
Scalr.OP_ANTIALIAS是可选的,但很多用户觉得当你在Java中缩小到足够小的缩略图时,一些像素值之间的转换有点过于离散,并使图像看起来“锐利”,因此很多用户要求软件提供一种方法来稍微软化缩略图。
这通过使用ConvolveOp
ConvolveOp 完成,如果您以前从未使用过它们,请尝试找出正确的“内核”是一个痛苦的过程。 OP_ANTIALIAS常量定义在类上,在与另一个将imgscalr部署到其巴西社交网络(用于缩放资料照片)的用户进行了一周的测试后,我发现这是最好的反锯齿操作。 我将其包含在内,使每个人的生活变得更轻松。
此外,在所有这些示例之上,您可能会注意到当您缩放GIF和某些其他类型的图像(BMP)时,有时缩放结果与原始图像相比看起来非常糟糕...这是由于图像以不受支持的BufferedImage类型存在,因此Java2D会回退到使用其软件渲染管道,而不是更好支持的图像类型的硬件加速管道。
无论如何,这是一个非常冗长的方式来说“您可以使用imgscalr为您完成所有这些操作,而不必担心任何事情”。