【问题标题】:Robot screen capture - heap OutOfMemory while resizing机器人屏幕截图 - 调整大小时堆 OutOfMemory
【发布时间】:2013-06-24 12:48:33
【问题描述】:

我正在使用 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);
    }

我做错了什么?

【问题讨论】:

  • public static ByteArrayOutputStream resizeImage( 代码是否包含对这些 BAIS 实例的引用?为了尽快获得更好的帮助,请发帖SSCCE
  • 你的意思是ByteArrayOutputStream吗? resizeImage 在通过套接字发送该对象后返回 ByteArrayOutputStream 对象我正在关闭它... ot = new DataOutputStream(s.getOutputStream());字节 [] 图像数据 = 空;尝试 (ByteArrayOutputStream baos = screenCap(new Rectangle(0,0,1000,500))) { byte[] bytesOut = baos.toByteArray(); imageData = encodeImage(bytesOut); ot.writeLong(imageData.length); ot.write(imageData); ot.flush(); } 捕捉(异常 e){ }
  • “你的意思是..” 我的意思是发布SSCCE 另外,不要将代码放入cmets,它是不可读的.

标签: java out-of-memory bufferedimage awtrobot


【解决方案1】:

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

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

使用 imgscalr 可以很简单:

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

【讨论】:

  • 这会减少 bufferedImage 中的像素数量,但是我想要相同的像素数量,但通过降低质量来减小尺寸......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-20
  • 1970-01-01
  • 1970-01-01
  • 2016-04-20
  • 1970-01-01
  • 2017-05-08
相关资源
最近更新 更多