4using System.Collections.Generic;
5using System.ComponentModel;
7using System.Drawing.Imaging;
8using System.Windows.Forms;
11 public partial class ChannelsTool : Form
13 private HistogramControl hist =
null;
14 private bool initializing;
15 private int histogramRequestVersion;
16 private BioLib.BioImage histogramLoadingImage;
17 private Task histogramLoadingTask;
18 private BioLib.BioImage histogramImage;
19 private ZCT histogramCoordinate;
20 private ZCT histogramLoadingCoordinate;
33 if (channelsBox.SelectedIndex != -1)
34 return Channels[channelsBox.SelectedIndex];
40 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
45 return (
int)sampleBox.Value;
49 sampleBox.Value = (decimal)value;
55 int selectedIndex = channelsBox.SelectedIndex;
57 channelsBox.Items.Clear();
60 channelsBox.Items.Add(item);
62 channelsBox.SelectedIndex = Channels.Count == 0
64 : Math.Clamp(selectedIndex, 0,
Channels.Count - 1);
71 InitializeComponent();
74 channelsBox.Items.Add(item);
76 MouseWheel +=
new System.Windows.Forms.MouseEventHandler(ChannelsTool_MouseWheel);
80 channelsBox.Enabled =
false;
81 sampleBox.Enabled =
false;
82 statsPanel.Controls.Add(
new Label
84 Dock = DockStyle.Fill,
85 Text =
"No channel metadata is available for this image.",
86 TextAlign = ContentAlignment.MiddleCenter
92 channelsBox.SelectedIndex = 0;
94 int sample = channel.range?.Length > 0 ? 0 : -1;
95 int defaultMax = channel.BitsPerPixel <= 8 ? byte.MaxValue : ushort.MaxValue;
96 int minimum = sample >= 0 ? channel.range[sample].Min : 0;
97 int maximum = sample >= 0 ? channel.range[sample].Max : defaultMax;
98 if (channel.stats?.Length > 0)
100 minimum = (int)channel.stats[0].StackMin;
101 maximum = (int)channel.stats[0].StackMax;
103 minBox.Value = Math.Clamp(minimum, (
int)minBox.Minimum, (
int)minBox.Maximum);
104 maxBox.Value = Math.Clamp(maximum, (
int)maxBox.Minimum, (
int)maxBox.Maximum);
106 hist.GraphMax = Math.Max(1, (
int)maxBox.Value);
107 maxGraphBox.Value = Math.Clamp(maxBox.Value, maxGraphBox.Minimum, maxGraphBox.Maximum);
108 statsPanel.Controls.Add(hist);
109 initializing =
false;
110 Shown += async (_, _) => await EnsureHistogramAsync();
120 private void minBox_ValueChanged(
object sender, EventArgs e)
122 if (initializing || channelsBox.SelectedIndex == -1)
126 hist.UpdateChannel(
Channels[channelsBox.SelectedIndex]);
128 hist.Min = (int)minBox.Value;
130 App.Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min = (
int)minBox.Value;
131 App.viewer.UpdateImage();
132 App.viewer.UpdateView();
141 private void maxBox_ValueChanged(
object sender, EventArgs e)
143 if (initializing || channelsBox.SelectedIndex == -1)
147 hist.UpdateChannel(
Channels[channelsBox.SelectedIndex]);
149 hist.Max = (int)maxBox.Value;
151 App.Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min = (
int)minBox.Value;
152 App.viewer.UpdateImage();
153 App.viewer.UpdateView();
162 private void channelsBox_SelectedIndexChanged(
object sender, EventArgs e)
164 if (initializing || channelsBox.SelectedIndex == -1)
166 Channel channel =
Channels[channelsBox.SelectedIndex];
167 if (channel.range ==
null || channel.range.Length == 0)
170 sampleBox.Maximum = channel.range.Length - 1;
171 if (minBox.Maximum <
Channels[channelsBox.SelectedIndex].range[(
int)sampleBox.Value].Min || maxBox.Maximum <
Channels[channelsBox.SelectedIndex].range[(
int)sampleBox.Value].Max)
174 maxBox.Value = ushort.MaxValue;
178 minBox.Value =
Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min;
179 maxBox.Value =
Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Max;
190 App.viewer.UpdateView();
198 private void maxUintBox_SelectedIndexChanged(
object sender, EventArgs e)
200 int i =
int.Parse((
string)maxUintBox.SelectedItem,System.Globalization.CultureInfo.InvariantCulture);
201 if(i<=maxBox.Maximum)
210 private void ChannelsTool_FormClosing(
object sender, FormClosingEventArgs e)
220 private void setMaxAllBut_Click(
object sender, EventArgs e)
224 for (
int i = 0; i < c.range.Length; i++)
226 c.range[i].Max = (int)maxBox.Value;
229 App.viewer.UpdateView();
236 private void setMinAllBut_Click(
object sender, EventArgs e)
240 for (
int i = 0; i < c.range.Length; i++)
242 c.range[i].Min = (int)minBox.Value;
245 App.viewer.UpdateView();
253 private void ChannelsTool_Activated(
object sender, EventArgs e)
256 if (
Channels.Count == 0 || channelsBox.SelectedIndex < 0 || hist ==
null)
259 if (channel.range ==
null || channel.range.Length == 0)
262 sampleBox.Maximum = channel.range.Length - 1;
263 sampleBox.Value = Math.Min(sampleBox.Value, sampleBox.Maximum);
264 minBox.Value = Math.Clamp(channel.range[(
int)sampleBox.Value].Min,
265 (
int)minBox.Minimum, (
int)minBox.Maximum);
266 maxBox.Value = Math.Clamp(channel.range[(
int)sampleBox.Value].Max,
267 (
int)maxBox.Minimum, (
int)maxBox.Maximum);
268 initializing =
false;
269 hist.UpdateChannel(channel);
271 _ = EnsureHistogramAsync();
279 private async Task EnsureHistogramAsync()
281 BioImage image = ImageView.SelectedImage;
282 if (IsDisposed || Disposing || image ==
null || hist ==
null || hist.IsDisposed)
285 ZCT coordinate = image.Coordinate;
286 int requestVersion = ++histogramRequestVersion;
287 if (ReferenceEquals(histogramImage, image) && SameCoordinate(histogramCoordinate, coordinate) &&
288 ZarrChannelView.HasHistogramStatistics(image))
290 hist.StatusMessage =
"";
295 hist.StatusMessage =
"Loading histogram…";
299 if (!ReferenceEquals(histogramLoadingImage, image) ||
300 !SameCoordinate(histogramLoadingCoordinate, coordinate) ||
301 histogramLoadingTask ==
null || histogramLoadingTask.IsCompleted)
303 histogramLoadingImage = image;
304 histogramLoadingCoordinate = coordinate;
305 histogramLoadingTask = ZarrChannelView.EnsureHistogramStatisticsAsync(
308 await histogramLoadingTask;
309 if (IsDisposed || Disposing || requestVersion != histogramRequestVersion || image != ImageView.SelectedImage)
311 histogramImage = image;
312 histogramCoordinate = coordinate;
313 hist.StatusMessage = ZarrChannelView.HasHistogramStatistics(image)
315 :
"Histogram data is unavailable for this image.";
322 if (requestVersion != histogramRequestVersion)
324 hist.StatusMessage = $
"Could not load histogram: {ex.Message}";
332 _ = EnsureHistogramAsync();
335 private void ApplyFrameRange()
341 int sample = Math.Clamp((
int)sampleBox.Value, 0,
SelectedChannel.stats.Length - 1);
343 int minimum = Math.Clamp((
int)statistics.StackMin, (
int)minBox.Minimum, (
int)minBox.Maximum);
344 int maximum = Math.Clamp((
int)statistics.StackMax, minimum, (
int)maxBox.Maximum);
345 int graphMaximum = Math.Max(1, maximum);
346 int graphMinimum = Math.Min(minimum, graphMaximum);
347 int histogramBin = Math.Max(1, (graphMaximum - graphMinimum + 255) / 256);
350 minBox.Value = minimum;
351 maxBox.Value = maximum;
352 minGraphBox.Value = Math.Clamp(graphMinimum,
353 (
int)minGraphBox.Minimum, (
int)minGraphBox.Maximum);
354 maxGraphBox.Value = Math.Clamp(graphMaximum,
355 (
int)maxGraphBox.Minimum, (
int)maxGraphBox.Maximum);
356 binBox.Value = Math.Clamp(histogramBin, (
int)binBox.Minimum, (
int)binBox.Maximum);
357 initializing =
false;
359 hist.GraphMin = graphMinimum;
360 hist.GraphMax = graphMaximum;
361 hist.Bin = histogramBin;
364 private static bool SameCoordinate(
ZCT left,
ZCT right) =>
365 left.Z == right.Z && left.C == right.C && left.T == right.T;
367 private void ChannelsTool_ResizeEnd(
object sender, EventArgs e)
377 private void maxUintBox2_SelectedIndexChanged(
object sender, EventArgs e)
379 int i =
int.Parse((
string)maxUintBox2.SelectedItem, System.Globalization.CultureInfo.InvariantCulture);
380 if(i <= maxGraphBox.Maximum)
381 maxGraphBox.Value = i;
384 maxGraphBox.Value = 255;
394 private void minGraphBox_ValueChanged(
object sender, EventArgs e)
398 hist.GraphMin = (int)minGraphBox.Value;
408 private void maxGraphBox_ValueChanged(
object sender, EventArgs e)
412 hist.GraphMax = (int)maxGraphBox.Value;
421 private void binBox_ValueChanged(
object sender, EventArgs e)
425 hist.Bin = (int)binBox.Value;
434 private void ChannelsTool_MouseDown(
object sender, MouseEventArgs e)
438 private bool pressedX1 =
false;
439 private bool pressedX2 =
false;
449 private void ChannelsTool_MouseMove(
object sender, MouseEventArgs e)
451 if (e.Button == MouseButtons.XButton1)
453 if (channelsBox.SelectedIndex < channelsBox.Items.Count-1)
455 if (pressedX1 ==
false)
457 channelsBox.SelectedIndex++;
464 if (e.Button == MouseButtons.XButton2)
466 if (channelsBox.SelectedIndex > 0)
468 if (pressedX2 ==
false)
470 channelsBox.SelectedIndex--;
487 private void ChannelsTool_MouseWheel(
object sender, MouseEventArgs e)
492 if (maxGraphBox.Value < 255)
496 if (maxGraphBox.Value + i < maxGraphBox.Maximum)
498 maxGraphBox.Value += i;
504 if (maxGraphBox.Value - i > maxGraphBox.Minimum)
506 maxGraphBox.Value -= i;
516 private void stackHistoBox_CheckedChanged(
object sender, EventArgs e)
518 hist.StackHistogram = stackHistoBox.Checked;
527 private void setMinToolStripMenuItem_Click(
object sender, EventArgs e)
529 minBox.Value = (int)hist.MouseValX;
537 private void setMaxToolStripMenuItem_Click(
object sender, EventArgs e)
539 maxBox.Value = (int)hist.MouseValX;
547 private void applyBut_Click(
object sender, EventArgs e)
549 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;
557 private void maxToolStripMenuItem_Click(
object sender, EventArgs e)
559 minBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMax;
562 private void medianToolStripMenuItem_Click(
object sender, EventArgs e)
564 minBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMedian;
567 private void meanToolStripMenuItem_Click(
object sender, EventArgs e)
569 minBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMean;
572 private void toolStripMenuItem1_Click(
object sender, EventArgs e)
574 maxBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMin;
577 private void toolStripMenuItem2_Click(
object sender, EventArgs e)
579 maxBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMax;
581 private void toolStripMenuItem3_Click(
object sender, EventArgs e)
583 maxBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMedian;
585 private void toolStripMenuItem4_Click(
object sender, EventArgs e)
587 maxBox.Value = (decimal)
SelectedChannel.stats[channelsBox.SelectedIndex].StackMean;
594 private void updateBut_Click(
object sender, EventArgs e)
596 if (ImageView.SelectedImage.bitsPerPixel > 8)
598 ImageView.SelectedImage.StackThreshold(
true);
599 if (ImageView.SelectedImage.RGBChannelCount == 1)
601 maxBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[0].StackMax;
602 minBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[0].StackMin;
606 maxBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[channelsBox.SelectedIndex].StackMax;
607 minBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[channelsBox.SelectedIndex].StackMin;
612 ImageView.SelectedImage.StackThreshold(
false);
614 App.viewer.UpdateImage();
622 private void sampleBox_ValueChanged(
object sender, EventArgs e)
624 if (initializing || channelsBox.SelectedIndex == -1)
625 channelsBox.SelectedIndex = 0;
626 minBox.Value =
Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min;
627 maxBox.Value =
Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Max;
634 App.viewer.UpdateView();
637 private void excBox_ValueChanged(
object sender, EventArgs e)
639 SelectedChannel.Excitation = (int)excBox.Value;
642 private void emisBox_ValueChanged(
object sender, EventArgs e)
644 SelectedChannel.Emission = (int)emisBox.Value;
647 private void fluorBox_TextChanged(
object sender, EventArgs e)
649 SelectedChannel.Fluor = fluorBox.Text;
static List< Channel > Channels