public void CutHighlights(double cut, double softness, int lines, double tailValueAtLeast, ProgressReporter callback)
{
double maxlight = CalcMaxLight();
HistogramCollector sc = new HistogramCollector(maxlight, lines);
sc.CollectData(this);
double red_tail = sc.LineToScale(sc.FindHighTailRed(tailValueAtLeast));
double green_tail = sc.LineToScale(sc.FindHighTailGreen(tailValueAtLeast));
double blue_tail = sc.LineToScale(sc.FindHighTailBlue(tailValueAtLeast));
double min_tail = Math.Min(red_tail, Math.Min(green_tail, blue_tail));
double max_tail = Math.Max(red_tail, Math.Max(green_tail, blue_tail));
// Building highlights matrix
double delta = softness; // Highlight distance
double alpha = Math.Log(2) / delta;
double q = min_tail + cut * (max_tail - min_tail);
for (int j = 0; j < mHeight; j++)
{
if (j % REPORT_EVERY_NTH_LINE == 0 && callback != null)
{
if (!callback((double)j / mHeight)) throw new UserCancelException();
}
for (int i = 0; i < mWidth; i++)
{
if (r_chan[i, j] > q) r_chan[i, j] = (float)q;
if (g_chan[i, j] > q) g_chan[i, j] = (float)q;
if (b_chan[i, j] > q) b_chan[i, j] = (float)q;
double x = Math.Sqrt(r_chan[i, j] * r_chan[i, j] +
g_chan[i, j] * g_chan[i, j] +
b_chan[i, j] * b_chan[i, j]) / Math.Sqrt(3) / q;
double beta = Math.Log(q) - alpha;
hl_chan[i, j] = (float)((Math.Exp(alpha * x + beta) - Math.Exp(beta)) / (Math.Exp(alpha + beta) - Math.Exp(beta)));
}
}
}