如何制作高质量的截图?

Posted

技术标签:

【中文标题】如何制作高质量的截图?【英文标题】:How to make a high quality screenshot? 【发布时间】:2019-12-13 14:50:54 【问题描述】:

我使用BufferedImage 截取屏幕截图,但是当我得到的图片显示质量很差。

这是我的代码:

Rectangle screenShot=new Rectangle(graphpanel.getX()+this.getX()+5,  
              graphPanel.getY()+this.getY()+navPanel.getHeight()+4, 
              graphPanel.getWidth(), graphPanel.getHeight());
BufferedImage capture=new Robot().createScreenCapture(screenShot);
ImageIO.write(capture, "jpg",new File("./PDFs/test"+"Graph"+".png"));

【问题讨论】:

Low quality of java.awt.Robot screen capture on scaled Windows desktops? @MadProgrammer 有other things 需要修复才能达到那种深奥的水平。 ;) 【参考方案1】:
ImageIO.write(capture, "jpg",new File("./PDFs/test"+"Graph"+".png"));

应该是:

ImageIO.write(capture, "png",new File("./PDFs/test"+"Graph"+".png")); 

在文件扩展名中将图像称为 PNG 不会使其成为 PNG。它还需要编码为 PNG。

[我]做了[更改]它,但没有结果

这段代码你得到了什么输出?我得到了:

type: jpg  Color difference: 926283 or 0.7852198282877604%.
type: png  Color difference: 0 or 0.0%.

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.imageio.ImageIO;
import java.io.*;
import java.net.*;

public class ImageSave 

    private JComponent ui = null;
    public final static String[] types = "jpg","png";
    private final JComboBox<String> typesBox = new JComboBox<>(types);
    BufferedImage image;
    BufferedImage imageCoded;
    JLabel imageLabel = new JLabel();
    JLabel imageCodedLabel = new JLabel();
    JLabel output = new JLabel("Output appears here..");

    ImageSave() 
        try 
            initUI();
         catch (Exception ex) 
            ex.printStackTrace();
        
    

    public final void initUI() throws Exception 
        if (ui != null) 
            return;
        

        ui = new JPanel(new BorderLayout(4,4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        URL url = new URL("https://i.stack.imgur.com/7bI1Y.jpg");
        image = ImageIO.read(url);
        imageLabel.setIcon(new ImageIcon(image));

        JPanel picsPanel = new JPanel(new GridLayout(1, 0, 4, 4));
        ui.add(picsPanel);

        picsPanel.add(imageLabel);
        picsPanel.add(imageCodedLabel);

        JToolBar toolBar = new JToolBar();
        ui.add(toolBar, BorderLayout.PAGE_START);
        toolBar.setLayout(new FlowLayout(FlowLayout.LEADING));
        toolBar.add(typesBox);
        ActionListener refreshListener = (ActionEvent e) -> 
            try 
                updateGUI();
             catch (Exception ex) 
                ex.printStackTrace();
            
        ;
        typesBox.addActionListener(refreshListener);

        toolBar.add(output);

        updateGUI();
    

    private void updateGUI() throws Exception 
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        String type = typesBox.getSelectedItem().toString();
        ImageIO.write(image, type, baos);
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        imageCoded = ImageIO.read(bais);
        imageCodedLabel.setIcon(new ImageIcon(imageCoded));

        int diff = compareImages();
        int max = image.getWidth()*image.getHeight()*256*3;
        double percent = 100d*(double)diff/(double)max;
        String s = "type: " + type + "  Color difference: " + diff + 
                " or " + percent + "%.";
        System.out.println(s);
        output.setText(s);
     

    private int compareImages() 
        int diff = 0;
        for (int xx=0; xx<image.getWidth(); xx++) 
            for (int yy=0; yy<image.getHeight(); yy++) 
                Color rgb1 = new Color(image.getRGB(xx, yy));
                Color rgb2 = new Color(imageCoded.getRGB(xx, yy));
                int r1 = rgb1.getRed();
                int g1 = rgb1.getGreen();
                int b1 = rgb1.getBlue();
                int r2 = rgb2.getRed();
                int g2 = rgb2.getGreen();
                int b2 = rgb2.getBlue();
                diff += Math.abs(r1-r2);
                diff += Math.abs(g1-g2);
                diff += Math.abs(b1-b2);
            
        
        return diff;
    

    public JComponent getUI() 
        return ui;
    

    public static void main(String[] args) 
        Runnable r = () -> 
            try 
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
             catch (Exception useDefault) 
            
            ImageSave o = new ImageSave();

            JFrame f = new JFrame(o.getClass().getSimpleName());
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            f.setLocationByPlatform(true);

            f.setContentPane(o.getUI());
            f.pack();
            f.setMinimumSize(f.getSize());

            f.setVisible(true);
        ;
        SwingUtilities.invokeLater(r);
    

【讨论】:

我确实改了,但没有结果 我发布了minimal reproducible example 作为对答案的编辑。请告诉我们它在您的系统上报告的内容(复制/粘贴文本输出)。如果它报告的内容与上述大致相同,请对其进行更改以获取屏幕截图并再次检查输出。

以上是关于如何制作高质量的截图?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 中从 MTKView 制作屏幕截图?

如何从网页制作截图? [重复]

如何制作小部件的屏幕截图并将其粘贴到 QGraphicsView 中?

如何使用c ++为最小尺寸的窗口制作屏幕截图

如何使用c ++为最小尺寸的窗口制作屏幕截图

如何提高使用 medial_axis 制作的骨架的质量