0

我正在使用返回 BufferedImage 的 Robot 的 screenCapture 方法,然后使用 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);
    }

我究竟做错了什么?

4

1 回答 1

0

OutOfMemory 错误在使用BufferedImage时并不少见,这是因为 BufferedImage 使用内存中未压缩的图像,因此 JPEG 编码并在磁盘上占用 300kb 的图像可能会占用 10mb 的内存,这取决于您如何处理图像大小调整过程可以占用更多(通过创建大量的 BufferedImages)。

我对您的建议是使用图像缩放库,例如imgscalr,我过去曾成功使用 imgscalr 来提高遗留 Java 应用程序的内存使用率,该应用程序疯狂地使用 BufferedImages 来调整图像大小

使用 imgscalr 可以很简单:

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

于 2013-06-24T13:12:52.653 回答