2using System.Collections.Generic;
3using System.ComponentModel;
8using System.Threading.Tasks;
9using System.Windows.Forms;
12using Color = System.Drawing.Color;
14using Size = System.Drawing.Size;
15using SizeF = System.Drawing.SizeF;
19using Point = System.Drawing.Point;
22 public partial class HistogramControl : UserControl
27 this.Dock = DockStyle.Fill;
28 InitializeComponent();
29 if (c.BitsPerPixel == 8)
36 graphMax = ushort.MaxValue;
41 private Channel channel =
null;
42 private float bin = 10;
43 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
56 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
68 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
79 private int graphMax = ushort.MaxValue;
80 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
83 get {
return graphMax; }
84 set { graphMax = value; }
86 private int graphMin = 0;
87 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
90 get {
return graphMin; }
91 set { graphMin = value; }
93 private bool stackHistogram =
true;
94 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
99 return stackHistogram;
103 stackHistogram = value;
106 private int mouseX = 0;
107 private int mouseY = 0;
122 private float mouseValX = 0;
123 private float mouseValY = 0;
139 private bool axisNumbers =
true;
140 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
143 get {
return axisNumbers;}
144 set { axisNumbers = value; }
147 private bool axisTicks =
true;
148 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
151 get {
return axisTicks; }
152 set { axisTicks = value; }
155 private float fx = 0;
156 private float fy = 0;
158 private System.Drawing.Graphics g;
176 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
178 private void HistogramControl_Paint(
object sender, PaintEventArgs e)
180 if (g ==
null || bm ==
null)
182 if (g ==
null || bm ==
null)
186 graphMax = ushort.MaxValue;
187 g.Clear(System.Drawing.Color.LightGray);
189 g.TranslateTransform(-graphMin, 0);
191 bool hasStatistics = ImageView.SelectedImage !=
null &&
196 var textSize = g.MeasureString(
StatusMessage, SystemFonts.DefaultFont);
197 g.DrawString(
StatusMessage, SystemFonts.DefaultFont, Brushes.DimGray,
198 Math.Max(4, (Width - textSize.Width) / 2),
199 Math.Max(4, (Height - textSize.Height) / 2));
200 e.Graphics.DrawImage(bm, 0, 0);
204 fx = ((float)this.Width) / ((
float)graphMax);
207 for (
int cc = 0; cc < ImageView.SelectedImage.Channels.Count; cc++)
209 for (
int i = 0; i < ImageView.SelectedImage.Channels[cc].stats.Length; i++)
211 float f = ImageView.SelectedImage.Channels[cc].stats[i].StackMedian;
221 fy = ((float)this.Height) / maxmedian;
222 for (
int c = 0; c < ImageView.SelectedImage.Channels.Count; c++)
224 Channel channel = ImageView.SelectedImage.Channels[c];
225 for (
int i = 0; i < channel.range.Length; i++)
228 if (ImageView.SelectedImage.RGBChannelCount == 1)
229 stat = channel.stats[0];
231 stat = channel.stats[i];
233 System.Drawing.Pen black =
new System.Drawing.Pen(System.Drawing.Color.FromArgb(35, 0, 0, 0), bin * fx);
234 System.Drawing.Pen blackd =
new System.Drawing.Pen(System.Drawing.Color.FromArgb(150, 0, 0, 0), bin * fx);
235 System.Drawing.Pen pen =
null;
236 System.Drawing.Pen pend =
null;
239 if (channel.Emission != 0)
241 pen =
new System.Drawing.Pen(SpectralColor(channel.Emission), bin * fx);
242 pen.Color =
Color.FromArgb(light, pen.Color);
243 pend =
new System.Drawing.Pen(SpectralColor(channel.Emission), bin * fx);
244 pend.Color =
Color.FromArgb(dark, pen.Color);
250 pen =
new System.Drawing.Pen(
Color.FromArgb(light, 255, 0, 0), bin * fx);
251 pend =
new System.Drawing.Pen(
Color.FromArgb(dark, 255, 0, 0), bin * fx);
255 pen =
new System.Drawing.Pen(
Color.FromArgb(light, 0, 255, 0), bin * fx);
256 pend =
new System.Drawing.Pen(
Color.FromArgb(dark, 0, 255, 0), bin * fx);
260 pen =
new System.Drawing.Pen(
Color.FromArgb(light, 0, 0, 255), bin * fx);
261 pend =
new System.Drawing.Pen(
Color.FromArgb(dark, 0, 0, 255), bin * fx);
265 g.DrawLine(Pens.Black,
new System.Drawing.PointF(mouseX, 0),
new System.Drawing.PointF(mouseX,
this.Height));
267 if (App.Image.bitsPerPixel <= 8)
275 System.Drawing.PointF? prevs =
null;
276 System.Drawing.PointF? prev =
null;
277 for (
float x = 0; x < gmax; x++)
279 if (
StackHistogram && c == ImageView.SelectedImage.Channels.Count - 1)
282 float val = (float)ImageView.SelectedImage.Statistics.StackValues[(
int)x];
286 float v = sumbin / binind;
287 float yy = this.Height - (fy * v);
290 g.DrawLine(blackd, prevs.Value,
new System.Drawing.PointF(fx * x, yy));
292 g.DrawLine(black,
new System.Drawing.PointF(fx * x,
this.Height),
new System.Drawing.PointF(fx * x, yy));
293 prevs =
new System.Drawing.PointF(fx * x, yy);
299 float rv = stat.StackValues[(int)x];
303 g.DrawLine(pen,
new System.Drawing.PointF(fx * x,
this.Height),
new System.Drawing.PointF(fx * x,
this.Height - (fy * (sumbins / bininds))));
306 g.DrawLine(pend, prev.Value,
new System.Drawing.PointF(fx * x,
this.Height - (fy * (sumbins / bininds))));
308 prev =
new System.Drawing.PointF(fx * x, this.Height - (fy * (sumbins / bininds)));
317 g.DrawLine(pend,
new System.Drawing.PointF((fx * channel.range[i].Max), 0),
new System.Drawing.PointF((fx * channel.range[i].Max),
this.Height));
318 g.DrawLine(pend,
new System.Drawing.PointF(fx * channel.range[i].Min, 0),
new System.Drawing.PointF(fx * channel.range[i].Min,
this.Height));
333 for (
float x = 0; x < graphMax; x += 2000)
335 System.Drawing.SizeF s = g.MeasureString(x.ToString(), SystemFonts.DefaultFont);
336 g.DrawString(x.ToString(), SystemFonts.DefaultFont, Brushes.Black, (fx * x) - (s.Width/2), tick + 6);
337 g.DrawLine(Pens.Black,
new System.Drawing.PointF((fx * x), 0),
new System.Drawing.PointF((fx * x), tick + 3));
339 for (
float x = 0; x < graphMax; x += 1000)
341 g.DrawLine(Pens.Black,
new System.Drawing.PointF((fx * x), 0),
new System.Drawing.PointF((fx * x), tick));
344 if (graphMax <= 16383)
345 for (
float x = 0; x < graphMax; x += 100)
347 g.DrawLine(Pens.Black,
new System.Drawing.PointF((fx * x), 0),
new System.Drawing.PointF((fx * x), tick));
351 for (
float x = 0; x < graphMax; x += 50)
353 g.DrawLine(Pens.Black,
new System.Drawing.PointF((fx * x), 0),
new System.Drawing.PointF((fx * x), 4));
355 for (
float x = 0; x < graphMax; x += 10)
357 g.DrawLine(Pens.Black,
new System.Drawing.PointF((fx * x), 0),
new System.Drawing.PointF((fx * x), 2));
362 if (ImageView.SelectedImage.RGBChannelCount == 3)
364 if (ImageView.SelectedImage.Channels.Count > 2)
367 "(" + (mouseX / fx).ToString() +
368 ",R:" + ImageView.SelectedImage.Channels[2].stats[2].StackValues[(int)(mouseX / fx)].ToString() +
369 ",G:" + ImageView.SelectedImage.Channels[1].stats[1].StackValues[(int)(mouseX / fx)].ToString() +
370 ",B:" + ImageView.SelectedImage.Channels[0].stats[0].StackValues[(int)(mouseX / fx)].ToString() +
")";
375 "(" + (mouseX / fx).ToString() +
376 ",R:" + ImageView.SelectedImage.Channels[0].stats[2].StackValues[(int)(mouseX / fx)].ToString() +
377 ",G:" + ImageView.SelectedImage.Channels[0].stats[1].StackValues[(int)(mouseX / fx)].ToString() +
378 ",B:" + ImageView.SelectedImage.Channels[0].stats[0].StackValues[(int)(mouseX / fx)].ToString() +
")";
383 int x = (int)(mouseX / fx);
384 if (ImageView.SelectedImage.bitsPerPixel < 8 && ImageView.SelectedImage.Channels[0].stats[0].StackValues.Length < 255)
385 st =
"(" + (mouseX / fx).ToString() +
"," + ImageView.SelectedImage.Channels[0].stats[0].StackValues[x].ToString() +
")";
388 System.Drawing.SizeF sf = g.MeasureString(st, SystemFonts.DefaultFont);
389 g.DrawString(st, SystemFonts.DefaultFont, Brushes.Black, mouseX, mouseY + sf.Height);
391 e.Graphics.DrawImage(bm, 0, 0);
398 private void HistogramControl_MouseDown(
object sender, MouseEventArgs e)
410 private void HistogramControl_MouseMove(
object sender, MouseEventArgs e)
412 mouseValX = e.X / fx;
413 mouseValY = e.Y / fy;
420 private void HistogramControl_SizeChanged(
object sender, EventArgs e)
428 private void InitGraphics()
430 if (Width == 0 || Height == 0)
432 bm =
new Bitmap(Width, Height);
435 g = System.Drawing.Graphics.FromImage(bm);
442 private void copyViewToClipboardToolStripMenuItem_Click(
object sender, EventArgs e)
444 Clipboard.SetImage(bm);
452 private void setMaxToolStripMenuItem_Click(
object sender, EventArgs e)
454 App.channelsTool.SelectedChannel.range[App.channelsTool.SelectedSample].Max = (int)
MouseValX;
456 App.viewer.UpdateImage();
464 private void setMinToolStripMenuItem_Click(
object sender, EventArgs e)
466 App.channelsTool.SelectedChannel.range[App.channelsTool.SelectedSample].Min = (int)
MouseValX;
468 App.viewer.UpdateImage();
475 private void setMaxAllToolStripMenuItem_Click(
object sender, EventArgs e)
477 foreach (Channel c
in ImageView.SelectedImage.Channels)
479 for (
int i = 0; i < c.range.Length; i++)
490 private void setMinAllToolStripMenuItem_Click(
object sender, EventArgs e)
492 foreach (Channel c
in ImageView.SelectedImage.Channels)
494 for (
int i = 0; i < c.range.Length; i++)
505 Color SpectralColor(
double l)
511 if ((l >= 400.0) && (l < 410.0)) { t = (l - 400.0) / (410.0 - 400.0); r = +(0.33 * t) - (0.20 * t * t); }
512 else if ((l >= 410.0) && (l < 475.0)) { t = (l - 410.0) / (475.0 - 410.0); r = 0.14 - (0.13 * t * t); }
513 else if ((l >= 545.0) && (l < 595.0)) { t = (l - 545.0) / (595.0 - 545.0); r = +(1.98 * t) - (t * t); }
514 else if ((l >= 595.0) && (l < 650.0)) { t = (l - 595.0) / (650.0 - 595.0); r = 0.98 + (0.06 * t) - (0.40 * t * t); }
515 else if ((l >= 650.0) && (l < 700.0)) { t = (l - 650.0) / (700.0 - 650.0); r = 0.65 - (0.84 * t) + (0.20 * t * t); }
516 if ((l >= 415.0) && (l < 475.0)) { t = (l - 415.0) / (475.0 - 415.0); g = +(0.80 * t * t); }
517 else if ((l >= 475.0) && (l < 590.0)) { t = (l - 475.0) / (590.0 - 475.0); g = 0.8 + (0.76 * t) - (0.80 * t * t); }
518 else if ((l >= 585.0) && (l < 639.0)) { t = (l - 585.0) / (639.0 - 585.0); g = 0.84 - (0.84 * t); }
519 if ((l >= 400.0) && (l < 475.0)) { t = (l - 400.0) / (475.0 - 400.0); b = +(2.20 * t) - (1.50 * t * t); }
520 else if ((l >= 475.0) && (l < 560.0)) { t = (l - 475.0) / (560.0 - 475.0); b = 0.7 - (t) + (0.30 * t * t); }
524 return Color.FromArgb(255, (
int)r, (
int)g, (
int)b);
AForge.RectangleD RectangleD
AForge.RectangleF RectangleF
AForge.Rectangle Rectangle
System.Drawing.SizeF SizeF
static ChannelsTool channelsTool
void UpdateChannel(Channel c)
HistogramControl(Channel c)
ImageView control for image stacks, pyramidal and whole-slide-images.
static BioImage SelectedImage