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

Add an open method to each source module. #550

Merged
merged 1 commit into from
Feb 22, 2021
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,23 @@
- 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)
- Added an `open` method to the core module as an alias to `getTileSource` (#550)
- Added an `open` method to each file source module (#550)
- Numerous improvement to image converversion (#533, #535, #537, #541, #544, #545, #546, #549)

### Improvements
- Better release bioformats resources (#502)
- Better handling of tiff files with JPEG compression and RGB colorspace (#503)
- The openjpeg tile source can decode with parallelism (#511)
- Geospatial tile sources are preferred for geospatial files (#512)
- Support decoding JP2k compressed tiles in the tiff tile source (#514)
- Hardened tests against transient timing issues (#532, #536)

### Bug Fixes
- Harden updates of the item view after making a large image (#508, #515)
- Tiles in an unexpected color mode weren't consistently adjusted (#510)
- Harden trying to add an annotation before the viewer is ready (#547)
- Correctly report the tile size after resampling in the tileIterator (#538)

## Version 1.3.2

Expand Down
2 changes: 1 addition & 1 deletion large_image/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from pkg_resources import DistributionNotFound, get_distribution

from . import tilesource # noqa
from .tilesource import canRead, getTileSource # noqa
from .tilesource import canRead, getTileSource, open # noqa


try:
Expand Down
12 changes: 12 additions & 0 deletions large_image/tilesource/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,18 @@ def getTileSource(*args, **kwargs):
return getTileSourceFromDict(AvailableTileSources, *args, **kwargs)


def open(*args, **kwargs):
"""
Alternate name of getTileSource.

Get a tilesource using the known sources. If tile sources have not yet
been loaded, load them.

:returns: A tilesource for the passed arguments.
"""
return getTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if large_image can read a path or uri.
Expand Down
14 changes: 14 additions & 0 deletions sources/bioformats/large_image_source_bioformats/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,3 +538,17 @@ def _getAssociatedImage(self, imageKey):
if javabridge.get_env():
javabridge.detach()
return large_image.tilesource.base._imageToPIL(image)


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return BioformatsFileTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return BioformatsFileTileSource.canRead(*args, **kwargs)
14 changes: 14 additions & 0 deletions sources/dummy/large_image_source_dummy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,17 @@ def canRead(cls, *args, **kwargs):

def getTile(self, x, y, z, **kwargs):
return b''


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return DummyTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return DummyTileSource.canRead(*args, **kwargs)
14 changes: 14 additions & 0 deletions sources/gdal/large_image_source_gdal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -940,3 +940,17 @@ def getPixel(self, **kwargs):
except RuntimeError:
pass
return pixel


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return GDALFileTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return GDALFileTileSource.canRead(*args, **kwargs)
14 changes: 14 additions & 0 deletions sources/mapnik/large_image_source_mapnik/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,17 @@ def getTile(self, x, y, z, **kwargs):
if overscan:
pilimg = pilimg.crop((1, 1, pilimg.width - overscan, pilimg.height - overscan))
return self._outputTile(pilimg, TILE_FORMAT_PIL, x, y, z, applyStyle=False, **kwargs)


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return MapnikFileTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return MapnikFileTileSource.canRead(*args, **kwargs)
14 changes: 14 additions & 0 deletions sources/nd2/large_image_source_nd2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,3 +318,17 @@ def getTile(self, x, y, z, pilImageAllowed=False, numpyAllowed=False, **kwargs):
tile = tileframe[y0:y1:step, x0:x1:step].copy()
return self._outputTile(tile, TILE_FORMAT_NUMPY, x, y, z,
pilImageAllowed, numpyAllowed, **kwargs)


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return ND2FileTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return ND2FileTileSource.canRead(*args, **kwargs)
14 changes: 14 additions & 0 deletions sources/ometiff/large_image_source_ometiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,3 +353,17 @@ def getPreferredLevel(self, level):
while level - baselevel > self._maxSkippedLevels:
level -= self._maxSkippedLevels
return level


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return OMETiffFileTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return OMETiffFileTileSource.canRead(*args, **kwargs)
17 changes: 16 additions & 1 deletion sources/openjpeg/large_image_source_openjpeg/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# limitations under the License.
##############################################################################

import builtins
import glymur
import io
import math
Expand Down Expand Up @@ -203,7 +204,7 @@ def _readbox(self, box):
if box.length > 16 * 1024 * 1024:
return
try:
fp = open(self._largeImagePath, 'rb')
fp = builtins.open(self._largeImagePath, 'rb')
headerLength = 16
fp.seek(box.offset + headerLength)
data = fp.read(box.length - headerLength)
Expand Down Expand Up @@ -255,3 +256,17 @@ def getTile(self, x, y, z, pilImageAllowed=False, numpyAllowed=False, **kwargs):
tile = tile[::scale, ::scale]
return self._outputTile(tile, TILE_FORMAT_NUMPY, x, y, z,
pilImageAllowed, numpyAllowed, **kwargs)


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return OpenjpegFileTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return OpenjpegFileTileSource.canRead(*args, **kwargs)
14 changes: 14 additions & 0 deletions sources/openslide/large_image_source_openslide/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,3 +370,17 @@ def _getAssociatedImage(self, imageKey):
_tiffFile.SetDirectory(images[imageKey])
img = _tiffFile.read_image()
return PIL.Image.fromarray(img)


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return OpenslideFileTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return OpenslideFileTileSource.canRead(*args, **kwargs)
14 changes: 14 additions & 0 deletions sources/pil/large_image_source_pil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,17 @@ def getTile(self, x, y, z, pilImageAllowed=False, numpyAllowed=False,
raise TileSourceException('y is outside layer')
return self._outputTile(self._pilImage, TILE_FORMAT_PIL, x, y, z,
pilImageAllowed, numpyAllowed, **kwargs)


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return PILFileTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return PILFileTileSource.canRead(*args, **kwargs)
14 changes: 14 additions & 0 deletions sources/test/large_image_source_test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,17 @@ def getState(self):
return 'test %r %r %r %r %r %r' % (
super().getState(), self.minLevel,
self.maxLevel, self.tileWidth, self.tileHeight, self.fractal)


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return TestTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return TestTileSource.canRead(*args, **kwargs)
14 changes: 14 additions & 0 deletions sources/tiff/large_image_source_tiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,3 +647,17 @@ def _getAssociatedImage(self, imageKey):
if imageKey in self._associatedImages:
return PIL.Image.fromarray(self._associatedImages[imageKey])
return None


def open(*args, **kwargs):
"""
Create an instance of the module class.
"""
return TiffFileTileSource(*args, **kwargs)


def canRead(*args, **kwargs):
"""
Check if an input can be read by the module class.
"""
return TiffFileTileSource.canRead(*args, **kwargs)
8 changes: 4 additions & 4 deletions test/test_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def testConvertJp2kCompression(tmpdir):
info = tifftools.read_tiff(outputPath)
assert (info['ifds'][0]['tags'][tifftools.Tag.Compression.value]['data'][0] ==
tifftools.constants.Compression.JP2000.value)
source = large_image_source_tiff.TiffFileTileSource(outputPath)
source = large_image_source_tiff.open(outputPath)
image, _ = source.getRegion(
output={'maxWidth': 200, 'maxHeight': 200}, format=constants.TILE_FORMAT_NUMPY)
assert (image[12][167] == [215, 135, 172]).all()
Expand All @@ -160,7 +160,7 @@ 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)
source = large_image_source_tiff.open(outputPath)
metadata = source.getMetadata()
assert metadata['levels'] == 6

Expand All @@ -169,7 +169,7 @@ def testConvertFromMultiframeImage(tmpdir):
imagePath = utilities.externaldata('data/sample.ome.tif.sha512')
outputPath = os.path.join(tmpdir, 'out.tiff')
large_image_converter.convert(imagePath, outputPath)
source = large_image_source_tiff.TiffFileTileSource(outputPath)
source = large_image_source_tiff.open(outputPath)
metadata = source.getMetadata()
assert metadata['levels'] == 5
assert len(metadata['frames']) == 3
Expand All @@ -181,7 +181,7 @@ def testConvertFromMultiframeImageNoSubIFDS(tmpdir):
imagePath = utilities.externaldata('data/sample.ome.tif.sha512')
outputPath = os.path.join(tmpdir, 'out.tiff')
large_image_converter.convert(imagePath, outputPath, subifds=False)
source = large_image_source_tiff.TiffFileTileSource(outputPath)
source = large_image_source_tiff.open(outputPath)
metadata = source.getMetadata()
assert metadata['levels'] == 5
assert len(metadata['frames']) == 3
Expand Down
4 changes: 2 additions & 2 deletions test/test_source_bioformats.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def testTilesFromBioformats():
import large_image_source_bioformats

imagePath = utilities.externaldata('data/HENormalN801.czi.sha512')
source = large_image_source_bioformats.BioformatsFileTileSource(imagePath)
source = large_image_source_bioformats.open(imagePath)
tileMetadata = source.getMetadata()

assert tileMetadata['tileWidth'] == 1024
Expand All @@ -28,7 +28,7 @@ def testInternalMetadata():
import large_image_source_bioformats

imagePath = utilities.externaldata('data/HENormalN801.czi.sha512')
source = large_image_source_bioformats.BioformatsFileTileSource(imagePath)
source = large_image_source_bioformats.open(imagePath)
metadata = source.getInternalMetadata()
assert 'sizeColorPlanes' in metadata

Expand Down
6 changes: 3 additions & 3 deletions test/test_source_dummy.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from large_image import getTileSource
import large_image
import large_image_source_dummy


def testDummyTileSource():
source = large_image_source_dummy.DummyTileSource()
source = large_image_source_dummy.open()
tileMetadata = source.getMetadata()
assert tileMetadata['tileWidth'] == 0
assert tileMetadata['tileHeight'] == 0
Expand All @@ -17,5 +17,5 @@ def testDummyTileSource():


def testGetDummyTileSource():
source = getTileSource('large_image://dummy')
source = large_image.open('large_image://dummy')
assert isinstance(source, large_image_source_dummy.DummyTileSource)
Loading