Skip to content

Commit

Permalink
Support a bands parameter for the test source.
Browse files Browse the repository at this point in the history
  • Loading branch information
manthey committed Aug 16, 2022
1 parent 50a53f8 commit 1c3d608
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 6 deletions.
6 changes: 6 additions & 0 deletions sources/multi/large_image_source_multi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,10 @@ def _collectFrames(self, checkAll=False):
self._nativeMagnification[key] or tsMag.get(key))
numChecked += 1
tsMeta = ts.getMetadata()
if 'bands' in tsMeta:
if not hasattr(self, '_bands'):
self._bands = {}
self._bands.update(tsMeta['bands'])
bbox = self._sourceBoundingBox(source, tsMeta['sizeX'], tsMeta['sizeY'])
computedWidth = max(computedWidth, int(math.ceil(bbox['right'])))
computedHeight = max(computedHeight, int(math.ceil(bbox['bottom'])))
Expand Down Expand Up @@ -774,6 +778,8 @@ def getMetadata(self):
{k: v for k, v in frame.items() if k.startswith('Index')}
for frame in self._frames]
self._addMetadataFrameInformation(result, self._channels)
if hasattr(self, '_bands'):
result['bands'] = self._bands.copy()
return result

def getInternalMetadata(self, **kwargs):
Expand Down
31 changes: 26 additions & 5 deletions sources/test/large_image_source_test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
import itertools
import math

import numpy
from PIL import Image, ImageDraw, ImageFont

from large_image.cache_util import LruCacheMetaclass, methodcache, strhash
from large_image.constants import TILE_FORMAT_PIL, SourcePriority
from large_image.constants import TILE_FORMAT_NUMPY, TILE_FORMAT_PIL, SourcePriority
from large_image.exceptions import TileSourceError
from large_image.tilesource import TileSource
from large_image.tilesource.utilities import _imageToNumpy

try:
from importlib.metadata import PackageNotFoundError
Expand Down Expand Up @@ -52,7 +54,8 @@ class TestTileSource(TileSource, metaclass=LruCacheMetaclass):

def __init__(self, ignored_path=None, minLevel=0, maxLevel=9,
tileWidth=256, tileHeight=256, sizeX=None, sizeY=None,
fractal=False, frames=None, monochrome=False, **kwargs):
fractal=False, frames=None, monochrome=False, bands=None,
**kwargs):
"""
Initialize the tile class. See the base class for other available
parameters.
Expand All @@ -71,6 +74,8 @@ def __init__(self, ignored_path=None, minLevel=0, maxLevel=9,
:param frames: if present, this is either a single number for generic
frames, or comma-separated list of c,z,t,xy.
:param monochrome: if True, return single channel tiles.
:param bands: if present, a comma-separated list of band names.
Defaults to red,green,blue.
"""
if not kwargs.get('encoding'):
kwargs = kwargs.copy()
Expand All @@ -93,6 +98,8 @@ def __init__(self, ignored_path=None, minLevel=0, maxLevel=9,
self.sizeX / self.tileWidth, self.sizeY / self.tileHeight))))
self.frameSpec = frames or None
self.monochrome = bool(monochrome)
self.bandSpec = bands or None
self._bands = bands.split(',') if bands else None
# Used for reporting tile information
self.levels = self.maxLevel + 1
if frames:
Expand Down Expand Up @@ -156,6 +163,9 @@ def getMetadata(self):
if hasattr(self, '_frames') and len(self._frames) > 1:
result['frames'] = self._frames
self._addMetadataFrameInformation(result)
if self._bands:
result['bands'] = {n + 1: {'interpretation': val}
for n, val in enumerate(self._bands)}
return result

def getInternalMetadata(self, **kwargs):
Expand Down Expand Up @@ -227,7 +237,17 @@ def getTile(self, x, y, z, *args, **kwargs):
_counters['tiles'] += 1
if self.monochrome:
image = image.convert('L')
return self._outputTile(image, TILE_FORMAT_PIL, x, y, z, **kwargs)
if not self._bands or len(self._bands) == len(image.mode):
return self._outputTile(image, TILE_FORMAT_PIL, x, y, z, **kwargs)
image = _imageToNumpy(image)[0]
newimg = numpy.zeros((image.shape[0], image.shape[1], len(self._bands)))
newimg[:, :, :image.shape[2]] = image
for b in range(image.shape[2], len(self._bands)):
newimg[:, :, b] = (b / len(self._bands) + (1 - b / len(self._bands)) * xFraction) * 255
newimg[image[:, :, 0] == 0] = 255 if self._bands[b] in {'alpha', 'A'} else 0
newimg[image[:, :, 0] == 255] = 255
image = newimg
return self._outputTile(image, TILE_FORMAT_NUMPY, x, y, z, **kwargs)

@staticmethod
def getLRUHash(*args, **kwargs):
Expand All @@ -238,13 +258,14 @@ def getLRUHash(*args, **kwargs):
kwargs.get('tileWidth'), kwargs.get('tileHeight'),
kwargs.get('fractal'), kwargs.get('sizeX'), kwargs.get('sizeY'),
kwargs.get('frames'), kwargs.get('monochrome'),
kwargs.get('bands'),
)

def getState(self):
return 'test %r %r %r %r %r %r %r %r %r %r' % (
return 'test %r %r %r %r %r %r %r %r %r %r %r' % (
super().getState(), self.minLevel, self.maxLevel, self.tileWidth,
self.tileHeight, self.fractal, self.sizeX, self.sizeY,
self.frameSpec, self.monochrome)
self.frameSpec, self.monochrome, self.bandSpec)


def open(*args, **kwargs):
Expand Down
17 changes: 17 additions & 0 deletions test/test_files/multi_band.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
sources:
- sourceName: test
path: __none__
params:
minLevel: 0
maxLevel: 6
tileWidth: 256
tileHeight: 256
sizeX: 10000
sizeY: 7500
fractal: True
# c,z,t,xy OR frames
frames: "4,6,1,1"
monochrome: False
# multiband
bands: "red,green,blue,ir1,ir2"
2 changes: 1 addition & 1 deletion test/test_files/multi_channels.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: Multi orientationa
name: Multi orientation
sources:
- path: ./test_orient1.tif
channel: CY3
Expand Down
8 changes: 8 additions & 0 deletions test/test_source_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,11 @@ def testCanRead():
assert large_image_source_multi.canRead(imagePath) is True
imagePath2 = os.path.join(testDir, 'test_files', 'test_orient1.tif')
assert large_image_source_multi.canRead(imagePath2) is False


def testMultiBand():
testDir = os.path.dirname(os.path.realpath(__file__))
imagePath = os.path.join(testDir, 'test_files', 'multi_band.yml')
source = large_image_source_multi.open(imagePath)
metadata = source.getMetadata()
assert len(metadata['bands']) == 5

0 comments on commit 1c3d608

Please sign in to comment.