使用robot类截屏-希望减少文件大小



我有一小段代码,每五分钟拍一次我的桌面截图-这是一个瞬间的工作,可以快速思考并计算出有多少截图,比如说,facebook。。。它非常有用,但充满屏幕截图的目录越来越大。我正在寻找减少图像文件大小的方法-我不需要它们具有完全完美的屏幕截图质量-我希望能够降低图像的整体质量-也许可以使用更有损的格式,或者让机器人以灰度保存。

我想知道如何修改下面的代码,使生成的图像占用更少的文件空间,并且我愿意在这个过程中承受相当高的质量损失。

/**
 * 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;
    }
}

为什么不简单地缩放您收到的图像:

  BufferedImage img = robot.createScreenCapture(allScreenBounds);
  // scaledWidth and scaledHeight are the new smaller image size
  Image scaledImg = img.getScaledInstance(scaledWidth, scaledHeight,
        BufferedImage.SCALE_AREA_AVERAGING);

如果您需要新图像为BufferedImage,则:

  BufferedImage scaledBufferedImg = new BufferedImage(scaledWidth, scaledHeight,
        BufferedImage.TYPE_INT_ARGB);
  Graphics g = scaledBufferedImg.getGraphics();
  g.drawImage(scaledImg, 0, 0, null);
  g.dispose();

除了按"悬停满鳗鱼"回答缩放图像外,您还可以尝试将jpeg质量设置为低于默认值:

Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer = (ImageWriter)iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(0.5);   // integer between 0 and 1

此外,根据您拍摄的屏幕截图的类型,您可能会通过使用基于调色板的不同图像文件格式(如PNG(8位)或GIF)来缩小文件大小。与jpeg相比,当图像包含相同颜色的频繁块中出现的有限颜色集时,这些格式可以使用更小的文件大小。。。像许多传统的GUI应用程序屏幕截图一样。

最新更新