No support for HDR gain maps (transcoded to SDR-only)
Describe the bug When a JPG image with an HDR ("high dynamic range") gain map is transcoded, the gain map is stripped. This results in significant degradation of the image (loss of support for enhanced HDR display).
Modern displays support brighter and more vibrant HDR images. This includes most smart phones, Apple computers, and a general trend towards widespread support on the web. More info at https://gregbenzphotography.com/hdr and https://gregbenzphotography.com/hdr-photos/jpg-hdr-gain-maps-in-adobe-camera-raw/. Instagram also supports HDR gain maps and sample images may be easily viewed with the iOS or Android app on most smart phones with comparison images at https://www.instagram.com/gregbenzphotography/
To Reproduce Upload an image with a gain map to WordPress (using GD) and the resulting image in the media library will no longer no longer have a gain map.
Expected behavior The image should retain a proper gain map, even after any resizing / compressing / cropping.
Actual results The transcoded JPG contains only the SDR ("standard dynamic range") base image, not the required auxiliary image / metadata to support HDR display.
Environment (please complete the following information): Any version of GD will fail.
Additional context The Google libultrahdr library fully supports proper transcoding of these images: https://gregbenzphotography.com/hdr-gain-map-gallery/
Somewhat related to #136.
@cmb69 Certainly keeping an ICC profile is beneficial to any image (including JPG gain maps which typically have a profile in the base SDR but not typically in the auxiliary gain map image), but beyond that I'm not clear what connection you see on these issues.
[ Note that longer term (later in 2025), AVIF images with a gain map should become a key format for sharing HDR as well. With AVIF, we can use CICP/NCLX to represent the color profile for web use. This is beneficial as CICP is 4 bytes, rather than 500-1000ish for a similar ICC profile. It also allows specifying an HDR EOTF like PQ or HLG (ICC profiles have no standard at this time for HDR). The CICP stuff is separate from the main consideration here for JPG gain maps, I'm just noting that we aren't far from a point where this more compact alternative to ICC will be a useful consideration for some file formats (a CICP tag can be added to an ICC profile as well for various reasons, but that approach would not reduce file size). ]
The connection is that both are meta-data, and libgd ignores almost all meta-data so far (heck, even Exif Orientation is ignored). That means that developers using libgd need to cater to that themselves (until libgd supports the relevant meta-data; given that the linked issue has been reported more than ten years ago, I wouldn't hold my breath).
Upload an image with a gain map to WordPress (using GD) and the resulting image in the media library will no longer no longer have a gain map.
I suggest you report that to the WordPress developers; they might be able add support sooner than we can.
@cmb69 There are open requests here for GB, and for ImageMagick. As far as I know there is no path for WP media library support without at least one of them supporting gain maps - and ideally both (given both get a lot of use for WP).
Good to know on the metadata support, thank you.
I haven't looked up where HDR gain maps are stored in JFIF files, but ICC color profiles can be handled in userland with plain PHP: get APP2 segment via getimagesize(), and write back using binary string manipulation. A bit fiddly, but is doable. And yes, that only caters to JFIF; but that is due to a limitation of getimagesize() which only reads JFIF APP markers; you could also read these (and other metadata) directly. And doing this is PHP instead of C shouldn't be a particular performance issue (contrary to image pixel manipulation).
Thinking about that, it might be best to not add support for (most) metadata to libgd, since that would drastically increase the API scope, and we're already barely focussing on image manipulation, due to the need to support yet another image format every other year.
Wrt HDR gain maps: these are to add support to image formats which don't allow to store HDR images directly. Now libgd supports AVIF and HEIF, and these formats are HDR ready; however, libgd doesn't support that, because we only support up to 8bits per color channel. If we ever extend that, it would make sense to read HDR gain maps, and apply these; and then figure out what to do with that additional information when writing back to a desired image format. However, as is it might not make much sense. Consider thumbnail creation: read JFIF including HDR gain map, resize in LDR, reapply the old HDR gain map when storing – would that even make much sense? The resizing already lost information. And if there is going to be more drastic image manipulation than resizing, keeping the old HDR gain map may even make no sense at all. This is, however, nothing libgd knows about up-front; only clients know what they are going to do with the image.
JPG gain maps store the auxiliary gain map per MPF. The Android XMP spec adds a GContainer header not required in the Adobe XMP spec. The more important ISO spec is at a draft international stage and therefore not available for review. However, it is not only supported by multiple providers, but the files are dual encoded with both Android, Adobe, or the undocumented Apple XMP - and ISO. So the ISO spec would be fully compatible with the published Adobe spec as far as the encoding of the image itself (the metadata for ISO moves from XMP to the image codestream).
The Google-backed open source C++ library libultrahdr contains all the code necessary to take an existing gain map and transcode it to another, with support for recompress, rescale, crop (as well as rotate/mirror).
Simply integrated it into libgd and using it when the source image has a supported gain map should be all that's needed (I don't if libgd supports a wider scope outside these gain maps and handling only gain map inputs with this path is probably ideal to avoid any risk of edge cases). This library supports both the widely used Android XMP standard, as well as the critical ISO standard (which is not yet official, but already supported by Android, Chrome, Adobe LR/ ACR, iOS, MacOS, etc). The mainline is feature complete and just needs a minor fix (which is complete/validated) to be merged to mainline. Within a few days, the mainline release should be fully ready for this use.
https://github.com/google/libultrahdr/discussions/254
ImageMagick has nearly completed integration of this library (a related PHP wrapper likely needs to be updated for this to be used by WP, but even when complete support in libgd will be ideal to support a wider range of WP hosting environments): https://github.com/ImageMagick/ImageMagick/issues/6377
libultra does not yet support AVIF / HEIF, but the team has noted that it is on their roadmap. I would think that could ultimately be managed via libultrahdr as well.