'writeToSequence does not work properly in TIFFImageWriter class
My primary intention is to merge multiple different tiff image files into one single file. I have a working code that uses TwelveMonkeys library. Now I want to use the default java library to achieve the same goal. I prepared a small code example to debug and find the problem.
public static ByteArrayOutputStream mergeIntoSingle(List<String> imagePaths) {
ImageWriter imageWriter = ImageIO.getImageWritersByFormatName("tiff").next();
ByteArrayOutputStream byteArrayOutputStream = null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
ImageOutputStream outputStream = ImageIO.createImageOutputStream(byteArrayOutputStream);
imageWriter.setOutput(outputStream);
imageWriter.prepareWriteSequence(null);
for (String path : imagePaths) {
BufferedImage image = ImageIO.read(new FileInputStream(path));
ImageWriteParam writeParams = imageWriter.getDefaultWriteParam();
IIOMetadata metadata = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(image),
writeParams);
IIOImage iioImage = new IIOImage(image, null, metadata);
imageWriter.writeToSequence(iioImage, null);
}
imageWriter.endWriteSequence();
byteArrayOutputStream.close();
} catch (IOException e) {
System.out.println(e.getLocalizedMessage());
}
return byteArrayOutputStream;
}
I debug the code and BufferedImage and IIOImage variables are not null. But endWriteSequence method does not write the content of image to the ImageOutputStream. Therefore, ImageOutputStream and ByteArrayOutputStream variables are being empty. I went through related questions and official documentation, but could not find any useful information about it.
Solution 1:[1]
As I wrote in my initial comment, there is a small problem with the code, in that you don't properly flush/close the outputStream (the ImageOutputStream that wraps the byteArrayOutputStream). Instead you only close the ByteArrayOutputStream (which is a no-op). That means that if the stream implementation does internal caching/buffering, it will never be flushed to the underlying stream. In my very limited testing, I could reproduce the problem and this does indeed seem to be the case.
A safer and more idiomatic Java 7+ version of the code would create the wrapped steam using try-with-resources, and fix the problem (by automatically invoking close()):
public static ByteArrayOutputStream mergeIntoSingle(List<String> imagePaths) {
ImageWriter imageWriter = ImageIO.getImageWritersByFormatName("tiff").next();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (ImageOutputStream outputStream = ImageIO.createImageOutputStream(byteArrayOutputStream)) {
imageWriter.setOutput(outputStream);
imageWriter.prepareWriteSequence(null);
for (String path : imagePaths) {
BufferedImage image = ImageIO.read(new FileInputStream(path));
ImageWriteParam writeParams = imageWriter.getDefaultWriteParam();
IIOMetadata metadata = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(image),
writeParams);
IIOImage iioImage = new IIOImage(image, null, metadata);
imageWriter.writeToSequence(iioImage, null);
}
imageWriter.endWriteSequence();
} catch (IOException e) {
System.out.println(e.getLocalizedMessage());
}
return byteArrayOutputStream;
}
PS: I think the TIFFImageWriter should have invoked flush() on the stream in the endWriteSequence() method (that's what TwelveMonkeys library does). However, you should always make sure you close any stream you open, so the above code is better in any case.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Harald K |
