Skip to content

Commit

Permalink
Add a style option.
Browse files Browse the repository at this point in the history
This better handles high bit-depth images.

The style option is an optional json-encoded parameter.  It is either an
object with "bands" followed by a list or a single entry as from that
list.  Each entry is an object with all optional parameters.  These are:

- band: either a number or a string.  If -1 or None, unspecified, the
  same as "gray".  If a number, a 1-based numerical index into the
  channels of the image.  If a string, one of ('red', 'green', 'blue',
  'gray', 'alpha').  Note that 'gray' on an RGB or RGBA image will use
  the green band, and all colors on a greyscale image will use the
  luminance band.

- min: the value to map to the first palette value.  Defaults to 0.
  'auto' to use 0 if the reported minimum and maximum of the band are
  between [0, 255] or use the reported minimum otherwise.  'min' or
  'max' to always uses the reported minimum or maximum.

- max: the value to map to the last palette value.  Defaults to 255.
  'auto' to use 0 if the reported minimum and maximum of the band are
  between [0, 255] or use the reported maximum otherwise.  'min' or
  'max' to always uses the reported minimum or maximum.

- palette: a list of two or more color strings, where color strings are
  of the form #RRGGBB, #RRGGBBAA, #RGB, #RGBA (or anything else PIL can
  parse).

- nodata: the value to use for missing data.  null or unset to not use a
  nodata value.

- composite: either 'lighten' or 'multiply'.  Defaults to 'lighten' for
  all except the alpha band.  Bands are composited in the order listed.

- clamp: either True to clamp values outside of the [min, max] to the
  ends of the palette or False to make outside values transparent.

TODO:

- Check that sparse and missing levels with 16-bit output are correct.
  • Loading branch information
manthey committed Dec 13, 2019
1 parent 6615e45 commit 1cfd89a
Show file tree
Hide file tree
Showing 25 changed files with 675 additions and 192 deletions.
19 changes: 12 additions & 7 deletions girder/girder_large_image/girder_tilesource.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,26 @@ def __init__(self, item, *args, **kwargs):

@staticmethod
def getLRUHash(*args, **kwargs):
return '%s,%s,%s,%s,%s,%s,%s' % (
str(args[0]['largeImage']['fileId']), args[0]['updated'],
kwargs.get('encoding', 'JPEG'), kwargs.get('jpegQuality', 95),
kwargs.get('jpegSubsampling', 0), kwargs.get('tiffCompression', 'raw'),
kwargs.get('edge', False))
return '%s,%s,%s,%s,%s,%s,%s,%s' % (
args[0]['largeImage']['fileId'],
args[0]['updated'],
kwargs.get('encoding', 'JPEG'),
kwargs.get('jpegQuality', 95),
kwargs.get('jpegSubsampling', 0),
kwargs.get('tiffCompression', 'raw'),
kwargs.get('edge', False),
kwargs.get('style', None))

def getState(self):
return '%s,%s,%s,%s,%s,%s,%s' % (
return '%s,%s,%s,%s,%s,%s,%s,%s' % (
self.item['largeImage']['fileId'],
self.item['updated'],
self.encoding,
self.jpegQuality,
self.jpegSubsampling,
self.tiffCompression,
self.edge)
self.edge,
self._jsonstyle)

def _getLargeImagePath(self):
# If self.mayHaveAdjacentFiles is True, we try to use the girder
Expand Down
4 changes: 4 additions & 0 deletions girder/girder_large_image/rest/tiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ def getTilesThumbnail(self, item, params):
('jpegSubsampling', int),
('tiffCompression', str),
('encoding', str),
('style', str),
('contentDisposition', str),
])
try:
Expand Down Expand Up @@ -636,6 +637,7 @@ def getTilesThumbnail(self, item, params):
.param('tiffCompression', 'Compression method when storing a TIFF '
'image', required=False,
enum=['raw', 'tiff_lzw', 'jpeg', 'tiff_adobe_deflate'])
.param('style', 'JSON-encoded style string', required=False)
.param('contentDisposition', 'Specify the Content-Disposition response '
'header disposition-type value.', required=False,
enum=['inline', 'attachment'])
Expand Down Expand Up @@ -669,6 +671,7 @@ def getTilesRegion(self, item, params):
('jpegQuality', int),
('jpegSubsampling', int),
('tiffCompression', str),
('style', str),
('contentDisposition', str),
])
try:
Expand Down Expand Up @@ -767,6 +770,7 @@ def getAssociatedImage(self, itemId, image, params):
('jpegSubsampling', int),
('tiffCompression', str),
('encoding', str),
('style', str),
('contentDisposition', str),
])
try:
Expand Down
3 changes: 0 additions & 3 deletions girder_annotation/test_annotation/test_annotations_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,6 @@ def testUpdateAnnotation(self, server, admin):
publicFolder = utilities.namedFolder(admin, 'Public')
item = Item().createItem('sample', admin, publicFolder)
annot = Annotation().createAnnotation(item, admin, sampleAnnotation)
import sys
sys.stderr.write('%r\n' % [annot]) # ##DWM::
sys.stderr.write('%r\n' % [sampleAnnotation])
resp = server.request(path='/annotation/%s' % annot['_id'], user=admin)
assert utilities.respStatus(resp) == 200
annot = resp.json
Expand Down
Loading

0 comments on commit 1cfd89a

Please sign in to comment.