2using System.ComponentModel;
5 public partial class ChannelsTool : Form
7 private HistogramControl hist =
null;
8 private bool initializing;
9 private int histogramRequestVersion;
10 private BioImage histogramLoadingImage;
11 private Task histogramLoadingTask;
12 private BioImage histogramImage;
13 private ZCT histogramCoordinate;
14 private ZCT histogramLoadingCoordinate;
28 if (channelsBox.SelectedIndex != -1)
29 return Channels[channelsBox.SelectedIndex];
35 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
40 return (
int)sampleBox.Value;
44 sampleBox.Value = (decimal)value;
50 int selectedIndex = channelsBox.SelectedIndex;
52 channelsBox.Items.Clear();
55 channelsBox.Items.Add(item);
57 channelsBox.SelectedIndex = Channels.Count == 0
59 : Math.Clamp(selectedIndex, 0,
Channels.Count - 1);
66 InitializeComponent();
69 channelsBox.Items.Add(item);
71 MouseWheel +=
new System.Windows.Forms.MouseEventHandler(ChannelsTool_MouseWheel);
75 channelsBox.Enabled =
false;
76 sampleBox.Enabled =
false;
77 statsPanel.Controls.Add(
new Label
79 Dock = DockStyle.Fill,
80 Text =
"No channel metadata is available for this image.",
81 TextAlign = ContentAlignment.MiddleCenter
87 channelsBox.SelectedIndex = 0;
89 int sample = channel.range?.Length > 0 ? 0 : -1;
90 int defaultMax = channel.BitsPerPixel <= 8 ? byte.MaxValue : ushort.MaxValue;
91 int minimum = sample >= 0 ? channel.range[sample].Min : 0;
92 int maximum = sample >= 0 ? channel.range[sample].Max : defaultMax;
93 if (channel.stats?.Length > 0)
95 minimum = (int)channel.stats[0].StackMin;
96 maximum = (int)channel.stats[0].StackMax;
98 minBox.Value = Math.Clamp(minimum, (
int)minBox.Minimum, (
int)minBox.Maximum);
99 maxBox.Value = Math.Clamp(maximum, (
int)maxBox.Minimum, (
int)maxBox.Maximum);
101 hist.GraphMax = Math.Max(1, (
int)maxBox.Value);
102 maxGraphBox.Value = Math.Clamp(maxBox.Value, maxGraphBox.Minimum, maxGraphBox.Maximum);
103 statsPanel.Controls.Add(hist);
104 initializing =
false;
105 Shown += async (_, _) => await EnsureHistogramAsync();
115 private void minBox_ValueChanged(
object sender, EventArgs e)
117 if (initializing || channelsBox.SelectedIndex == -1)
121 hist.UpdateChannel(
Channels[channelsBox.SelectedIndex]);
123 hist.Min = (int)minBox.Value;
125 App.Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Max = (
int)maxBox.Value;
126 App.viewer.UpdateImage();
127 App.viewer.UpdateView();
136 private void maxBox_ValueChanged(
object sender, EventArgs e)
138 if (initializing || channelsBox.SelectedIndex == -1)
142 hist.UpdateChannel(
Channels[channelsBox.SelectedIndex]);
144 hist.Max = (int)maxBox.Value;
146 App.Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min = (
int)minBox.Value;
147 App.viewer.UpdateImage();
148 App.viewer.UpdateView();
157 private void channelsBox_SelectedIndexChanged(
object sender, EventArgs e)
159 if (initializing || channelsBox.SelectedIndex == -1)
161 Channel channel =
Channels[channelsBox.SelectedIndex];
162 if (channel.range ==
null || channel.range.Length == 0)
165 sampleBox.Maximum = channel.range.Length - 1;
166 if (minBox.Maximum <
Channels[channelsBox.SelectedIndex].range[(
int)sampleBox.Value].Min || maxBox.Maximum <
Channels[channelsBox.SelectedIndex].range[(
int)sampleBox.Value].Max)
169 maxBox.Value = ushort.MaxValue;
173 minBox.Value =
Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min;
174 maxBox.Value =
Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Max;
185 App.viewer.UpdateView();
194 private void maxUintBox_SelectedIndexChanged(
object sender, EventArgs e)
196 int i =
int.Parse((
string)maxUintBox.SelectedItem, System.Globalization.CultureInfo.InvariantCulture);
197 if (i <= maxBox.Maximum)
206 private void ChannelsTool_FormClosing(
object sender, FormClosingEventArgs e)
216 private void setMaxAllBut_Click(
object sender, EventArgs e)
220 for (
int i = 0; i < c.range.Length; i++)
222 c.range[i].Max = (int)maxBox.Value;
225 App.viewer.UpdateView();
232 private void setMinAllBut_Click(
object sender, EventArgs e)
236 for (
int i = 0; i < c.range.Length; i++)
238 c.range[i].Min = (int)minBox.Value;
241 App.viewer.UpdateView();
249 private void ChannelsTool_Activated(
object sender, EventArgs e)
252 if (
Channels.Count == 0 || channelsBox.SelectedIndex < 0 || hist ==
null)
255 if (channel.range ==
null || channel.range.Length == 0)
258 sampleBox.Maximum = channel.range.Length - 1;
259 sampleBox.Value = Math.Min(sampleBox.Value, sampleBox.Maximum);
260 minBox.Value = Math.Clamp(channel.range[(
int)sampleBox.Value].Min,
261 (
int)minBox.Minimum, (
int)minBox.Maximum);
262 maxBox.Value = Math.Clamp(channel.range[(
int)sampleBox.Value].Max,
263 (
int)maxBox.Minimum, (
int)maxBox.Maximum);
264 initializing =
false;
265 hist.UpdateChannel(channel);
267 _ = EnsureHistogramAsync();
271 private async Task EnsureHistogramAsync()
273 BioImage image = ImageView.SelectedImage;
274 if (image ==
null || hist ==
null)
277 ZCT coordinate = image.Coordinate;
278 int requestVersion = ++histogramRequestVersion;
279 if (ReferenceEquals(histogramImage, image) && SameCoordinate(histogramCoordinate, coordinate) &&
280 ZarrChannelView.HasHistogramStatistics(image))
282 hist.StatusMessage =
"";
288 hist.StatusMessage =
"Loading histogram…";
292 if (!ReferenceEquals(histogramLoadingImage, image) ||
293 !SameCoordinate(histogramLoadingCoordinate, coordinate) ||
294 histogramLoadingTask ==
null || histogramLoadingTask.IsCompleted)
296 histogramLoadingImage = image;
297 histogramLoadingCoordinate = coordinate;
298 histogramLoadingTask = ZarrChannelView.EnsureHistogramStatisticsAsync(
301 await histogramLoadingTask;
302 if (requestVersion != histogramRequestVersion || image != ImageView.SelectedImage)
304 histogramImage = image;
305 histogramCoordinate = coordinate;
306 hist.StatusMessage = ZarrChannelView.HasHistogramStatistics(image)
308 :
"Histogram data is unavailable for this image.";
315 if (requestVersion != histogramRequestVersion)
317 hist.StatusMessage = $
"Could not load histogram: {ex.Message}";
325 _ = EnsureHistogramAsync();
328 private void ApplyFrameRange()
334 int sample = Math.Clamp((
int)sampleBox.Value, 0,
SelectedChannel.stats.Length - 1);
336 int minimum = Math.Clamp((
int)statistics.StackMin, (
int)minBox.Minimum, (
int)minBox.Maximum);
337 int maximum = Math.Clamp((
int)statistics.StackMax, minimum, (
int)maxBox.Maximum);
338 int graphMaximum = Math.Max(1, maximum);
339 int graphMinimum = Math.Min(minimum, graphMaximum);
340 int histogramBin = Math.Max(1, (graphMaximum - graphMinimum + 255) / 256);
343 minBox.Value = minimum;
344 maxBox.Value = maximum;
345 minGraphBox.Value = Math.Clamp(graphMinimum,
346 (
int)minGraphBox.Minimum, (
int)minGraphBox.Maximum);
347 maxGraphBox.Value = Math.Clamp(graphMaximum,
348 (
int)maxGraphBox.Minimum, (
int)maxGraphBox.Maximum);
349 binBox.Value = Math.Clamp(histogramBin, (
int)binBox.Minimum, (
int)binBox.Maximum);
350 initializing =
false;
352 hist.GraphMin = graphMinimum;
353 hist.GraphMax = graphMaximum;
354 hist.Bin = histogramBin;
357 private static bool SameCoordinate(ZCT left, ZCT right) =>
358 left.Z == right.Z && left.C == right.C && left.T == right.T;
364 private void ChannelsTool_ResizeEnd(
object sender, EventArgs e)
374 private void maxUintBox2_SelectedIndexChanged(
object sender, EventArgs e)
376 int i =
int.Parse((
string)maxUintBox2.SelectedItem, System.Globalization.CultureInfo.InvariantCulture);
377 if (i <= maxGraphBox.Maximum)
378 maxGraphBox.Value = i;
381 maxGraphBox.Value = 255;
391 private void minGraphBox_ValueChanged(
object sender, EventArgs e)
395 hist.GraphMin = (int)minGraphBox.Value;
405 private void maxGraphBox_ValueChanged(
object sender, EventArgs e)
409 hist.GraphMax = (int)maxGraphBox.Value;
418 private void binBox_ValueChanged(
object sender, EventArgs e)
422 hist.Bin = (int)binBox.Value;
431 private void ChannelsTool_MouseDown(
object sender, MouseEventArgs e)
435 private bool pressedX1 =
false;
436 private bool pressedX2 =
false;
445 private void ChannelsTool_MouseMove(
object sender, MouseEventArgs e)
447 if (e.Button == MouseButtons.XButton1)
449 if (channelsBox.SelectedIndex < channelsBox.Items.Count - 1)
451 if (pressedX1 ==
false)
453 channelsBox.SelectedIndex++;
460 if (e.Button == MouseButtons.XButton2)
462 if (channelsBox.SelectedIndex > 0)
464 if (pressedX2 ==
false)
466 channelsBox.SelectedIndex--;
483 private void ChannelsTool_MouseWheel(
object sender, MouseEventArgs e)
488 if (maxGraphBox.Value < 255)
492 if (maxGraphBox.Value + i < maxGraphBox.Maximum)
494 maxGraphBox.Value += i;
500 if (maxGraphBox.Value - i > maxGraphBox.Minimum)
502 maxGraphBox.Value -= i;
512 private void stackHistoBox_CheckedChanged(
object sender, EventArgs e)
514 hist.StackHistogram = stackHistoBox.Checked;
523 private void setMinToolStripMenuItem_Click(
object sender, EventArgs e)
525 minBox.Value = (int)hist.MouseValX;
532 private void setMaxToolStripMenuItem_Click(
object sender, EventArgs e)
534 maxBox.Value = (int)hist.MouseValX;
542 private void applyBut_Click(
object sender, EventArgs e)
544 ImageView.SelectedImage.Bake(ImageView.SelectedImage.RChannel.RangeR, ImageView.SelectedImage.GChannel.RangeG, ImageView.SelectedImage.BChannel.RangeB);
552 private void minToolStripMenuItem_Click(
object sender, EventArgs e)
554 minBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMin;
562 private void maxToolStripMenuItem_Click(
object sender, EventArgs e)
564 minBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMax;
572 private void medianToolStripMenuItem_Click(
object sender, EventArgs e)
574 minBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMedian;
582 private void meanToolStripMenuItem_Click(
object sender, EventArgs e)
584 minBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMean;
592 private void toolStripMenuItem1_Click(
object sender, EventArgs e)
594 maxBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMin;
602 private void toolStripMenuItem2_Click(
object sender, EventArgs e)
604 maxBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMax;
611 private void toolStripMenuItem3_Click(
object sender, EventArgs e)
613 maxBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMedian;
620 private void toolStripMenuItem4_Click(
object sender, EventArgs e)
622 maxBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMean;
629 private void updateBut_Click(
object sender, EventArgs e)
631 if (ImageView.SelectedImage.bitsPerPixel > 8)
633 ImageView.SelectedImage.StackThreshold(
true);
634 if (ImageView.SelectedImage.RGBChannelCount == 1)
636 maxBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[0].StackMax;
637 minBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[0].StackMin;
641 maxBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[channelsBox.SelectedIndex].StackMax;
642 minBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[channelsBox.SelectedIndex].StackMin;
647 ImageView.SelectedImage.StackThreshold(
false);
649 App.viewer.UpdateImage();
657 private void sampleBox_ValueChanged(
object sender, EventArgs e)
659 if (initializing ||
Channels.Count == 0)
661 if (channelsBox.SelectedIndex == -1)
662 channelsBox.SelectedIndex = 0;
663 minBox.Value =
Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min;
664 maxBox.Value =
Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Max;
671 App.viewer.UpdateView();
679 private void excBox_ValueChanged(
object sender, EventArgs e)
681 SelectedChannel.Excitation = (int)excBox.Value;
689 private void emisBox_ValueChanged(
object sender, EventArgs e)
691 SelectedChannel.Emission = (int)emisBox.Value;
699 private void fluorBox_TextChanged(
object sender, EventArgs e)
701 SelectedChannel.Fluor = fluorBox.Text;
static List< Channel > Channels