Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compression error/ how to define the "compression_type" argument? #22

Open
Phlpp-S opened this issue Jan 20, 2024 · 7 comments
Open

Compression error/ how to define the "compression_type" argument? #22

Phlpp-S opened this issue Jan 20, 2024 · 7 comments

Comments

@Phlpp-S
Copy link

Phlpp-S commented Jan 20, 2024

Hello,

I like this package as it's easy to install and use, however I have a question regarding the compression setting, specifically the compression type.

compression_type=None

What to pass here instead of the None to activate a compression?
I saw in the code that it counterchecks with the tifffile.TIFF.COMPRESSION(), but was not able to figure out what to pass here.

Help would be appreciated

@Milad4849
Copy link

@Phlpp-S
Thank you for bringing up this issue. The options for compression_type as specified by tifffile.TIFF.COMPRESSION() should be:

NONE, CCITTRLE, CCITT_T4, CCITT_T6, LZW, OJPEG, JPEG, ADOBE_DEFLATE , JBIG_BW , JBIG_COLOR , JPEG_99 , KODAK_262 , JPEGXR_NDPI , NEXT , SONY_ARW , PACKED_RAW , SAMSUNG_SRW , CCIRLEW , SAMSUNG_SRW2 , PACKBITS , THUNDERSCAN , IT8CTPAD , IT8LW , IT8MP , IT8BL , PIXARFILM , PIXARLOG , DEFLATE , DCS , APERIO_JP2000_YCBC , JPEG_2000_LOSSY , APERIO_JP2000_RGB , ALT_JPEG , JBIG , SGILOG , SGILOG24 , JPEG2000 , NIKON_NEF , JBIG2 , MDI_BINARY , MDI_PROGRESSIVE , MDI_VECTOR , LERC , JPEG_LOSSY , LZMA , ZSTD_DEPRECATED , WEBP_DEPRECATED , PNG , JPEGXR , JETRAW , ZSTD , WEBP , JPEGXL , PIXTIFF , EER_V0 , EER_V1 , EER_V2

However xtiff.to_tiff(<a numpy ndarray>,<path/to/tiff/file>, compression_type = 'JPEG') returns the following error for me:

TypeError: __call__() missing 1 required positional argument: 'value'

This is caused by the line 191 and compression_type not in tifffile.TIFF.COMPRESSION(). It appears that tifffile.TIFF.COMPRESSION() is not what is expected in the current code. substituting the check with something like: hasattr(tifffile.TIFF.COMPRESSION, 'compression_type') seems to fix the issue.

@jwindhager what do you think?
@Phlpp-S Could you please confirm that you get the above error if you specify: compression_type = 'JPEG'?

@jwindhager
Copy link
Contributor

jwindhager commented Jan 26, 2024

Hi @Milad4849

Without looking into this in too much detail, I would suspect that the TiffWriter.write API may have changed since the last release of xtiff: instead of a single compression argument, there now seems to be compression and compressionargs: https://github.com/cgohlke/tifffile/blob/5ced58caa74936ecc53f58ade94938e251e83138/tifffile/tifffile.py#L1637-L1638

Searching for compressionargs in the tifffile changelog, this is indeed the case (version 2022.7.28):

Deprecate tuple type compression argument on write (use compressionargs).

As you can see in xtiff's setup.cfg, the last tested version for xtiff was 2022.4.22. I therefore see two options:

  1. Pin the max tifffile version to the last supported version (probably anything between 2022.4.22 and 2022.7.28, you'd need to check the changelog) and deprecate xtiff (add a deprecation warning to both the Python package and the GitHub repository)
  2. Work through the changes in the tifffile changelog and update xtiff accordingly (not just compression-related issues)

Option 1 is probably the easiest, but xtiff seems to be used quite regularly, still (it's also a dependency of steinbock!). In general, I suspect that tifffile has become much more powerful wrt. OME-TIFF since the last version of xtiff was released, so I'm not sure how justified xtiff's existence still is nowadays?

@Phlpp-S as a quick fix, could you try installing tifffile==2022.4.22 into your environment where xtiff is installed?

@Phlpp-S
Copy link
Author

Phlpp-S commented Jan 28, 2024

Hi @Milad4849 and @jwindhager , thank you very much for taking a look into this issue.

  • First, I got the same error TypeError: __call__() missing 1 required positional argument: 'value'.
  • Substituting with hasattr(tifffile.TIFF.COMPRESSION, 'compression_type') also fixed this issue for me, however I got a follow up error stating that the compression needs the "imagecodecs" package.
    This was easily solved with pip install imagecodecs and from imagecodecs import *.
  • Without the substitution, but with the installation of tifffile==2022.4.22 the value error remains for me.

With the substitution and imagecodecs, now the .tiff export works with a specified compression.

However now it seems that the array is not exported correct. I tried it with

comp = 'JPEG'
prof = xtiff.TiffProfile.OME_TIFF

xtiff.to_tiff(img_out_tif.astype('uint8'), 'xtiff_test_out.ome.tiff', image_name=None, image_date=None, channel_names=['Red', 'Green', 'Blue', 'Classnumber'], description=None,
        profile = prof, big_endian=None, big_tiff=None, big_tiff_threshold=4261412864,
        compression_type = comp, compression_level = 8, pixel_size=None, pixel_depth=None,
        interleaved=True, software='xtiff', ome_xml_fun=xtiff.get_ome_xml)

where img_out_tif is a (4 x N x M) matrix, where the first three channels are RGB from my input image, and the fourth channel contains class-values. I guess my simple list channel_names=['Red', 'Green', 'Blue', 'Classnumber'] is not sufficient?
The corresponding xtiff doc states channel_names: A list of channel names. If True, channel names are determined using the DataArray channel coordinate;. How to specify the DataArray channel coordinate names?

@Milad4849
Copy link

Milad4849 commented Jan 30, 2024

Hi @Phlpp-S
What is the exact problem when you execute the above command? I tested your command, I can write out arrays of shape (4 x N x M) and when I read it the the channel names are correctly assigned in the metadata.

@Phlpp-S
Copy link
Author

Phlpp-S commented Jan 31, 2024

Hi @Milad484
The export with the command I posted works, but when reading the exported file again it only contains 1 channel. What library (& function) do you use to read the .tiff image?
I tried cv2.imread() which reads 3 channels, and matplotlib plt.imread() which reads only 1 channel.

@Milad4849
Copy link

Milad4849 commented Feb 1, 2024

This is the code I use check the metadata of the tiff file:

import tifffile
import xml.dom.minidom

with tifffile.TiffFile('xtiff_test_out.ome.tiff') as tiff:
    #ImageDescription tag
    Image_description = tiff.pages[0].tags.values()[5].value

    xml_tree = xml.dom.minidom.parseString(Image_description)
    prettified_xml = xml_tree.toprettyxml(indent="  ")
    print(prettified_xml)

and the output:

<?xml version="1.0" ?>
<OME xmlns="http://www.openmicroscopy.org/Schemas/OME/2016-06" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openmicroscopy.org/Schemas/OME/2016-06 http://www.openmicroscopy.org/Schemas/OME/2016-06/ome.xsd">
  <Image ID="Image:0" Name="xtiff_test_out.ome.tiff">
    <Pixels ID="Pixels:0" Type="uint8" SizeX="600" SizeY="400" SizeC="4" SizeZ="1" SizeT="1" DimensionOrder="XYCZT" Interleaved="true" BigEndian="false">
      <Channel ID="Channel:0:0" SamplesPerPixel="1" Name="Red"/>
      <Channel ID="Channel:0:1" SamplesPerPixel="1" Name="Green"/>
      <Channel ID="Channel:0:2" SamplesPerPixel="1" Name="Blue"/>
      <Channel ID="Channel:0:3" SamplesPerPixel="1" Name="Classnumber"/>
      <TiffData/>
    </Pixels>
  </Image>
</OME>

The value of the ImageDescription tag in the first page of the TiffFile object is the above OME XML. Reading the image with tifffile: tifffile.imread('xtiff_test_out.ome.tiff'), I get an array of shape (4 x N xM). As far as know the functions that you are using are primary for reading standard formats, tifffile or imageio can handle multi-channel TIFFs better.

@Phlpp-S
Copy link
Author

Phlpp-S commented Feb 4, 2024

Hi @Milad484
thanks for your answer.
tifffile.imread() did what I wanted, to read in the image as a matrix for further processing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants