diff --git a/src/gamut_mapping.c b/src/gamut_mapping.c index fe59ee8c..cdee877c 100644 --- a/src/gamut_mapping.c +++ b/src/gamut_mapping.c @@ -716,7 +716,15 @@ hueshift_done: ; struct ICh target = saturate(ich.h, dst); ich.C = softclip(ich.C, margin * source.C, target.C); - ipt = ich2ipt(ich); + // Soft-clip the resulting RGB color. This will generally distort + // hues slightly, but hopefully in an aesthetically pleasing way. + struct ICh saturated = { ich.I, target.C, ich.h }; + struct RGB peak = ipt2rgb(ich2ipt(saturated), dst); + struct RGB rgb = ipt2rgb(ich2ipt(ich), dst); + rgb.R = fmaxf(softclip(rgb.R, peak.R, dst.max_rgb), dst.min_rgb); + rgb.G = fmaxf(softclip(rgb.G, peak.G, dst.max_rgb), dst.min_rgb); + rgb.B = fmaxf(softclip(rgb.B, peak.B, dst.max_rgb), dst.min_rgb); + ipt = rgb2ipt(rgb, dst); } } diff --git a/src/tests/tone_mapping.c b/src/tests/tone_mapping.c index 13c18b5a..69313f27 100644 --- a/src/tests/tone_mapping.c +++ b/src/tests/tone_mapping.c @@ -152,7 +152,7 @@ int main() float hue_mapped = atan2f(c[2], c[1]); float hue_ref = atan2f(ref[2], ref[1]); - REQUIRE_FEQ(hue_mapped, hue_ref, 1e-3); + REQUIRE_FEQ(hue_mapped, hue_ref, 1e-2); } float *tmp = malloc(sizeof(float[LUT3D_SIZE][LUT3D_SIZE][LUT3D_SIZE][3]));