【问题标题】:Java- Convert bufferedimage to byte[] without writing to diskJava-将缓冲图像转换为字节[]而不写入磁盘
【发布时间】:2012-04-20 13:22:37
【问题描述】:

我正在尝试使用 java 通过套接字发送多个图像,但我需要一种更快的方法将图像转换为字节数组,以便我可以发送它们。我尝试了以下代码,但它向我的 C:\ 驱动器写入了大约 10,000 张图像。有没有办法在不写入磁盘的情况下进行这种转换?谢谢!

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

                    //ImageIO.setUseCache(false);
                    ImageIO.write(bi.getImage(), "jpg", outputStream);

                    byte[] imageBytes = outputStream.toByteArray();

【问题讨论】:

  • 请注意,使用较高压缩率(较低质量)JPEG 进行图像压缩的额外时间可以节省大量网络时间。我认为您需要考虑实际发送的字节大小,纯BufferedImage 会明显更大。顺便说一句 - 这些图像的来源是什么?例如,如果是屏幕截图,通常 PNG 可以提供比默认压缩 JPEG 更小的字节大小。如果是连续截图,甚至可能是视频流。
  • 来源是连续的截图,我基本上是在制作流。但是,是的,我需要弄清楚如何压缩图像而不将它们写入磁盘。这是我的终极目标

标签: java byte bufferedimage


【解决方案1】:

这应该可行:

byte[] imageBytes = ((DataBufferByte) bufferedImage.getData().getDataBuffer()).getData();

【讨论】:

  • 这将创建图像的副本。如果您只想直接引用字节,请调用 bufferedImage.getRaster().getDataBuffer() 并相应地进行转换(转换为 DataBufferByte 并不总是安全的)
  • 这似乎对我不起作用。我得到java.awt.image.DataBufferInt cannot be cast to java.awt.image.DataBufferByte 我的缓冲图像来自Robot.createScreenCapture() 不确定这是否重要
  • @user3712476 似乎 Robot 不是 JRE 库中的类,您可以尝试将其分配给 DataBufferInt 类型的变量并将其转换为 DataBufferInt 。
  • bufferedImage.getData().getDataBuffer() 正在为缓冲图像创建无效字节数组
【解决方案2】:

下面的代码真的很快(几毫秒)

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public byte[] toByteArray(BufferedImage image) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();            
    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baos);
    encoder.encode(image);            
    return baos.toByteArray();
}

【讨论】:

【解决方案3】:
ByteArrayOutputStream baos;
ImageIO.write(bufferedImage, "png", baos);
byte[] imageBytes = baos.toByteArray();

【讨论】:

    【解决方案4】:

    尝试使用:

    ImageIO.setUseCache(false);
    

    在写作之前,也许这会有所帮助。

    【讨论】:

    • 我试过了,但是,我相信这仍然会写入磁盘,它只是在操作完成后将其删除。
    • 不应该,至少根据文档:Setting this flag to false disallows the use of disk for future streams, which may be advantageous when working with small images, as the overhead of creating and destroying files is removed.。也许您的程序会在其他地方写入磁盘?
    • 是的,我在文档中也看到了这一点。无论哪种方式,对于我想要做的事情来说,操作都非常缓慢。不过还是谢谢。
    • AFAIU setUseCache() 标志仅适用于从流中读取图像时的输入流。 ImageIO 要么将其加载到内存中,要么将其移动到磁盘(当使用 cache = true 时),以支持 InputStream 通常无法实现的各种随机访问操作。但是文件格式解析器(对 ImageInputStream 进行操作)将始终创建一个 BufferedImage 作为结果,它将完全在内存中并且未压缩。只有 Java Advanced Imaging 具有解析器来支持基于图块的读取和转换,而无需将整个图像存储在内存中。
    【解决方案5】:
    BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
    byte[] bytes = new byte[buf.capacity()];
    buf.get(bytes, 0, bytes.length);
    

    【讨论】:

      【解决方案6】:

      使用 Apache Commons IO Utils Apache Commons

      IOUtils.copy(inputStream,outputStream);

      IO Utils API 轻松支持大缓冲区

      【讨论】:

        猜你喜欢
        • 2017-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多