public override void AnalyzeImage(IBitmapCore image) { int points = 100; // TODO: Make option ToneStageOperationParameters pm = (ToneStageOperationParameters)Parameters; if (pm.AutoDarkTone) { mAnalyzedDarkTone = image.FindDarkTone( pm.LightTone, pm.Edge, pm.Softness, pm.AutoDarkCenter, pm.AutoDarkRadius, points); toneselectorwidget1.SelectedDarkTone = mAnalyzedDarkTone; toneselectorwidget1.DarkToneSelectorSymbol = ToneSelectorSymbol.Dot; } if (pm.AutoLightTone) { mAnalyzedLightTone = image.FindLightTone( pm.DarkTone, pm.Edge, pm.Softness, pm.AutoLightCenter, pm.AutoLightRadius, points); toneselectorwidget1.SelectedLightTone = mAnalyzedLightTone; toneselectorwidget1.LightToneSelectorSymbol = ToneSelectorSymbol.Dot; } }
public Color ApplyDualToning(Tone dark_tone, Tone light_tone, double softness, double edge) { // Calculating relative brightness double brightness_before = CalcBrightness() + 0.0001; double x = brightness_before; // Calculating new color double K = Math.Atan2(softness * x, edge * edge - x * x) / Math.PI; double R1 = dark_tone.R * mR; double G1 = dark_tone.G * mG; double B1 = dark_tone.B * mB; double R2 = light_tone.R * mR; double G2 = light_tone.G * mG; double B2 = light_tone.B * mB; return(new Color(R2 * K + R1 * (1 - K), G2 * K + G1 * (1 - K), B2 * K + B1 * (1 - K)).ChangeBrightness(brightness_before)); }
public Color ApplyDualToning(Tone dark_tone, Tone light_tone, double softness, double edge) { // Calculating relative brightness double brightness_before = CalcBrightness() + 0.0001; double x = brightness_before; // Calculating new color double K = Math.Atan2(softness * x, edge * edge - x * x) / Math.PI; double R1 = dark_tone.R * mR; double G1 = dark_tone.G * mG; double B1 = dark_tone.B * mB; double R2 = light_tone.R * mR; double G2 = light_tone.G * mG; double B2 = light_tone.B * mB; return new Color(R2 * K + R1 * (1 - K), G2 * K + G1 * (1 - K), B2 * K + B1 * (1 - K)).ChangeBrightness(brightness_before); }
public override void OnDo(IBitmapCore hdp) { int points = 500; // TODO: Make option ToneStageOperationParameters pm = (ToneStageOperationParameters)Parameters; Tone darkTone = pm.DarkTone; Tone lightTone = pm.LightTone; if (pm.AutoDarkTone) { darkTone = hdp.FindDarkTone( pm.LightTone, pm.Edge, pm.Softness, pm.AutoDarkCenter, pm.AutoDarkRadius, points); } if (pm.AutoLightTone) { lightTone = hdp.FindLightTone( pm.DarkTone, pm.Edge, pm.Softness, pm.AutoLightCenter, pm.AutoLightRadius, points); } Console.WriteLine("Basic operations: toning... "); hdp.ApplyTone(darkTone, lightTone, pm.Edge, pm.Softness, delegate(double progress) { return(OnReportProgress(progress)); } ); }
private void SelectNewLightTone(double winX, double winY) { double x = (double)(winX - margin) / (Allocation.Width - 2*margin); double y = (double)(winY - margin) / (Allocation.Height - 2*margin); if (x < 0) x = 0; if (y < 0) y = 0; if (x > 1) x = 1; if (y > 1) y = 1; SelectedLightTone = XY_to_Tone(x, y); OnLightToneSelected(); QueueDraw(); }
public double Tone_to_Y(Tone t) { // This is a norm coefficient which is needed to // place the gray point into the center in any mAlpha value double p = Math.Pow(0.5 / Math.Tan(Math.PI / 4), mAlpha); double pown = 1.0 / (Math.Pow(t.B, 1.0 / mAlpha) + Math.Pow(t.R, 1.0 / mAlpha)); double n = Math.Pow(pown, mAlpha); return Math.Atan(Math.Pow(t.G * n / p, 1.0 / mAlpha)) / (Math.PI / 2 - 0.0001); }
public double Tone_to_X(Tone t) { double pown = 1.0 / (Math.Pow(t.B, 1.0 / mAlpha) + Math.Pow(t.R, 1.0 / mAlpha)); return Math.Pow(t.R, 1.0 / mAlpha) * pown; }
public Tone FindLightTone(Tone dark_tone, double edge, double softness, Point light_center, double light_radius, int points) { int i = (int)(light_center.X * Width); int j = (int)(light_center.Y * Height); // Selecting points for analysis Random rnd = new Random(); int n = 0; Color[] sel = new Color[points]; for (int p = 0; p < points; p++) { double phi = rnd.NextDouble() * 2 * Math.PI; double rad = light_radius * (Width + Height) / 2 * rnd.NextDouble(); int u = i + (int)(rad * Math.Cos(phi)); int v = j + (int)(rad * Math.Sin(phi)); if (u >= 0 && u < mWidth && v >= 0 && v < mHeight) { sel[n] = new Color(r_chan[u, v], g_chan[u, v], b_chan[u, v]); n++; } } // Searching for minimum tone distance to (1, 1, 1) int steps_count = 100; double dc = 0.01; Tone cur_light_tone = new Tone(1, 1, 1); for (int step = 0; step < steps_count; step++) { // Calculationg distance from current point to "gray" Tone(1, 1, 1) double r0 = 0, g0 = 0, b0 = 0; for (int p = 0; p < n; p++) { Color changed = sel[p].ApplyDualToning(dark_tone, cur_light_tone, softness, edge); r0 += changed.R; g0 += changed.G; b0 += changed.B; } double dist0 = Tone.Distance(new Tone(r0, g0, b0), new Tone(1, 1, 1)); // Calculationg gradient // Red shift double Pdist_dR; //if (cur_light_tone.R + dc < 1) { Tone cur_light_tone_dR = new Tone(cur_light_tone.R + dc, cur_light_tone.G, cur_light_tone.B); double r_dR = 0, g_dR = 0, b_dR = 0; for (int p = 0; p < n; p++) { Color changed = sel[p].ApplyDualToning(dark_tone, cur_light_tone_dR, softness, edge); r_dR += changed.R; g_dR += changed.G; b_dR += changed.B; } double dist_dR = Tone.Distance(new Tone(r_dR, g_dR, b_dR), new Tone(1, 1, 1)); Pdist_dR = (dist_dR - dist0) / dc; } //else // Pdist_dR = 0; // Green shift double Pdist_dG; //if (cur_light_tone.G + dc < 1) { Tone cur_light_tone_dG = new Tone(cur_light_tone.R, cur_light_tone.G + dc, cur_light_tone.B); double r_dG = 0, g_dG = 0, b_dG = 0; for (int p = 0; p < n; p++) { Color changed = sel[p].ApplyDualToning(dark_tone, cur_light_tone_dG, softness, edge); r_dG += changed.R; g_dG += changed.G; b_dG += changed.B; } double dist_dG = Tone.Distance(new Tone(r_dG, g_dG, b_dG), new Tone(1, 1, 1)); Pdist_dG = (dist_dG - dist0) / dc; } //else // Pdist_dG = 0; // Blue shift double Pdist_dB; //if (cur_light_tone.B + dc < 1) { Tone cur_light_tone_dB = new Tone(cur_light_tone.R, cur_light_tone.G, cur_light_tone.B + dc); double r_dB = 0, g_dB = 0, b_dB = 0; for (int p = 0; p < n; p++) { Color changed = sel[p].ApplyDualToning(dark_tone, cur_light_tone_dB, softness, edge); r_dB += changed.R; g_dB += changed.G; b_dB += changed.B; } double dist_dB = Tone.Distance(new Tone(r_dB, g_dB, b_dB), new Tone(1, 1, 1)); Pdist_dB = (dist_dB - dist0) / dc; } //else // Pdist_dB = 0; // Moving up the gradient double delta = 0.01; double newR = cur_light_tone.R - Pdist_dR * delta; double newG = cur_light_tone.G - Pdist_dG * delta; double newB = cur_light_tone.B - Pdist_dB * delta; newR = Math.Max(newR, 0); newG = Math.Max(newG, 0); newB = Math.Max(newB, 0); cur_light_tone = new Tone(newR, newG, newB); } return cur_light_tone; }
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); } } } }
public void ApplyTone(Tone dark_tone, Tone light_tone, double edge, double softness, ProgressReporter callback) { for (int i = 0; i < mWidth; i++) { if (i % REPORT_EVERY_NTH_LINE == 0 && callback != null) { if (!callback((double)i / mWidth)) { throw new UserCancelException(); } } for (int j = 0; j < mHeight; j++) { Color res_ij = new Color(r_chan[i, j], g_chan[i, j], b_chan[i, j]).ApplyDualToning(dark_tone, light_tone, softness, edge); lock (this) { r_chan[i, j] = (float)(res_ij.R); g_chan[i, j] = (float)(res_ij.G); b_chan[i, j] = (float)(res_ij.B); } } } }
public static double Distance(Tone t1, Tone t2) { return Math.Sqrt( (t1.mR - t2.mR) * (t1.mR - t2.mR) + (t1.mG - t2.mG) * (t1.mG - t2.mG) + (t1.mB - t2.mB) * (t1.mB - t2.mB)); }