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

Support reading ICC color profiles #81

Merged
merged 3 commits into from
May 3, 2024
Merged

Conversation

bgilbert
Copy link
Member

@bgilbert bgilbert commented May 3, 2024

BufferedImage uses an sRGB ColorModel by default. If a slide pyramid or associated image has an ICC profile, attach a ColorModel containing that profile to all BufferedImages produced from that image.

Callers of paintRegionARGB() don't receive a BufferedImage. For those users, add OpenSlide.getColorModel() so the profile can be read separately. To simplify reading slide regions with a ColorModel, add an OpenSlide.readRegion() method that returns a BufferedImage.

Graphics2D's documentation suggests that it handles color management, but its drawImage() method apparently does not. If we therefore manually invoke a ColorConvertOp in paintRegion(), the DICOM/Leica-4 test slide throws an exception:

Exception in thread "AWT-EventQueue-0" java.awt.color.CMMException: LCMS error 13: Couldn't link the profiles
    at java.desktop/sun.java2d.cmm.lcms.LCMS.createNativeTransform(Native Method)
    at java.desktop/sun.java2d.cmm.lcms.LCMS.createTransform(LCMS.java:113)
    at java.desktop/sun.java2d.cmm.lcms.LCMSTransform.doTransform(LCMSTransform.java:114)
    at java.desktop/sun.java2d.cmm.lcms.LCMSTransform.colorConvert(LCMSTransform.java:149)
    at java.desktop/java.awt.image.ColorConvertOp.ICCBIFilter(ColorConvertOp.java:350)
    at java.desktop/java.awt.image.ColorConvertOp.filter(ColorConvertOp.java:277)
    at org.openslide.OpenSlide.paintRegion(OpenSlide.java:326)
    [...]

It seems that ColorConvertOp always uses perceptual rendering intent, not the default intent encoded in the profile. Not all profiles support perceptual rendering, which may be the cause of the exception. If we're going to automatically perform color conversion, we should do it predictably, not just when the Java CMS glue happens to do the right thing. For now, don't try to do color conversion, either in paintRegion() or any of the GUI code.

Closes: #53

bgilbert added 3 commits May 3, 2024 09:00
We have paintRegionARGB() which writes directly into an int array, and
paintRegion() which scales and draws into a Graphics2D, but we could use an
intermediate-level API that returns an image object directly from
OpenSlide.

Signed-off-by: Benjamin Gilbert <[email protected]>
BufferedImage uses an sRGB ColorModel by default.  If a slide pyramid or
associated image has an ICC profile, attach a ColorModel containing that
profile to all BufferedImages produced from that image.

Callers of paintRegionARGB() don't receive a BufferedImage.  For those
users, add OpenSlide.getColorModel() so the profile can be read
separately.

Graphics2D's documentation suggests that it handles color management, but
its drawImage() method apparently does not.  If we therefore manually
invoke a ColorConvertOp in paintRegion(), the DICOM/Leica-4 test slide
throws an exception:

    Exception in thread "AWT-EventQueue-0" java.awt.color.CMMException: LCMS error 13: Couldn't link the profiles
        at java.desktop/sun.java2d.cmm.lcms.LCMS.createNativeTransform(Native Method)
        at java.desktop/sun.java2d.cmm.lcms.LCMS.createTransform(LCMS.java:113)
        at java.desktop/sun.java2d.cmm.lcms.LCMSTransform.doTransform(LCMSTransform.java:114)
        at java.desktop/sun.java2d.cmm.lcms.LCMSTransform.colorConvert(LCMSTransform.java:149)
        at java.desktop/java.awt.image.ColorConvertOp.ICCBIFilter(ColorConvertOp.java:350)
        at java.desktop/java.awt.image.ColorConvertOp.filter(ColorConvertOp.java:277)
        at org.openslide.OpenSlide.paintRegion(OpenSlide.java:326)
        [...]

It seems that ColorConvertOp always uses perceptual rendering intent, not
the default intent encoded in the profile:

    https://bugs.openjdk.org/browse/JDK-8216369

Not all profiles support perceptual rendering, which may be the cause of
the exception.  If we're going to automatically perform color conversion,
we should do it predictably, not just when the Java CMS glue happens to do
the right thing.  For now, don't try to do color conversion, either in
paintRegion() or any of the GUI code.

Closes: openslide#53
Signed-off-by: Benjamin Gilbert <[email protected]>
@openslide-bot
Copy link
Member

DCO signed off ✔️

All commits have been signed off. You have certified to the terms of the Developer Certificate of Origin, version 1.1. In particular, you certify that this contribution has not been developed using information obtained under a non-disclosure agreement or other license terms that forbid you from contributing it under the GNU Lesser General Public License, version 2.1.

@bgilbert bgilbert merged commit 39c3814 into openslide:main May 3, 2024
5 checks passed
@bgilbert bgilbert deleted the icc branch May 3, 2024 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Implement ICC profile API in OpenSlide 4.0.0
2 participants