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

[MRG] Fix decoding of JPEG compressed color images with Photometric Interpretation "RGB" #878

Merged
merged 72 commits into from
Apr 17, 2021
Merged

[MRG] Fix decoding of JPEG compressed color images with Photometric Interpretation "RGB" #878

merged 72 commits into from
Apr 17, 2021

Conversation

hackermd
Copy link
Contributor

@hackermd hackermd commented Jul 8, 2019

The Pixel Data element of DICOM image instances may contain JPEG bitstreams that were not converted to YCbCr color space upon compression. In these cases the value of PhotometricInterpretation is "RGB" rather than "YBR_FULL_422".

JPEG is color blind, i.e. the JPEG bitstream may not contain any information about any color transformation, and Pillow's JpegImagePlugin assumes that images have been transformed into YCbCr space before compression. As a consequence, the pillow_handler doesn't decode images correctly, which were compressed directly in RGB color space (see python-pillow/Pillow#3952).

This PR fixes the color "mode" of the Pillow.Image object by providing additional color information to the decoder and thereby ensure that images are decoded correctly.

@pep8speaks
Copy link

pep8speaks commented Jul 8, 2019

Hello @hackermd! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2021-04-17 02:11:38 UTC

@hackermd
Copy link
Contributor Author

hackermd commented Jul 8, 2019

I noticed that the test_PI_RGB test now fails. Are we sure that this test case has been correct in the first place?

@darcymason
Copy link
Member

I noticed that the test_PI_RGB test now fails. Are we sure that this test case has been correct in the first place

I'm not sure ... @rhaxton might know ... from quick check it may come from #521 but I didn't really follow the history fully.

@rhaxton
Copy link
Contributor

rhaxton commented Jul 11, 2019

The test_PI_RGB tests just test that the reading of lossy compressed jpegs behaves the same way that using dcmtk's dcmcjpeg and dcmdjpeg do.

The filenames being tested include the command line options passed to dcmcjpeg (version 3.6.1 as indicated in the file metadata). For example:

SC_rgb_dcmtk_+eb+cy+np.dcm

was created by running:

dcmcjpeg +eb +cy +np SC_rgb.dcm SC_rgb_dcmtk_+eb+cy+np.dcm

and the expected result was created by running:

dcmdjpeg SC_rgb_dcmtk_+eb+cy+np.dcm SC_rgb_dcmtk_ebcynp_dcmd.dcm

These tests only assert that we decode these files the same way dcmtk decodes them.

as noted in the discussion of #521, the gdcm and dcmtk command line tools disagreed in some of these cases. The dcmtk results "looked" better, so that is what is in the test (and what is supported).

If these tests are failing, then the pillow handler is not replicating dcmtk's dcmdjpeg command line tool for that file. Whether it is correct or not is an open question. I would like to note that quite a lot of lossy compressed color jpeg DICOM files have the PI tag set to "RGB" incorrectly, and we should have some way to support them....

@hackermd
Copy link
Contributor Author

I would like to note that quite a lot of lossy compressed color jpeg DICOM files have the PI tag set to "RGB" incorrectly, and we should have some way to support them....

I think you are right about the incorrectly set "RGB". If the set the value of PhotometricInterpretation of the data set contained in file SC_rgb_dcmtk_+eb+cr.dcm to "YBR_FULL_422", then the pillow_handler.py implementation in this PR decodes the pixel data correctly.

I really don't like the idea of supporting invalid files, since this will lead to unexpected behavior down the line because users assume that files are valid and are then surprised if a different application fails to handle them.
If a file is invalid, the pixel handler should not try to provide a workaround IMO, but rather fail by raising an appropriate exception. I updated the test case and removed the invalid file (ab9c3fc).

@hackermd
Copy link
Contributor Author

@darcymason @rhaxton Are there any objections against merging this PR?

@scaramallion
Copy link
Member

scaramallion commented Oct 12, 2019

There's no test coverage of the actual correction.

@hackermd
Copy link
Contributor Author

@scaramallion I added a test case via 9cb6fc2. It would great if this bug fix could make it into the next release.

@codecov
Copy link

codecov bot commented Jul 22, 2020

Codecov Report

Merging #878 (a0c3307) into master (0949488) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #878   +/-   ##
=======================================
  Coverage   95.22%   95.23%           
=======================================
  Files          60       60           
  Lines        9682     9691    +9     
=======================================
+ Hits         9220     9229    +9     
  Misses        462      462           
Impacted Files Coverage Δ
pydicom/dataset.py 97.70% <ø> (ø)
pydicom/pixel_data_handlers/pillow_handler.py 95.04% <100.00%> (+0.48%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0949488...a0c3307. Read the comment docs.

@scaramallion
Copy link
Member

scaramallion commented Jul 22, 2020

The two test datasets you added aren't based on the same image as the other SC* datasets, they should be renamed and their source and an explanation of what they contain/how they're encoded be added to the README in the test_files directory.

@hackermd
Copy link
Contributor Author

@scaramallion I renamed the file and added a description to the README as requested. Please let me know if anything else is required for getting this merged. I think it's important to get this fix released.

Image without the fix (pydicom 2.0.0):

Screen Shot 2020-11-27 at 5 10 46 PM

Image with fix (b88d9b6):

Screen Shot 2020-11-27 at 5 12 10 PM

darcymason and others added 19 commits January 9, 2021 18:43
* some changes to PR workflow, harmonize flags between the two
* flake8 for only the changed files
* start pymedphys pydicom-only test setup, but not active currently
Remove unicode literals no longer needed since dropping Python 2
* Install pymedphys[tests]
* Add pymedphys cache
* add download.py, delete test files that are hosted elsewhere
* update data manager to filter the zenodo files as if they were still within that directory
* add installation notes
* fix-1062

* Revert explicit comparisons, add check that value is set

* Add test
* Refactor codedict._filtered
* use generators/lazy evaluation where possible
* Added Dataset.copy() method

- used method inherited from dict before, which always returned empty dict
- fixes #1146
- adapt test for shallow/deep copy
* Move larger test files to separate repo (pydicom/pydicom-data)
* update github actions scripts to cache the .pydicom data location
* Change to commit hash for urls
* Add JLS tests
* Add as_array() test
* Add versioning info
@hackermd
Copy link
Contributor Author

@scaramallion I updated the branch. First tried to rebase, but gave up after rebasing for over half an hour. Ultimately, ended up merging current master into the branch.

Tests are passing. It would really be great if you could get this merged.

@scaramallion
Copy link
Member

Dang, I thought that would re-run the CI

@scaramallion scaramallion changed the title Fix decoding of JPEG compressed color images with Photometric Interpretation "RGB" [MRG] Fix decoding of JPEG compressed color images with Photometric Interpretation "RGB" Apr 17, 2021
@scaramallion scaramallion merged commit 7fb7773 into pydicom:master Apr 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants