我想要重用一些旧的Java 2D代码,但是想知道,这是获得最高质量图像的最佳方式吗?
public static BufferedImage getScaled(BufferedImage imgSrc, Dimension dim) {
// This code ensures that all the pixels in the image are loaded.
Image scaled = imgSrc.getScaledInstance(
dim.width, dim.height, Image.SCALE_SMOOTH);
// This code ensures that all the pixels in the image are loaded.
Image temp = new ImageIcon(scaled).getImage();
// Create the buffered image.
BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null),
temp.getHeight(null), BufferedImage.TYPE_INT_RGB);
// Copy image to buffered image.
Graphics g = bufferedImage.createGraphics();
// Clear background and paint the image.
g.setColor(Color.white);
g.fillRect(0, 0, temp.getWidth(null),temp.getHeight(null));
g.drawImage(temp, 0, 0, null);
g.dispose();
// j2d's image scaling quality is rather poor, especially when
// scaling down an image to a much smaller size. We'll post filter
// our images using a trick found at
// http://blogs.cocoondev.org/mpo/archives/003584.html
// to increase the perceived quality....
float origArea = imgSrc.getWidth() * imgSrc.getHeight();
float newArea = dim.width * dim.height;
if (newArea <= (origArea / 2.)) {
bufferedImage = blurImg(bufferedImage);
}
return bufferedImage;
}
public static BufferedImage blurImg(BufferedImage src) {
// soften factor - increase to increase blur strength
float softenFactor = 0.010f;
// convolution kernel (blur)
float[] softenArray = {
0, softenFactor, 0,
softenFactor, 1-(softenFactor*4), softenFactor,
0, softenFactor, 0};
Kernel kernel = new Kernel(3, 3, softenArray);
ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
return cOp.filter(src, null);
}
答案 0 :(得分:4)
克里斯·坎贝尔(Chris Campbell)对缩放图像进行了精彩而详尽的报道 - 请参阅 this article 。
Chet Haase和Romain Guy在他们的书 Filthy Rich Clients 中也有详细而且内容丰富的图像缩放文章。
答案 1 :(得分:3)
在此处添加一些澄清信息。
不,这不是最好的方式,可以在Java中获得漂亮的缩放图像。 Java2D团队不推荐使用getScaledInstance和底层的AreaAveragingScaleFilter,而是支持一些更高级的方法。
如果你只是想获得一个好看的缩略图,那么使用大卫建议的克里斯坎贝尔的方法是可行的方法。为了它的价值,我在Java图像缩放库中实现了该算法以及另外两种更快的方法,称为imgscalr(Apache 2许可证)。该库的目的是在一个易于使用的高度调整的库中专门解决这个问题:
BufferedImage thumbnail = Scalr.resize(srcImg, 150);
为了在Java中获得最好看的缩放实例,方法调用看起来像这样:
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY,
150, 100, Scalr.OP_ANTIALIAS);
库将使用Java2D团队推荐的增量缩放方法缩放原始图像,然后使其看起来更好,将非常温和的convolveop应用于图像,有效地对其进行轻微抗锯齿处理。这对于小缩略图来说非常好,对于巨大的图像来说并不那么重要。
如果您以前没有使用过convolveops,那么为了让op在所有用例中看起来都很好看,这需要很多工作才能获得完美的内核。在Scalr类中定义的OP常量是与巴西社交网站合作一周的结果,该网站已经推出imgscalr来处理其成员的个人资料图片。我们来回走动,尝试了10种不同的内核,直到我们发现一个非常微妙,不会使图像看起来柔和或模糊,但仍然平滑像素值之间的过渡,使图像看起来不那么“尖锐”和噪音小尺寸。
如果您想要最佳外观缩放图像而不考虑速度,请使用Juha建议使用java-image-scaling库。它是一个非常全面的Java2D Ops集合,包括对Lanczsos algorithm的支持,它将为您提供最佳效果。
我会远离JAI,不是因为它很糟糕,而是因为它只是一个与你想要解决的不同/更广泛的工具。前面提到的3种方法中的任何一种都可以为您提供精美的缩略图,而无需在更少的代码行中为您的项目添加全新的成像平台。
答案 2 :(得分:2)
您可以使用JAI(Java高级成像)来获得更复杂的图像大小调整选项。见https://jai.dev.java.net/。这些允许您比java.awt.image包更灵活。
答案 3 :(得分:1)
您还可以查看java-image-scaling库。
答案 4 :(得分:1)
您可以使用开源库调整图像大小 enter link description here
我已经完成了大图像到小,结果很好,保持纵横比很好。
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import org.imgscalr.*;
import org.imgscalr.Scalr.Method;
public class ImageScaller {
static String SRC_FILES_PATH = "I:\\BigGreen\\";
static String IMAGE_FILE_PATH = "I:\\Resized\\";
public ImageScaller() {
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try
{
ResizeLoad(SRC_FILES_PATH);
}
catch(Exception ex)
{
System.out.println(ex.toString());
}
}
public static int ResizeLoad(String path)
{
String file;
File folder ;
File[] listOfFiles = null;
listOfFiles = null;
try
{
folder = new File(path);
listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++)
{
if (listOfFiles[i].isFile())
{
file = listOfFiles[i].getName();
ScalledImageWrite(listOfFiles[i].getPath(),file);
//System.out.println(file);
}
}
System.out.println("All Resized");
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null,e.toString(),"Resize & Load :Exception",JOptionPane.WARNING_MESSAGE);
}
return listOfFiles.length;
}
private static File ScalledImageWrite(String path,String fileName)
{
try
{
BufferedImage img = ImageIO.read(new File(path));
BufferedImage scaledImg = Scalr.resize(img, Method.AUTOMATIC, 24, 24);
File destFile = new File(IMAGE_FILE_PATH + fileName);
ImageIO.write(scaledImg, "png", destFile);
//System.out.println("Done resizing");
return destFile;
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null,e.toString(),"Scalled Images Write: Exception",JOptionPane.WARNING_MESSAGE);
return null;
}
}
}
以下是此代码的图片格式输出。