Sunday, 11 August 2013

Using robot class to take screenshot - would like to reduce filesize

Using robot class to take screenshot - would like to reduce filesize

I have a small piece of code that takes a screenshot of my desktop every
five minutes - it's the work of a moment to flick thought and work out how
many screenshots are of, say, facebook... It's very useful, but the
directories full of screenshots are getting pretty big. I'm looking for
ways to reduce the filesize of the images - I don't need them to be full
perfect screenshot quality - I'd like to be able to just reduce the
overall quality of the image - perhaps use a more lossy format or ask
robot to save in grayscale.
I'm asking ways I can modify the below code so that the resulting images
take up less filespace, and I'm willing to tolerate quite a high level of
quality loss in the process.
/**
* Code modified from code given in
http://whileonefork.blogspot.co.uk/2011/02/java-multi-monitor-screenshots.html
following a SE question at
*
http://stackoverflow.com/questions/10042086/screen-capture-in-java-not-capturing-whole-screen
and then modified by a code review at
http://codereview.stackexchange.com/questions/10783/java-screengrab
*/
package com.tmc.personal;
import java.awt.AWTException;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
class ScreenCapture {
static int minsBetweenScreenshots = 5;
public static void main(String args[]) {
int indexOfPicture = 1000;// should be only used for naming file...
while (true) {
takeScreenshot("ScreenCapture" + indexOfPicture++);
try {
TimeUnit.MINUTES.sleep(minsBetweenScreenshots);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//from http://www.coderanch.com/t/409980/java/java/append-file-timestamp
private final static String getDateTime()
{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd_hh:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("PST"));
return df.format(new Date());
}
public static void takeScreenshot(String filename) {
Rectangle allScreenBounds = getAllScreenBounds();
Robot robot;
try {
robot = new Robot();
BufferedImage screenShot =
robot.createScreenCapture(allScreenBounds);
ImageIO.write(screenShot, "jpg", new File(filename +
getDateTime()+ ".jpg"));
} catch (AWTException e) {
System.err.println("Something went wrong starting the robot");
e.printStackTrace();
} catch (IOException e) {
System.err.println("Something went wrong writing files");
e.printStackTrace();
}
}
/**
* Okay so all we have to do here is find the screen with the lowest
x, the
* screen with the lowest y, the screen with the higtest value of X+
width
* and the screen with the highest value of Y+height
*
* @return A rectangle that covers the all screens that might be
nearby...
*/
private static Rectangle getAllScreenBounds() {
Rectangle allScreenBounds = new Rectangle();
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens = ge.getScreenDevices();
int farx = 0;
int fary = 0;
for (GraphicsDevice screen : screens) {
Rectangle screenBounds =
screen.getDefaultConfiguration().getBounds();
// finding the one corner
if (allScreenBounds.x > screenBounds.x) {
allScreenBounds.x = screenBounds.x;
}
if (allScreenBounds.y > screenBounds.y) {
allScreenBounds.y = screenBounds.y;
}
// finding the other corner
if (farx < (screenBounds.x + screenBounds.width)) {
farx = screenBounds.x + screenBounds.width;
}
if (fary < (screenBounds.y + screenBounds.height)) {
fary = screenBounds.y + screenBounds.height;
}
allScreenBounds.width = farx - allScreenBounds.x;
allScreenBounds.height = fary - allScreenBounds.y;
}
return allScreenBounds;
}
}

No comments:

Post a Comment