Skip to content

Commit

Permalink
Handle tiff files with RGB colorspace JPEG compression.
Browse files Browse the repository at this point in the history
When a TIFF is marked as having a photometric space of RGB and uses JPEG
compression, the JPEG data does not have to encode its colorspace;
since, once a tile is extracted, we don't decode the tile unless
necessary, ensure that it is marked with the appropriate colorspace.
  • Loading branch information
manthey committed Dec 18, 2020
1 parent 5a22556 commit 6e061d4
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Improvements
- Better release bioformats resources (#502)
- Better handling of tiff files with JPEG compression and RGB colorspace (#503)

## Version 1.3.2

Expand Down
16 changes: 15 additions & 1 deletion sources/tiff/large_image_source_tiff/tiff_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,21 @@ def _getJpegFrame(self, tileNum, entire=False):
frameStartPos = frameBuffer.raw.find(b'\xff\xc2', 2, -2)
if frameStartPos == -1:
raise IOTiffException('Missing JPEG Start Of Frame marker')

# If the photometric value is RGB and the JPEG component ids are just
# 0, 1, 2, change the component ids to R, G, B to ensure color space
# information is preserved.
if self._tiffInfo.get('photometric') == libtiff_ctypes.PHOTOMETRIC_RGB:
sof = frameBuffer.raw.find(b'\xff\xc0')
if sof == -1:
sof = frameBuffer.raw.find(b'\xff\xc2')
sos = frameBuffer.raw.find(b'\xff\xda')
if (sof >= frameStartPos and sos >= frameStartPos and
frameBuffer[sof + 2:sof + 4] == b'\x00\x11' and
frameBuffer[sof + 10:sof + 19:3] == b'\x00\x01\x02' and
frameBuffer[sos + 5:sos + 11:2] == b'\x00\x01\x02'):
for idx, val in enumerate(b'RGB'):
frameBuffer[sof + 10 + idx * 3] = val
frameBuffer[sos + 5 + idx * 2] = val
# Strip the Start / End Of Image markers
tileData = frameBuffer.raw[frameStartPos:-2]
return tileData
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1b75a4ec911017aef5c885760a3c6575dacf5f8efb59fb0e011108dce85b1f4e97b8d358f3363c1f5ea6f1c3698f037554aec1620bbdd4cac54e3d5c9c1da1fd
8 changes: 8 additions & 0 deletions test/test_source_tiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,3 +653,11 @@ def testInternalMetadata():
source = large_image_source_tiff.TiffFileTileSource(imagePath)
metadata = source.getInternalMetadata()
assert 'xml' in metadata


def testFromTiffRGBJPEG():
imagePath = utilities.externaldata(
'data/TCGA-AA-A02O-11A-01-BS1.8b76f05c-4a8b-44ba-b581-6b8b4f437367.svs.sha512')
source = large_image_source_tiff.TiffFileTileSource(imagePath)
tile = source.getSingleTile()
assert list(tile['tile'][0, 0]) == [243, 243, 243]

0 comments on commit 6e061d4

Please sign in to comment.