4

以下代码使用十二猴子创建一个 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();
}
4

1 回答 1

3

为了防止ImageIO创建缓存的磁盘ImageOutputStream,您可以调用 static ImageIO.setUseCache(false)。这里的问题是它将禁用 global 的磁盘缓存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(..)包装 aByteArrayOutputStream来保存结果。

例子:

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

第三种选择(可能稍微更有效)是子类ImageOutputStreamImpl化和实现自己,使用更花哨的东西,比如内存ByteChannel或 aByteBuffer作为支持。很酷的一点是,您可以使用内存映射文件或堆外内存。但它需要更多的努力来实施。

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

于 2016-02-07T20:55:21.493 回答