之前写过一个图片缩放的功能,对于大幅度缩小,效果很差,这里做了小部分改进
原理是缩小的时候不是一次就缩小完,而是分成几次缩小,这样的好处是算法对像素的计算更加准确,
final int bs = 2;
int currentWidth = source.getWidth();
int currentHeight = source.getHeight();
BufferedImage tempImage = new BufferedImage(currentWidth,
currentHeight, source.getType());
Graphics2D g = tempImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setComposite(AlphaComposite.Src);
int startWidth = targetW;
int startHeight = targetH;
while (startWidth < currentWidth && startHeight < currentHeight) {
startWidth *= bs;
startHeight *= bs;
}
currentWidth = startWidth / bs;
currentHeight = startHeight / bs;
g.drawImage(source, 0, 0, currentWidth, currentHeight, null);
while ((currentWidth >= targetW * bs)
&& (currentHeight >= targetH * bs)) {
currentWidth /= bs;
currentHeight /= bs;
if (currentWidth < targetW)
currentWidth = targetW;
if (currentHeight < targetH)
currentHeight = targetH;
g.drawImage(tempImage, 0, 0, currentWidth, currentHeight, 0, 0, currentWidth
* bs, currentHeight * bs, null);
}
g.dispose();
Graphics2D destg = target.createGraphics();
destg.drawImage(tempImage, 0, 0, targetW, targetH, 0, 0, currentWidth, currentHeight, null);
destg.dispose();
其中: RenderingHints.KEY_INTERPOLATION RenderingHints.VALUE_INTERPOLATION_BILINEAR
API说明如下:
插值提示值——图像中最接近整数坐标样本的 4 种颜色样本被线性地插入,以生成一个颜色样本。从概念上讲,图像被视为一组无穷小的点颜色样本,其值只位于整数坐标像素的中心,而且这些像素中心之间的空间是用线性延伸的颜色填充的,并用直线连接相邻的离散样本。
当放大图像时,因为有 NEAREST_NEIGHBOR,在图像中的颜色之间没有斑驳模糊边缘,但是混合可能沿样本排列的水平和垂直边缘显示一些微小的间断,这是由于插值斜面从样本的一侧到另一侧的突然更改造成的。当缩小图像时,更多图像像素具有它们自己的以结果输出表示的颜色样本,因为每个输出像素都从多达 4 个图像像素中接收颜色信息。
在这种情况下,图片缩小后的质量比较可观,
也可换成其它值,比如
RenderingHints.VALUE_INTERPOLATION_BICUBIC
具体看API说明。