Skip to content

Commit

Permalink
Make threadsafe.
Browse files Browse the repository at this point in the history
  • Loading branch information
manthey committed Apr 11, 2022
1 parent 81966f4 commit 3595967
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 18 deletions.
14 changes: 7 additions & 7 deletions sources/vips/large_image_source_vips/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def _initNew(self, **kwargs):
self._output = None
self._editable = True
self._bandRanges = None
self._addLock = threading.Lock()
self._addLock = threading.RLock()

def getState(self):
# Use the _cacheValue to avoid caching the source and tiles if we are
Expand Down Expand Up @@ -247,7 +247,7 @@ def _addVipsImage(self, vimg, x=0, y=0):
vimgTemp = pyvips.Image.new_temp_file('%s.v')
vimg.write(vimgTemp)
vimg = vimgTemp
with self._addLock():
with self._addLock:
if self._output is None:
self._output = {
'images': [],
Expand Down Expand Up @@ -297,10 +297,10 @@ def addTile(self, tile, x=0, y=0, mask=None, interpretation=None):
if type(tile) != pyvips.vimage.Image:
tile, mode = _imageToNumpy(tile)
interpretation = interpretation or mode
with self._addLock():
with self._addLock:
self._updateBandRanges(tile)
if interpretation == 'pixelmap':
with self._addLock():
with self._addLock:
self._interpretation = 'pixelmap'
tile = numpy.dstack((
(tile % 256).astype(int),
Expand Down Expand Up @@ -343,7 +343,7 @@ def _outputToImage(self):
alpha channel is always included unless the intrepretation is
multichannel.
"""
with self._addLock():
with self._addLock:
bands = self._output['bands']
if bands in {1, 3}:
bands += 1
Expand Down Expand Up @@ -396,7 +396,7 @@ def write(self, path, lossy=True, alpha=True, overwriteAllowed=True):
"""
if not overwriteAllowed and os.path.exists(path):
raise TileSourceError('Output path exists (%s)' % str(path))
with self._addLock():
with self._addLock:
img = self._getFrameImage(0)
# TODO: set image description: e.g.,
# img.set_type(
Expand All @@ -408,7 +408,7 @@ def write(self, path, lossy=True, alpha=True, overwriteAllowed=True):
img = img[:-1]
if not lossy:
img.write_to_file(
path, tile_width=self.tileWidth, tile_height=self.tileHieght,
path, tile_width=self.tileWidth, tile_height=self.tileHeight,
pyramid=True, bigtiff=True,
region_shrink='nearest', compression='lzw', predictor='horizontal')
else:
Expand Down
44 changes: 33 additions & 11 deletions test/test_source_vips.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import tempfile

import large_image_source_vips
import pytest

import large_image

Expand All @@ -12,21 +11,20 @@


def testTilesFromVips():
imagePath = datastore.fetch('sample_image.ptif')
imagePath = datastore.fetch('d042-353.crop.small.float32.tif')
source = large_image_source_vips.open(imagePath)
tileMetadata = source.getMetadata()

assert tileMetadata['tileWidth'] == 256
assert tileMetadata['tileHeight'] == 256
assert tileMetadata['sizeX'] == 58368
assert tileMetadata['sizeY'] == 12288
assert tileMetadata['levels'] == 9
assert tileMetadata['magnification'] == pytest.approx(40, 1)
assert tileMetadata['sizeX'] == 480
assert tileMetadata['sizeY'] == 320
assert tileMetadata['levels'] == 2
utilities.checkTilesZXY(source, tileMetadata)


def testInternalMetadata():
imagePath = datastore.fetch('sample_image.ptif')
imagePath = datastore.fetch('d042-353.crop.small.float32.tif')
source = large_image_source_vips.open(imagePath)
metadata = source.getInternalMetadata()
assert 'vips-loader' in metadata
Expand All @@ -35,18 +33,42 @@ def testInternalMetadata():
def testNewAndWrite():
imagePath = datastore.fetch('sample_image.ptif')
source = large_image.open(imagePath)
sourceMetadata = source.getMetadata()
out = large_image_source_vips.new()
for tile in source.tileIterator(format=large_image.constants.TILE_FORMAT_NUMPY):
for tile in source.tileIterator(
format=large_image.constants.TILE_FORMAT_NUMPY,
region=dict(right=4000, bottom=2000),
):
out.addTile(tile['tile'], x=tile['x'], y=tile['y'])

tmpdir = tempfile.mkdtemp()
outputPath = os.path.join(tmpdir, 'temp.tiff')
try:
out.write(outputPath)
assert os.path.getsize(outputPath) > 500000
assert os.path.getsize(outputPath) > 50000
result = large_image.open(outputPath)
resultMetadata = result.getMetadata()
assert resultMetadata['sizeX'] == 4000
finally:
shutil.rmtree(tmpdir)


def testNewAndWriteLossless():
imagePath = datastore.fetch('sample_image.ptif')
source = large_image.open(imagePath)
out = large_image_source_vips.new()
for tile in source.tileIterator(
format=large_image.constants.TILE_FORMAT_NUMPY,
region=dict(right=4000, bottom=2000),
):
out.addTile(tile['tile'], x=tile['x'], y=tile['y'])

tmpdir = tempfile.mkdtemp()
outputPath = os.path.join(tmpdir, 'temp.tiff')
try:
out.write(outputPath, lossy=False)
assert os.path.getsize(outputPath) > 50000
result = large_image.open(outputPath)
resultMetadata = result.getMetadata()
assert sourceMetadata['sizeX'] == resultMetadata['sizeX']
assert resultMetadata['sizeX'] == 4000
finally:
shutil.rmtree(tmpdir)

0 comments on commit 3595967

Please sign in to comment.