Java 从JPanel获取高分辨率图像

Java 从JPanel获取高分辨率图像,java,swing,awt,Java,Swing,Awt,假设我有一个叫做panel的JPanel,并且已经有了一个paintComponent,我画了一些像矩形的形状。我可以从面板中获取缓冲图像,如: int w = panel.getWidth(); int h = panel.getHeight(); BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g = bi.createGraphics();

假设我有一个叫做panel的JPanel,并且已经有了一个paintComponent,我画了一些像矩形的形状。我可以从面板中获取缓冲图像,如:

    int w = panel.getWidth();
    int h = panel.getHeight();
    BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = bi.createGraphics();
    panel.paint(g);
    ImageIO.write(bi1, "png", new File("test.png"));
如何从面板中获取高分辨率图像?当前输出图像仅基于监视器中JPanel的分辨率

我试过仿射变换,但它不能满足我的需要

请注意,我已经在面板中绘制了所有内容,不想在paintComponent方法中更改图形


我真的在寻找一种实用的方法,非常感谢您的帮助。

有两种可能的方法可以实现这一点,您可以实际调整组件的大小,或者将仿射变换应用于图形上下文,两者都有问题

所以,从这个屏幕开始

背景图像是相当大的开始,并已大致缩小,以适应目前的组成部分,这是很重要的是什么即将到来

然后我将它的大小调整了4,这大概可以让你达到300dpi左右

Dimension original = tp.getSize();

System.out.println("Original = " + original);

int width = tp.getWidth() * 4;
int height = tp.getHeight() * 4;

System.out.println("Target = " + width + "x" + height);
tp.setSize(width, height);
tp.doLayout();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
tp.print(g2d);
g2d.dispose();

tp.setSize(original);
tp.doLayout();

try {
    ImageIO.write(img, "png", new File("Test.png"));
} catch (IOException ex) {
    ex.printStackTrace();
}
这导致了

好吧,背景图片看起来很酷,但文字是关闭的

好的,我们可以用仿射变换

这导致了

好的,现在图像看起来很糟糕,文本也很好

作为参考,测试代码

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class HiRes {

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

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

                final TestPane tp = new TestPane();
                JButton print = new JButton("Print");
                print.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {

                        Dimension original = tp.getSize();

                        System.out.println("Original = " + original);

                        int width = tp.getWidth() * 4;
                        int height = tp.getHeight() * 4;

                        System.out.println("Target = " + width + "x" + height);
                        tp.setSize(width, height);
                        tp.doLayout();
                        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                        Graphics2D g2d = img.createGraphics();
                        g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                        g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                        g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
//                      g2d.setTransform(AffineTransform.getScaleInstance(4, 4));
                        tp.print(g2d);
                        g2d.dispose();
                        tp.setSize(original);
                        tp.doLayout();

                        try {
                            ImageIO.write(img, "png", new File("Test.png"));
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(tp);
                frame.add(print, BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage background;

        public TestPane() {

            setLayout(new GridBagLayout());

            try {
                background = ImageIO.read(new File("/some/image/some/where"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            setLayout(new GridBagLayout());

            JLabel label = new JLabel("This is a test");
            label.setForeground(Color.WHITE);
            label.setFont(label.getFont().deriveFont(24f));
            add(label);

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                Image scaled = background;
                if (getWidth() < getHeight()) {
                    scaled = background.getScaledInstance(getWidth(), -1, Image.SCALE_SMOOTH);
                } else {
                    scaled = background.getScaledInstance(-1, getHeight(), Image.SCALE_SMOOTH);
                }
                int x = (getWidth() - scaled.getWidth(this)) / 2;
                int y = (getHeight() - scaled.getHeight(this)) / 2;
                g2d.drawImage(scaled, x, y, this);
                g2d.dispose();
            }
        }

    }

}

有两种可能的方法可以实现这一点,可以物理地调整组件的大小,也可以将仿射变换应用于图形上下文,两者都有问题

所以,从这个屏幕开始

背景图像是相当大的开始,并已大致缩小,以适应目前的组成部分,这是很重要的是什么即将到来

然后我将它的大小调整了4,这大概可以让你达到300dpi左右

Dimension original = tp.getSize();

System.out.println("Original = " + original);

int width = tp.getWidth() * 4;
int height = tp.getHeight() * 4;

System.out.println("Target = " + width + "x" + height);
tp.setSize(width, height);
tp.doLayout();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
tp.print(g2d);
g2d.dispose();

tp.setSize(original);
tp.doLayout();

try {
    ImageIO.write(img, "png", new File("Test.png"));
} catch (IOException ex) {
    ex.printStackTrace();
}
这导致了

好吧,背景图片看起来很酷,但文字是关闭的

好的,我们可以用仿射变换

这导致了

好的,现在图像看起来很糟糕,文本也很好

作为参考,测试代码

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class HiRes {

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

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

                final TestPane tp = new TestPane();
                JButton print = new JButton("Print");
                print.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {

                        Dimension original = tp.getSize();

                        System.out.println("Original = " + original);

                        int width = tp.getWidth() * 4;
                        int height = tp.getHeight() * 4;

                        System.out.println("Target = " + width + "x" + height);
                        tp.setSize(width, height);
                        tp.doLayout();
                        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                        Graphics2D g2d = img.createGraphics();
                        g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                        g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                        g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
//                      g2d.setTransform(AffineTransform.getScaleInstance(4, 4));
                        tp.print(g2d);
                        g2d.dispose();
                        tp.setSize(original);
                        tp.doLayout();

                        try {
                            ImageIO.write(img, "png", new File("Test.png"));
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(tp);
                frame.add(print, BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage background;

        public TestPane() {

            setLayout(new GridBagLayout());

            try {
                background = ImageIO.read(new File("/some/image/some/where"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            setLayout(new GridBagLayout());

            JLabel label = new JLabel("This is a test");
            label.setForeground(Color.WHITE);
            label.setFont(label.getFont().deriveFont(24f));
            add(label);

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                Image scaled = background;
                if (getWidth() < getHeight()) {
                    scaled = background.getScaledInstance(getWidth(), -1, Image.SCALE_SMOOTH);
                } else {
                    scaled = background.getScaledInstance(-1, getHeight(), Image.SCALE_SMOOTH);
                }
                int x = (getWidth() - scaled.getWidth(this)) / 2;
                int y = (getHeight() - scaled.getHeight(this)) / 2;
                g2d.drawImage(scaled, x, y, this);
                g2d.dispose();
            }
        }

    }

}
用印刷品代替油漆 放大组件和图像尺寸,然后将图像缩放回目标尺寸 使用“变换”会使图像模糊,尝试将图像缩放8次,您将看到差异 用印刷品代替油漆 放大组件和图像尺寸,然后将图像缩放回目标尺寸 使用“变换”会使图像模糊,尝试将图像缩放8次,您将看到差异
首先,使用print或printAll代替paintDefine high Resolution,但它不能满足我的需要。如果它不能满足您的需要,那么我不明白您需要什么。首先,使用print或printAll代替paintDefine high Resolution我尝试了仿射变换,但它不能满足我的需要。如果它不能满足你的需要,那么我就不明白你需要什么。你太棒了。第二种方法在我的情况下非常有效。你能给我解释一下那里发生了什么吗?这只是一个简单的扩大规模的例子。基本上,您创建了一个满足您所需大小4x的BuffereImage在本例中,您使用所需比例4x的缩放变换将仿射变换应用于图形上下文,并将组件绘制到BuffereImage的图形中,API会处理REST。您真是太棒了。第二种方法在我的情况下非常有效。你能给我解释一下那里发生了什么吗?这只是一个简单的扩大规模的例子。基本上,创建一个满足所需大小4x的BuffereImage在本例中,使用所需比例4x的缩放变换将仿射变换应用于图形上下文,并将组件绘制到BuffereImage的图形上,其余部分由API处理