มีวิธีถ่ายภาพหน้าจอโดยใช้ Java และบันทึกเป็นภาพบางประเภทหรือไม่?


128

เรียบง่ายตามสถานะของหัวเรื่อง: คุณสามารถใช้เฉพาะคำสั่ง Java เพื่อถ่ายภาพหน้าจอและบันทึกได้หรือไม่? หรือฉันต้องใช้โปรแกรมเฉพาะของระบบปฏิบัติการเพื่อจับภาพหน้าจอจากนั้นจึงนำออกจากคลิปบอร์ด?



ฉันไม่เคยรู้เลยว่ามันจะง่ายขนาดนี้
jjnguy

2
ด้วยคำถามนี้ฉันจึงเขียนบทช่วยสอนสำหรับผู้เริ่มต้นอย่างแท้จริงในบล็อกของฉัน: thepcwizard.in/2012/12/java-screen-capturing-tutorial.html
ThePCWizard

คำตอบ:


187

เชื่อหรือไม่ว่าคุณสามารถใช้java.awt.Robot"สร้างภาพที่มีพิกเซลที่อ่านจากหน้าจอ" ได้ จากนั้นคุณสามารถเขียนภาพนั้นลงในไฟล์บนดิสก์ได้

ฉันเพิ่งลองและทุกอย่างก็จบลงเช่น:

Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capture = new Robot().createScreenCapture(screenRect);
ImageIO.write(capture, "bmp", new File(args[0]));

หมายเหตุ: จะจับเฉพาะจอภาพหลักเท่านั้น ดูการกำหนดค่ากราฟิกสำหรับการสนับสนุนหลายจอภาพ


1
ฉันสงสัยว่านี่คือแอปพลิเคชั่นแชร์หน้าจอที่ Elluminate ( elluminate.com ) ใช้หรือไม่
Chris Wagner

@java_enthu ใช่มันจะใช้งานได้โดยไม่ต้องใช้คอนโซลถ้าคุณจะฮาร์ดโค้ดพา ธ ไปยังภาพหน้าจอในแอพของคุณ
Dmitry Zagorulkin

2
Robot ไม่รวมเมาส์ในการจับภาพหน้าจอ มีฟังก์ชั่นที่คล้ายกันซึ่งเหมือนกันทุกประการ แต่มีเมาส์หรือไม่?
nullUser

3
มีวิธีจับเคอร์เซอร์ของเมาส์ด้วยหรือไม่!
Mehdi Karamosly

23

ฉันไม่เคยชอบใช้ Robot ดังนั้นฉันจึงสร้างวิธีง่ายๆในการสร้างภาพหน้าจอของวัตถุ JFrame:

public static final void makeScreenshot(JFrame argFrame) {
    Rectangle rec = argFrame.getBounds();
    BufferedImage bufferedImage = new BufferedImage(rec.width, rec.height, BufferedImage.TYPE_INT_ARGB);
    argFrame.paint(bufferedImage.getGraphics());

    try {
        // Create temp file
        File temp = File.createTempFile("screenshot", ".png");

        // Use the ImageIO API to write the bufferedImage to a temporary file
        ImageIO.write(bufferedImage, "png", temp);

        // Delete temp file when program exits
        temp.deleteOnExit();
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
}

17
มีเหตุผลอะไรที่คุณไม่ชอบ Robot?
Simon Forsberg

2
คิดว่ามันเป็นเรื่องของรสนิยม
DejanLekic

3
ดูเหมือนว่าสิ่งนี้จะได้เปรียบในการทำงานแม้ว่าหน้าต่างเป้าหมายจะถูกบดบังก่อนที่จะถ่ายภาพหน้าจอก็ตาม
Brad Mace

7
ในทางกลับกันสิ่งนี้จะได้รับเฉพาะเนื้อหาของหน้าต่างในขณะที่Robotคุณสามารถรับกรอบหน้าต่างและแถบชื่อเรื่องได้ด้วย
Brad Mace

1
สำหรับ HiDPI (Mac retina) จะแสดงภาพหน้าจอที่มีความละเอียดครึ่งหนึ่ง เพื่อแก้ไข bufferedImage.getGraphics (). scale (2, 2) ก่อนการเรียก argFrame.paint (bufferedImage.getGraphics ()) และใช้ BufferedImage ใหม่ (rec.width * 2, rec.height * 2, BufferedImage.TYPE_INT_ARGB) เป็น สร้าง BufferedImage
nyholku

18

หากคุณต้องการจับภาพหน้าจอทั้งหมดคุณสามารถใช้รหัสต่อไปนี้:

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens = ge.getScreenDevices();

Rectangle allScreenBounds = new Rectangle();
for (GraphicsDevice screen : screens) {
    Rectangle screenBounds = screen.getDefaultConfiguration().getBounds();

    allScreenBounds.width += screenBounds.width;
    allScreenBounds.height = Math.max(allScreenBounds.height, screenBounds.height);
}

Robot robot = new Robot();
BufferedImage screenShot = robot.createScreenCapture(allScreenBounds);

4
จะดีกว่าถ้าคำนวณด้วยวิธีนี้
Brad Mace

10
public void captureScreen(String fileName) throws Exception {
   Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
   Rectangle screenRectangle = new Rectangle(screenSize);
   Robot robot = new Robot();
   BufferedImage image = robot.createScreenCapture(screenRectangle);
   ImageIO.write(image, "png", new File(fileName));
}

3
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File; 
import javax.imageio.ImageIO;
import javax.swing.*;  

public class HelloWorldFrame extends JFrame implements ActionListener {

JButton b;
public HelloWorldFrame() {
    this.setVisible(true);
    this.setLayout(null);
    b = new JButton("Click Here");
    b.setBounds(380, 290, 120, 60);
    b.setBackground(Color.red);
    b.setVisible(true);
    b.addActionListener(this);
    add(b);
    setSize(1000, 700);
}
public void actionPerformed(ActionEvent e)
{
    if (e.getSource() == b) 
    {
        this.dispose();
        try {
            Thread.sleep(1000);
            Toolkit tk = Toolkit.getDefaultToolkit(); 
            Dimension d = tk.getScreenSize();
            Rectangle rec = new Rectangle(0, 0, d.width, d.height);  
            Robot ro = new Robot();
            BufferedImage img = ro.createScreenCapture(rec);
            File f = new File("myimage.jpg");//set appropriate path
            ImageIO.write(img, "jpg", f);
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }
}

public static void main(String[] args) {
    HelloWorldFrame obj = new HelloWorldFrame();
}
}

ฉันทำเกณฑ์มาตรฐานและอันนี้ช้าที่สุดยังมีการสูญเสียมากที่สุดและขนาดไฟล์ใหญ่ที่สุด ขออภัย
Liam Larsen

3
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();  
GraphicsDevice[] screens = ge.getScreenDevices();       
Rectangle allScreenBounds = new Rectangle();  
for (GraphicsDevice screen : screens) {  
       Rectangle screenBounds = screen.getDefaultConfiguration().getBounds();        
       allScreenBounds.width += screenBounds.width;  
       allScreenBounds.height = Math.max(allScreenBounds.height, screenBounds.height);
       allScreenBounds.x=Math.min(allScreenBounds.x, screenBounds.x);
       allScreenBounds.y=Math.min(allScreenBounds.y, screenBounds.y);
      } 
Robot robot = new Robot();
BufferedImage bufferedImage = robot.createScreenCapture(allScreenBounds);
File file = new File("C:\\Users\\Joe\\Desktop\\scr.png");
if(!file.exists())
    file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
ImageIO.write( bufferedImage, "png", fos );

bufferedImage จะมีภาพหน้าจอแบบเต็มซึ่งได้รับการทดสอบกับจอภาพสามจอ


0

คุณสามารถใช้java.awt.Robotเพื่อบรรลุภารกิจนี้

ด้านล่างนี้คือรหัสของเซิร์ฟเวอร์ซึ่งจะบันทึกภาพหน้าจอเป็นภาพในไดเรกทอรีของคุณ

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.imageio.ImageIO;

public class ServerApp extends Thread
{
       private ServerSocket serverSocket=null;
       private static Socket server = null;
       private Date date = null;
       private static final String DIR_NAME = "screenshots";

   public ServerApp() throws IOException, ClassNotFoundException, Exception{
       serverSocket = new ServerSocket(61000);
       serverSocket.setSoTimeout(180000);
   }

public void run()
   {
       while(true)
      {
           try
           {
              server = serverSocket.accept();
              date = new Date();
                  DateFormat dateFormat = new SimpleDateFormat("_yyMMdd_HHmmss");
              String fileName = server.getInetAddress().getHostName().replace(".", "-");
              System.out.println(fileName);
              BufferedImage img=ImageIO.read(ImageIO.createImageInputStream(server.getInputStream()));
              ImageIO.write(img, "png", new File("D:\\screenshots\\"+fileName+dateFormat.format(date)+".png"));
              System.out.println("Image received!!!!");
              //lblimg.setIcon(img);
          }
         catch(SocketTimeoutException st)
         {
               System.out.println("Socket timed out!"+st.toString());
 //createLogFile("[stocktimeoutexception]"+stExp.getMessage());
                  break;
             }
             catch(IOException e)
             {
                  e.printStackTrace();
                  break;
         }
         catch(Exception ex)
        {
              System.out.println(ex);
        }
      }
   }

   public static void main(String [] args) throws IOException, SQLException, ClassNotFoundException, Exception{
          ServerApp serverApp = new ServerApp();
          serverApp.createDirectory(DIR_NAME);
          Thread thread = new Thread(serverApp);
            thread.start();
   }

private void createDirectory(String dirName) {
    File newDir = new File("D:\\"+dirName);
    if(!newDir.exists()){
        boolean isCreated = newDir.mkdir();
    }
 }
} 

และนี่คือรหัสไคลเอนต์ที่ทำงานบนเธรดและหลังจากนั้นไม่กี่นาทีมันก็กำลังจับภาพหน้าจอของผู้ใช้

package com.viremp.client;

import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.Socket;
import java.util.Random;

import javax.imageio.ImageIO;

public class ClientApp implements Runnable {
    private static long nextTime = 0;
    private static ClientApp clientApp = null;
    private String serverName = "192.168.100.18"; //loop back ip
    private int portNo = 61000;
    //private Socket serverSocket = null;

    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        clientApp = new ClientApp();
        clientApp.getNextFreq();
        Thread thread = new Thread(clientApp);
        thread.start();
    }

    private void getNextFreq() {
        long currentTime = System.currentTimeMillis();
        Random random = new Random();
        long value = random.nextInt(180000); //1800000
        nextTime = currentTime + value;
        //return currentTime+value;
    }

    @Override
    public void run() {
        while(true){
            if(nextTime < System.currentTimeMillis()){
                System.out.println(" get screen shot ");
                try {
                    clientApp.sendScreen();
                    clientApp.getNextFreq();
                } catch (AWTException e) {
                    // TODO Auto-generated catch block
                    System.out.println(" err"+e);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch(Exception e){
                    e.printStackTrace();
                }

            }
            //System.out.println(" statrted ....");
        }

    }

    private void sendScreen()throws AWTException, IOException {
           Socket serverSocket = new Socket(serverName, portNo);
             Toolkit toolkit = Toolkit.getDefaultToolkit();
             Dimension dimensions = toolkit.getScreenSize();
                 Robot robot = new Robot();  // Robot class 
                 BufferedImage screenshot = robot.createScreenCapture(new Rectangle(dimensions));
                 ImageIO.write(screenshot,"png",serverSocket.getOutputStream());
                 serverSocket.close();
    }
}

0

Toolkit ส่งคืนพิกเซลตาม PPI ดังนั้นภาพหน้าจอจะไม่ถูกสร้างขึ้นสำหรับทั้งหน้าจอเมื่อใช้ PPI> 100% ใน Windows ฉันเสนอให้ทำสิ่งนี้:

DisplayMode displayMode = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0].getDisplayMode();
Rectangle screenRectangle = new Rectangle(displayMode.getWidth(), displayMode.getHeight());
BufferedImage screenShot = new Robot().createScreenCapture(screenRectangle);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.