Skip to content

Commit

Permalink
Merge pull request #529 from girder/convert-from-large-image
Browse files Browse the repository at this point in the history
Convert from large_image sources.
  • Loading branch information
manthey authored Jan 20, 2021
2 parents b1e3c49 + b012dd3 commit 6011a63
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
### Features
- Added a `canRead` method to the core module (#512)
- Image conversion supports JPEG 2000 (jp2k) compression (#522)
- Image conversion can now convert images readable by large_image sources but not by vips (#529)

### Improvements
- Better release bioformats resources (#502)
Expand Down
10 changes: 9 additions & 1 deletion test/test_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,15 @@ def testConvertJp2kCompression(tmpdir):
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)
# ##DWM::


def testConvertFromLargeImage(tmpdir):
imagePath = utilities.externaldata('data/sample_image.jp2.sha512')
outputPath = os.path.join(tmpdir, 'out.tiff')
large_image_converter.convert(imagePath, outputPath)
source = large_image_source_tiff.TiffFileTileSource(outputPath)
metadata = source.getMetadata()
assert metadata['levels'] == 6


def testConverterMain(tmpdir):
Expand Down
63 changes: 61 additions & 2 deletions utilities/converter/large_image_converter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ def _convert_via_vips(inputPathOrBuffer, outputPath, tempPath, forTiled=True,
# value needs to be specified if they are True.
convertParams = _vips_parameters(forTiled, **kwargs)
status = (', ' + status) if status else ''
if type(inputPathOrBuffer) == bytes:
if type(inputPathOrBuffer) == pyvips.vimage.Image:
source = 'vips image'
image = inputPathOrBuffer
elif type(inputPathOrBuffer) == bytes:
source = 'buffer'
image = pyvips.Image.new_from_buffer(inputPathOrBuffer, '')
else:
Expand Down Expand Up @@ -268,6 +271,59 @@ def _convert_to_jp2k(path, **kwargs):
os.rename(tmppath, path)


def _convert_large_image(inputPath, outputPath, tempPath, lidata, **kwargs):
"""
Take a large_image source and convert it by resaving each tiles image with
vips.
:params inputPath: the path to the input file or base file of a set.
:params outputPath: the path of the output file.
:params tempPath: a temporary file in a temporary directory.
:params lidata: data from a large_image tilesource including associated
images.
"""
ts = lidata['tilesource']
numFrames = len(lidata['metadata'].get('frames', [0]))
outputList = []
_iterTileSize = 1024
for frame in range(numFrames):
subOutputPath = tempPath + '-%d-%s.tiff' % (
frame + 1, time.strftime('%Y%m%d-%H%M%S'))
strips = []
for tile in ts.tileIterator(tile_size=dict(width=_iterTileSize), frame=frame):
data = tile['tile']
dtypeToGValue = {
'b': 'char',
'B': 'uchar',
'd': 'double',
'D': 'dpcomplex',
'f': 'float',
'F': 'complex',
'h': 'short',
'H': 'ushort',
'i': 'int',
'I': 'uint',
}
if data.dtype.char not in dtypeToGValue:
data = data.astype('d')
vimg = pyvips.Image.new_from_memory(
data.data, data.shape[1], data.shape[0], data.shape[2],
dtypeToGValue[data.dtype.char])
x = tile['x']
ty = tile['tile_position']['level_y']
if ty >= len(strips):
strips.append(vimg)
else:
strips[ty] = strips[ty].insert(vimg, x, 0, expand=True)
img = strips[0]
for stripidx in range(1, len(strips)):
img = img.insert(strips[stripidx], 0, stripidx * _iterTileSize, expand=True)
_convert_via_vips(
img, subOutputPath, tempPath, status='%d/%d' % (frame, numFrames), **kwargs)
outputList.append(subOutputPath)
_output_tiff(outputList, outputPath, lidata)


def _output_tiff(inputs, outputPath, lidata, extraImages=None):
"""
Given a list of input tiffs and data as parsed by _data_from_large_image,
Expand Down Expand Up @@ -562,7 +618,10 @@ def convert(inputPath, outputPath=None, **kwargs):
tempPath = os.path.join(tempDir, os.path.basename(outputPath))
lidata = _data_from_large_image(inputPath, tempPath)
logger.debug('large_image information for %s: %r' % (inputPath, lidata))
_generate_tiff(inputPath, outputPath, tempPath, lidata, **kwargs)
if not is_vips(inputPath) and lidata:
_convert_large_image(inputPath, outputPath, tempPath, lidata, **kwargs)
else:
_generate_tiff(inputPath, outputPath, tempPath, lidata, **kwargs)
return outputPath


Expand Down

0 comments on commit 6011a63

Please sign in to comment.