机器人屏幕捕获 - 在调整大小时堆叠OutOfMemory

时间:2013-06-24 12:48:33

标签: java out-of-memory bufferedimage awtrobot

我正在使用Robot的screenCapture方法返回BufferedImage,然后使用Socket发送到Android上的客户端。如果我不降低质量,那么它工作正常,但它非常慢,因为图像很大,需要很长时间才能发送。 我正在尝试降低BufferedImage的质量(使用ImageResizer类),但它的工作时间非常有限,然后在服务器端崩溃....它给了我以下异常

Exception in thread "Thread-7" Exception in thread "Thread-8" java.lang.OutOfMemoryError: Java heap space
    at sun.awt.windows.WRobotPeer.getRGBPixels(WRobotPeer.java:64)
    at java.awt.Robot.createScreenCapture(Robot.java:444)
    at SystemController.screenCap(SystemController.java:71)
    at Server$ImageServer.run(Server.java:356)
    at java.lang.Thread.run(Thread.java:722)**

我正在使用以下课程来调整大小

public class ImageResizer {
    public static ByteArrayOutputStream resizeImage(BufferedImage image) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            float quality = 0.3f; // Change this as needed
            // get all image writers for JPG format
            Iterator<ImageWriter> writers = ImageIO
                    .getImageWritersByFormatName("jpg");
            if (!writers.hasNext()) {
                throw new IllegalStateException("No writers found");
            }
            ImageWriter writer = writers.next();
            //ImageOutputStream ios = ImageIO.createImageOutputStream(os);
            try (ImageOutputStream ios = ImageIO.createImageOutputStream(out)) {
                writer.setOutput(ios);
                // set compression quality
                ImageWriteParam param = writer.getDefaultWriteParam();
                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                param.setCompressionQuality(quality);
                writer.write(null, new IIOImage(image, null, null), param);
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return out;
    }
}

此方法用于捕获

public ByteArrayOutputStream screenCap(Rectangle captureSize, int i) {
        robot = new Robot();
        screenImage = robot.createScreenCapture(captureSize);
        return ImageResizer.resizeImage(screenImage);
    }

我做错了什么?

1 个答案:

答案 0 :(得分:0)

OutOfMemory错误在使用BufferedImage时并不罕见,因为BufferedImage与内存中的未压缩图像一起使用,因此JPEG编码的图像在光盘上可能需要300kb,这可能占用10mb内存,具体取决于方式你可以处理图像大小调整过程,这可以占用更多(通过创建很多BufferedImages)。

我的建议是使用像imgscalr这样的图像缩放库,过去我曾经使用imgscalr来改善使用BufferedImages疯狂调整图像的传统Java应用程序的内存使用情况

使用imgscalr可以很简单:

BufferedImage thumbnail = Scalr.resize(image, 150);