22

Each tiff file has 4 images in it. I do not wish to extract and save them if possible, I would just like to use a for loop to look at each of them. (Like look at the pixel [0,0] )and depending on what color it is in all 4 I will do something accordingly.

Is this possible using PIL? If not what should I use.

1478963
  • 1,198
  • 4
  • 11
  • 25

5 Answers5

34

Rather than looping until an EOFError, one can iterate over the image pages using PIL.ImageSequence (which effectively is equivalent as seen on the source code).

from PIL import Image, ImageSequence

im = Image.open("multipage.tif")

for i, page in enumerate(ImageSequence.Iterator(im)):
    page.save("page%d.png" % i)
Maxim
  • 7,207
  • 1
  • 30
  • 29
22

You can use the "seek" method of a PIL image to have access to the different pages of a tif (or frames of an animated gif).

from PIL import Image

img = Image.open('multipage.tif')

for i in range(4):
    try:
        img.seek(i)
        print img.getpixel( (0, 0))
    except EOFError:
        # Not enough frames in img
        break
MatthieuW
  • 2,292
  • 15
  • 25
  • 8
    FYI, This solution worked >1000x faster to later access the individual pixels in a frame (0.0002sec) than the pims library (0.348093sec). pims is supposedly based on tiffile.py. PIL was still slower than opencv (6.7e-05sec), but opencv doesn't support multi-page tiffs (tiff stacks). – user391339 May 27 '15 at 22:50
  • @user391339 FYI: OpenCV now supports multi-page tiffs with imreadmulti (link below). https://docs.opencv.org/3.4/d4/da8/group__imgcodecs.html#ga4dd47c9ae3d55cc42286cff005825e31 – JStrahl Sep 16 '22 at 07:33
7

Had to do the same thing today,

I followed @stochastic_zeitgeist's code, with an improvement (don't do manual loop to read per-pixel) to speed thing up.

from PIL import Image
import numpy as np

def read_tiff(path):
    """
    path - Path to the multipage-tiff file
    """
    img = Image.open(path)
    images = []
    for i in range(img.n_frames):
        img.seek(i)
        images.append(np.array(img))
    return np.array(images)
Mohd Shahril
  • 2,257
  • 5
  • 25
  • 30
4

Here's a method that reads a multipage tiff and returns the images as a numpy array

from PIL import Image
import numpy as np

def read_tiff(path, n_images):
    """
    path - Path to the multipage-tiff file
    n_images - Number of pages in the tiff file
    """
    img = Image.open(path)
    images = []
    for i in range(n_images):
        try:
            img.seek(i)
            slice_ = np.zeros((img.height, img.width))
            for j in range(slice_.shape[0]):
                for k in range(slice_.shape[1]):
                    slice_[j,k] = img.getpixel((j, k))

            images.append(slice_)

        except EOFError:
            # Not enough frames in img
            break

    return np.array(images)
stochastic_zeitgeist
  • 1,037
  • 1
  • 14
  • 21
  • PIL/Pillow stores and refers to images using [col,row] whereas numpy uses [row,col]. I got the above code to work by changing the height and width locations, i.e. ``slice_ = np.zeros((img.width, img.height))`` – StuckInPhDNoMore Nov 09 '18 at 15:59
  • 1
    The number of frames within TIFF file is stored within `n_frames` property. Also, to convert them into numpy array you don't need to copy each individual pixel - it's as easy as `numpy.array(image)` where `image` is PIL image. – Maksym Ganenko Apr 16 '19 at 13:59
0

Thanks to the answers on this thread I wrote this python module for reading and operating on multipage tiff files: https://github.com/mpascucci/multipagetiff

It also allows to color-code the image stack "depth-wise" and make z-projections.

Hope it can help

MarcoP
  • 1,438
  • 10
  • 17