jai-imageio / jai-imageio-core

JAI ImageIO Core (without javax.media.jai dependencies)
Other
234 stars 87 forks source link

Writing large TIFFs is not supported #80

Open StephanPreibisch opened 1 year ago

StephanPreibisch commented 1 year ago

Hi, I wanted to use the TIFFImageWriter.java class to write large TIFFs in strips. However, the writing is limited to a maximal size of 2^31 pixels because the stripOffsets are written as int's and not as long's:

https://github.com/jai-imageio/jai-imageio-core/blob/f81bc1ab19faa210ad289c6ae2588bc1157fd07a/src/main/java/com/github/jaiimageio/impl/plugins/tiff/TIFFImageWriter.java#L2664

I wanted to ask if there is an easy fix for that? Just writings longs there does not work since it needs to be specified in the header somehow as well that longs are used for stripOffsets, but wasn't able to find out where this is defined.

Thanks so much, Stephan

lbellonda commented 1 year ago

Hello, the field is already using a "long" value, I think. In the TIFF specifications the "long" value is a 32-bit (4-byte) unsigned integer. The header is defined at line 1372, TIFFField stripOffsetsField (and in some other location in same file) using TIFF.LONG type, so the only thing that you can check is if the long Java value is really converted to an unsigned 32bit integer. The specification I found are at: https://web.archive.org/web/20210108172855/https://www.adobe.io/open/standards/TIFF.html

Best regards

StephanPreibisch commented 1 year ago

Correct, my bad, you would have to support BigTIFF (https://en.wikipedia.org/wiki/TIFF#BigTIFF). It is still a bug in a sense that your implementation is limited to 2^31 pixels, while it could be 2^32 -- you would need to cast the long into an int so that it is saved as an unsigned int, like we do it in ImgLib2:

https://github.com/imglib/imglib2/blob/078f5af1c64808227f4eff6e1bb73594e5f49588/src/main/java/net/imglib2/type/numeric/integer/UnsignedIntType.java#L86-L89

Thanks so much, Stephan

StephanPreibisch commented 1 year ago

Happy to make a pull-request if you like ... it would maybe also be better to throw an exception if the file size exceeds 2^32 pixels instead of silently failing?

stain commented 1 year ago

Agree on throwing an exception if it's out of bounds.

If you want to support longs up to 2^32-1 without going for BigTiff, then I think you would have to fake the equivalent negative int (Note: NOT -pos), to be equivalent to flipping the uppermost bit only.

Somthing like long fred = MININT+ pos (with the correct off-by-one adjustments) to approach from the bottom before casting?

I think you can't write with java.io.DataOutputStream.writeLong, it would output 8 bytes instead of 4, which being big endian means a padding of 0s come before the then effectively unsigned int.

Daniel-Alievsky commented 1 year ago

Are there any plans to support BigTIFF in nearest future? Now I'm using SCIFIO for reading/writing large TIFF, and I would like to use JAI instead, but I need correctly process BigTIFF SVS files.