Sunday, November 13, 2016

Create Desktop Screenshot Maker Software using Java

In this blog post we will learn to create a Java program which can take screenshots from your desktop. It will also support taking screenshots of a selected region.

Features of the software:
1) Take Screenshots of a selected region or fullscreen
2) You can press F6 to start taking Screenshots and F8 to exit from the application
3) Once you press F6, just select the screenshot region by dragging your mouse and a screenshot would be created for selected region.
4) All screenshots are kept at same directory from where program is run

Logic Used:
1) Java can take screenshots using Robot class
2) It can act on custom key like F6 & F8 using JNI (https://cooltrickshome.blogspot.in/2016/11/creating-your-personal-keylogger-from.html)
3) Challenge is how we can make user select region of a screen for which he want to take screenshot.
 A) We take the full size screenshot of the user screen and show the same screenshot as background image of a full window JFrame.
 B) When user drags the region, he is actually dragging the region from the background image of a JFrame. Hence we can show a rectangle for the selection region.

Running Software:

Please find a working copy of the software at:
https://github.com/csanuragjain/recorder/blob/master/DesktopScreenshotMaker/Software/DesktopScreenshotMaker.zip?raw=true

Unzip it and then Use below command to run (make sure you use 64 bit java)
 java -jar DesktopScreenshotMaker.jar  

Source Code:
https://github.com/csanuragjain/recorder/tree/master/DesktopScreenshotMaker/Code

Language Used:
Java, C++

C++ Usage:

C++ captures all the user keys and passes them to Java using JNI (Already discussed in https://cooltrickshome.blogspot.in/2016/11/creating-your-personal-keylogger-from.html)
When user press F6 then Java program starts the screen capture module and likewise when it receives F8 then it exits.

Java Usage:

DesktopScreenshot.java

Variables:
 public class DesktopScreenshot implements MouseListener,  
           MouseMotionListener {  
      int drag_status = 0;  
      int c1;  
      int c2;  
      int c3;  
      int c4;  
      JFrame frame=null;  
      static int counter=0;  
      JLabel background=null;  
      static  
      {  
           System.loadLibrary("MyLogger");  
      }  
      public static native int GetKey();  

Explanation:
1) drag_status tells if mouse is currently dragging a region or not
2) c1,c2,c3,c4 defines the coordinate of the region for which screenshot would be taken
3)  Screenshot are saved as screenshot<counter>.jpg so counter will help naming screenshot files.
4) MyLogger is the dll which is tracking the user key input
5) GetKey gives the key input by user.

Main method:
      public static void main(String args[]) throws AWTException, IOException, InterruptedException  
      {  
           DesktopScreenshot ds=new DesktopScreenshot();  
           System.out.println("Press F6 and then drag your mouse to take screenshot. For exiting press F8");  
           while(true)  
           {  
           int d=GetKey();  
           if(d==117)  
           {  
                ds.getImage();  
           }  
           else  
                if(d==119)  
                {  
                     System.exit(0);  
                }  
           }  
      }  

Explanation:
1) We make an infinite loop and keep track of all user key pressed
2) If key input is 117 which is the code for F6 then we call the screenshot maker module getImage
3) If key input is 119 which is code for F8 then program exits using System.exit

getImage method:
      public void getImage() throws AWTException, IOException, InterruptedException {  
           Dimension size = Toolkit.getDefaultToolkit().getScreenSize();  
        Robot robot = new Robot();  
        BufferedImage img = robot.createScreenCapture(new Rectangle(size));  
        ImagePanel panel = new ImagePanel(img);  
        frame=new JFrame();  
        frame.add(panel);  
        frame.setLocation(0, 0);  
        frame.setSize(size);  
        frame.setLayout(new FlowLayout());  
        frame.setUndecorated(true);  
        frame.setVisible(true);  
        frame.addMouseListener(this);  
        frame.addMouseMotionListener(this);  
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);  
      }  

Explanation:
1) Toolkit.getDefaultToolkit().getScreenSize() is used to determine the size of screen
2) Now we use the createScreenCapture method of Robot class to capture the screen. Full screen would be captured since we pass the size to be screen size
3) We have made a custom ImagePanel class which would add the screenshot captured on a Frame
4) Now we create a frame and add the panel containing the screenshot of the screen.
5) We set the function setUndecorated to true so that the frame appears without any title bar
6) We add mouse listener so that user can crop the regions from the screenshot in the frame as discussed later.

Mouse events:
      public void mouseClicked(MouseEvent arg0) {  
      }  
      public void mouseEntered(MouseEvent arg0) {  
      }  
      public void mouseExited(MouseEvent arg0) {  
      }  
      public void mouseMoved(MouseEvent arg0) {  
      }  
      public void mousePressed(MouseEvent arg0) {  
           paint();  
           this.c1 = arg0.getX();  
           this.c2 = arg0.getY();  
      }  
      public void mouseDragged(MouseEvent arg0) {  
           paint();  
           this.drag_status = 1;  
           this.c3 = arg0.getX();  
           this.c4 = arg0.getY();  
      }  
      public void mouseReleased(MouseEvent arg0) {  
           paint();  
           if (this.drag_status == 1) {  
                this.c3 = arg0.getX();  
                this.c4 = arg0.getY();  
                try {  
                     draggedScreen();  
                } catch (Exception e) {  
                     e.printStackTrace();  
                }  
           }  
      }  
      public void paint() {  
           Graphics g = frame.getGraphics();  
           frame.repaint();  
           int w = this.c1 - this.c3;  
           int h = this.c2 - this.c4;  
           w *= -1;  
           h *= -1;  
           if (w < 0) {  
                w *= -1;  
           }  
           g.drawRect(this.c1, this.c2, w, h);  
      }  
      public void draggedScreen() throws Exception {  
           int w = this.c1 - this.c3;  
           int h = this.c2 - this.c4;  
           w *= -1;  
           h *= -1;  
           Robot robot = new Robot();  
           BufferedImage img = robot.createScreenCapture(new Rectangle(this.c1,  
                     this.c2, w, h));  
           counter++;  
           File save_path = new File("screenshot"+counter+".jpg");  
           ImageIO.write(img, "JPG", save_path);  
           c1=0;  
           c2=0;  
           c3=0;  
           c4=0;       
           frame.disable();  
           frame.dispose();  
           new File("desktop.jpg").delete();  
      }  

Explanation:
1) When mouse is pressed we record the starting coordinate in c1 & c2
2) When mouse is dragged then we record the ending coordinate in c3 & c4. We call the paint method which starts drawing the rectangle to show the selected region described by (c1,c2) & (c3,c4)
3) When mouse is released we get the final region for which screenshot need to taken and update c3 and c4.
4) We call draggedScreen method which simply takes the screenshot of the region selected by user and saves it using ImageIO write method.

ImagePanel.java
 package com.cooltrickshome;  
 import java.awt.Dimension;  
 import java.awt.Graphics;  
 import java.awt.Image;  
 import javax.swing.ImageIcon;  
 import javax.swing.JPanel;  
 class ImagePanel  
  extends JPanel  
 {  
  private Image img;  
  public ImagePanel(String img)  
  {  
   this(new ImageIcon(img).getImage());  
  }  
  public ImagePanel(Image img)  
  {  
   this.img = img;  
   Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));  
   setPreferredSize(size);  
   setMinimumSize(size);  
   setMaximumSize(size);  
   setSize(size);  
   setLayout(null);  
  }  
  public void paintComponent(Graphics g)  
  {  
   g.drawImage(this.img, 0, 0, null);  
  }  
 }  

Explanation:
1) We determine the height and width of the image passed
2) We make the JPanel with same size
3) We draw the image over JPanel using Graphics drawImage method.

Sample Screenshot:


Full Code:
DesktopScreenshot.java
 package com.cooltrickshome;  
 import java.awt.AWTException;  
 import java.awt.Dimension;  
 import java.awt.FlowLayout;  
 import java.awt.Graphics;  
 import java.awt.Rectangle;  
 import java.awt.Robot;  
 import java.awt.Toolkit;  
 import java.awt.event.MouseEvent;  
 import java.awt.event.MouseListener;  
 import java.awt.event.MouseMotionListener;  
 import java.awt.image.BufferedImage;  
 import java.io.File;  
 import java.io.IOException;  
 import javax.imageio.ImageIO;  
 import javax.swing.JFrame;  
 import javax.swing.JLabel;  
 public class DesktopScreenshot implements MouseListener,  
           MouseMotionListener {  
      int drag_status = 0;  
      int c1;  
      int c2;  
      int c3;  
      int c4;  
      JFrame frame=null;  
      static int counter=0;  
      JLabel background=null;  
      static  
      {  
           System.loadLibrary("MyLogger");  
      }  
      public static native int GetKey();  
      /**  
       * @param args  
       * @throws AWTException   
       * @throws IOException   
       * @throws InterruptedException   
       */  
      public static void main(String args[]) throws AWTException, IOException, InterruptedException  
      {  
           DesktopScreenshot ds=new DesktopScreenshot();  
           System.out.println("Press F6 and then drag your mouse to take screenshot. For exiting press F8");  
           while(true)  
           {  
           int d=GetKey();  
           if(d==117)  
           {  
                ds.getImage();  
           }  
           else  
                if(d==119)  
                {  
                     System.exit(0);  
                }  
           }  
      }  
      public void getImage() throws AWTException, IOException, InterruptedException {  
           Dimension size = Toolkit.getDefaultToolkit().getScreenSize();  
        Robot robot = new Robot();  
        BufferedImage img = robot.createScreenCapture(new Rectangle(size));  
        ImagePanel panel = new ImagePanel(img);  
        frame=new JFrame();  
        frame.add(panel);  
        frame.setLocation(0, 0);  
        frame.setSize(size);  
        frame.setLayout(new FlowLayout());  
        frame.setUndecorated(true);  
        frame.setVisible(true);  
        frame.addMouseListener(this);  
        frame.addMouseMotionListener(this);  
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);  
      }  
      public void draggedScreen() throws Exception {  
           int w = this.c1 - this.c3;  
           int h = this.c2 - this.c4;  
           w *= -1;  
           h *= -1;  
           Robot robot = new Robot();  
           BufferedImage img = robot.createScreenCapture(new Rectangle(this.c1,  
                     this.c2, w, h));  
           counter++;  
           File save_path = new File("screenshot"+counter+".jpg");  
           ImageIO.write(img, "JPG", save_path);  
           c1=0;  
           c2=0;  
           c3=0;  
           c4=0;       
           frame.disable();  
           frame.dispose();  
           new File("desktop.jpg").delete();  
      }  
      public void mouseClicked(MouseEvent arg0) {  
      }  
      public void mouseEntered(MouseEvent arg0) {  
      }  
      public void mouseExited(MouseEvent arg0) {  
      }  
      public void mousePressed(MouseEvent arg0) {  
           paint();  
           this.c1 = arg0.getX();  
           this.c2 = arg0.getY();  
      }  
      public void mouseReleased(MouseEvent arg0) {  
           paint();  
           if (this.drag_status == 1) {  
                this.c3 = arg0.getX();  
                this.c4 = arg0.getY();  
                try {  
                     draggedScreen();  
                } catch (Exception e) {  
                     e.printStackTrace();  
                }  
           }  
      }  
      public void mouseDragged(MouseEvent arg0) {  
           paint();  
           this.drag_status = 1;  
           this.c3 = arg0.getX();  
           this.c4 = arg0.getY();  
      }  
      public void mouseMoved(MouseEvent arg0) {  
      }  
      public void paint() {  
           Graphics g = frame.getGraphics();  
           frame.repaint();  
           int w = this.c1 - this.c3;  
           int h = this.c2 - this.c4;  
           w *= -1;  
           h *= -1;  
           if (w < 0) {  
                w *= -1;  
           }  
           g.drawRect(this.c1, this.c2, w, h);  
      }  
 }  

ImagePanel.java
 package com.cooltrickshome;  
 import java.awt.Dimension;  
 import java.awt.Graphics;  
 import java.awt.Image;  
 import javax.swing.ImageIcon;  
 import javax.swing.JPanel;  
 class ImagePanel  
  extends JPanel  
 {  
  private Image img;  
  public ImagePanel(String img)  
  {  
   this(new ImageIcon(img).getImage());  
  }  
  public ImagePanel(Image img)  
  {  
   this.img = img;  
   Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));  
   setPreferredSize(size);  
   setMinimumSize(size);  
   setMaximumSize(size);  
   setSize(size);  
   setLayout(null);  
  }  
  public void paintComponent(Graphics g)  
  {  
   g.drawImage(this.img, 0, 0, null);  
  }  
 }  

DLL:
https://github.com/csanuragjain/recorder/blob/master/DesktopScreenshotMaker/Code/dll/MyLogger.dll?raw=true

Hope it helps :)

No comments:

Post a Comment