Java 2D和调整大小

时间:2009-02-12 20:39:11

标签: java image resize 2d image-scaling

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

5 个答案:

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

}

以下是此代码的图片格式输出。 enter image description here