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

Adding ImageDepth support to pylibtiff #106

Open
markemus opened this issue May 15, 2019 · 5 comments
Open

Adding ImageDepth support to pylibtiff #106

markemus opened this issue May 15, 2019 · 5 comments

Comments

@markemus
Copy link

Hey @pearu, I wrote some code to allow pylibtiff to read 3D TIFF images. It's a modified version of the TIFF.read_tiles() method in libtiff_ctypes.py. Currently it's a monkeypatch that is applied to libtiff at runtime.

If you're interested in it, I'd be happy to refactor it to be part of:

  1. read_tiles(), or
  2. a separate method, TIFF.read_z_tiles()

I'm hopefully also going to be doing this for write_tiles() in the near future.

Thanks for writing this great library!

Here's the code:

"""Adds a method to libtiff.TIFF to read z-stack tiff images (images with an ImageDepth tag).
Import this module anywhere in your code but before instantiating the TIFF class to apply the patch."""
import numpy as np

from libtiff import TIFF


def read_z_tiles(self, dtype=np.uint8):
    num_tcols = int(self.GetField("TileWidth")/2)
    num_trows = int(self.GetField("TileLength")/2)
    num_icols = int(self.GetField("ImageWidth")/2)
    num_irows = int(self.GetField("ImageLength")/2)
    num_depths = self.GetField("ImageDepth")
    # this number includes extra samples
    samples_pp = self.GetField('SamplesPerPixel') * 2

    def read_plane(plane, tmp_tile, plane_index=0, depth_index=0):
        for y in range(0, num_irows, num_trows):
            for x in range(0, num_icols, num_tcols):
                # input data is 2x as many dims per pixel as parameters state.
                r = self.ReadTile(tmp_tile.ctypes.data, x*2, y*2, depth_index, plane_index)
                if not r:
                    raise ValueError(
                        "Could not read tile x:%d,y:%d,z:%d,sample:%d from file" %
                        (x, y, plane_index, depth_index))

                # if the tile is on the edge, it is smaller
                tile_width = min(num_tcols, num_icols - x)
                tile_height = min(num_trows, num_irows - y)

                plane[y:y + tile_height, x:x + tile_width] = \
                    tmp_tile[:tile_height, :tile_width]

    full_image = np.zeros((num_depths, num_irows, num_icols, samples_pp), dtype=dtype, order='C')
    tmp_tile = np.zeros((num_trows, num_tcols, samples_pp), dtype=dtype, order='C')

    for depth_index in range(num_depths):
        read_plane(full_image[depth_index], tmp_tile, depth_index=depth_index)

    return full_image

# Apply monkeypatch
TIFF.read_z_tiles = read_z_tiles```
@markemus
Copy link
Author

Just to be clear, this is for color image stacks- the current version already should support 3D grayscale stacks. So I guess these are really "4D" stacks.

@pearu
Copy link
Owner

pearu commented Feb 3, 2020

Thanks for reporting the issue and sorry for the long delay in responding.
Could you submit your changes as a PR?

@markemus
Copy link
Author

markemus commented Feb 3, 2020

I've developed it more since then, including code for rewriting the data into separate directories. I'll post a PR when I get a chance.

@markemus
Copy link
Author

markemus commented Feb 3, 2020

@pearu I opened the PR- not sure if you get an alert when that happens.

@pearu
Copy link
Owner

pearu commented Feb 3, 2020

@markemus thanks for the PR. I'll give it a review and I believe github should send any relevant messages to you.

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

2 participants