Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust multisource multi layer compositing. #1736

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## 1.30.5

### Improvements

- When using the multisource to composite multiple images with alpha channels, use nearest neighbor for upper tiles ([#1736](../../pull/1736))

### Changes

- Adjust how compositing is done on styled images by adjusting the expected full alpha value ([#1735](../../pull/1735))
Expand Down
16 changes: 12 additions & 4 deletions sources/multi/large_image_source_multi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1037,7 +1037,8 @@ def _mergeTiles(self, base, tile, x, y):
base[y:y + tile.shape[0], x:x + tile.shape[1], :] = tile
return base

def _getTransformedTile(self, ts, transform, corners, scale, frame, crop=None):
def _getTransformedTile(self, ts, transform, corners, scale, frame,
crop=None, firstMerge=False):
"""
Determine where the target tile's corners are located on the source.
Fetch that so that we have at least sqrt(2) more resolution, then use
Expand All @@ -1054,6 +1055,9 @@ def _getTransformedTile(self, ts, transform, corners, scale, frame, crop=None):
:param crop: an optional dictionary to crop the source image in full
resolution, untransformed coordinates. This may contain left, top,
right, and bottom values in pixels.
:param firstMerge: if False and using an alpha channel, transform
with nearest neighbor rather than a higher order function to
avoid transparency effects.
:returns: a numpy array tile or None, x, y coordinates within the
target tile for the placement of the numpy tile array.
"""
Expand Down Expand Up @@ -1145,9 +1149,12 @@ def _getTransformedTile(self, ts, transform, corners, scale, frame, crop=None):
destShape = [min(destShape[0], outh - y), min(destShape[1], outw - x)]
if destShape[0] <= 0 or destShape[1] <= 0:
return None, None, None
# Add an alpha band if needed
# Add an alpha band if needed. This has to be done before the
# transform if it isn't the first tile, since the unused transformed
# areas need to have a zero alpha value
if srcImage.shape[2] in {1, 3}:
_, srcImage = _makeSameChannelDepth(np.zeros((1, 1, srcImage.shape[2] + 1)), srcImage)
useNearest = srcImage.shape[2] in {2, 4} and not firstMerge
# skimage.transform.warp is faster and has less artifacts than
# scipy.ndimage.affine_transform. It is faster than using cupy's
# version of scipy's affine_transform when the source and destination
Expand All @@ -1157,7 +1164,7 @@ def _getTransformedTile(self, ts, transform, corners, scale, frame, crop=None):
# provide any speed improvement
srcImage.astype(float),
skimage.transform.AffineTransform(np.linalg.inv(transform)),
order=3,
order=0 if useNearest else 3,
output_shape=(destShape[0], destShape[1], srcImage.shape[2]),
).astype(srcImage.dtype)
return destImage, x, y
Expand Down Expand Up @@ -1234,7 +1241,8 @@ def _addSourceToTile(self, tile, sourceEntry, corners, scale):
else:
sourceTile, x, y = self._getTransformedTile(
ts, transform, corners, scale, sourceEntry.get('frame', 0),
source.get('position', {}).get('crop'))
source.get('position', {}).get('crop'),
firstMerge=tile is None)
if sourceTile is not None and all(dim > 0 for dim in sourceTile.shape):
targetDtype = np.dtype(self._info.get('dtype', ts.dtype))
changeDtype = sourceTile.dtype != targetDtype
Expand Down
Loading