Java 2D 和调整大小

发布于 2024-07-13 09:53:59 字数 1957 浏览 6 评论 0原文

我有一些旧的 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);
}

I have some old Java 2D code I want to reuse, but was wondering, is this the best way to get the highest quality images?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

与之呼应 2024-07-20 09:53:59

Chris Campbell 对缩放图像有一篇精彩而详细的文章 - 请参阅 本文

Chet Haase 和 Romain Guy 在他们的书中也有关于图像缩放的详细且内容丰富的文章,肮脏的富客户端< /a>

Chris Campbell has an excellent and detailed write-up on scaling images - see this article.

Chet Haase and Romain Guy also have a detailed and very informative write-up of image scaling in their book, Filthy Rich Clients.

傲娇萝莉攻 2024-07-20 09:53:59

在此添加一些澄清信息。

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

如果您只是想获得好看的缩略图,那么使用 David 建议的 Chris Campbell 方法是不错的选择。 无论如何,我已经在名为 imgscalr(Apache 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 种方法中的任何一种都将为您提供美观的缩略图,而无需以更少的代码行向您的项目添加全新的成像平台。

Adding some clarifying information here.

No, that isn't the best way to get a good looking scaled image in Java. Use of getScaledInstance and the underlying AreaAveragingScaleFilter are deprecated by the Java2D team in favor of some more advanced methods.

If you are just trying to get a good-looking thumbnail, using Chris Campbell's method as suggested by David is the way to go. For what it's worth, I have implemented that algorithm along with 2 other faster methods in a Java image-scaling library called imgscalr (Apache 2 license). The point of the library was to specifically address this question in a highly tuned library that is easy to use:

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

To get the best-looking scaled instance possible in Java, the method call would look something like this:

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

The library will scale the original image using the incremental-scaling approach recommended by the Java2D team and then to make it look even nicer a very mild convolveop is applied to the image, effectively anti-aliasing it slightly. This is really nice for small thumbnails, not so important for huge images.

If you haven't worked with convolveops before, it's a LOT of work just to get the perfect looking kernel for the op to look good in all use-cases. The OP constant defined on the Scalr class is the result of a week of collaboration with a social networking site in Brazil that had rolled out imgscalr to process profile pictures for it's members. We went back and forth and tried something like 10 different kernels until we found one that was subtle enough not to make the image look soft or fuzzy but still smooth out the transitions between pixel values so the image didn't look "sharp" and noisey at small sizes.

If you want the best looking scaled image regardless of speed, go with Juha's suggestion of using the java-image-scaling library. It is a very comprehensive collection of Java2D Ops and includes support for the Lanczsos algorithm which will give you the best-looking result.

I would stay away from JAI, not because it's bad, but because it is just a different/broader tool than what you are trying to solve. Any of the previous 3 approaches mentioned will give you great looking thumbnails without needing to add a whole new imaging platform to your project in fewer lines of code.

初见你 2024-07-20 09:53:59

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

You can use JAI (Java Advanced Imaging) to get more sophisticated image resizing options. See https://jai.dev.java.net/. These allow you much more flexibility than the java.awt.image package.

淡淡離愁欲言轉身 2024-07-20 09:53:59

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

You could also look into java-image-scaling library.

蒗幽 2024-07-20 09:53:59

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

我已经完成了大图像体积小,效果出色,保持良好的纵横比。

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

}

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

You can Resize Image using a Open Source Library
enter link description here

I have done with Large Image to Small and result excellent, keeping the aspect ratio fine.

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

}

Here is the output in pictorial format of this code.
enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文