Có cách nào để chụp ảnh màn hình bằng Java và lưu nó vào một số loại hình ảnh không?


128

Đơn giản như tiêu đề nêu: Bạn có thể chỉ sử dụng các lệnh Java để chụp ảnh màn hình và lưu nó không? Hoặc, tôi có cần sử dụng một chương trình cụ thể cho hệ điều hành để chụp ảnh màn hình và sau đó lấy nó ra khỏi bảng tạm không?



Tôi không bao giờ biết nó sẽ đơn giản như vậy.
jjnguy

2
Nhờ câu hỏi này, tôi đã viết một hướng dẫn cho người mới bắt đầu tuyệt đối trên blog của mình: thepcwizard.in/2012/12/java-screen-capturing-tutorial.html
ThePCWizard

Câu trả lời:


187

Dù bạn có tin hay không, bạn thực sự có thể sử dụng java.awt.Robotđể "tạo một hình ảnh chứa các pixel được đọc từ màn hình." Sau đó bạn có thể ghi hình ảnh đó vào một tệp trên đĩa.

Tôi vừa thử nó, và toàn bộ kết thúc như:

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

LƯU Ý: Điều này sẽ chỉ chụp màn hình chính. Xem GraphicsConfiguration để được hỗ trợ nhiều màn hình.


1
Tôi tự hỏi nếu đây là những gì các ứng dụng chia sẻ màn hình như Elluminate ( elluminate.com ) sử dụng.
Chris Wagner

@java_enthu thực sự là có, nó sẽ hoạt động mà không có giao diện điều khiển nếu bạn sẽ mã hóa đường dẫn đến ảnh chụp màn hình trong ứng dụng của mình.
Dmitry Zagorulkin

2
Robot không bao gồm chuột trong chụp màn hình. Có một chức năng tương tự làm điều tương tự chính xác, nhưng DOES bao gồm chuột?
null Người dùng

3
Có cách nào để bắt con trỏ chuột không?!
Mehdi Karamosly

23

Tôi chưa bao giờ thích sử dụng Robot, vì vậy tôi đã tạo ra phương pháp đơn giản của riêng mình để tạo ảnh chụp màn hình các đối tượng 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
Bất kỳ lý do tại sao bạn không thích Robot?
Simon Forsberg

2
Hãy nghĩ về nó đơn giản là một vấn đề của hương vị.
DejanLekic

3
Có vẻ như điều này sẽ có lợi thế làm việc ngay cả khi cửa sổ mục tiêu bị che khuất trước khi chụp ảnh màn hình.
Brad Mace

7
Mặt khác, điều này chỉ nhận được nội dung của cửa sổ, trong khi với Robotbạn cũng có thể lấy khung và thanh tiêu đề của cửa sổ.
Brad Mace

1
Đối với màn hình HiDPI (Mac retina), điều này tạo ra ảnh chụp màn hình ở độ phân giải một nửa. Để sửa lỗi bufferedImage.getGraphics (). (2, 2) trước lệnh argFrame.paint (bufferedImage.getGraphics ()) và sử dụng BufferedImage mới (rec. Thong * 2, rec.height * 2, BufferedImage.TYPE_INT_AR) tạo BufferedImage
nyholku

18

Nếu bạn muốn chụp tất cả các màn hình, bạn có thể sử dụng mã sau:

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
sẽ tốt hơn để tính toán theo cách này
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();
}
}

Tôi đã làm một điểm chuẩn và cái này là chậm nhất, cũng có tổn thất lớn nhất và kích thước tệp lớn nhất. Xin lỗi,
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 sẽ chứa một ảnh chụp màn hình đầy đủ, điều này đã được thử nghiệm với ba màn hình


0

Bạn có thể sử dụng java.awt.Robotđể đạt được nhiệm vụ này.

bên dưới là mã của máy chủ, lưu ảnh chụp màn hình dưới dạng hình ảnh trong Thư mục của bạn.

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

Và đây là mã Client đang chạy trên luồng và sau vài phút, nó sẽ chụp ảnh màn hình của màn hình người dùng.

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

Bộ công cụ trả về pixel dựa trên PPI, do đó, ảnh chụp màn hình không được tạo cho toàn bộ màn hình khi sử dụng PPI> 100% trong Windows. Tôi đề nghị làm điều này:

DisplayMode displayMode = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0].getDisplayMode();
Rectangle screenRectangle = new Rectangle(displayMode.getWidth(), displayMode.getHeight());
BufferedImage screenShot = new Robot().createScreenCapture(screenRectangle);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.