I'm using Magick.NET to apply colour corrections to photographs. I adjust red, green and blue channels by adding or subtracting a percentage to each using the Evaluate method. The value here is the +/- amount of change to apply to the specified channel.
image.Evaluate(channel, EvaluateOperator.Add, new Percentage(value));
Adding colour to a channel is fine, but removing colour from a channel will change the colour balance of white in the image (remove red, the image becomes green/blue). I need to be able to apply the adjustment to each channel without changing white.
I've tried applying Level after Evaluate, and also ContrastStretch, thinking that I could specify a black/white point below/above which the adjustment is ignored.
ColorMatrix looks promising but gives really weird results and Modulate does colour rotation, which isn't right.
Thanks
tldr; create a white mask and apply it to the image using .WriteMask() so that any white areas excluded from the .Evaluate(..) call.
var newImage = magickImage.Clone();
var stats = newImage.Statistics().GetChannel(PixelChannel.Composite);
var mean = stats.Mean / (stats.Maximum - stats.Minimum);
var stDev = stats.StandardDeviation / (stats.Maximum - stats.Minimum);
var whiteThreshold = new Percentage(100 - (mean + 0.5 * stDev));
var blackThreshold = new Percentage(mean - 0.5 * stDev);
newImage.ColorFuzz = new Percentage(3);
newImage.WhiteThreshold(whiteThreshold);
newImage.BlackThreshold(blackThreshold);
newImage.Opaque(MagickColors.Black, MagickColors.Green);
newImage.Opaque(MagickColors.White, MagickColors.Black);
newImage.InverseOpaque(MagickColors.Black, MagickColors.White);
magickImage.WriteMask = newImage;
Useful sites included https://www.imagemagick.org/script/index.php and http://www.fmwconcepts.com/imagemagick/index.php. Credit to Fred for his "color balance" script which is a really good example of how to do this with ImageMagick command line.