You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I would like to suggest to add the addition of the Ultra HDR format as a new way to read and write HDR images.
From a technical point of view it's similar to the MPO format, that it's a JPEG image, containing an additional data stream. In case of Ultra HDR this data stream is a gainmap.
This way a reader implementation not aware of Ultra HDR only sees the SDR JPEG image.
There are currently several open enhancement requests to add the format to various well (and less well known) libraries and tools:
@radarhere: It's possible to generate one using libultrahdr. What are the requirements, does it have to be somehow very colorful or something like that?
If it needs to be beautiful @gregbenz might be able to help out.
@cmahnke Happy to answer any questions here. I'm not clear what the intended use of this library/feature is. I'd be happy to consider any requests for a few sample images, though for testing code I would recommend creating dedicated test images to most easily and reliably validate results.
Is the goal here to alter the image (resize, compress, crop, rotate, flip), convert to another image format as is, filter, or to render for display? The first couple are well supported by libultrahdr and I'm assuming that's probably the intent here.
If you start changing image content (such as filtering), you'll have to get more involved (things can get pretty tricky and some edits would only be suitable if you're willing to render to SDR / HDR and give up the adaptive nature of a gain map). And actual display (such as in a browser) involves linear interpolation between the base SDR and full HDR rendering as appropriate for the encoding of the image relative to the display's available HDR headroom.
I have seen numerous issues with various efforts to render or transcode gain maps (improper alteration of metadata, gain map artifacts, scaling of the images before merge causing edge artiffacts, etc). If libultrahdr meets your needs, I would recommend leveraging that rather than trying to build the capability from scratch. It is supported by Google (who has been very supportive of gain maps in both Chrome and Android), well maintained, and aligned with efforts towards an official ISO standard for common file formats (supports JPG now, but the project team has mentioned AVIF / HEIF on the roadmap).
It's not all that clear to me what the goal of this issue is.
If the goal is just to load the basic JPEG data as an image, then it is possible that this was resolved by #8056 in Pillow 10.4.0. If someone has an image that isn't able to be processed in that way by Pillow, please attach it to demonstrate.
If the goal is to load something more advanced from an image, then it would be helpful if someone could attach an image and describe what they would like to see when Pillow reads it.
I think the ambiguity @radarhere flagged comes down to two different asks that this thread has conflated:
"Can Pillow open an Ultra HDR JPEG without erroring?" — Yes, this looks resolved. Ultra HDR/gain-map JPEGs are valid MPO-style files (base SDR image + auxiliary gain-map image via MPF), and Image.open() reads the base image fine.
"Does the gain map survive Pillow's normal resize/save pipeline?" — No, and this is the part that actually affects real usage. Any tool that does the standard Image.open() -> resize -> save() (thumbnailers, gallery generators, CMS upload pipelines) silently drops the gain map with no error or warning. The output is a flattened SDR JPEG that looks like a successful, lossless-ish resize — nothing signals that HDR data was discarded.
Repro (Pillow 12.3.0, current as of this writing):
fromPILimportImagefrompilkit.processorsimportResizeToFit# or any resize pathimg=Image.open("ultrahdr.jpg")
print(img.format) # MPOprint("mp"inimg.info) # True -- Pillow *does* parse the MPF/gain-map segment into img.infoimg2=ResizeToFit(1152, 1100).process(img)
img2.save("out.jpg", quality=85)
# out.jpg: gain map is gone. exiftool confirms no MPImage/MPImageLength on the output,# vs. several MB of MP Image 2 data on the source.
So Pillow already parses enough to know a gain map is present (img.info['mp']), it just never re-attaches it on save. That's a narrower, more tractable ask than full gain-map editing support (which @gregbenz's comment correctly notes gets complicated fast) — even just preserving the gain map unmodified when the base image is resized would cover the common case (most resizes don't need to touch the gain map's tone curve, just its dimensions).
Failing that, a UserWarning when save() drops a known gain map would at least stop this from being a silent data-loss bug for anyone using Pillow as a generic image-processing step (that's my case — I ran into this via sigal, a static gallery generator that uses Pillow for exactly this resize-and-save pattern).
Happy to attach a minimal reproducer file if that would help.
Activity
radarhere commentedon Jun 25, 2024
Are you aware of any small images (under 500kb) images that could be added to our test suite and distributed under the Pillow license?
cmahnke commentedon Jun 25, 2024
@radarhere: It's possible to generate one using
libultrahdr. What are the requirements, does it have to be somehow very colorful or something like that?If it needs to be beautiful @gregbenz might be able to help out.
gregbenz commentedon Jun 25, 2024
@cmahnke Happy to answer any questions here. I'm not clear what the intended use of this library/feature is. I'd be happy to consider any requests for a few sample images, though for testing code I would recommend creating dedicated test images to most easily and reliably validate results.
Is the goal here to alter the image (resize, compress, crop, rotate, flip), convert to another image format as is, filter, or to render for display? The first couple are well supported by libultrahdr and I'm assuming that's probably the intent here.
If you start changing image content (such as filtering), you'll have to get more involved (things can get pretty tricky and some edits would only be suitable if you're willing to render to SDR / HDR and give up the adaptive nature of a gain map). And actual display (such as in a browser) involves linear interpolation between the base SDR and full HDR rendering as appropriate for the encoding of the image relative to the display's available HDR headroom.
I have seen numerous issues with various efforts to render or transcode gain maps (improper alteration of metadata, gain map artifacts, scaling of the images before merge causing edge artiffacts, etc). If libultrahdr meets your needs, I would recommend leveraging that rather than trying to build the capability from scratch. It is supported by Google (who has been very supportive of gain maps in both Chrome and Android), well maintained, and aligned with efforts towards an official ISO standard for common file formats (supports JPG now, but the project team has mentioned AVIF / HEIF on the roadmap).
For anyone who has questions on gain maps, I have lots of information at https://gregbenzphotography.com/hdr-photos/jpg-hdr-gain-maps-in-adobe-camera-raw/ and https://gregbenzphotography.com/hdr/.
javilm commentedon Sep 17, 2025
@radarhere I found this thread because I use Pillow to process images on my site and I wanted to add support for HDR.
I can "donate" some of my HDR photos. How do we proceed?
I'd like to see HDR support in Pillow instead of having to rewrite the image processing code with ImageMagick.
radarhere commentedon Sep 17, 2025
It's not all that clear to me what the goal of this issue is.
If the goal is just to load the basic JPEG data as an image, then it is possible that this was resolved by #8056 in Pillow 10.4.0. If someone has an image that isn't able to be processed in that way by Pillow, please attach it to demonstrate.
If the goal is to load something more advanced from an image, then it would be helpful if someone could attach an image and describe what they would like to see when Pillow reads it.
reagle commentedon Aug 12, 2026
I think the ambiguity @radarhere flagged comes down to two different asks that this thread has conflated:
Repro (Pillow 12.3.0, current as of this writing):
So Pillow already parses enough to know a gain map is present (img.info['mp']), it just never re-attaches it on save. That's a narrower, more tractable ask than full gain-map editing support (which @gregbenz's comment correctly notes gets complicated fast) — even just preserving the gain map unmodified when the base image is resized would cover the common case (most resizes don't need to touch the gain map's tone curve, just its dimensions).
Failing that, a UserWarning when save() drops a known gain map would at least stop this from being a silent data-loss bug for anyone using Pillow as a generic image-processing step (that's my case — I ran into this via sigal, a static gallery generator that uses Pillow for exactly this resize-and-save pattern).
Happy to attach a minimal reproducer file if that would help.