4

我有一些想要重用的旧 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);
}
4

5 回答 5

4

Chris Campbell 有一篇关于缩放图像的出色而详细的文章 - 请参阅这篇文章

Chet Haase 和 Romain Guy 在他们的书《 Filthy Rich Clients》中也有关于图像缩放的详细且内容丰富的文章。

于 2009-02-12T21:41:43.920 回答
3

在此处添加一些澄清信息。

不,这不是在 Java 中获得好看的缩放图像的最佳方法。Java2D 团队不推荐使用 getScaledInstance 和底层的 AreaAveragingScaleFilter,而支持一些更高级的方法。

如果您只是想获得一个好看的缩略图,那么使用 David 建议的 Chris Campbell 的方法是可行的方法。值得一提的是,我已经在名为imgscalr(Apache 2 许可证)的 Java 图像缩放库中实现了该算法以及其他 2 种更快的方法。该库的重点是在一个易于使用的高度优化的库中专门解决这个问题:

BufferedImage thumbnail = Scalr.resize(srcImg, 150);

为了在 Java 中获得最好的缩放实例,方法调用看起来像这样:

BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
                                       150, 100, Scalr.OP_ANTIALIAS);

该库将使用 Java2D 团队推荐的增量缩放方法缩放原始图像,然后将非常温和的卷积运算应用于图像,使其看起来更漂亮,有效地对其进行轻微的抗锯齿处理。这对于小缩略图来说非常好,对于大图像来说不是那么重要。

如果您以前没有使用过 convolveops,那么要获得外观完美的内核以使操作在所有用例中看起来都很好,就需要做很多工作。Scalr 类上定义的 OP 常量是与巴西的一个社交网站合作一周的结果,该网站推出了 imgscalr 来处理其成员的个人资料图片。我们来回尝试了 10 种不同的内核,直到我们找到了一个足够细微的内核,不会使图像看起来柔和或模糊,但仍能平滑像素值之间的过渡,因此图像看起来不会“锐利”和噪点在小尺寸。

如果您想要最好看的缩放图像而不考虑速度,请使用 Juha 的使用 java-image-scaling 库的建议。它是一个非常全面的 Java2D Ops 集合,包括对Lanczsos 算法的支持,它将为您提供最好的结果。

我会远离 JAI,不是因为它不好,而是因为它只是一个与您要解决的问题不同/更广泛的工具。前面提到的 3 种方法中的任何一种都将为您提供漂亮的缩略图,而无需以更少的代码行将全新的成像平台添加到您的项目中。

于 2011-02-06T17:32:18.197 回答
2

您可以使用 JAI(Java 高级成像)来获得更复杂的图像大小调整选项。请参阅https://jai.dev.java.net/。这些比 java.awt.image 包更灵活。

于 2009-02-12T20:45:32.697 回答
1

您还可以查看java-image-scaling库。

于 2010-05-13T10:20:29.527 回答
1

您可以使用开源库调整图像大小 在此处输入链接描述

我已经完成了从大图像到小图像的处理,结果非常好,保持了良好的纵横比。

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;
      }
  }

}

这是此代码的图形格式输出。 在此处输入图像描述

于 2013-06-20T12:56:58.743 回答