Java 将TIFF图像逐块写入outputstream

Java 将TIFF图像逐块写入outputstream,java,javax.imageio,Java,Javax.imageio,我试图动态创建一个巨大的TIFF图像,而不将整个图像保存在内存中。我之所以选择TIFF格式,是因为它似乎是Java ImageWriter中唯一支持此功能的格式 然而,无论我尝试什么,我都会得到一个多页文件(当我使用writeToSequence方法时)或一个只包含最后一个磁贴的图像(当我使用write()方法时) 我的基本代码如下所示: final ImageWriter tiffImageWriter = ImageIO.getImageWritersByFormatName

我试图动态创建一个巨大的TIFF图像,而不将整个图像保存在内存中。我之所以选择TIFF格式,是因为它似乎是Java ImageWriter中唯一支持此功能的格式

然而,无论我尝试什么,我都会得到一个多页文件(当我使用
writeToSequence
方法时)或一个只包含最后一个磁贴的图像(当我使用
write()
方法时)

我的基本代码如下所示:

        final ImageWriter tiffImageWriter = ImageIO.getImageWritersByFormatName("TIFF").next();
        final ImageWriteParam param = tiffImageWriter.getDefaultWriteParam();
        param.setTilingMode(MODE_EXPLICIT);
        param.setTiling(TILE_SIZE, TILE_SIZE, 0, 0);

        try (ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(response.getOutputStream())) {
            tiffImageWriter.setOutput(imageOutputStream);

            for (int tileX = 0; tileX < 10; tileX++) {
                for (int tileY = 0; tileY < 10; tileY++) {
                    final BufferedImage bufferedImage = ... // some method producing a BufferedImage of size TILE_SIZExTILE_SIZE

                    tiffImageWriter.write(null, new IIOImage(bufferedImage, null, null), param);
                    imageOutputStream.flush();
                }
            }
        }
        tiffImageWriter.dispose();
final ImageWriter tiffImageWriter=ImageIO.getImageWritersByFormatName(“TIFF”).next();
最终ImageWriteParam参数=tiffImageWriter.getDefaultWriteParam();
参数setTilingMode(模式_显式);
参数设置平铺(平铺尺寸,平铺尺寸,0,0);
try(ImageOutputStream ImageOutputStream=ImageIO.createImageOutputStream(response.getOutputStream())){
tiffImageWriter.setOutput(imageOutputStream);
对于(int-tileX=0;tileX<10;tileX++){
对于(int-tileY=0;tileY<10;tileY++){
final BuffereImage BuffereImage=…//生成大小为TILE\u SizeTextile\u size的BuffereImage的某些方法
tiffImageWriter.write(null,新IIOImage(BuffereImage,null,null),参数);
imageOutputStream.flush();
}
}
}
tiffImageWriter.dispose();
这里的
response.getOutputStream()
是来自我的服务的输出流

运行此代码的结果是
TILE\u SIZE x TILE\u SIZE
SIZE的图像,最后一个TILE作为内容


我想知道是否有可能做到这一点,或者这项功能是为其他目的而设计的?

正如您已经了解到的,
write
writeToSequence
在这种情况下不起作用。他们不应该这样做。这些方法分别用于写入单个图像文件或多个图像文件。它们不用于部分写入图像。要使用
javax.imageio
API编写图像,而不必一次将整个图像保存在内存中,您至少有两个选项:

  • 使用一个平铺的
    渲染图像
    。您需要创建一个自定义实现,按需创建每个磁贴(您可能已经这样做了)。但正如您在中所了解的,磁贴大小(以及写入程序是否会使用磁贴)取决于
    ImageWriter
    实现。因此,您可能需要调整所用书写器的磁贴大小。并且可能有一个内存中的磁贴缓存来获得良好的性能
  • 使用
    ImageWriter
    方法
    canWriteEmpty
    /
    canReplacePixels
    ,如果它们都返回
    true
    ,则使用
    prepareWriteEmpty
    /
    endWriteEmpty
    (对于整个图像),然后为每个磁贴使用
    prepareReplacePixels
    replacePixels
    。这似乎适用于JAI或Java9+
    TIFFImageWriter
    (仅适用于未压缩图像)。我知道目前这并不适用于TwelveMonkeys
    TIFFImageWriter
    ,因为这是一个非常罕见的用例

考虑到您的代码示例和期望,第二个选项似乎与您想要的最接近。

这里的QA似乎与您的问题重复:如果它对您有效,您可以让我们知道,我们可以让这个问题重复吗?@ControlAltDel一点也不,与我的问题无关。那么,你能把它作为一个完整的例子吗?甚至可能只是生成一个带有一些简单图形的BuffereImage,以及您希望它们如何结合在一起。