Skip to content

Commit a451075

Browse files
committed
Add ICC profile in ImageSlide.read_region() and get_thumbnail()
Have ImageSlide.read_region() and AbstractSlide.get_thumbnail() preserve a reference to the underlying ICC profile, if any. Add sRGB profile to boxes.png; retain the previous fixture as boxes-no-icc.png. Signed-off-by: Benjamin Gilbert <[email protected]>
1 parent 051abe9 commit a451075

File tree

5 files changed

+27
-0
lines changed

5 files changed

+27
-0
lines changed

openslide/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ def get_thumbnail(self, size):
147147
# Image.Resampling added in Pillow 9.1.0
148148
# Image.LANCZOS removed in Pillow 10
149149
thumb.thumbnail(size, getattr(Image, 'Resampling', Image).LANCZOS)
150+
if self._profile is not None:
151+
thumb.info['icc_profile'] = self._profile
150152
return thumb
151153

152154

@@ -341,6 +343,7 @@ def __init__(self, file):
341343
else:
342344
self._close = True
343345
self._image = Image.open(file)
346+
self._profile = self._image.info.get('icc_profile')
344347

345348
def __repr__(self):
346349
return f'{self.__class__.__name__}({self._file_arg!r})'
@@ -430,6 +433,8 @@ def read_region(self, location, level, size):
430433
crop = self._image.crop(image_topleft + [d + 1 for d in image_bottomright])
431434
tile_offset = tuple(il - l for il, l in zip(image_topleft, location))
432435
tile.paste(crop, tile_offset)
436+
if self._profile is not None:
437+
tile.info['icc_profile'] = self._profile
433438
return tile
434439

435440
def set_cache(self, cache):

tests/fixtures/boxes-no-icc.png

204 Bytes
Loading

tests/fixtures/boxes.png

385 Bytes
Loading

tests/test_imageslide.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ def test_metadata(self):
8888
self.assertEqual(self.osr.properties, {})
8989
self.assertEqual(self.osr.associated_images, {})
9090

91+
def test_color_profile(self):
92+
self.assertEqual(
93+
len(self.osr.read_region((0, 0), 0, (100, 100)).info['icc_profile']), 588
94+
)
95+
self.assertEqual(
96+
len(self.osr.get_thumbnail((100, 100)).info['icc_profile']), 588
97+
)
98+
9199
def test_read_region(self):
92100
self.assertEqual(
93101
self.osr.read_region((-10, -10), 0, (400, 400)).size, (400, 400)
@@ -113,3 +121,13 @@ def test_thumbnail(self):
113121
def test_set_cache(self):
114122
self.osr.set_cache(OpenSlideCache(64 << 10))
115123
self.assertEqual(self.osr.read_region((0, 0), 0, (400, 400)).size, (400, 400))
124+
125+
126+
class TestNoIccImage(_SlideTest, unittest.TestCase):
127+
FILENAME = 'boxes-no-icc.png'
128+
129+
def test_color_profile(self):
130+
self.assertNotIn(
131+
'icc_profile', self.osr.read_region((0, 0), 0, (100, 100)).info
132+
)
133+
self.assertNotIn('icc_profile', self.osr.get_thumbnail((100, 100)).info)

tests/test_openslide.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ def test_color_profile(self):
130130
self.assertEqual(
131131
len(self.osr.read_region((0, 0), 0, (100, 100)).info['icc_profile']), 588
132132
)
133+
self.assertEqual(
134+
len(self.osr.get_thumbnail((100, 100)).info['icc_profile']), 588
135+
)
133136

134137
def test_read_region(self):
135138
self.assertEqual(
@@ -197,6 +200,7 @@ def test_color_profile(self):
197200
'icc_profile', self.osr.read_region((0, 0), 0, (100, 100)).info
198201
)
199202
self.assertNotIn('icc_profile', self.osr.associated_images['thumbnail'].info)
203+
self.assertNotIn('icc_profile', self.osr.get_thumbnail((100, 100)).info)
200204

201205

202206
# Requires DICOM support in OpenSlide. Use associated image ICC support as

0 commit comments

Comments
 (0)