【问题标题】:Zooming an image in java by Repication Method通过复制方法在java中缩放图像
【发布时间】:2016-08-17 06:30:05
【问题描述】:

我正在尝试读取图像,将其放大到 80*60,然后通过复制方法使其大小重复。我的方法单独运行良好,但是当我在 main 方法中调用它们时,我的图像变黑了。任何人都可以帮助我吗? 这是我的代码:

import java.awt.BorderLayout;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        BufferedImage Image = null;
        File fc = null;

          try{

              fc = new File("C:\\1.jpg");
              Image = ImageIO.read(fc);
              BufferedImage zoomin = new BufferedImage(ScaledImage(Image,80,60).getWidth(null),ScaledImage(Image,80,60).getWidth(null), BufferedImage.TYPE_BYTE_GRAY);
              JFrame frame = new JFrame("Scaled Resolution");
              frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
              JLabel lbl = new JLabel();
                lbl.setIcon(new  ImageIcon(ImgReplication(zoomin,2)));
                frame.getContentPane().add(lbl, BorderLayout.CENTER);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

          }
          catch (Exception e1){
            System.out.println(e1);
            } 


    }
public static BufferedImage ImgReplication(BufferedImage image, int n) {

        int w = n * image.getWidth();
        int h = n * image.getHeight();

        BufferedImage enlargedImage =
                new BufferedImage(w, h, image.getType());

        for (int y=0; y < h; ++y)
            for (int x=0; x < w; ++x)
                enlargedImage.setRGB(x, y, image.getRGB(x/n, y/n));

        return enlargedImage;

    }
public static BufferedImage ScaledImage(Image img, int w , int h){

    BufferedImage resizedImage = new BufferedImage(w , h , BufferedImage.TYPE_BYTE_GRAY);
    Graphics2D g2 = resizedImage.createGraphics();
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g2.drawImage(img, 0, 0, w, h, null);
    g2.dispose();
    return resizedImage;
}


}

【问题讨论】:

  • 您是否考虑了 Alpha 通道?
  • 单独使用效果好吗?你在哪里绘制图像并且效果很好?
  • 我应该阅读的图像是灰度 BYTE。我没有 alpha。
  • 是的,每种方法在我正在开发的另一个程序中单独工作。我的意思是我可以使用 ScaledImage() 将图像调整到我想要的比例,我可以通过 ImgReplication 方法放大我的图像。但是,当我尝试在我的主要方法中调用它们时,我得到的图像是黑色的。问题来自这一行:BufferedImage zoomin = new BufferedImage(ScaledImage(Image,80,60).getWidth(null),ScaledImage(Image,80,60).getWidth(null), BufferedImage.TYPE_BYTE_GRAY);
  • 重点是我不想向用户显示 scaledImage 或将其保存在某处。我只是想显示放大的图像,以显示使用复制方法缩放图片的分辨率将如何变化。

标签: java swing image-processing replication bufferedimage


【解决方案1】:

我的建议是这样的:

    BufferedImage Image = null;
    File fc = null;

      try{

          fc = new File("C:\\1.jpg");
          Image = ImageIO.read(fc);
          BufferedImage sc=ScaledImage(Image,80,60);
          JFrame frame = new JFrame("Scaled Resolution");
          frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          JLabel lbl = new JLabel();
            lbl.setIcon(new  ImageIcon(ImgReplication(sc,2)));
            frame.getContentPane().add(lbl, BorderLayout.CENTER);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

      }
      catch (Exception e1){
        System.out.println(e1);
        } 


}

public static BufferedImage ImgReplication(BufferedImage image, int n) {

    int w = n * image.getWidth();
    int h = n * image.getHeight();

    BufferedImage enlargedImage =
            new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

    for (int y=0; y < h; ++y)
        for (int x=0; x < w; ++x)
            enlargedImage.setRGB(x, y, image.getRGB(x/n, y/n));

    return enlargedImage;

}

public static BufferedImage ScaledImage(Image img, int w , int h){

  BufferedImage resizedImage = new BufferedImage(w , h , BufferedImage.TYPE_INT_RGB);
  Graphics2D g2 = resizedImage.createGraphics();
  g2.drawImage(img, 0, 0, w, h, null);
  g2.dispose();
  return resizedImage;
}


}

【讨论】:

  • 没有任何区别。我仍然会得到黑色。我不知道为什么我会得到这个。虽然对我来说一切都很好。不过感谢您的努力。:)
  • 你也错过了正确的参数 ImgReplication(sc,2)
  • 不,我没有错过。这是行: lbl.setIcon(new ImageIcon(ImgReplication(sc,2)));我知道问题出在调用 scaledImage 方法。因为一切正常,直到达到使图像变黑的这条线。但我不明白发生了什么。
【解决方案2】:

那么,“核心”问题就在这里……

BufferedImage zoomin = new BufferedImage(
            ScaledImage(Image,80,60).getWidth(null),
            ScaledImage(Image,80,60).getWidth(null), 
            BufferedImage.TYPE_BYTE_GRAY);

所有这一切都是创建一个空白图像80x60 并做很多工作来实现它。

相反,您应该只使用类似...

BufferedImage zoomin = ScaledImage(Image,80,60);

现在,如果你想让它变成灰度,那么你需要创建一个与zoomin 图像大小相同的BufferedImage.TYPE_BYTE_GRAY 类型的新BufferedImage 图像并将zoomin 图像绘制到它上面...

您可能还想查看Quality of Image after resize very low -- JavaJava: maintaining aspect ratio of JPanel background image,了解有关缩放图像的更多想法。 get/setRGB 效率不是特别高,drawImage(x, y, w, h) 的质量也不是很好

可运行示例...

所以,在进行了建议的修改之后,我运行了你的算法,它想出了这个......

原创,ScaledImageImgReplication

import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();;
                }
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() throws IOException {
            BufferedImage master = ImageIO.read(new File("..."));
            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            add(new JLabel(new ImageIcon(master)), gbc);
            add(new JLabel(new ImageIcon(ScaledImage(master, 80, 60))), gbc);
            add(new JLabel(new ImageIcon(ImgReplication(master, 2))), gbc);
        }

    }

    public static BufferedImage ScaledImage(Image img, int w, int h) {

        BufferedImage resizedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D g2 = resizedImage.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2.drawImage(img, 0, 0, w, h, null);
        g2.dispose();
        return resizedImage;
    }

    public static BufferedImage ImgReplication(BufferedImage image, int n) {

        int w = n * image.getWidth();
        int h = n * image.getHeight();

        BufferedImage enlargedImage
                = new BufferedImage(w, h, image.getType());

        for (int y = 0; y < h; ++y) {
            for (int x = 0; x < w; ++x) {
                enlargedImage.setRGB(x, y, image.getRGB(x / n, y / n));
            }
        }

        return enlargedImage;

    }
}

所以对我来说似乎没问题

【讨论】:

  • 16 多年以来,我对图像缩放进行了大量研究,试图提出快速但有效的算法 this examplethis example 基于类似原理,这些原理基于来自The Perils of Image.getScaledInstance() 和其他博客的结果
  • 放大总是不好的,你无能为力,如果可能的话,总是尝试缩小比例
  • 所以,根据你的原始代码,它是从生成一个空白图像开始的,你应该可以举个例子,将 ScaledImage 的结果直接传递给 ImgReplicate
  • 类似 ImgReplication(ScaledImage(master, 80, 60), 2)
  • 本质上,你的代码只是在做 BufferedImage zoomin = new BufferedImage(80,60, BufferedImage.TYPE_BYTE_GRAY);
猜你喜欢
  • 1970-01-01
  • 2012-12-25
  • 2014-03-08
  • 1970-01-01
  • 2010-10-23
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多