Example #1
0
        def readblockfromtif(pidxbidx_):
            planeidx, blockidx = pidxbidx_
            blocks = []
            planeshape = None
            blockstart = None
            blockend = None
            for fname in filenames:
                reader_ = getFileReaderForPath(fname)()
                fp = reader_.open(fname)
                try:
                    if minimize_reads:
                        # use multitif module to generate a fake, in-memory one-page tif file
                        # the advantage of this is that it cuts way down on the many small reads
                        # that PIL/pillow will make otherwise, which would be a problem for s3
                        tiffparser_ = multitif.TiffParser(fp, debug=False)
                        tiffilebuffer = multitif.packSinglePage(
                            tiffparser_, page_idx=planeidx)
                        bytebuf = io.BytesIO(tiffilebuffer)
                        try:
                            pilimg = Image.open(bytebuf)
                            ary = pil_to_array(pilimg).T
                        finally:
                            bytebuf.close()
                        del tiffilebuffer, tiffparser_, pilimg, bytebuf
                    else:
                        # read tif using PIL directly
                        pilimg = Image.open(fp)
                        pilimg.seek(planeidx)
                        ary = pil_to_array(pilimg).T
                        del pilimg

                    if not planeshape:
                        planeshape = ary.shape[:]
                        blockstart = blockidx * blocklenPixels
                        blockend = min(blockstart + blocklenPixels,
                                       planeshape[0] * planeshape[1])
                    blocks.append(ary.ravel(order='C')[blockstart:blockend])
                    del ary
                finally:
                    fp.close()

            buf = vstack(
                blocks).T  # dimensions are now linindex x time (images)
            del blocks
            buf = buf.astype(newdtype, casting=casting, copy=False)

            # append subscript keys based on dimensions
            linindx = arange(blockstart, blockend)  # zero-based

            serieskeys = zip(
                *map(tuple, unravel_index(linindx, planeshape, order='C')))
            # add plane index to end of keys
            serieskeys = [
                tuple(list(keys_)[::-1] + [planeidx]) for keys_ in serieskeys
            ]
            return zip(serieskeys, buf)
Example #2
0
    def __readMetadataFromFirstPageOfMultiTif(reader, filePath):
        import thunder.rdds.fileio.multitif as multitif

        # read first page of first file to get expected image size
        tiffFP = reader.open(filePath)
        tiffParser = multitif.TiffParser(tiffFP, debug=False)
        tiffHeaders = multitif.TiffData()
        tiffParser.parseFileHeader(destinationTiff=tiffHeaders)
        firstIfd = tiffParser.parseNextImageFileDirectory(
            destinationTiff=tiffHeaders)
        if not firstIfd.isLuminanceImage():
            raise ValueError(("File %s does not appear to be a luminance " %
                              filePath) +
                             "(greyscale or bilevel) TIF image, " +
                             "which are the only types currently supported")

        # keep reading pages until we reach the end of the file, in order to get number of planes:
        while tiffParser.parseNextImageFileDirectory(
                destinationTiff=tiffHeaders):
            pass

        # get dimensions
        npages = len(tiffHeaders.ifds)
        height = firstIfd.getImageHeight()
        width = firstIfd.getImageWidth()

        # get datatype
        bitsPerSample = firstIfd.getBitsPerSample()
        if not (bitsPerSample in (8, 16, 32, 64)):
            raise ValueError(
                "Only 8, 16, 32, or 64 bit per pixel TIF images are supported, got %d"
                % bitsPerSample)

        sampleFormat = firstIfd.getSampleFormat()
        if sampleFormat == multitif.SAMPLE_FORMAT_UINT:
            dtStr = 'uint'
        elif sampleFormat == multitif.SAMPLE_FORMAT_INT:
            dtStr = 'int'
        elif sampleFormat == multitif.SAMPLE_FORMAT_FLOAT:
            dtStr = 'float'
        else:
            raise ValueError(
                "Unknown TIF SampleFormat tag value %d, should be 1, 2, or 3 for uint, int, or float"
                % sampleFormat)
        dtype = dtStr + str(bitsPerSample)

        return height, width, npages, dtype