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))); } } }
public void CutBlackPoint(double cut, int blur_radius, double blur_dark_level, int lines, double tailValueAtLeast, ProgressReporter callback) { double max_light = CalcMaxLight(); HistogramCollector sc = new HistogramCollector(max_light, lines); sc.CollectData(this); double min_tail = sc.LineToScale(sc.FindLowTailLightness(tailValueAtLeast)); double max_tail = sc.LineToScale(sc.FindHighTailLightness(tailValueAtLeast)); for (int j = 0; j < mHeight; j++) { if (j % REPORT_EVERY_NTH_LINE == 0 && callback != null) { if (!callback((double)j / this.mHeight * 0.3)) return; } for (int i = 0; i < mWidth; i++) { double light = 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); Tone curtone = new Tone(r_chan[i, j], g_chan[i, j], b_chan[i, j]); double newlight = light - min_tail * cut; if (newlight < 0) newlight = 0; lock (this) { r_chan[i, j] = (float)(curtone.R * newlight); g_chan[i, j] = (float)(curtone.G * newlight); b_chan[i, j] = (float)(curtone.B * newlight); } } } }