For anyone else who ends up finding this post, while waiting for the "proper" fix to hit the repos I have discovered that the following workaround works very well, without messing up the colors:
- resize image up to 140% size
- modulate image to reduce contrast by 75% and reduce lightness by 3%
- modulate image to perform the desired hue shift
- modulate image to increase the contrast and lightness back to original (in this case, increase contrast by 400% and lightness by 3%)
- resize image back to original size
The reduction and restoration of contrast and lightness around the hue shift almost entirely solves the problem, but there's a few stray black pixels left over. Performing it on a scaled-up version before scaling it back down again made even those black pixels go away.
The Imagick code for this procedure is as follows:
Code: Select all
function modulate_wrapper($image, $lightness, $contrast, $hue) {
// set up parameters
$size_factor = 1.4;
$contrast_drop_percent = 75;
$lightness_drop_percent = 3;
// calculate lightness and contrast targets
$contrast_dn = 100 - $contrast_drop_percent;
$lightness_dn = 100 - $lightness_drop_percent;
$contrast_up = 100 / (100 - $contrast_drop_percent) * 100;
$lightness_up = 100 / (100 - $lightness_drop_percent) * 100;
// expand the image
$d = $image->getImageGeometry();
$expanded_width = $d['width'] * $size_factor;
$expanded_height = $d['height'] * $size_factor;
$image->resizeImage($expanded_width, $expanded_height, imagick::FILTER_LANCZOS, 1);
// drop contrast / lightness, hue shift, then restore contrast / lightness
$image->modulateImage($lightness_dn, $contrast_dn, 100);
$image->modulateImage($lightness, $contrast, $hue);
$image->modulateImage($lightness_up, $contrast_up, 100);
// size the image back
$image->resizeImage($d['width'], $d['height'], imagick::FILTER_LANCZOS, 1);
}
I'm looking forward to updating ImageMagick as soon as the fix hits the repos, but in the interim this works decently well, and with very little overhead. While I'm certain that it's there, I have not been able to perceive the loss in lightness / contrast fidelity from the compression or the loss in image quality from the resizing.