Closed ben-manes closed 6 years ago
I think it might be due to the header?
That did it! I think you should be setting this for the caller, as it requires setting the writer manually.
rout.setWriteStrategy((settings.byteOrder() == BIG_ENDIAN)
? WriteStrategyMM.getInstance()
: WriteStrategyII.getInstance());
$ identify -verbose out.tif | grep Endian
Endianess: LSB
@ben-manes The method writeHeader(RandomAccessOutputStream rout) itself is called by different methods. Most of the methods already set the byte order before calling this method.
For this reason, I believe writeMultipageTIFF(RandomAccessOutputStream rout, ImageParam[] imageParam, BufferedImage ... images) method should be the right place to set the byte order before calling writeHeader(RandomAccessOutputStream rout).
One catch here is multiple page TIFF only allows one byte order on the image level, not page level. As we allow each page to be associated with an ImageParam, theoretically, the user can set different byte order for different pages but this is not supported by multipage TIFF.
What I can do is to grab the first ImageParam from the ImageParam array and use the byte order in there.
That sounds reasonable to me. Thanks!
I also added an overloaded prepareForWrite(RandomAccessOutputStream, ByteOrder) method which takes a second argument of type ByteOrder. This way, writing multipage TIFF page by page will also respect ByteOrder. The old single argument method will by default take ByteOrder.BIG_ENDIAN.
Thanks! If I use prepareForWrite
with writeMultipageTIFF
, won't it write the header twice?
Just for fyi, my usage currently looks like:
public final class MultipageTiff {
private MultipageTiff() {}
/** Creates a TIFF with a page per image. */
public static void create(TiffSettings settings) {
try (var fileOutput = Files.newOutputStream(settings.destination());
var rout = new FileCacheRandomAccessOutputStream(fileOutput)) {
BufferedImage[] bufferedImages = new BufferedImage[settings.images().size()];
for (int i = 0; i < settings.images().size(); i++) {
bufferedImages[i] = ImageIO.read(settings.images().get(i).toFile());
}
TIFFOptions tiffOptions = new TIFFOptions();
tiffOptions.setTiffCompression(settings.compression());
tiffOptions.setXResolution(settings.xResolution());
tiffOptions.setYResolution(settings.yResolution());
tiffOptions.setByteOrder(settings.byteOrder());
tiffOptions.setJPEGQuality(100);
ImageParam imageSetting = ImageParam.getBuilder()
.colorType(settings.colorType())
.imageOptions(tiffOptions)
.build();
rout.setWriteStrategy((settings.byteOrder() == BIG_ENDIAN)
? WriteStrategyMM.getInstance()
: WriteStrategyII.getInstance());
TIFFTweaker.writeMultipageTIFF(rout, new ImageParam[] { imageSetting }, bufferedImages);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@AutoValue @AutoBuilder
public static abstract class TiffSettings {
public abstract Path destination();
public abstract List<Path> images();
public abstract Compression compression();
public abstract ImageColorType colorType();
public abstract int xResolution();
public abstract int yResolution();
public abstract ByteOrder byteOrder();
public static MultipageTiff_TiffSettings_Builder group4() {
return MultipageTiff_TiffSettings_Builder.builder()
.compression(CCITTFAX4)
.byteOrder(BIG_ENDIAN)
.colorType(BILEVEL)
.xResolution(200)
.yResolution(200);
}
public static MultipageTiff_TiffSettings_Builder color() {
return MultipageTiff_TiffSettings_Builder.builder()
.colorType(FULL_COLOR)
.byteOrder(BIG_ENDIAN)
.compression(LZW)
.xResolution(72)
.yResolution(72);
}
}
}
prepareForWrite() is supposed to be used along with writePage() and finishWrite() not together with any of the writeMultipageTIFF(). This is to save memory.
You call prepareForWrite() first. Then writePage() one or multiple times depending on how many pages you want to write. Then finally wrap up calling finishWrite().
A similar work flow exists for inserting pages into existing TIFF.
Refer to this issue: https://github.com/dragon66/icafe/issues/25
I am using
TIFFTweaker.writeMultipageTIFF
withTIFFOptions
set toLITTLE_ENDIAN
andCCITTFAX4
. Unfortunately the resulting image is big endian, as confirmed by ImageMagik ($ identify -verbose out.tif | grep Endianess
). Toggling the setting doesn't seem to have an effect.Since the source jar isn't being published, I can't step through it to debug. It does naively look correct in TIFFWriter, but doesn't seem to be working.