예제 #1
0
def test_split_sub_subifds(tmp_path):
    path = datastore.fetch('subsubifds.tif')
    tifftools.tiff_split(str(path), tmp_path / 'test', subifds=True)
    info = tifftools.read_tiff(tmp_path / 'testaaa.tif')
    assert len(info['ifds']) == 1
    info = tifftools.read_tiff(tmp_path / 'testaai.tif')
    assert len(info['ifds']) == 1
예제 #2
0
def testRegionTiledOutputIsTiled():
    imagePath = datastore.fetch('sample_image.ptif')
    source = large_image_source_tiff.open(imagePath)

    # TIFF isn't tiled and has only one layer
    params = {'output': {'maxWidth': 500, 'maxHeight': 500},
              'encoding': 'TIFF'}
    image, mimeType = source.getRegion(**params)
    info = tifftools.read_tiff(io.BytesIO(image))
    assert len(info['ifds']) == 1
    assert tifftools.Tag.StripOffsets.value in info['ifds'][0]['tags']
    assert tifftools.Tag.TileOffsets.value not in info['ifds'][0]['tags']

    # TILED is tiled and has multiple layers
    params = {'output': {'maxWidth': 500, 'maxHeight': 500},
              'encoding': 'TILED'}
    image, mimeType = source.getRegion(**params)
    info = tifftools.read_tiff(image)
    assert len(info['ifds']) == 2
    assert tifftools.Tag.StripOffsets.value not in info['ifds'][0]['tags']
    assert tifftools.Tag.TileOffsets.value in info['ifds'][0]['tags']
    os.unlink(image)

    # Bigger outputs should have more layers
    params = {'output': {'maxWidth': 3000, 'maxHeight': 3000},
              'encoding': 'TILED'}
    image, mimeType = source.getRegion(**params)
    info = tifftools.read_tiff(image)
    assert len(info['ifds']) == 5
    assert tifftools.Tag.StripOffsets.value not in info['ifds'][0]['tags']
    assert tifftools.Tag.TileOffsets.value in info['ifds'][0]['tags']
    os.unlink(image)
예제 #3
0
def test_write_switch_to_bigtiff(tmp_path):
    path = datastore.fetch('hamamatsu.ndpi')
    info = tifftools.read_tiff(path)
    info['ifds'].extend(info['ifds'])
    info['ifds'].extend(info['ifds'])
    info['ifds'].extend(info['ifds'])
    destpath = tmp_path / 'sample.tiff'
    tifftools.write_tiff(info, destpath)
    destinfo = tifftools.read_tiff(destpath)
    assert destinfo['bigtiff'] is True
예제 #4
0
def test_write_bigtiff_from_datatype(tmp_path):
    path = os.path.join(os.path.dirname(__file__), 'data', 'good_single.tif')
    info = tifftools.read_tiff(path)
    info['ifds'][0]['tags'][23456] = {
        'datatype': tifftools.Datatype.LONG8,
        'data': [8],
    }
    destpath = tmp_path / 'sample.tiff'
    tifftools.write_tiff(info, destpath)
    destinfo = tifftools.read_tiff(destpath)
    assert destinfo['bigtiff'] is True
예제 #5
0
def test_write_bad_strip_offset(tmp_path, caplog):
    path = os.path.join(os.path.dirname(__file__), 'data',
                        'bad_strip_offset.tif')
    info = tifftools.read_tiff(path)
    destpath = tmp_path / 'sample.tiff'
    with caplog.at_level(logging.WARNING):
        tifftools.write_tiff(info, destpath)
    assert 'from desired offset' in caplog.text
    destinfo = tifftools.read_tiff(destpath)
    assert destinfo['ifds'][0]['tags'][
        tifftools.Tag.StripOffsets.value]['data'][0] == 0
예제 #6
0
def test_tiff_set_self(tmp_path):
    path = datastore.fetch('d043-200.tif')
    dest = tmp_path / 'results.tif'
    shutil.copy(path, dest)
    with pytest.raises(Exception):
        tifftools.tiff_set(dest, setlist=[('ImageDescription', 'Dog digging')])
    info = tifftools.read_tiff(str(dest))
    assert int(tifftools.Tag.ImageDescription) not in info['ifds'][0]['tags']
    tifftools.tiff_set(dest,
                       overwrite=True,
                       setlist=[('ImageDescription', 'Dog digging')])
    info = tifftools.read_tiff(str(dest))
    assert info['ifds'][0]['tags'][int(
        tifftools.Tag.ImageDescription)]['data'] == 'Dog digging'
예제 #7
0
def test_write_bigtiff_with_offset_data(tmp_path):
    path = datastore.fetch('hamamatsu.ndpi')
    info = tifftools.read_tiff(path)
    info['ifds'][0]['tags'][tifftools.Tag.FreeOffsets.value] = {
        'datatype': tifftools.Datatype.LONG,
        'data': [8] * 256,
    }
    info['ifds'][0]['tags'][tifftools.Tag.FreeByteCounts.value] = {
        'datatype': tifftools.Datatype.LONG,
        'data': [16777216] * 256,
    }
    destpath = tmp_path / 'sample.tiff'
    tifftools.write_tiff(info, destpath)
    destinfo = tifftools.read_tiff(destpath)
    assert destinfo['bigtiff'] is True
예제 #8
0
def test_write_wrong_counts():
    path = os.path.join(os.path.dirname(__file__), 'data', 'good_single.tif')
    info = tifftools.read_tiff(path)
    info['ifds'][0]['tags'][tifftools.Tag.StripByteCounts.value]['data'].pop()
    with pytest.raises(Exception) as exc:
        tifftools.write_tiff(info, '-')
    assert 'Offsets and byte counts do not correspond' in str(exc.value)
예제 #9
0
def test_tiff_set_setfrom(tmp_path):
    path = datastore.fetch('d043-200.tif')
    dest = tmp_path / 'results.tif'
    tifftools.tiff_set(str(path) + ',1', dest, setfrom=[('Model', path)])
    info = tifftools.read_tiff(str(dest))
    assert info['ifds'][0]['tags'][int(
        tifftools.Tag.Model)]['data'] == 'NIKON D500'
예제 #10
0
def testConvertJp2kCompression(tmpdir):
    imagePath = datastore.fetch('sample_Easy1.png')
    outputPath = os.path.join(tmpdir, 'out.tiff')
    large_image_converter.convert(imagePath, outputPath, compression='jp2k')
    info = tifftools.read_tiff(outputPath)
    assert (info['ifds'][0]['tags'][tifftools.Tag.Compression.value]['data'][0]
            == tifftools.constants.Compression.JP2000.value)
    source = large_image_source_tiff.open(outputPath)
    image, _ = source.getRegion(output={
        'maxWidth': 200,
        'maxHeight': 200
    },
                                format=constants.TILE_FORMAT_NUMPY)
    assert (image[12][167] == [215, 135, 172]).all()

    outputPath2 = os.path.join(tmpdir, 'out2.tiff')
    large_image_converter.convert(imagePath,
                                  outputPath2,
                                  compression='jp2k',
                                  psnr=50)
    assert os.path.getsize(outputPath2) < os.path.getsize(outputPath)

    outputPath3 = os.path.join(tmpdir, 'out3.tiff')
    large_image_converter.convert(imagePath,
                                  outputPath3,
                                  compression='jp2k',
                                  cr=100)
    assert os.path.getsize(outputPath3) < os.path.getsize(outputPath)
    assert os.path.getsize(outputPath3) != os.path.getsize(outputPath2)
예제 #11
0
def test_bigtiff_bigendian(tmp_path, bigtiff, bigendian):
    path = datastore.fetch('d043-200.tif')
    dest = tmp_path / 'results.tif'
    cmd = ['merge', path, str(dest)]
    cmd.extend(bigtiff)
    cmd.extend(bigendian)
    tifftools.main(cmd)
    srcinfo = tifftools.read_tiff(path)
    destinfo = tifftools.read_tiff(dest)
    srcval = srcinfo['ifds'][0]['tags'][int(
        tifftools.Tag.EXIFIFD)]['ifds'][0][0]['tags'][int(
            tifftools.constants.EXIFTag.MakerNote)]['data']
    destval = destinfo['ifds'][0]['tags'][int(
        tifftools.Tag.EXIFIFD)]['ifds'][0][0]['tags'][int(
            tifftools.constants.EXIFTag.MakerNote)]['data']
    assert srcval == destval
예제 #12
0
def testConverterMainFullStats(tmpdir):
    imagePath = datastore.fetch('sample_Easy1.png')
    outputPath = os.path.join(tmpdir, 'out.tiff')
    main.main([imagePath, outputPath, '--full-stats'])
    info = tifftools.read_tiff(outputPath)
    desc = json.loads(info['ifds'][0]['tags'][tifftools.Tag.ImageDescription.value]['data'])
    assert 'psnr' in desc['large_image_converter']['conversion_stats']
예제 #13
0
def testConvertTiffFloatPixels(tmpdir):
    imagePath = datastore.fetch('d042-353.crop.small.float32.tif')
    outputPath = os.path.join(tmpdir, 'out.tiff')
    large_image_converter.convert(imagePath, outputPath)
    info = tifftools.read_tiff(outputPath)
    assert (info['ifds'][0]['tags'][tifftools.Tag.SampleFormat.value]['data'][0] ==
            tifftools.constants.SampleFormat.uint.value)
예제 #14
0
def test_write_allow_existing(tmp_path):
    path = datastore.fetch('d043-200.tif')
    info = tifftools.read_tiff(path)
    destpath = tmp_path / 'sample.tiff'
    tifftools.write_tiff(info, destpath)
    len = os.path.getsize(destpath)
    tifftools.write_tiff(info, destpath, allowExisting=True)
    assert len == os.path.getsize(destpath)
예제 #15
0
def testConvert(tmpdir, convert_args, taglist):
    testDir = os.path.dirname(os.path.realpath(__file__))
    imagePath = os.path.join(testDir, 'test_files', 'yb10kx5k.png')
    outputPath = os.path.join(tmpdir, 'out.tiff')
    large_image_converter.convert(imagePath, outputPath, **convert_args)
    info = tifftools.read_tiff(outputPath)
    for key, value in taglist.items():
        assert info['ifds'][0]['tags'][key]['data'][0] == value
예제 #16
0
def testConverterMainFullStatsWithWebp(tmpdir):
    imagePath = datastore.fetch('d042-353.crop.small.float32.tif')
    outputPath = os.path.join(tmpdir, 'out.tiff')
    main.main([imagePath, outputPath, '--compression', 'webp', '--full-stats'])
    info = tifftools.read_tiff(outputPath)
    desc = json.loads(info['ifds'][0]['tags'][tifftools.Tag.ImageDescription.value]['data'])
    assert 'psnr' in desc['large_image_converter']['conversion_stats']
    assert desc['large_image_converter']['conversion_stats']['psnr'] < 60
예제 #17
0
def testConverterMainStats(tmpdir):
    testDir = os.path.dirname(os.path.realpath(__file__))
    imagePath = os.path.join(testDir, 'test_files', 'yb10kx5k.png')
    outputPath = os.path.join(tmpdir, 'out.tiff')
    main.main([imagePath, outputPath, '--stats'])
    info = tifftools.read_tiff(outputPath)
    desc = json.loads(info['ifds'][0]['tags'][tifftools.Tag.ImageDescription.value]['data'])
    assert 'conversion_stats' in desc['large_image_converter']
예제 #18
0
def testConvertOMETif(tmpdir):
    imagePath = datastore.fetch('sample.ome.tif')
    outputPath = os.path.join(tmpdir, 'out.tiff')
    # Note: change this when we convert multi-frame files differently
    large_image_converter.convert(imagePath, outputPath)
    info = tifftools.read_tiff(outputPath)
    assert len(info['ifds']) == 3
    assert len(info['ifds'][0]['tags'][tifftools.Tag.SubIFD.value]['ifds']) == 4
예제 #19
0
def test_write_already_exists(tmp_path):
    path = datastore.fetch('d043-200.tif')
    info = tifftools.read_tiff(path)
    destpath = tmp_path / 'sample.tiff'
    tifftools.write_tiff(info, destpath)
    with pytest.raises(Exception) as exc:
        tifftools.write_tiff(info, destpath)
    assert 'File already exists' in str(exc.value)
예제 #20
0
def testConvertFromTestSourceFrames(tmpdir):
    outputPath = os.path.join(tmpdir, 'out.tiff')
    large_image_converter.convert('large_image://test?maxLevel=3&frames=4', outputPath)
    source = large_image_source_tiff.open(outputPath)
    metadata = source.getMetadata()
    assert metadata['levels'] == 4
    assert len(metadata['frames']) == 4
    info = tifftools.read_tiff(outputPath)
    assert len(info['ifds']) == 4
예제 #21
0
def testConvertFromMultiframeImageOnlyOneFrame(tmpdir):
    imagePath = datastore.fetch('sample.ome.tif')
    outputPath = os.path.join(tmpdir, 'out.tiff')
    large_image_converter.convert(imagePath, outputPath, onlyFrame=2)
    source = large_image_source_tiff.open(outputPath)
    metadata = source.getMetadata()
    assert metadata['levels'] == 5
    info = tifftools.read_tiff(outputPath)
    assert len(info['ifds']) == 5
예제 #22
0
def testConvertPTIF(tmpdir):
    imagePath = datastore.fetch('sample_image.ptif')
    outputPath = os.path.join(tmpdir, 'out.tiff')
    large_image_converter.convert(imagePath,
                                  outputPath,
                                  compression='jpeg',
                                  quality=50)
    info = tifftools.read_tiff(outputPath)
    assert len(info['ifds']) == 11
예제 #23
0
def testConvertGeospatial(tmpdir):
    testDir = os.path.dirname(os.path.realpath(__file__))
    imagePath = os.path.join(testDir, 'test_files', 'rgb_geotiff.tiff')
    inputPath = os.path.join(tmpdir, 'in.geo.tiff')
    shutil.copy(imagePath, inputPath)
    outputPath = large_image_converter.convert(inputPath, level=5)
    assert 'geo.tiff' in outputPath
    assert outputPath != inputPath
    info = tifftools.read_tiff(outputPath)
    assert tifftools.Tag.ModelTiepointTag.value in info['ifds'][0]['tags']
예제 #24
0
def testConvertFromMultiframeImageNoSubIFDS(tmpdir):
    imagePath = datastore.fetch('sample.ome.tif')
    outputPath = os.path.join(tmpdir, 'out.tiff')
    large_image_converter.convert(imagePath, outputPath, subifds=False)
    source = large_image_source_tiff.open(outputPath)
    metadata = source.getMetadata()
    assert metadata['levels'] == 5
    assert len(metadata['frames']) == 3
    info = tifftools.read_tiff(outputPath)
    assert len(info['ifds']) == 15
예제 #25
0
def test_write_single_subifd(tmp_path):
    path = os.path.join(os.path.dirname(__file__), 'data', 'good_single.tif')
    info = tifftools.read_tiff(path)
    info['ifds'][0]['tags'][tifftools.Tag.SubIFD.value] = {
        'ifds': [copy.deepcopy(info['ifds'][0])]
    }
    dest1path = tmp_path / 'sample1.tiff'
    tifftools.write_tiff(info, dest1path)
    dest1info = tifftools.read_tiff(dest1path)
    assert len(dest1info['ifds'][0]['tags'][tifftools.Tag.SubIFD.value]['ifds']
               [0]) == 1
    info = tifftools.read_tiff(path)
    info['ifds'][0]['tags'][tifftools.Tag.SubIFD.value] = {
        'ifds': [copy.deepcopy(info['ifds'])]
    }
    dest2path = tmp_path / 'sample2.tiff'
    tifftools.write_tiff(info, dest2path)
    dest2info = tifftools.read_tiff(dest2path)
    assert len(dest2info['ifds'][0]['tags'][tifftools.Tag.SubIFD.value]['ifds']
               [0]) == 1
예제 #26
0
def test_write_bytecount_data(tmp_path):
    path = os.path.join(os.path.dirname(__file__), 'data', 'good_single.tif')
    info = tifftools.read_tiff(path)
    # Just use data from within the file itself; an actual sample file with
    # compression 6 and defined Q, AC, and DC tables would be better.
    info['ifds'][0]['tags'][tifftools.Tag.JPEGQTables.value] = {
        'datatype': tifftools.Datatype.LONG,
        'data': [8],
    }
    destpath = tmp_path / 'sample.tiff'
    tifftools.write_tiff(info, destpath)
    assert os.path.getsize(destpath) > os.path.getsize(path) + 64
예제 #27
0
def test_tiff_set_fromfile(tmp_path):
    path = datastore.fetch('d043-200.tif')
    dest = tmp_path / 'results.tif'
    tagfile = tmp_path / 'tag.txt'
    with open(tagfile, 'w') as fptr:
        fptr.write('Dog digging')
    tifftools.tiff_set(str(path),
                       dest,
                       setlist=[('ImageDescription', '@%s' % tagfile)])
    info = tifftools.read_tiff(str(dest))
    assert info['ifds'][0]['tags'][int(
        tifftools.Tag.ImageDescription)]['data'] == 'Dog digging'
예제 #28
0
def testTileFrames():
    imagePath = datastore.fetch('sample.ome.tif')
    source = large_image_source_tiff.open(imagePath)

    params = {'encoding': 'PNG', 'output': {'maxWidth': 200, 'maxHeight': 200}}
    image, mimeType = source.tileFrames(**params)
    assert image[:len(utilities.PNGHeader)] == utilities.PNGHeader
    (width, height) = struct.unpack('!LL', image[16:24])
    assert width == 400
    assert height == 382

    params['fill'] = 'corner:black'
    image, mimeType = source.tileFrames(**params)
    assert image[:len(utilities.PNGHeader)] == utilities.PNGHeader
    (width, height) = struct.unpack('!LL', image[16:24])
    assert width == 400
    assert height == 400

    params['framesAcross'] = 3
    image, mimeType = source.tileFrames(**params)
    assert image[:len(utilities.PNGHeader)] == utilities.PNGHeader
    (width, height) = struct.unpack('!LL', image[16:24])
    assert width == 600
    assert height == 200

    params['frameList'] = [0, 2]
    image, mimeType = source.tileFrames(**params)
    assert image[:len(utilities.PNGHeader)] == utilities.PNGHeader
    (width, height) = struct.unpack('!LL', image[16:24])
    assert width == 400
    assert height == 200

    params['frameList'] = [0]
    image, mimeType = source.tileFrames(**params)
    assert image[:len(utilities.PNGHeader)] == utilities.PNGHeader
    (width, height) = struct.unpack('!LL', image[16:24])
    assert width == 200
    assert height == 200

    params.pop('frameList')
    params['encoding'] = 'TILED'
    image, mimeType = source.tileFrames(**params)
    info = tifftools.read_tiff(image)
    assert len(info['ifds']) == 3
    os.unlink(image)
예제 #29
0
def test_tiff_set_stdin(tmp_path, monkeypatch):
    mock_stdin = io.BytesIO()
    mock_stdin.write(b'Dog digging')
    mock_stdin.seek(0)
    mock_stdin.seekable = lambda: False

    class Namespace(object):
        pass

    mock_obj = Namespace()
    mock_obj.buffer = mock_stdin
    monkeypatch.setattr('sys.stdin', mock_obj)

    path = datastore.fetch('d043-200.tif')
    dest = tmp_path / 'results.tif'
    tifftools.tiff_set(str(path), dest, setlist=[('ImageDescription', '@-')])
    info = tifftools.read_tiff(str(dest))
    assert info['ifds'][0]['tags'][int(
        tifftools.Tag.ImageDescription)]['data'] == 'Dog digging'
예제 #30
0
def create_thumbnail_and_label(tempPath, info, ifdCount, needsLabel,
                               labelPosition, **kwargs):
    """
    Create a thumbnail and, optionally, label image for the aperio file.

    :param tempPath: a temporary file in a temporary directory.
    :param info: the tifftools info that will be written to the tiff tile;
        modified.
    :param ifdCount: the number of ifds in the first tiled image.  This is 1 if
        there are subifds.
    :param needsLabel: true if a label image needs to be added.
    :param labelPosition: the position in the ifd list where a label image
        should be inserted.
    """
    thumbnailSize = 1024
    labelSize = 640
    maxLabelAspect = 1.5
    tileSize = info['ifds'][0]['tags'][
        tifftools.Tag.TileWidth.value]['data'][0]
    levels = int(
        math.ceil(
            math.log(max(thumbnailSize, labelSize) / tileSize) /
            math.log(2))) + 1

    neededList = ['thumbnail']
    if needsLabel:
        neededList[0:0] = ['label']
    tiledPath = tempPath + '-overview.tiff'
    firstFrameIfds = info['ifds'][max(0, ifdCount - levels):ifdCount]
    tifftools.write_tiff(firstFrameIfds, tiledPath)
    ts = large_image_source_tiff.open(tiledPath)
    for subImage in neededList:
        if subImage == 'label':
            x = max(0,
                    (ts.sizeX - min(ts.sizeX, ts.sizeY) * maxLabelAspect) // 2)
            y = max(0,
                    (ts.sizeY - min(ts.sizeX, ts.sizeY) * maxLabelAspect) // 2)
            regionParams = {
                'output':
                dict(maxWidth=labelSize, maxHeight=labelSize),
                'region':
                dict(left=x, right=ts.sizeX - x, top=y, bottom=ts.sizeY - y),
            }
        else:
            regionParams = {
                'output': dict(maxWidth=thumbnailSize, maxHeight=thumbnailSize)
            }
        image, _ = ts.getRegion(format=large_image.constants.TILE_FORMAT_PIL,
                                **regionParams)
        if image.mode not in {'RGB', 'L'}:
            image = image.convert('RGB')
        if subImage == 'label':
            image = image.rotate(90, expand=True)
        imagePath = tempPath + '-image_%s.tiff' % subImage
        image.save(imagePath,
                   'TIFF',
                   compression='tiff_jpeg',
                   quality=int(kwargs.get('quality', 90)))
        imageInfo = tifftools.read_tiff(imagePath)
        ifd = imageInfo['ifds'][0]
        if subImage == 'label':
            ifd['tags'][tifftools.Tag.Orientation.value] = {
                'data': [tifftools.constants.Orientation.RightTop.value],
                'datatype': tifftools.Datatype.LONG,
            }
            description = AperioHeader + AssociatedHeader.format(
                name='label',
                width=ifd['tags'][tifftools.Tag.ImageWidth.value]['data'][0],
                height=ifd['tags'][tifftools.Tag.ImageHeight.value]['data'][0],
            )
            ifd['tags'][tifftools.Tag.ImageDescription.value] = {
                'data': description,
                'datatype': tifftools.Datatype.ASCII,
            }
            ifd['tags'][tifftools.Tag.NewSubfileType.value] = {
                'data':
                [tifftools.constants.NewSubfileType.ReducedImage.value],
                'datatype': tifftools.Datatype.LONG,
            }
            info['ifds'][labelPosition:labelPosition] = imageInfo['ifds']
        else:
            fullDesc = info['ifds'][0]['tags'][
                tifftools.Tag.ImageDescription.value]['data']
            description = fullDesc.split('[', 1)[0] + ThumbnailHeader.format(
                width=ifd['tags'][tifftools.Tag.ImageWidth.value]['data'][0],
                height=ifd['tags'][tifftools.Tag.ImageHeight.value]['data'][0],
            ) + fullDesc.split('|', 1)[1]
            ifd['tags'][tifftools.Tag.ImageDescription.value] = {
                'data': description,
                'datatype': tifftools.Datatype.ASCII,
            }
            info['ifds'][1:1] = imageInfo['ifds']