From 37c0c0aab038c7abd96f9b60b460118b55eec636 Mon Sep 17 00:00:00 2001 From: Benjamin Grimm-Lebsanft Date: Sat, 20 Jun 2026 10:23:31 +0200 Subject: [PATCH 1/3] Support compensation for Canon's Highlight tone priority Checked independently of ALO since both tags can be set simultaneously on modern Canon bodies. On My R5m2 with HTP on, ALO doesn't seem to affect the raw files. +1 EV yielded perfect compensation for D+ and in my scene as well for D+2 but results may vary for different scenes. +1 EV is a good starting point still and better than the nothing we currently have. --- src/common/exif.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/common/exif.cc b/src/common/exif.cc index 6fd7b862ebcb..17ca5d1b2129 100644 --- a/src/common/exif.cc +++ b/src/common/exif.cc @@ -1146,6 +1146,17 @@ static void _check_highlight_preservation(Exiv2::ExifData &exifData, img->exif_highlight_preservation = 0.0f; Exiv2::ExifData::const_iterator pos; + + // Canon Highlight Tone Priority: checked independently of ALO since both tags + // can be set simultaneously on modern Canon bodies. + // D+ (1) and D+2 (2) both apply ~1 EV sensor underexposure; D+2 is scene dependent + // according to Canon but start with 1 EV here as well. + if(FIND_EXIF_TAG("Exif.CanonLiOp.HighlightTonePriority")) + { + const long state = pos->toLong(0); + if(state > 0) + img->exif_highlight_preservation = 1.0f; // D+ or D+2: ~1 EV underexposure + } if(FIND_EXIF_TAG("Exif.Canon.LightingOpt")) // Active Lighting Optimization { // tag consists of an array of long values From f5aee4549f4cab52c8010e4533e4772c9fa4293a Mon Sep 17 00:00:00 2001 From: Benjamin Grimm-Lebsanft Date: Sun, 21 Jun 2026 07:17:55 +0200 Subject: [PATCH 2/3] Move HTP to override position --- src/common/exif.cc | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/common/exif.cc b/src/common/exif.cc index 17ca5d1b2129..b5176ca83100 100644 --- a/src/common/exif.cc +++ b/src/common/exif.cc @@ -1145,18 +1145,8 @@ static void _check_highlight_preservation(Exiv2::ExifData &exifData, // Compute exposure bias applied by HDR/highlight-preservation/Dynamic Range Expansion/HLG-tone modes img->exif_highlight_preservation = 0.0f; - Exiv2::ExifData::const_iterator pos; - - // Canon Highlight Tone Priority: checked independently of ALO since both tags - // can be set simultaneously on modern Canon bodies. - // D+ (1) and D+2 (2) both apply ~1 EV sensor underexposure; D+2 is scene dependent - // according to Canon but start with 1 EV here as well. - if(FIND_EXIF_TAG("Exif.CanonLiOp.HighlightTonePriority")) - { - const long state = pos->toLong(0); - if(state > 0) - img->exif_highlight_preservation = 1.0f; // D+ or D+2: ~1 EV underexposure - } + Exiv2::ExifData::const_iterator pos; + if(FIND_EXIF_TAG("Exif.Canon.LightingOpt")) // Active Lighting Optimization { // tag consists of an array of long values @@ -1183,6 +1173,17 @@ static void _check_highlight_preservation(Exiv2::ExifData &exifData, else if(state == 2) img->exif_highlight_preservation = 0.66f; // estimated strength for Strong } + // Canon Highlight Tone Priority overrides ALO if active -- both tags can be set + // simultaneously, and HTP represents a deliberate sensor underexposure that takes + // priority. + // D+ (1) and D+2 (2) both apply ~1 EV sensor underexposure; D+2 differs mainly + // in its stronger in-camera JPEG tone curve, not additional raw underexposure. + if(FIND_EXIF_TAG("Exif.CanonLiOp.HighlightTonePriority")) + { + const long state = pos->toLong(0); + if(state > 0) + img->exif_highlight_preservation = 1.0f; // D+ or D+2: ~1 EV underexposure + } else if(FIND_EXIF_TAG("Exif.Fujifilm.DevelopmentDynamicRange") // manual mode DR100/DR200/DR400 || FIND_EXIF_TAG("Exif.Fujifilm.AutoDynamicRange")) // auto mode { From 09b6c3ce1566596a297d4a58fcbd345adc4f5301 Mon Sep 17 00:00:00 2001 From: Benjamin Grimm-Lebsanft Date: Mon, 22 Jun 2026 15:32:19 +0200 Subject: [PATCH 3/3] Make HTP additive --- src/common/exif.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/exif.cc b/src/common/exif.cc index b5176ca83100..a8a87388c147 100644 --- a/src/common/exif.cc +++ b/src/common/exif.cc @@ -1182,7 +1182,7 @@ static void _check_highlight_preservation(Exiv2::ExifData &exifData, { const long state = pos->toLong(0); if(state > 0) - img->exif_highlight_preservation = 1.0f; // D+ or D+2: ~1 EV underexposure + img->exif_highlight_preservation += 1.0f; // D+ or D+2: ~1 EV underexposure } else if(FIND_EXIF_TAG("Exif.Fujifilm.DevelopmentDynamicRange") // manual mode DR100/DR200/DR400 || FIND_EXIF_TAG("Exif.Fujifilm.AutoDynamicRange")) // auto mode