Skip to content

Commit

Permalink
Merge pull request #1401 from girder/add-tile-negative
Browse files Browse the repository at this point in the history
Support negative x, y in addTile
  • Loading branch information
manthey authored Dec 7, 2023
2 parents 018fef8 + 5936d4e commit 86053c9
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Reduce stderr noise in PIL and rasterio sources ([#1397](../../pull/1397))
- Harden OME tiff reader ([#1398](../../pull/1398))
- Improve checks for formats we shouldn't read ([#1399](../../pull/1399))
- Support negative x, y in addTile ([#1401](../../pull/1401))

### Changes
- Use an enum for priority constants ([#1400](../../pull/1400))
Expand Down
20 changes: 16 additions & 4 deletions sources/vips/large_image_source_vips/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ def _invalidateImage(self):
"""
if self._output is not None:
self._image = None
w, h = self._output['width'], self._output['height']
w = self._output['width'] - min(0, self._output['minx'])
h = self._output['height'] - min(0, self._output['miny'])
w = max(self.minWidth or w, w)
h = max(self.minHeight or h, h)
self.sizeX = w
Expand All @@ -311,7 +312,10 @@ def _invalidateImage(self):
def addTile(self, tile, x=0, y=0, mask=None, interpretation=None):
"""
Add a numpy or image tile to the image, expanding the image as needed
to accommodate it.
to accommodate it. Note that x and y can be negative. If so, the
output image (and internal memory access of the image) will act as if
the 0, 0 point is the most negative position. Cropping is applied
after this offset.
:param tile: a numpy array, PIL Image, vips image, or a binary string
with an image. The numpy array can have 2 or 3 dimensions.
Expand Down Expand Up @@ -432,7 +436,9 @@ def _outputToImage(self):
if img.format == 'float' and entry['image'].format == 'double':
entryimage = entryimage.cast(img.format)
branch = branch.composite(
entryimage, pyvips.BlendMode.OVER, x=entry['x'], y=entry['y'])
entryimage, pyvips.BlendMode.OVER,
x=entry['x'] - min(0, self._output['minx']),
y=entry['y'] - min(0, self._output['miny']))
if not ((idx + 1) % leaves) or idx + 1 == len(self._output['images']):
trunk = trunk.composite(branch, pyvips.BlendMode.OVER, x=0, y=0)
branch = baseimg.copy()
Expand Down Expand Up @@ -594,9 +600,15 @@ def bandFormat(self):
if not self._editable:
return self._image.format
return self._getVipsFormat()

# TODO: specify bit depth / bandFormat explicitly

@property
def origin(self):
if not self._editable:
return {'x': 0, 'y': 0}
return {'x': min(0, self._output['minx'] or 0),
'y': min(0, self._output['miny'] or 0)}


def open(*args, **kwargs):
"""Create an instance of the module class."""
Expand Down
28 changes: 28 additions & 0 deletions test/test_source_vips.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import tempfile

import large_image_source_vips
import numpy as np
import pytest
import pyvips

Expand Down Expand Up @@ -210,3 +211,30 @@ def testNewAndWriteWithMask():
assert resultMetadata['sizeX'] == 4000
finally:
shutil.rmtree(tmpdir)


def testNewAndWriteNegative():
out = large_image_source_vips.new()
out.addTile(np.full((4, 4, 3), 1, dtype=np.uint8), x=0, y=0)
out.addTile(np.full((5, 4, 3), 2, dtype=np.uint8), x=-2, y=1)
with tempfile.TemporaryDirectory() as tmpdir:
outputPath = os.path.join(tmpdir, 'temp.tiff')
out.write(outputPath, lossy=False)
region = out.getRegion(format=large_image.constants.TILE_FORMAT_NUMPY)[0]
assert (region[:, :, 0] == np.array([
[0, 0, 1, 1, 1, 1],
[2, 2, 2, 2, 1, 1],
[2, 2, 2, 2, 1, 1],
[2, 2, 2, 2, 1, 1],
[2, 2, 2, 2, 0, 0],
[2, 2, 2, 2, 0, 0]])).all()

ts = large_image.open(outputPath)
region = ts.getRegion(format=large_image.constants.TILE_FORMAT_NUMPY)[0]
assert (region[:, :, 0] == np.array([
[0, 0, 1, 1, 1, 1],
[2, 2, 2, 2, 1, 1],
[2, 2, 2, 2, 1, 1],
[2, 2, 2, 2, 1, 1],
[2, 2, 2, 2, 0, 0],
[2, 2, 2, 2, 0, 0]])).all()

0 comments on commit 86053c9

Please sign in to comment.