Existe-t-il un moyen de prendre une capture d'écran en utilisant Java et de l'enregistrer dans une sorte d'image?


128

Simple comme l'indique le titre: pouvez-vous utiliser uniquement des commandes Java pour prendre une capture d'écran et l'enregistrer? Ou dois-je utiliser un programme spécifique au système d'exploitation pour prendre la capture d'écran, puis la récupérer dans le presse-papiers?



Je n'ai jamais su que ce serait si simple.
jjnguy

2
Grâce à cette question, j'ai écrit un tutoriel pour les débutants absolus sur mon blog: thepcwizard.in/2012/12/java-screen-capturing-tutorial.html
ThePCWizard

Réponses:


187

Croyez-le ou non, vous pouvez en fait utiliser java.awt.Robotpour "créer une image contenant des pixels lus à l'écran". Vous pouvez ensuite écrire cette image dans un fichier sur le disque.

Je viens de l'essayer, et le tout se termine comme:

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

REMARQUE: cela ne capturera que le moniteur principal. Voir GraphicsConfiguration pour la prise en charge de plusieurs moniteurs.


1
Je me demande si c'est ce qu'utilisent les applications de partage d'écran comme Elluminate ( elluminate.com ).
Chris Wagner

@java_enthu en fait oui, cela fonctionnera sans console si vous codez en dur le chemin de la capture d'écran dans votre application.
Dmitry Zagorulkin

2
Robot n'inclut pas la souris dans la capture d'écran. Existe-t-il une fonction similaire qui fait exactement la même chose, mais qui inclut la souris?
nullUser le

3
existe-t-il également un moyen de capturer le curseur de la souris?!
Mehdi Karamosly

23

Je n'ai jamais aimé utiliser Robot, j'ai donc créé ma propre méthode simple pour faire des captures d'écran d'objets 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
Une raison pour laquelle vous n'aimez pas Robot?
Simon Forsberg

2
Pensez-y simplement comme une question de goût.
DejanLekic

3
Il semble que cela devrait avoir l'avantage de fonctionner même si la fenêtre cible est obscurcie avant la capture d'écran.
Brad Mace

7
D'un autre côté, cela n'obtient que le contenu de la fenêtre, alors qu'avec Robotvous pouvez également obtenir le cadre et la barre de titre de la fenêtre.
Brad Mace

1
Pour les affichages HiDPI (Mac retina), cela crée des captures d'écran à demi-résolution. Pour corriger cet appel bufferedImage.getGraphics (). Scale (2, 2) avant l'appel argFrame.paint (bufferedImage.getGraphics ()) et utiliser new BufferedImage (rec.width * 2, rec.height * 2, BufferedImage.TYPE_INT_ARGB) pour créer la BufferedImage
nyholku

18

Si vous souhaitez capturer tous les moniteurs, vous pouvez utiliser le code suivant:

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
serait préférable de le calculer de cette façon
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();
}
}

J'ai fait un benchmark et celui-ci est le plus lent, a également la plus grande perte et la plus grande taille de fichier. Désolé,
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 contiendra une capture d'écran complète, cela a été testé avec trois moniteurs


0

Vous pouvez utiliser java.awt.Robot pour accomplir cette tâche.

ci-dessous se trouve le code du serveur, qui enregistre la capture d'écran capturée comme image dans votre annuaire.

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

Et c'est le code client qui s'exécute sur le thread et après quelques minutes, il capture la capture d'écran de l'écran de l'utilisateur.

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 renvoie des pixels basés sur PPI, par conséquent, une capture d'écran n'est pas créée pour tout l'écran lors de l'utilisation de PPI> 100% sous Windows. Je propose de faire ceci:

DisplayMode displayMode = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0].getDisplayMode();
Rectangle screenRectangle = new Rectangle(displayMode.getWidth(), displayMode.getHeight());
BufferedImage screenShot = new Robot().createScreenCapture(screenRectangle);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.