Skip to content

Commit

Permalink
Merge pull request #1155 from girder/getpixel-improvement
Browse files Browse the repository at this point in the history
getPixel method and endpoint now returns rawer values
  • Loading branch information
manthey authored May 12, 2023
2 parents 2bcc4f0 + f7dbee3 commit 851d921
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 14 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change Log

## 1.20.7

### Improvements
- getPixel method and endpoint now returns rawer values ([#1155](../../pull/1155))

## 1.20.6

### Improvements
Expand Down
5 changes: 3 additions & 2 deletions large_image/tilesource/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2716,12 +2716,13 @@ def getPixel(self, includeTileRecord=False, **kwargs):
# img, format = self.getRegion(format=TILE_FORMAT_PIL, **regionArgs)
# where img is the PIL image (rather than tile['tile'], but using
# _tileIteratorInfo and the _tileIterator is slightly more efficient.
iterInfo = self._tileIteratorInfo(format=TILE_FORMAT_PIL, **regionArgs)
iterInfo = self._tileIteratorInfo(format=TILE_FORMAT_NUMPY, **regionArgs)
if iterInfo is not None:
tile = next(self._tileIterator(iterInfo), None)
if includeTileRecord:
pixel['tile'] = tile
img = tile['tile']
pixel['value'] = [v.item() for v in tile['tile'][0][0]]
img = _imageToPIL(tile['tile'])
if img.size[0] >= 1 and img.size[1] >= 1:
if len(img.mode) > 1:
pixel.update(dict(zip(img.mode.lower(), img.load()[0, 0])))
Expand Down
8 changes: 8 additions & 0 deletions test/test_source_gdal.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ def testPixel():
# Test in pixel coordinates
source = large_image_source_gdal.open(imagePath)
pixel = source.getPixel(region={'left': 212, 'top': 198})
assert 'value' in pixel
pixel.pop('value')
assert pixel == {
'r': 76, 'g': 78, 'b': 77, 'a': 255, 'bands': {1: 62.0, 2: 65.0, 3: 66.0}}
pixel = source.getPixel(region={'left': 2120, 'top': 198})
Expand All @@ -178,6 +180,7 @@ def testPixel():
# Test with a projection
source = large_image_source_gdal.open(imagePath, projection='EPSG:3857')
pixel = source.getPixel(region={'left': -13132910, 'top': 4010586, 'units': 'projection'})
pixel.pop('value')
assert pixel == {
'r': 94, 'g': 98, 'b': 99, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}

Expand All @@ -187,6 +190,7 @@ def testPixel():
source = large_image_source_gdal.open(
imagePath, projection='EPSG:3857', style=style)
pixel = source.getPixel(region={'left': -13132910, 'top': 4010586, 'units': 'projection'})
pixel.pop('value')
assert pixel == {
'r': 247, 'g': 156, 'b': 60, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}

Expand All @@ -196,21 +200,25 @@ def testPixel():
source = large_image_source_gdal.open(
imagePath, projection='EPSG:3857', style=style)
pixel = source.getPixel(region={'left': -13132910, 'top': 4010586, 'units': 'projection'})
pixel.pop('value')
assert pixel == {
'r': 137, 'g': 117, 'b': 0, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}

# Test with projection units
source = large_image_source_gdal.open(imagePath, projection='EPSG:3857')
pixel = source.getPixel(region={'left': -13132910, 'top': 4010586, 'units': 'EPSG:3857'})
pixel.pop('value')
assert pixel == {
'r': 94, 'g': 98, 'b': 99, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}
pixel = source.getPixel(region={'left': -117.975, 'top': 33.865, 'units': 'WGS84'})
pixel.pop('value')
assert pixel == {
'r': 94, 'g': 98, 'b': 99, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}
# When the tile has a different projection, the pixel is the same as
# the band values.
source = large_image_source_gdal.open(imagePath)
pixel = source.getPixel(region={'left': -13132910, 'top': 4010586, 'units': 'EPSG:3857'})
pixel.pop('value')
assert pixel == {
'r': 94, 'g': 98, 'b': 99, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}

Expand Down
28 changes: 21 additions & 7 deletions test/test_source_mapnik.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,19 @@ def testPixel():
source = large_image_source_mapnik.open(imagePath)
pixel = source.getPixel(region={'left': 212, 'top': 198})
assert pixel == {
'r': 62, 'g': 65, 'b': 66, 'a': 255, 'bands': {1: 62.0, 2: 65.0, 3: 66.0}}
'r': 62, 'g': 65, 'b': 66, 'a': 255,
'bands': {1: 62.0, 2: 65.0, 3: 66.0},
'value': [62, 65, 66, 255]}
pixel = source.getPixel(region={'left': 2120, 'top': 198})
assert pixel == {}

# Test with a projection
source = large_image_source_mapnik.open(imagePath, projection='EPSG:3857')
pixel = source.getPixel(region={'left': -13132910, 'top': 4010586, 'units': 'projection'})
assert pixel == {
'r': 77, 'g': 82, 'b': 84, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}
'r': 77, 'g': 82, 'b': 84, 'a': 255,
'bands': {1: 77.0, 2: 82.0, 3: 84.0},
'value': [77, 82, 84, 255]}

# Check if the point is outside of the image
pixel = source.getPixel(region={'left': 10000000, 'top': 4000000, 'units': 'projection'})
Expand All @@ -214,7 +218,9 @@ def testPixel():
imagePath, projection='EPSG:3857', style=style)
pixel = source.getPixel(region={'left': -13132910, 'top': 4010586, 'units': 'projection'})
assert pixel == {
'r': 225, 'g': 100, 'b': 98, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}
'r': 225, 'g': 100, 'b': 98, 'a': 255,
'bands': {1: 77.0, 2: 82.0, 3: 84.0},
'value': [225, 100, 98, 255]}

# Test with palette as an array of colors
style = json.dumps({'band': 1, 'min': 0, 'max': 100,
Expand All @@ -224,22 +230,30 @@ def testPixel():
imagePath, projection='EPSG:3857', style=style)
pixel = source.getPixel(region={'left': -13132910, 'top': 4010586, 'units': 'projection'})
assert pixel == {
'r': 0, 'g': 255, 'b': 0, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}
'r': 0, 'g': 255, 'b': 0, 'a': 255,
'bands': {1: 77.0, 2: 82.0, 3: 84.0},
'value': [0, 255, 0, 255]}

# Test with projection units
source = large_image_source_mapnik.open(imagePath, projection='EPSG:3857')
pixel = source.getPixel(region={'left': -13132910, 'top': 4010586, 'units': 'EPSG:3857'})
assert pixel == {
'r': 77, 'g': 82, 'b': 84, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}
'r': 77, 'g': 82, 'b': 84, 'a': 255,
'bands': {1: 77.0, 2: 82.0, 3: 84.0},
'value': [77, 82, 84, 255]}
pixel = source.getPixel(region={'left': -117.975, 'top': 33.865, 'units': 'WGS84'})
assert pixel == {
'r': 77, 'g': 82, 'b': 84, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}
'r': 77, 'g': 82, 'b': 84, 'a': 255,
'bands': {1: 77.0, 2: 82.0, 3: 84.0},
'value': [77, 82, 84, 255]}
# When the tile has a different projection, the pixel is the same as
# the band values.
source = large_image_source_mapnik.open(imagePath)
pixel = source.getPixel(region={'left': -13132910, 'top': 4010586, 'units': 'EPSG:3857'})
assert pixel == {
'r': 77, 'g': 82, 'b': 84, 'a': 255, 'bands': {1: 77.0, 2: 82.0, 3: 84.0}}
'r': 77, 'g': 82, 'b': 84, 'a': 255,
'bands': {1: 77.0, 2: 82.0, 3: 84.0},
'value': [77, 82, 84, 255]}


def testSourceErrors():
Expand Down
10 changes: 5 additions & 5 deletions test/test_source_openslide.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,16 +321,16 @@ def testGetPixel():
source = large_image_source_openslide.open(imagePath, style={'icc': False})

pixel = source.getPixel(region={'left': 12125, 'top': 10640})
assert pixel == {'r': 156, 'g': 98, 'b': 138, 'a': 255}
assert pixel == {'r': 156, 'g': 98, 'b': 138, 'a': 255, 'value': [156, 98, 138, 255]}

pixel = source.getPixel(region={'left': 3.0555, 'top': 2.68128, 'units': 'mm'})
assert pixel == {'r': 156, 'g': 98, 'b': 138, 'a': 255}
assert pixel == {'r': 156, 'g': 98, 'b': 138, 'a': 255, 'value': [156, 98, 138, 255]}

pixel = source.getPixel(region={'top': 10640, 'right': 12126, 'bottom': 12000})
assert pixel == {'r': 156, 'g': 98, 'b': 138, 'a': 255}
assert pixel == {'r': 156, 'g': 98, 'b': 138, 'a': 255, 'value': [156, 98, 138, 255]}

pixel = source.getPixel(region={'left': 12125, 'top': 10640, 'right': 13000})
assert pixel == {'r': 156, 'g': 98, 'b': 138, 'a': 255}
assert pixel == {'r': 156, 'g': 98, 'b': 138, 'a': 255, 'value': [156, 98, 138, 255]}

pixel = source.getPixel(region={'left': 12125, 'top': 10640}, includeTileRecord=True)
assert 'tile' in pixel
Expand All @@ -342,7 +342,7 @@ def testGetPixelWithICCCorrection():
'4a70-9ae3-50e3ab45e242.svs')
source = large_image_source_openslide.open(imagePath)
pixel = source.getPixel(region={'left': 12125, 'top': 10640})
assert pixel == {'r': 169, 'g': 99, 'b': 151, 'a': 255}
assert pixel == {'r': 169, 'g': 99, 'b': 151, 'a': 255, 'value': [169, 99, 151, 255]}
source = large_image_source_openslide.open(imagePath, style={'icc': True})
pixel2 = source.getPixel(region={'left': 12125, 'top': 10640})
assert pixel == pixel2
Expand Down

0 comments on commit 851d921

Please sign in to comment.