如何将 ImageOutputStream 的流保存在内存中?

How to keep the stream of ImageOutputStream in memory?

以下代码使用 twelvemonkeys 创建一个 tiff 文件。创建的文件会自动刷新到磁盘。但我希望该文件仅在内存中创建。如何使用 ImageOutputStream 实现此目的?

try {
  // Create output stream
  ImageOutputStream output = ImageIO.createImageOutputStream(targetFile);

  try {
    writer.setOutput(output);

    ImageWriteParam param = writer.getDefaultWriteParam();
    TIFFImageWriteParam tiffWriteParam = (TIFFImageWriteParam) param;
    tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);     

    TIFFImageMetadata metadata = (TIFFImageMetadata) createMetadata(sourceFile);     

    // Set dpi
    String nativeFormat = TIFFMedataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME;
    // Node nativeTree = metadata.getAsTree(nativeFormat);
    IIOMetadataNode newTree =
        new IIOMetadataNode("com_sun_media_imageio_plugins_tiff_image_1.0");
    IIOMetadataNode ifdNode = new IIOMetadataNode("TIFFIFD");
    newTree.appendChild(ifdNode);
    createTIFFFieldNode(ifdNode, TIFF.TAG_RESOLUTION_UNIT, TIFF.TYPE_SHORT, 2);
    createTIFFFieldNode(ifdNode, TIFF.TAG_X_RESOLUTION, TIFF.TYPE_RATIONAL, new Rational(300));
    createTIFFFieldNode(ifdNode, TIFF.TAG_Y_RESOLUTION, TIFF.TYPE_RATIONAL, new Rational(300));
    metadata.mergeTree(nativeFormat, newTree);

    IIOImage iioimage = new IIOImage(image, null, metadata);
    writer.write(metadata, iioimage, tiffWriteParam);
  } finally {      
    output.close();
  }
} finally {  
  writer.dispose();
}

要防止 ImageIO 创建缓存磁盘 ImageOutputStream,您可以调用静态 ImageIO.setUseCache(false)。这里的问题是,它将禁用 ImageIO 全局 的磁盘缓存,这可能是不可取的。此外,您需要使用 ByteArrayOutputStream 或其他内存结构来实际存储 TIFF 图像数据。

例如:

ImageIO.setUseCache(false);  // Typically in a static initializer somewhere

...

ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (ImageOutputStream output = ImageIO.createImageOutputStream(bytes)) {
    ... // Write image & meta data
}

另一个不影响 ImageIO 全局的选项是替换 ImageIO.createImageOutputStream(...) 调用并创建一个 new MemoryCacheImageOutputStream(..) 包装一个 ByteArrayOutputStream 来保存结果。

示例:

ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (ImageOutputStream output = new MemoryCacheImageOutputStream(bytes)) {
    ... // Write image & meta data
}

第三个选项(可能稍微更有效)是继承 ImageOutputStreamImpl 并自己实现,使用更奇特的东西,如内存中 ByteChannelByteBuffer 作为支持。这很酷,显然你可以使用内存映射文件或堆外内存。但它需要更多的努力来实施。

我可能会选择第二个选项,除非分析或以其他方式告诉您这对您来说效果不够好,然后研究选项三。