Как сохранить поток ImageOutputStream в памяти?
Следующий код использует двенадцать обезьян для создания файла 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();
}
1 ответ
Предотвращать 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
и реализовать себя, используя что-то более причудливое, например, в памяти ByteChannel
или ByteBuffer
как поддержка. Крутая вещь в этом, очевидно, что вы можете использовать отображенные в памяти файлы или память вне кучи. Но для его реализации потребуются дополнительные усилия.
Я, вероятно, пойду со вторым вариантом, если профилирование или иное не скажет вам, что он не работает достаточно хорошо для вас, а затем рассмотрим третий вариант.