2using System.Collections.Generic;
3using System.ComponentModel;
8using System.Threading.Tasks;
9using System.Windows.Forms;
11using Pen = System.Drawing.Pen;
12using Color = System.Drawing.Color;
15 public partial class HistogramControl : UserControl
20 this.Dock = DockStyle.Fill;
21 InitializeComponent();
22 if (c.BitsPerPixel == 8)
29 graphMax = ushort.MaxValue;
34 private Channel channel =
null;
35 private float bin = 10;
36 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
49 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
61 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
72 private int graphMax = ushort.MaxValue;
73 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
76 get {
return graphMax; }
77 set { graphMax = value; }
79 private int graphMin = 0;
80 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
83 get {
return graphMin; }
84 set { graphMin = value; }
86 private bool stackHistogram =
true;
87 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
92 return stackHistogram;
96 stackHistogram = value;
99 private int mouseX = 0;
100 private int mouseY = 0;
115 private float mouseValX = 0;
116 private float mouseValY = 0;
132 private bool axisNumbers =
true;
133 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
136 get {
return axisNumbers;}
137 set { axisNumbers = value; }
140 private bool axisTicks =
true;
141 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
144 get {
return axisTicks; }
145 set { axisTicks = value; }
148 private float fx = 0;
149 private float fy = 0;
150 private System.Drawing.Bitmap bm;
151 private System.Drawing.Graphics g;
165 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
171 private void HistogramControl_Paint(
object sender, PaintEventArgs e)
173 if (g ==
null || bm ==
null)
175 if (g ==
null || bm ==
null)
179 graphMax = ushort.MaxValue;
180 g.Clear(System.Drawing.Color.LightGray);
182 g.TranslateTransform(-graphMin, 0);
184 bool hasStatistics = ImageView.SelectedImage !=
null &&
189 var textSize = g.MeasureString(
StatusMessage, SystemFonts.DefaultFont);
190 g.DrawString(
StatusMessage, SystemFonts.DefaultFont, Brushes.DimGray,
191 Math.Max(4, (Width - textSize.Width) / 2),
192 Math.Max(4, (Height - textSize.Height) / 2));
193 e.Graphics.DrawImage(bm, 0, 0);
197 fx = ((float)this.Width) / ((
float)graphMax);
200 for (
int cc = 0; cc < ImageView.SelectedImage.Channels.Count; cc++)
202 for (
int i = 0; i < ImageView.SelectedImage.Channels[cc].stats.Length; i++)
204 float f = ImageView.SelectedImage.Channels[cc].stats[i].StackMedian;
214 fy = ((float)this.Height) / maxmedian;
215 for (
int c = 0; c < ImageView.SelectedImage.Channels.Count; c++)
217 Channel channel = ImageView.SelectedImage.Channels[c];
218 for (
int i = 0; i < channel.range.Length; i++)
221 if (ImageView.SelectedImage.RGBChannelCount == 1)
222 stat = channel.stats[0];
224 stat = channel.stats[i];
226 System.Drawing.Pen black =
new System.Drawing.Pen(System.Drawing.Color.FromArgb(35, 0, 0, 0), bin * fx);
227 System.Drawing.Pen blackd =
new System.Drawing.Pen(System.Drawing.Color.FromArgb(150, 0, 0, 0), bin * fx);
228 System.Drawing.Pen pen =
null;
229 System.Drawing.Pen pend =
null;
232 if (channel.Emission != 0)
234 pen =
new System.Drawing.Pen(SpectralColor(channel.Emission), bin * fx);
235 pen.Color =
Color.FromArgb(light, pen.Color);
236 pend =
new System.Drawing.Pen(SpectralColor(channel.Emission), bin * fx);
237 pend.Color =
Color.FromArgb(dark, pen.Color);
243 pen =
new System.Drawing.Pen(
Color.FromArgb(light, 255, 0, 0), bin * fx);
244 pend =
new System.Drawing.Pen(
Color.FromArgb(dark, 255, 0, 0), bin * fx);
248 pen =
new System.Drawing.Pen(
Color.FromArgb(light, 0, 255, 0), bin * fx);
249 pend =
new System.Drawing.Pen(
Color.FromArgb(dark, 0, 255, 0), bin * fx);
253 pen =
new System.Drawing.Pen(
Color.FromArgb(light, 0, 0, 255), bin * fx);
254 pend =
new System.Drawing.Pen(
Color.FromArgb(dark, 0, 0, 255), bin * fx);
258 g.DrawLine(Pens.Black,
new System.Drawing.PointF(mouseX, 0),
new System.Drawing.PointF(mouseX,
this.Height));
260 if (App.Image.bitsPerPixel <= 8)
268 System.Drawing.PointF? prevs =
null;
269 System.Drawing.PointF? prev =
null;
270 for (
float x = 0; x < gmax; x++)
272 if (
StackHistogram && c == ImageView.SelectedImage.Channels.Count - 1)
275 float val = (float)ImageView.SelectedImage.Statistics.StackValues[(
int)x];
279 float v = sumbin / binind;
280 float yy = this.Height - (fy * v);
283 g.DrawLine(blackd, prevs.Value,
new System.Drawing.PointF(fx * x, yy));
285 g.DrawLine(black,
new System.Drawing.PointF(fx * x,
this.Height),
new System.Drawing.PointF(fx * x, yy));
286 prevs =
new System.Drawing.PointF(fx * x, yy);
292 float rv = stat.StackValues[(int)x];
296 g.DrawLine(pen,
new System.Drawing.PointF(fx * x,
this.Height),
new System.Drawing.PointF(fx * x,
this.Height - (fy * (sumbins / bininds))));
299 g.DrawLine(pend, prev.Value,
new System.Drawing.PointF(fx * x,
this.Height - (fy * (sumbins / bininds))));
301 prev =
new System.Drawing.PointF(fx * x, this.Height - (fy * (sumbins / bininds)));
310 g.DrawLine(pend,
new System.Drawing.PointF((fx * channel.range[i].Max), 0),
new System.Drawing.PointF((fx * channel.range[i].Max),
this.Height));
311 g.DrawLine(pend,
new System.Drawing.PointF(fx * channel.range[i].Min, 0),
new System.Drawing.PointF(fx * channel.range[i].Min,
this.Height));
326 for (
float x = 0; x < graphMax; x += 2000)
328 System.Drawing.SizeF s = g.MeasureString(x.ToString(), SystemFonts.DefaultFont);
329 g.DrawString(x.ToString(), SystemFonts.DefaultFont, Brushes.Black, (fx * x) - (s.Width/2), tick + 6);
330 g.DrawLine(Pens.Black,
new System.Drawing.PointF((fx * x), 0),
new System.Drawing.PointF((fx * x), tick + 3));
332 for (
float x = 0; x < graphMax; x += 1000)
334 g.DrawLine(Pens.Black,
new System.Drawing.PointF((fx * x), 0),
new System.Drawing.PointF((fx * x), tick));
337 if (graphMax <= 16383)
338 for (
float x = 0; x < graphMax; x += 100)
340 g.DrawLine(Pens.Black,
new System.Drawing.PointF((fx * x), 0),
new System.Drawing.PointF((fx * x), tick));
344 for (
float x = 0; x < graphMax; x += 50)
346 g.DrawLine(Pens.Black,
new System.Drawing.PointF((fx * x), 0),
new System.Drawing.PointF((fx * x), 4));
348 for (
float x = 0; x < graphMax; x += 10)
350 g.DrawLine(Pens.Black,
new System.Drawing.PointF((fx * x), 0),
new System.Drawing.PointF((fx * x), 2));
355 if (ImageView.SelectedImage.RGBChannelCount == 3)
357 if (ImageView.SelectedImage.Channels.Count > 2)
360 "(" + (mouseX / fx).ToString() +
361 ",R:" + ImageView.SelectedImage.Channels[2].stats[2].StackValues[(int)(mouseX / fx)].ToString() +
362 ",G:" + ImageView.SelectedImage.Channels[1].stats[1].StackValues[(int)(mouseX / fx)].ToString() +
363 ",B:" + ImageView.SelectedImage.Channels[0].stats[0].StackValues[(int)(mouseX / fx)].ToString() +
")";
368 "(" + (mouseX / fx).ToString() +
369 ",R:" + ImageView.SelectedImage.Channels[0].stats[2].StackValues[(int)(mouseX / fx)].ToString() +
370 ",G:" + ImageView.SelectedImage.Channels[0].stats[1].StackValues[(int)(mouseX / fx)].ToString() +
371 ",B:" + ImageView.SelectedImage.Channels[0].stats[0].StackValues[(int)(mouseX / fx)].ToString() +
")";
376 int x = (int)(mouseX / fx);
377 if (ImageView.SelectedImage.bitsPerPixel < 8 && ImageView.SelectedImage.Channels[0].stats[0].StackValues.Length < 255)
378 st =
"(" + (mouseX / fx).ToString() +
"," + ImageView.SelectedImage.Channels[0].stats[0].StackValues[x].ToString() +
")";
381 System.Drawing.SizeF sf = g.MeasureString(st, SystemFonts.DefaultFont);
382 g.DrawString(st, SystemFonts.DefaultFont, Brushes.Black, mouseX, mouseY + sf.Height);
384 e.Graphics.DrawImage(bm, 0, 0);
391 private void HistogramControl_MouseDown(
object sender, MouseEventArgs e)
403 private void HistogramControl_MouseMove(
object sender, MouseEventArgs e)
405 mouseValX = e.X / fx;
406 mouseValY = e.Y / fy;
413 private void HistogramControl_SizeChanged(
object sender, EventArgs e)
421 private void InitGraphics()
423 if (Width == 0 || Height == 0)
425 bm =
new System.Drawing.Bitmap(Width, Height);
428 g = System.Drawing.Graphics.FromImage(bm);
435 private void copyViewToClipboardToolStripMenuItem_Click(
object sender, EventArgs e)
437 Clipboard.SetImage(bm);
445 private void setMaxToolStripMenuItem_Click(
object sender, EventArgs e)
447 App.channelsTool.SelectedChannel.range[App.channelsTool.SelectedSample].Max = (int)
MouseValX;
449 App.viewer.UpdateImage();
457 private void setMinToolStripMenuItem_Click(
object sender, EventArgs e)
459 App.channelsTool.SelectedChannel.range[App.channelsTool.SelectedSample].Min = (int)
MouseValX;
461 App.viewer.UpdateImage();
468 private void setMaxAllToolStripMenuItem_Click(
object sender, EventArgs e)
470 foreach (Channel c
in ImageView.SelectedImage.Channels)
472 for (
int i = 0; i < c.range.Length; i++)
483 private void setMinAllToolStripMenuItem_Click(
object sender, EventArgs e)
485 foreach (Channel c
in ImageView.SelectedImage.Channels)
487 for (
int i = 0; i < c.range.Length; i++)
498 Color SpectralColor(
double l)
504 if ((l >= 400.0) && (l < 410.0)) { t = (l - 400.0) / (410.0 - 400.0); r = +(0.33 * t) - (0.20 * t * t); }
505 else if ((l >= 410.0) && (l < 475.0)) { t = (l - 410.0) / (475.0 - 410.0); r = 0.14 - (0.13 * t * t); }
506 else if ((l >= 545.0) && (l < 595.0)) { t = (l - 545.0) / (595.0 - 545.0); r = +(1.98 * t) - (t * t); }
507 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); }
508 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); }
509 if ((l >= 415.0) && (l < 475.0)) { t = (l - 415.0) / (475.0 - 415.0); g = +(0.80 * t * t); }
510 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); }
511 else if ((l >= 585.0) && (l < 639.0)) { t = (l - 585.0) / (639.0 - 585.0); g = 0.84 - (0.84 * t); }
512 if ((l >= 400.0) && (l < 475.0)) { t = (l - 400.0) / (475.0 - 400.0); b = +(2.20 * t) - (1.50 * t * t); }
513 else if ((l >= 475.0) && (l < 560.0)) { t = (l - 475.0) / (560.0 - 475.0); b = 0.7 - (t) + (0.30 * t * t); }
517 return Color.FromArgb(255, (
int)r, (
int)g, (
int)b);
System.Drawing.Color Color
static ChannelsTool channelsTool
void UpdateChannel(Channel c)
HistogramControl(Channel c)
ImageView control for image stacks, pyramidal and whole-slide-images.
static BioImage SelectedImage