Save LZW compressed Tiff in java

tiff
scifio
bio-formats
Tags: #<Tag:0x00007fd542ec7a88> #<Tag:0x00007fd542ec7920> #<Tag:0x00007fd542ec77e0>

#1

Dear @ctrueden, would you be able to provide a short example java code of how to write LZW compressed tiff stacks (I guess using bio-formats code)? For us it would be especially important to be able to specify the rowsPerStrip as we optimize this for fast (cropped) loading of the data.


#2

I am sorry to say I’m too busy with NEUBIAS stuff this month to code up a full working example. Perhaps one of the other Bio-Formats developers such as @melissa or @dgault have some code they can share. Or you could email the ome-users list directly asking for help.

The basic idea is to pass the IFD object when calling one of the writeImage methods of TiffSaver. And that IFD should set the compression like ifd.put(IFD.COMPRESSION, TiffCompression.LZW). Since you also want to set the RowsPerStrip you would need to add ifd.put(IFD.ROWS_PER_STRIP, new long[] {...}) or whatever. Looking at the TiffSaver code, it appears that customizing RowsPerStrip should be supported.

If you cook up a working example, I’m sure the Bio-Formats team would appreciate it if you shared—it could be included on the web site in the list of sample code.

P.S. In SCIFIO, it works similarly, since the relevant code originated from Bio-Formats. See the writing image planes tutorial, with the difference being that you would need to get a handle on a TIFFFormat.Writer specifically to gain access to the IFD-specific API. However, if all you want to do is set the compression type without overriding RowsPerStrip, it is much easier: simply call writerSetCompression(lzw) on your SCIFIOConfig passed to DatasetIOService.save. No need to muck about with writing individual planes then.


#3

Thanks for the prompt reply!
I got the idea!
I think I will try with the Bioformats implementation first, as I need the rowsPerStrip.
See you next week, looking forward to meeting you in person :slight_smile:


#4

Hi @ctrueden,

Of course I am struggling now with the maven import…
Looked around here: https://mvnrepository.com/search?q=loci+formats
But was not sure which one to choose.

Do you know what i have to write into my pom.xml to make this working:

import loci.formats.tiff.TiffSaver;

In general, how would I search for this to find the right dependency on my own? IntelliJ seems not to be able to find it by itself unfortunately (at least I do not manage).


#5

Hi Christian,

The following repository has basic examples of Bio-Formats projects using Maven or Gradle: https://github.com/dgault/bio-formats-examples

The Maven pom that you would be interested in would be https://github.com/openmicroscopy/bio-formats-examples/blob/master/pom.xml

Also you can find all of the Bio-Formats released jars available on the OME artifactory and you can generate Maven pom snippets to use on the Client settings tab - Generate Maven settings

Hopefully that should get you up and running, if you need any further help or examples for Bio-Formats do just let us know.


#6

Thanks! This worked!
It could not find version 5.3.3 though, only 5.2.4 …


#7

If it cant find the latest you may be missing the OME Artifactory repository from the pom:

    <repository>
      <id>ome</id>
      <name>OME Artifactory</name>
      <url>http://artifacts.openmicroscopy.org/artifactory/maven/</url>
    </repository>

#8

Rather than depending on the OME Maven repository, I would suggest instead to:

  1. Extend the pom-scijava parent; and
  2. Add the ImageJ Maven repository’s imagej.public group. This includes OME and much more.

See the example-imagej-command project as a starting point.

When you do this, you will receive much build goodness for free, including versions of Bio-Formats etc. which all play nicely together. You will no longer need to declare <version> tags for any component which is part of the SciJava component collection.

Side note to the Bio-Formats team: pom-scijava (the Bill of Materials) is now split from pom-scijava-base (the build goodness), and they serve as the central extension point for all SciJava-based software. So it should be even easier for Bio-Formats to extend either pom-scijava or pom-scijava-base and inherit all the build goodness, eliminating hundreds of lines of XML from the current Maven POMs. These parent POMs are published to Maven Central so there should be no technical issues.


#9

that seems not to the issue as i have this repository…but it’s also working with 5.2.4.


#10

That sounds like it may be picking up the earlier version from a dependency elsewhere. You could perhaps use the dependency tree to check if multiple versions are being requested:

https://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html


#11

I am trying to use the TiffWriter but I am getting an error that I do not understand:

                        TiffWriter writer = new TiffWriter();
                        writer.setCompression(TiffWriter.COMPRESSION_LZW);
                        writer.setValidBitsPerPixel(16);
                        writer.setId(pathCT);

It still starts creating the file pathCT but then crashes with an
NegativeArraySizeException
Do you know what I am doing wrong?


#12

It is likely due to not having the minimum amount of metadata populated. You will have to create a metadata object and populate it, then add it to your writer.

Some sample code for writing out raw data, including setting up metadata and the minimum required values can be found here: http://www.openmicroscopy.org/site/support/bio-formats5.3/developers/export2.html


#13

thanks! now it works!


#14

…do you maybe have some convenience method within loci for casting short[] to byte[]?
My images are 16bit and it looks like the writer can only save byte arrays!?
I can of course use an own shortToByteConverter, but it feels cleaner to me to use one of loci if it exists.


#15

In the bioformats and ome-common library there are a few utility classes which will provide helper functions, DataTools and FormatTools are probably the most useful.

In your particular example the DataTools class has functions for converting from various types to and from byte arrays. Hopefully those will save you some time and effort.


#16

Use SciJava Common’s org.scijava.util.Bytes class. We originally wrote those methods in Bio-Formats as loci.common.DataTools, but they have been updated and streamlined in SciJava Common. The method you want specifically is bytes[] b = Bytes.fromShorts(shorts, little) where little is the little-endianness.

In general, I would love to see more unification between e.g. ome-common and scijava-common.