BioGTK  6.5.0
A .NET library & program for annotating, editing various microscopy imaging formats using Bioformats supported images. Including whole slide, pyramidal, and series.
Loading...
Searching...
No Matches
BioGTK.Tools Class Reference

Implementations for all tool types defined in Tools.cs. More...

Inheritance diagram for BioGTK.Tools:

Classes

class  Tool
 

Public Member Functions

void ToolDown (PointD e, ButtonPressEventArgs buts)
 
void ToolUp (PointD e, ButtonReleaseEventArgs buts)
 
void ToolMove (PointD e, MotionNotifyEventArgs buts)
 
void ToolDown_Move (PointD e, ButtonPressEventArgs buts)
 
void ToolMove_Move (PointD e, MotionNotifyEventArgs buts)
 
void ToolUp_Move (PointD e, ButtonReleaseEventArgs buts)
 
void ToolDown_Point (PointD e, ButtonPressEventArgs buts)
 
void ToolDown_Line (PointD e, ButtonPressEventArgs buts)
 
void ToolMove_Line (PointD e, MotionNotifyEventArgs buts)
 
void ToolUp_Line (PointD e, ButtonReleaseEventArgs buts)
 
void ToolDown_Rectangle (PointD e, ButtonPressEventArgs buts)
 
void ToolMove_Rectangle (PointD e, MotionNotifyEventArgs buts)
 
void ToolUp_Rectangle (PointD e, ButtonReleaseEventArgs buts)
 
void ToolDown_Ellipse (PointD e, ButtonPressEventArgs buts)
 
void ToolMove_Ellipse (PointD e, MotionNotifyEventArgs buts)
 
void ToolUp_Ellipse (PointD e, ButtonReleaseEventArgs buts)
 
void ToolDown_Polygon (PointD e, ButtonPressEventArgs buts)
 
void ToolDown_Freeform (PointD e, ButtonPressEventArgs buts)
 
void ToolMove_Freeform (PointD e, MotionNotifyEventArgs buts)
 
void ToolUp_Freeform (PointD e, ButtonReleaseEventArgs buts)
 
void ToolDown_Text (PointD e, ButtonPressEventArgs buts)
 
void ToolDown_Delete (PointD e, ButtonPressEventArgs buts)
 
void ToolDown_Brush (PointD e, ButtonPressEventArgs buts)
 
void ToolMove_Brush (PointD e, MotionNotifyEventArgs buts)
 
void ToolDown_Eraser (PointD e, ButtonPressEventArgs buts)
 
void ToolMove_Eraser (PointD e, MotionNotifyEventArgs buts)
 
void ToolUp_Bucket (PointD e, ButtonReleaseEventArgs buts)
 
void ToolUp_Dropper (PointD e, ButtonReleaseEventArgs buts)
 
void ToolDown_Pan (PointD e, ButtonPressEventArgs buts)
 
void ToolMove_Pan (PointD e, MotionNotifyEventArgs buts)
 
void ToolUp_Pan (PointD e, ButtonReleaseEventArgs buts)
 
void ToolDown_Magic (PointD e, ButtonPressEventArgs buts)
 
void ToolMove_Magic (PointD e, MotionNotifyEventArgs buts)
 
void ToolUp_Magic (PointD e, ButtonReleaseEventArgs buts)
 

Static Public Member Functions

static Tools Create ()
 
static bool HitTestMask (ROI ann, PointD worldPoint)
 
static Tool GetTool (string name)
 
static Tool GetTool (Tool.Type t)
 
static int CalculateThreshold (int index, Statistics stat)
 Helper method to calculate threshold for magic select.
 

Static Public Attributes

static bool applyToStack = false
 
static ColorTool colorTool
 
static bool rEnabled = true
 
static bool gEnabled = true
 
static bool bEnabled = true
 
static ColorS drawColor = new ColorS(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)
 
static ColorS eraseColor = new ColorS(0, 0, 0)
 
static ColorS tolerance = new ColorS(0, 0, 0)
 
static Rectangle selectionRectangle
 
static Dictionary< string, Tooltools = new Dictionary<string, Tool>()
 
static bool colorOne = true
 
static double PanSpeed = 0.75
 
static Tool currentTool
 
static RectangleD selectionRect
 
static TextInput ti = null
 

Protected Member Functions

 Tools (Builder builder, IntPtr handle)
 
void SetupHandlers ()
 Sets up the handlers.
 

Properties

static ROI selectedROI [get, set]
 
static List< ROI > selectedROIs [get, set]
 
static ColorS DrawColor [get, set]
 
static ColorS EraseColor [get, set]
 
static int StrokeWidth [get, set]
 
bool IsPanning [get, set]
 

Detailed Description

Implementations for all tool types defined in Tools.cs.

Definition at line 22 of file Tools.cs.

Constructor & Destructor Documentation

◆ Tools()

BioGTK.Tools.Tools ( Builder builder,
IntPtr handle )
protected

Definition at line 42 of file Tools.cs.

42 : base(handle)
43 {
44 selectColor = AForge.Color.FromArgb(0, 0, 150, 255);
45 AForge.Color white = AForge.Color.FromArgb(255, 255, 255, 255);
46 _builder = builder;
47 builder.Autoconnect(this);
49 Tool.Init();
50 ColorS col = new ColorS(ushort.MaxValue);
51 //We initialize the tools
52 currentTool = GetTool(Tool.Type.move.ToString());
53 floodFiller = new QueueLinearFloodFiller(floodFiller);
54 magicSelect = MagicSelect.Create(0);
55 App.ApplyStyles(this);
56 }
static MagicSelect Create(int index)
static Tool GetTool(string name)
Definition Tools.cs:1809
void SetupHandlers()
Sets up the handlers.
Definition Tools.cs:143

Member Function Documentation

◆ CalculateThreshold()

static int BioGTK.Tools.CalculateThreshold ( int index,
Statistics stat )
static

Helper method to calculate threshold for magic select.

Definition at line 1826 of file Tools.cs.

1827 {
1828 return index switch
1829 {
1830 2 => (int)(stat.Min + stat.Mean),
1831 1 => (int)stat.Median,
1832 _ => (int)stat.Min
1833 };
1834 }

◆ Create()

static Tools BioGTK.Tools.Create ( )
static

It creates a new instance of the Tools class, which is a class that inherits from the Gtk.Window class

Returns
A new instance of the Tools class.

Definition at line 36 of file Tools.cs.

37 {
38 Builder builder = new Builder(new FileStream(System.IO.Path.GetDirectoryName(Environment.ProcessPath) + "/" + "Glade/Tools.glade", FileMode.Open));
39 return new Tools(builder, builder.GetObject("tools").Handle);
40 }

◆ GetTool() [1/2]

static Tool BioGTK.Tools.GetTool ( string name)
static

If the tools dictionary contains the name of the tool, return the tool, otherwise return the move tool

Parameters
nameThe name of the tool to get.
Returns
The tool that is being returned is the tool that is being used.

Definition at line 1809 of file Tools.cs.

1810 {
1811 if (tools.Count == 0)
1812 return null;
1813 if (tools.ContainsKey(name))
1814 return (Tool)tools[name];
1815 else return tools[Tool.Type.move.ToString()];
1816 }

◆ GetTool() [2/2]

static Tool BioGTK.Tools.GetTool ( Tool.Type t)
static

Definition at line 1817 of file Tools.cs.

1818 {
1819 if (tools.ContainsKey(t.ToString()))
1820 return (Tool)tools[t.ToString()];
1821 else return tools.FirstOrDefault().Value;
1822 }

◆ HitTestMask()

static bool BioGTK.Tools.HitTestMask ( ROI ann,
PointD worldPoint )
static

Definition at line 109 of file Tools.cs.

110 {
111 if (ann == null || ann.type != ROI.Type.Mask || ann.roiMask == null)
112 return false;
113
114 double x = ann.X;
115 double y = ann.Y;
116 double w = ann.W;
117 double h = ann.H;
118 if (worldPoint.X < x || worldPoint.Y < y ||
119 worldPoint.X > x + w || worldPoint.Y > y + h)
120 return false;
121
122 if (ann.roiMask.PhysicalSizeX == 0 || ann.roiMask.PhysicalSizeY == 0)
123 return false;
124
125 int mx = (int)Math.Floor((worldPoint.X - x) / ann.roiMask.PhysicalSizeX);
126 int my = (int)Math.Floor((worldPoint.Y - y) / ann.roiMask.PhysicalSizeY);
127 if (mx < 0 || my < 0 || mx >= ann.roiMask.Width || my >= ann.roiMask.Height)
128 return false;
129
130 return ann.roiMask.IsSelected(mx, my);
131 }

◆ SetupHandlers()

void BioGTK.Tools.SetupHandlers ( )
protected

Sets up the handlers.

It sets up the handlers for the buttons

Definition at line 143 of file Tools.cs.

144 {
145 this.ButtonPressEvent += Tools_ButtonPressEvent;
146 ti = TextInput.Create();
147 view.Drawn += View_Drawn;
148 view.DeleteEvent += View_DeleteEvent;
149 }
static TextInput Create(bool ROItype=true)
Definition TextInput.cs:36

◆ ToolDown()

void BioGTK.Tools.ToolDown ( PointD e,
ButtonPressEventArgs buts )

Definition at line 332 of file Tools.cs.

333 {
334 if (App.viewer == null || currentTool == null || ImageView.SelectedImage == null)
335 return;
336
337 Plugins.MouseDown(ImageView.SelectedImage, e, buts);
338 Scripting.UpdateState(Scripting.State.GetDown(e, buts.Event.Button));
339
340 switch (currentTool.type)
341 {
342 case Tool.Type.pan:
343 ToolDown_Pan(e, buts);
344 break;
345 case Tool.Type.magic:
346 ToolDown_Magic(e, buts);
347 break;
348 case Tool.Type.point:
349 ToolDown_Point(e, buts);
350 break;
351 case Tool.Type.move:
352 ToolDown_Move(e, buts);
353 break;
354 case Tool.Type.line:
355 ToolDown_Line(e, buts);
356 break;
357 case Tool.Type.rect:
358 ToolDown_Rectangle(e, buts);
359 break;
360 case Tool.Type.ellipse:
361 ToolDown_Ellipse(e, buts);
362 break;
363 case Tool.Type.polygon:
364 ToolDown_Polygon(e, buts);
365 break;
366 case Tool.Type.text:
367 ToolDown_Text(e, buts);
368 break;
369 case Tool.Type.delete:
370 ToolDown_Delete(e, buts);
371 break;
372 case Tool.Type.freeform:
373 ToolDown_Freeform(e, buts);
374 break;
375 default:
376 break;
377 }
378 }

◆ ToolDown_Brush()

void BioGTK.Tools.ToolDown_Brush ( PointD e,
ButtonPressEventArgs buts )

Definition at line 1229 of file Tools.cs.

1230 {
1231 if (currentTool.type != Tool.Type.brush || buts.Event.Button != 1)
1232 return;
1233
1234 PointD ip = ImageView.SelectedImage.ToImageSpace(e);
1235 if (ImageView.SelectedImage.isPyramidal)
1236 ip = new PointD(e.X, e.Y);
1237
1238 Bio.Graphics.Graphics g = Bio.Graphics.Graphics.FromImage(ImageView.SelectedBuffer);
1239 g.pen = new Bio.Graphics.Pen(DrawColor, (int)StrokeWidth, ImageView.SelectedImage.bitsPerPixel);
1240 g.FillEllipse(new Rectangle((int)ip.X, (int)ip.Y, (int)StrokeWidth, (int)StrokeWidth), g.pen.color);
1241
1242 App.viewer.UpdateImage();
1243 App.viewer.UpdateView();
1244 }

◆ ToolDown_Delete()

void BioGTK.Tools.ToolDown_Delete ( PointD e,
ButtonPressEventArgs buts )

Definition at line 1181 of file Tools.cs.

1182 {
1183 if (currentTool.type != Tool.Type.delete || buts.Event.Button != 1)
1184 return;
1185
1186 for (int i = ImageView.SelectedImage.Annotations.Count - 1; i >= 0; i--)
1187 {
1188 ROI an = ImageView.SelectedImage.Annotations[i];
1189 if (an == null) continue;
1190
1191 if (an.BoundingBox.IntersectsWith(new RectangleD(e.X, e.Y, 1, 1)))
1192 {
1193 if (an.selectedPoints == null || an.selectedPoints.Count == 0)
1194 {
1195 // Delete entire ROI
1196 ImageView.SelectedImage.Annotations.RemoveAt(i);
1197 break;
1198 }
1199 else if (an.selectedPoints.Count == 1 &&
1200 !(an.type == ROI.Type.Polygon ||
1201 an.type == ROI.Type.Polyline ||
1202 an.type == ROI.Type.Freeform))
1203 {
1204 // Delete ROI with single selected point (for non multi-point types)
1205 ImageView.SelectedImage.Annotations.RemoveAt(i);
1206 break;
1207 }
1208 else
1209 {
1210 // Delete selected points from polygon/polyline/freeform
1211 if (an.type == ROI.Type.Polygon ||
1212 an.type == ROI.Type.Polyline ||
1213 an.type == ROI.Type.Freeform)
1214 {
1215 an.closed = false;
1216 an.RemovePoints(an.selectedPoints.ToArray());
1217 an.UpdateBoundingBox();
1218 break;
1219 }
1220 }
1221 }
1222 }
1223 UpdateView();
1224 }

◆ ToolDown_Ellipse()

void BioGTK.Tools.ToolDown_Ellipse ( PointD e,
ButtonPressEventArgs buts )

Definition at line 964 of file Tools.cs.

965 {
966 if (currentTool.type != Tool.Type.ellipse || buts.Event.Button != 1)
967 return;
968
969 selectedROI = new ROI();
970 selectedROI.type = ROI.Type.Ellipse;
971 selectedROI.BoundingBox = new RectangleD(e.X, e.Y, 0, 0); // Start with 0 size
972 selectedROI.coord = App.viewer.GetCoordinate();
973 selectedROI.serie = ImageView.SelectedImage.isPyramidal ? App.viewer.Level : ImageView.SelectedImage.series;
974 AddROI(selectedROI);
975 }

◆ ToolDown_Eraser()

void BioGTK.Tools.ToolDown_Eraser ( PointD e,
ButtonPressEventArgs buts )

Definition at line 1267 of file Tools.cs.

1268 {
1269 if (currentTool.type != Tool.Type.eraser || buts.Event.Button != 1)
1270 return;
1271
1272 PointD ip = ImageView.SelectedImage.ToImageSpace(e);
1273 if (ImageView.SelectedImage.isPyramidal)
1274 ip = new PointD(e.X, e.Y);
1275
1276 Bio.Graphics.Graphics g = Bio.Graphics.Graphics.FromImage(ImageView.SelectedBuffer);
1277 Bio.Graphics.Pen pen = new Bio.Graphics.Pen(EraseColor, (int)StrokeWidth, ImageView.SelectedBuffer.BitsPerPixel);
1278 g.FillEllipse(new Rectangle((int)ip.X, (int)ip.Y, (int)StrokeWidth, (int)StrokeWidth), pen.color);
1279
1280 App.viewer.UpdateImages();
1281 App.viewer.UpdateView();
1282 }

◆ ToolDown_Freeform()

void BioGTK.Tools.ToolDown_Freeform ( PointD e,
ButtonPressEventArgs buts )

Definition at line 1083 of file Tools.cs.

1084 {
1085 if (currentTool.type != Tool.Type.freeform || buts.Event.Button != 1)
1086 return;
1087
1088 if (selectedROI == null || selectedROI.type != ROI.Type.Polygon)
1089 {
1090 // Start new freeform
1091 selectedROI = new ROI();
1092 selectedROI.type = ROI.Type.Polygon;
1093 selectedROI.closed = false;
1094 selectedROI.AddPoint(new PointD(e.X, e.Y));
1095 selectedROI.coord = App.viewer.GetCoordinate();
1096 selectedROI.serie = ImageView.SelectedImage.isPyramidal ? App.viewer.Level : ImageView.SelectedImage.series;
1097 AddROI(selectedROI);
1098 UpdateView();
1099 }
1100 else if (!selectedROI.closed)
1101 {
1102 // Check if clicking near first point to close freeform
1103 if (selectedROI.Points.Count >= 3)
1104 {
1105 PointD firstPoint = selectedROI.Points[0];
1106 double distance = Math.Sqrt(Math.Pow(e.X - firstPoint.X, 2) + Math.Pow(e.Y - firstPoint.Y, 2));
1107 double threshold = 10.0; // Adjust based on your zoom/scale
1108
1109 if (distance < threshold)
1110 {
1111 // Close freeform
1112 selectedROI.closed = true;
1113 selectedROI.Selected = false;
1114 selectedROI.UpdateBoundingBox();
1115 selectedROI.Validate();
1116 selectedROI = null;
1117 UpdateView();
1118 return;
1119 }
1120 }
1121
1122
1123 }
1124 // Add new point to polygon
1125 selectedROI.AddPoint(new PointD(e.X, e.Y));
1126 selectedROI.UpdateBoundingBox();
1127 UpdateView();
1128 }

◆ ToolDown_Line()

void BioGTK.Tools.ToolDown_Line ( PointD e,
ButtonPressEventArgs buts )

Definition at line 862 of file Tools.cs.

863 {
864 if (currentTool.type != Tool.Type.line || buts.Event.Button != 1)
865 return;
866
867 selectedROI = new ROI();
868 selectedROI.type = ROI.Type.Line;
869 selectedROI.AddPoint(new PointD(e.X, e.Y));
870 selectedROI.AddPoint(new PointD(e.X + ImageView.SelectedImage.PhysicalSizeX * ROI.selectBoxSize,
871 e.Y + ImageView.SelectedImage.PhysicalSizeX * ROI.selectBoxSize));
872 selectedROI.coord = App.viewer.GetCoordinate();
873 selectedROI.serie = ImageView.SelectedImage.isPyramidal ? App.viewer.Level : ImageView.SelectedImage.series;
874 AddROI(selectedROI);
875 }

◆ ToolDown_Magic()

void BioGTK.Tools.ToolDown_Magic ( PointD e,
ButtonPressEventArgs buts )

Definition at line 1532 of file Tools.cs.

1533 {
1534 if (selectedROI == null)
1535 {
1536 selectedROI = new ROI();
1537 selectedROI.type = ROI.Type.Freeform;
1538 selectedROI.AddPoint(new PointD(e.X, e.Y));
1539 selectedROI.coord = App.viewer.GetCoordinate();
1540 if (ImageView.SelectedImage.isPyramidal)
1541 selectedROI.serie = App.viewer.Level;
1542 else
1543 selectedROI.serie = ImageView.SelectedImage.series;
1544 AddROI(selectedROI);
1545 }
1546 else
1547 {
1548 selectedROI.AddPoint(new PointD(e.X, e.Y));
1549 }
1550 }

◆ ToolDown_Move()

void BioGTK.Tools.ToolDown_Move ( PointD e,
ButtonPressEventArgs buts )

Definition at line 495 of file Tools.cs.

496 {
497 if (currentTool.type != Tool.Type.move || buts.Event.Button != 1)
498 return;
499
500 App.viewer.MouseDown = e;
501 bool ctrl = buts.Event.State.HasFlag(ModifierType.ControlMask);
502 var selectableRois = GetSelectableRois(ImageView.SelectedImage).ToList();
503 var selectedRois = selectableRois.Where(r => r != null && r.Selected).Reverse().ToList();
504 var unselectedRois = selectableRois.Where(r => r != null && !r.Selected).Reverse().ToList();
505
506 selectedROI = null;
507
508 // 1 — Vertex hit test on selected ROIs
509 foreach (var ann in selectedRois)
510 {
511 if (ann.type == ROI.Type.Mask)
512 continue;
513
514 var boxes = ann.GetSelectBoxes(ROI.selectBoxSize * ImageView.SelectedImage.PhysicalSizeX);
515 if (boxes == null) continue;
516
517 for (int i = 0; i < boxes.Length; i++)
518 {
519 if (boxes[i].Contains(ann.coord, e))
520 {
521 selectedROI = ann;
522 if (ctrl)
523 {
524 if (ann.selectedPoints.Contains(i)) ann.selectedPoints.Remove(i);
525 else ann.selectedPoints.Add(i);
526 }
527 else
528 {
529 ann.selectedPoints.Clear();
530 ann.selectedPoints.Add(i);
531 }
532 UpdateView();
533 return;
534 }
535 }
536 }
537
538 // 2 — Click on body of already-selected ROI
539 foreach (var ann in selectedRois)
540 {
541 if (ann == null)
542 continue;
543
544 if (ann.type == ROI.Type.Mask)
545 {
546 if (HitTestMask(ann, e))
547 {
548 selectedROI = ann;
549 UpdateView();
550 return;
551 }
552 continue;
553 }
554
555 if (ann.BoundingBox.Contains(ann.coord, e))
556 {
557 selectedROI = ann;
558 UpdateView();
559 return;
560 }
561 }
562
563 // 3 — Click on any ROI (select it)
564 foreach (var ann in selectedRois.Concat(unselectedRois))
565 {
566 if (ann == null)
567 continue;
568
569 bool hit = ann.type == ROI.Type.Mask ? HitTestMask(ann, e) : ann.BoundingBox.Contains(ann.coord, e);
570 if (hit)
571 {
572 if (!ctrl)
573 {
574 foreach (var other in selectableRois)
575 {
576 if (other != ann)
577 {
578 other.Selected = false;
579 other.selectedPoints?.Clear();
580 }
581 }
582 }
583
584 ann.Selected = true;
585 ann.selectedPoints?.Clear();
586 selectedROI = ann;
587 UpdateView();
588 return;
589 }
590 }
591
592 // 4 — Start selection rectangle
593 if (!ctrl)
594 {
595 foreach (var ann in selectableRois)
596 {
597 if (ann != null)
598 {
599 ann.Selected = false;
600 ann.selectedPoints?.Clear();
601 }
602 }
603 selectedROI = null;
604 }
605
606 Tools.GetTool(Tools.Tool.Type.move).Rectangle = new RectangleD(e.X, e.Y, 0, 0);
607 UpdateView();
608 }

◆ ToolDown_Pan()

void BioGTK.Tools.ToolDown_Pan ( PointD e,
ButtonPressEventArgs buts )

Definition at line 1373 of file Tools.cs.

1374 {
1375 if (buts.Event.Button != 1 && buts.Event.Button != 2)
1376 return;
1377
1378 currentTool = GetTool(Tool.Type.pan);
1379 panStartX = buts.Event.X;
1380 panStartY = buts.Event.Y;
1381 initialPanScale = ImageView.SelectedImage.isPyramidal
1382 ? App.viewer.Resolution
1383 : App.viewer.Scale.Width;
1384
1385 if (ImageView.SelectedImage.isPyramidal)
1386 {
1387 initialPanOrigin = new PointD(
1388 App.viewer.PyramidalOrigin.X,
1389 App.viewer.PyramidalOrigin.Y);
1390 }
1391 else
1392 {
1393 initialPanOrigin = new PointD(
1394 App.viewer.Origin.X,
1395 App.viewer.Origin.Y);
1396 }
1397 }

◆ ToolDown_Point()

void BioGTK.Tools.ToolDown_Point ( PointD e,
ButtonPressEventArgs buts )

Definition at line 842 of file Tools.cs.

843 {
844 if (currentTool.type != Tool.Type.point || buts.Event.Button != 1)
845 return;
846
847 ROI an = new ROI();
848 an.type = ROI.Type.Point;
849 an.Points.Clear();
850 an.Points.Add(new PointD(e.X, e.Y));
851 an.coord = App.viewer.GetCoordinate();
852 an.serie = ImageView.SelectedImage.isPyramidal ? App.viewer.Level : ImageView.SelectedImage.series;
853 an.Selected = true;
854 selectedROI = an;
855 AddROI(selectedROI);
856 UpdateView();
857 }

◆ ToolDown_Polygon()

void BioGTK.Tools.ToolDown_Polygon ( PointD e,
ButtonPressEventArgs buts )

Definition at line 1014 of file Tools.cs.

1015 {
1016 if (currentTool.type != Tool.Type.polygon || buts.Event.Button != 1)
1017 return;
1018
1019 if (selectedROI == null || selectedROI.type != ROI.Type.Polygon)
1020 {
1021 // Start new polygon
1022 selectedROI = new ROI();
1023 selectedROI.type = ROI.Type.Polygon;
1024 selectedROI.closed = false;
1025 selectedROI.AddPoint(new PointD(e.X, e.Y));
1026 selectedROI.coord = App.viewer.GetCoordinate();
1027 selectedROI.serie = ImageView.SelectedImage.isPyramidal ? App.viewer.Level : ImageView.SelectedImage.series;
1028 AddROI(selectedROI);
1029 UpdateView();
1030 }
1031 else if (!selectedROI.closed)
1032 {
1033 // Check if clicking near first point to close polygon
1034 if (selectedROI.Points.Count >= 3)
1035 {
1036 PointD firstPoint = selectedROI.Points[0];
1037 double distance = Math.Sqrt(Math.Pow(e.X - firstPoint.X, 2) + Math.Pow(e.Y - firstPoint.Y, 2));
1038 double threshold = 10.0; // Adjust based on your zoom/scale
1039
1040 if (distance < threshold)
1041 {
1042 // Close polygon
1043 selectedROI.closed = true;
1044 selectedROI.Selected = false;
1045 selectedROI.UpdateBoundingBox();
1046 selectedROI.Validate();
1047 selectedROI = null;
1048 UpdateView();
1049 return;
1050 }
1051 }
1052
1053
1054 }
1055 // Add new point to polygon
1056 selectedROI.AddPoint(new PointD(e.X, e.Y));
1057 selectedROI.UpdateBoundingBox();
1058 UpdateView();
1059 }

◆ ToolDown_Rectangle()

void BioGTK.Tools.ToolDown_Rectangle ( PointD e,
ButtonPressEventArgs buts )

Definition at line 914 of file Tools.cs.

915 {
916 if (currentTool.type != Tool.Type.rect || buts.Event.Button != 1)
917 return;
918
919 selectedROI = new ROI();
920 selectedROI.type = ROI.Type.Rectangle;
921 selectedROI.BoundingBox = new RectangleD(e.X, e.Y, 0, 0); // Start with 0 size
922 selectedROI.coord = App.viewer.GetCoordinate();
923 selectedROI.serie = ImageView.SelectedImage.isPyramidal ? App.viewer.Level : ImageView.SelectedImage.series;
924 AddROI(selectedROI);
925 }

◆ ToolDown_Text()

void BioGTK.Tools.ToolDown_Text ( PointD e,
ButtonPressEventArgs buts )

Definition at line 1157 of file Tools.cs.

1158 {
1159 if (currentTool.type != Tool.Type.text || buts.Event.Button != 1)
1160 return;
1161
1162 selectedROI = new ROI();
1163 selectedROI.type = ROI.Type.Label;
1164 selectedROI.AddPoint(new PointD(e.X, e.Y));
1165 selectedROI.coord = App.viewer.GetCoordinate();
1166 selectedROI.serie = ImageView.SelectedImage.isPyramidal ? App.viewer.Level : ImageView.SelectedImage.series;
1167
1168 // Show text input dialog
1169 ti = TextInput.Create();
1170 ti.ShowAll();
1171 ti.Run();
1172
1173 AddROI(selectedROI);
1174 selectedROI.UpdateBoundingBox();
1175 UpdateView();
1176 }

◆ ToolMove()

void BioGTK.Tools.ToolMove ( PointD e,
MotionNotifyEventArgs buts )

Definition at line 431 of file Tools.cs.

432 {
433 if (App.viewer == null)
434 return;
435
436 Plugins.MouseMove(ImageView.SelectedImage, e, buts);
437
438 // Update scripting state using available button masks
439 if (buts.Event.State.HasFlag(ModifierType.Button1Mask))
440 Scripting.UpdateState(Scripting.State.GetMove(e, 1));
441 else if (buts.Event.State.HasFlag(ModifierType.Button2Mask))
442 Scripting.UpdateState(Scripting.State.GetMove(e, 2));
443 else if (buts.Event.State.HasFlag(ModifierType.Button3Mask))
444 Scripting.UpdateState(Scripting.State.GetMove(e, 3));
445 else if (buts.Event.State.HasFlag(ModifierType.Button4Mask))
446 Scripting.UpdateState(Scripting.State.GetMove(e, 4));
447 else if (buts.Event.State.HasFlag(ModifierType.Button5Mask))
448 Scripting.UpdateState(Scripting.State.GetMove(e, 5));
449 else
450 Scripting.UpdateState(Scripting.State.GetMove(e, 0));
451
452 switch (currentTool.type)
453 {
454 case Tool.Type.pan:
455 ToolMove_Pan(e, buts);
456 break;
457 case Tool.Type.move:
458 ToolMove_Move(e, buts);
459 break;
460 case Tool.Type.magic:
461 ToolMove_Magic(e, buts);
462 break;
463 case Tool.Type.line:
464 ToolMove_Line(e, buts);
465 break;
466 case Tool.Type.rect:
467 ToolMove_Rectangle(e, buts);
468 break;
469 case Tool.Type.ellipse:
470 ToolMove_Ellipse(e, buts);
471 break;
472 case Tool.Type.polygon:
473 ToolMove_Polygon(e, buts);
474 break;
475 case Tool.Type.text:
476 //ToolMove_Text(e, buts);
477 break;
478 case Tool.Type.freeform:
479 ToolMove_Freeform(e, buts);
480 break;
481 case Tool.Type.brush:
482 ToolMove_Brush(e, buts);
483 break;
484 case Tool.Type.eraser:
485 ToolMove_Eraser(e, buts);
486 break;
487 default:
488 break;
489 }
490 }

◆ ToolMove_Brush()

void BioGTK.Tools.ToolMove_Brush ( PointD e,
MotionNotifyEventArgs buts )

Definition at line 1246 of file Tools.cs.

1247 {
1248 if (currentTool.type != Tool.Type.brush ||
1249 !buts.Event.State.HasFlag(ModifierType.Button1Mask))
1250 return;
1251
1252 PointD ip = ImageView.SelectedImage.ToImageSpace(e);
1253 if (ImageView.SelectedImage.isPyramidal)
1254 ip = new PointD(e.X, e.Y);
1255
1256 Bio.Graphics.Graphics g = Bio.Graphics.Graphics.FromImage(ImageView.SelectedBuffer);
1257 g.pen = new Bio.Graphics.Pen(DrawColor, (int)StrokeWidth, ImageView.SelectedImage.bitsPerPixel);
1258 g.FillEllipse(new Rectangle((int)ip.X, (int)ip.Y, (int)StrokeWidth, (int)StrokeWidth), g.pen.color);
1259
1260 App.viewer.UpdateImages();
1261 App.viewer.UpdateView();
1262 }

◆ ToolMove_Ellipse()

void BioGTK.Tools.ToolMove_Ellipse ( PointD e,
MotionNotifyEventArgs buts )

Definition at line 977 of file Tools.cs.

978 {
979 if (currentTool.type != Tool.Type.ellipse ||
980 !buts.Event.State.HasFlag(ModifierType.Button1Mask))
981 return;
982
983 if (selectedROI != null && selectedROI.type == ROI.Type.Ellipse)
984 {
985 selectedROI.BoundingBox = RectangleDExtensions.FromCorners(
986 new PointD(selectedROI.BoundingBox.X, selectedROI.BoundingBox.Y),
987 new PointD(e.X, e.Y));
988 UpdateView();
989 }
990 }

◆ ToolMove_Eraser()

void BioGTK.Tools.ToolMove_Eraser ( PointD e,
MotionNotifyEventArgs buts )

Definition at line 1284 of file Tools.cs.

1285 {
1286 if (currentTool.type != Tool.Type.eraser ||
1287 !buts.Event.State.HasFlag(ModifierType.Button1Mask))
1288 return;
1289
1290 PointD ip = ImageView.SelectedImage.ToImageSpace(e);
1291 if (ImageView.SelectedImage.isPyramidal)
1292 ip = new PointD(e.X, e.Y);
1293
1294 Bio.Graphics.Graphics g = Bio.Graphics.Graphics.FromImage(ImageView.SelectedBuffer);
1295 Bio.Graphics.Pen pen = new Bio.Graphics.Pen(EraseColor, (int)StrokeWidth, ImageView.SelectedBuffer.BitsPerPixel);
1296 g.FillEllipse(new Rectangle((int)ip.X, (int)ip.Y, (int)StrokeWidth, (int)StrokeWidth), pen.color);
1297
1298 App.viewer.UpdateImages();
1299 App.viewer.UpdateView();
1300 }

◆ ToolMove_Freeform()

void BioGTK.Tools.ToolMove_Freeform ( PointD e,
MotionNotifyEventArgs buts )

Definition at line 1130 of file Tools.cs.

1131 {
1132 if (selectedROI != null)
1133 if (currentTool.type == Tool.Type.freeform && buts.Event.State.HasFlag(ModifierType.Button1Mask))
1134 {
1135 selectedROI.AddPoint(new PointD(e.X, e.Y));
1136 selectedROI.coord = App.viewer.GetCoordinate();
1137 selectedROI.serie = ImageView.SelectedImage.isPyramidal ? App.viewer.Level : ImageView.SelectedImage.series;
1138 }
1139 }

◆ ToolMove_Line()

void BioGTK.Tools.ToolMove_Line ( PointD e,
MotionNotifyEventArgs buts )

Definition at line 877 of file Tools.cs.

878 {
879 if (currentTool.type != Tool.Type.line ||
880 !buts.Event.State.HasFlag(ModifierType.Button1Mask))
881 return;
882
883 if (selectedROI != null)
884 {
885 if (selectedROI.selectedPoints.Count == 1)
886 {
887 selectedROI.UpdatePoint(new PointD(e.X, e.Y), selectedROI.selectedPoints[0]);
888 selectedROI.UpdateBoundingBox();
889 UpdateView();
890 }
891 else
892 {
893 selectedROI.UpdatePoint(new PointD(e.X, e.Y), 1);
894 selectedROI.UpdateBoundingBox();
895 UpdateView();
896 }
897 }
898 }

◆ ToolMove_Magic()

void BioGTK.Tools.ToolMove_Magic ( PointD e,
MotionNotifyEventArgs buts )

Definition at line 1552 of file Tools.cs.

1553 {
1554 //First we draw the selection rectangle
1555 PointD d = new PointD(e.X - App.viewer.MouseDown.X, e.Y - App.viewer.MouseDown.Y);
1556 Tools.GetTool(Tools.Tool.Type.move).Rectangle = new RectangleD(App.viewer.MouseDown.X, App.viewer.MouseDown.Y, d.X, d.Y);
1557 UpdateView();
1558 }

◆ ToolMove_Move()

void BioGTK.Tools.ToolMove_Move ( PointD e,
MotionNotifyEventArgs buts )

Definition at line 629 of file Tools.cs.

630 {
631 if (currentTool.type != Tool.Type.move ||
632 !buts.Event.State.HasFlag(ModifierType.Button1Mask))
633 return;
634
635 // Moving selected vertices/control points or ROIs
636 if (selectedROI != null && selectedROI.Selected && selectedROI.selectedPoints != null)
637 {
638 PointD delta = new PointD(e.X - App.viewer.MouseDown.X, e.Y - App.viewer.MouseDown.Y);
639
640 // Rectangle / Ellipse special handling
641 if (selectedROI.type == ROI.Type.Rectangle || selectedROI.type == ROI.Type.Ellipse)
642 {
643 // If exactly one corner is selected -> resize by that corner
644 if (selectedROI.selectedPoints.Count == 1)
645 {
646 int pointIndex = selectedROI.selectedPoints[0];
647 RectangleD rect = selectedROI.BoundingBox;
648
649 // Work with normalized copy to make logic clearer
650 double left = rect.X;
651 double top = rect.Y;
652 double right = rect.X + rect.W;
653 double bottom = rect.Y + rect.H;
654
655 switch (pointIndex)
656 {
657 case 0: // Top-Left
658 left += delta.X;
659 top += delta.Y;
660 break;
661 case 1: // Top-Right
662 right += delta.X;
663 top += delta.Y;
664 break;
665 case 2: // Bottom-Right
666 right += delta.X;
667 bottom += delta.Y;
668 break;
669 case 3: // Bottom-Left
670 left += delta.X;
671 bottom += delta.Y;
672 break;
673 default:
674 break;
675 }
676
677 // Build and assign normalized bounding box
678 RectangleD newRect = new RectangleD(
679 Math.Min(left, right),
680 Math.Min(top, bottom),
681 Math.Abs(right - left),
682 Math.Abs(bottom - top)
683 );
684
685 selectedROI.BoundingBox = newRect;
686
687 // Important: keep points and bbox in sync
688 SyncPointsFromBoundingBox(selectedROI);
689 selectedROI.UpdateBoundingBox(); // if your ROI uses this to recalc derived fields
690
691 App.viewer.MouseDown = new PointD(e.X, e.Y);
692 App.viewer.UpdateView();
693 return;
694 }
695 else
696 {
697 // No corner selected -> move entire ROI by delta
698 for (int i = 0; i < selectedROI.Points.Count; i++)
699 {
700 selectedROI.UpdatePoint(
701 new PointD(selectedROI.Points[i].X + delta.X,
702 selectedROI.Points[i].Y + delta.Y), i);
703 }
704
705 // Keep bounding box in sync with points
706 SyncBoundingBoxFromPoints(selectedROI);
707 selectedROI.UpdateBoundingBox();
708
709 App.viewer.MouseDown = new PointD(e.X, e.Y);
710 App.viewer.UpdateView();
711 return;
712 }
713 }
714 else
715 {
716 // Other shapes: polygons, polylines, freeforms, lines, points
717 if (selectedROI.selectedPoints.Count == 0)
718 {
719 // Move all points
720 for (int i = 0; i < selectedROI.Points.Count; i++)
721 {
722 selectedROI.UpdatePoint(
723 new PointD(selectedROI.Points[i].X + delta.X,
724 selectedROI.Points[i].Y + delta.Y), i);
725 }
726 }
727 else
728 {
729 // Move only selected points
730 foreach (int pointIndex in selectedROI.selectedPoints.ToArray())
731 {
732 if (pointIndex >= 0 && pointIndex < selectedROI.Points.Count)
733 {
734 PointD pt = selectedROI.Points[pointIndex];
735 selectedROI.UpdatePoint(
736 new PointD(pt.X + delta.X, pt.Y + delta.Y), pointIndex);
737 }
738 }
739 }
740
741 // Keep bbox updated
742 SyncBoundingBoxFromPoints(selectedROI);
743 selectedROI.UpdateBoundingBox();
744
745 App.viewer.MouseDown = new PointD(e.X, e.Y);
746 App.viewer.UpdateView();
747 return;
748 }
749 }
750 // Dragging entire selected ROI (no selectedPoints list)
751 else if (selectedROI != null && selectedROI.Selected)
752 {
753 PointD delta = new PointD(e.X - App.viewer.MouseDown.X, e.Y - App.viewer.MouseDown.Y);
754
755 for (int i = 0; i < selectedROI.Points.Count; i++)
756 {
757 selectedROI.UpdatePoint(
758 new PointD(selectedROI.Points[i].X + delta.X,
759 selectedROI.Points[i].Y + delta.Y), i);
760 }
761
762 SyncBoundingBoxFromPoints(selectedROI);
763 selectedROI.UpdateBoundingBox();
764
765 App.viewer.MouseDown = new PointD(e.X, e.Y);
766 App.viewer.UpdateView();
767 return;
768 }
769 // Drawing / updating selection rectangle
770 else
771 {
772 PointD d = new PointD(e.X - App.viewer.MouseDown.X, e.Y - App.viewer.MouseDown.Y);
773 RectangleD selRect = new RectangleD(
774 Math.Min(App.viewer.MouseDown.X, e.X),
775 Math.Min(App.viewer.MouseDown.Y, e.Y),
776 Math.Abs(d.X), Math.Abs(d.Y));
777
778 Tools.GetTool(Tools.Tool.Type.move).Rectangle = selRect;
779
780 bool controlHeld = buts.Event.State.HasFlag(ModifierType.ControlMask);
781
782 // Select ROIs intersecting with rectangle
783 foreach (ROI an in ImageView.SelectedImage.Annotations)
784 {
785 if (an == null) continue;
786
787 RectangleD selBound = an.GetSelectBound(
788 ROI.selectBoxSize * ImageView.SelectedImage.PhysicalSizeX,
789 ROI.selectBoxSize * ImageView.SelectedImage.PhysicalSizeY);
790
791 if (selBound.IntersectsWith(selRect))
792 {
793 an.Selected = true;
794
795 if (!controlHeld)
796 an.selectedPoints?.Clear();
797
798 // Select points within rectangle
799 RectangleD[] sels = an.GetSelectBoxes(
800 ROI.selectBoxSize * ImageView.SelectedImage.PhysicalSizeX);
801 if (sels != null)
802 {
803 for (int i = 0; i < sels.Length; i++)
804 {
805 if (sels[i].IntersectsWith(selRect))
806 {
807 if (an.selectedPoints == null) an.selectedPoints = new List<int>();
808 if (!an.selectedPoints.Contains(i))
809 an.selectedPoints.Add(i);
810 }
811 }
812 }
813 }
814 else if (!controlHeld)
815 {
816 an.Selected = false;
817 an.selectedPoints?.Clear();
818 }
819 }
820
821 if (selectedROI != null)
822 selectedROI.UpdateBoundingBox();
823
824 App.viewer.UpdateView();
825 }
826 }

◆ ToolMove_Pan()

void BioGTK.Tools.ToolMove_Pan ( PointD e,
MotionNotifyEventArgs buts )

Definition at line 1402 of file Tools.cs.

1403 {
1404 if (currentTool.type != Tool.Type.pan)
1405 return;
1406
1407 if (!buts.Event.State.HasFlag(ModifierType.Button1Mask) &&
1408 !buts.Event.State.HasFlag(ModifierType.Button2Mask))
1409 return;
1410
1411 double dx = buts.Event.X - panStartX;
1412 double dy = buts.Event.Y - panStartY;
1413
1414 if (ImageView.SelectedImage.isPyramidal)
1415 {
1416 // PyramidalOrigin is in full-resolution (level-0) pixel space.
1417 // Resolution = full-res pixels per screen pixel, so multiplying
1418 // screen-pixel delta by Resolution gives the correct full-res shift.
1419 // PanSpeed applies a user-tunable multiplier on top.
1420 double deltaX = dx * App.viewer.Resolution * PanSpeed;
1421 double deltaY = dy * App.viewer.Resolution * PanSpeed;
1422 App.viewer.PyramidalOrigin = new PointD(
1423 initialPanOrigin.X - deltaX,
1424 initialPanOrigin.Y - deltaY);
1425 }
1426 else
1427 {
1428 // Non-pyramidal: convert screen pixels back into world units so
1429 // a 1 px drag produces a 1 px screen move at the current zoom.
1430 double scale = Math.Max(initialPanScale, double.Epsilon);
1431 double deltaX = dx / (App.viewer.PxWmicron * scale);
1432 double deltaY = dy / (App.viewer.PxHmicron * scale);
1433 App.viewer.Origin = new PointD(
1434 initialPanOrigin.X + deltaX,
1435 initialPanOrigin.Y + deltaY);
1436 }
1437 }

◆ ToolMove_Rectangle()

void BioGTK.Tools.ToolMove_Rectangle ( PointD e,
MotionNotifyEventArgs buts )

Definition at line 927 of file Tools.cs.

928 {
929 if (currentTool.type != Tool.Type.rect ||
930 !buts.Event.State.HasFlag(ModifierType.Button1Mask))
931 return;
932
933 if (selectedROI != null && selectedROI.type == ROI.Type.Rectangle)
934 {
935 selectedROI.BoundingBox = RectangleDExtensions.FromCorners(
936 new PointD(selectedROI.BoundingBox.X, selectedROI.BoundingBox.Y),
937 new PointD(e.X, e.Y));
938 UpdateView();
939 }
940 }

◆ ToolUp()

void BioGTK.Tools.ToolUp ( PointD e,
ButtonReleaseEventArgs buts )

Definition at line 380 of file Tools.cs.

381 {
382 if (App.viewer == null || currentTool == null || ImageView.SelectedImage == null)
383 return;
384
385 Plugins.MouseUp(ImageView.SelectedImage, e, buts);
386 Scripting.UpdateState(Scripting.State.GetUp(e, buts.Event.Button));
387
388 switch (currentTool.type)
389 {
390 case Tool.Type.pan:
391 ToolUp_Pan(e, buts);
392 break;
393 case Tool.Type.move:
394 ToolUp_Move(e, buts);
395 break;
396 case Tool.Type.magic:
397 ToolUp_Magic(e, buts);
398 break;
399 case Tool.Type.line:
400 ToolUp_Line(e, buts);
401 break;
402 case Tool.Type.rect:
403 ToolUp_Rectangle(e, buts);
404 break;
405 case Tool.Type.ellipse:
406 ToolUp_Ellipse(e, buts);
407 break;
408 case Tool.Type.polygon:
409 ToolUp_Polygon(e, buts);
410 break;
411 case Tool.Type.text:
412 //ToolUp_Text(e, buts);
413 break;
414 case Tool.Type.delete:
415 //
416 break;
417 case Tool.Type.freeform:
418 ToolUp_Freeform(e, buts);
419 break;
420 case Tool.Type.bucket:
421 ToolUp_Bucket(e, buts);
422 break;
423 case Tool.Type.dropper:
424 ToolUp_Dropper(e, buts);
425 break;
426 default:
427 break;
428 }
429 }

◆ ToolUp_Bucket()

void BioGTK.Tools.ToolUp_Bucket ( PointD e,
ButtonReleaseEventArgs buts )

Definition at line 1305 of file Tools.cs.

1306 {
1307 if (currentTool.type != Tool.Type.bucket || buts.Event.Button != 1)
1308 return;
1309
1310 PointD ip = ImageView.SelectedImage.ToImageSpace(e);
1311
1312 if (ip.X >= ImageView.SelectedImage.SizeX || ip.Y >= ImageView.SelectedImage.SizeY)
1313 return;
1314
1315 floodFiller.FillColor = DrawColor;
1316 floodFiller.Tolerance = tolerance;
1317 floodFiller.Bitmap = ImageView.SelectedBuffer;
1318 floodFiller.FloodFill(new AForge.Point((int)ip.X, (int)ip.Y));
1319
1320 App.viewer.UpdateImages();
1321 App.viewer.UpdateView();
1322 }

◆ ToolUp_Dropper()

void BioGTK.Tools.ToolUp_Dropper ( PointD e,
ButtonReleaseEventArgs buts )

Definition at line 1327 of file Tools.cs.

1328 {
1329 if (currentTool.type != Tool.Type.dropper || buts.Event.Button != 1)
1330 return;
1331
1332 PointD ip = ImageView.SelectedImage.ToImageSpace(e);
1333
1334 if (ip.X >= 0 && ip.Y >= 0 && ip.X < ImageView.SelectedImage.SizeX && ip.Y < ImageView.SelectedImage.SizeY)
1335 {
1336 DrawColor = ImageView.SelectedBuffer.GetPixel((int)ip.X, (int)ip.Y);
1337 App.viewer.UpdateView();
1338 }
1339 }

◆ ToolUp_Ellipse()

void BioGTK.Tools.ToolUp_Ellipse ( PointD e,
ButtonReleaseEventArgs buts )

Definition at line 992 of file Tools.cs.

993 {
994 if (currentTool.type != Tool.Type.ellipse || buts.Event.Button != 1)
995 return;
996
997 if (selectedROI != null && selectedROI.type == ROI.Type.Ellipse)
998 {
999 // Update final ellipse bounds
1000 selectedROI.BoundingBox = RectangleDExtensions.FromCorners(
1001 new PointD(selectedROI.BoundingBox.X, selectedROI.BoundingBox.Y),
1002 new PointD(e.X, e.Y));
1003
1004 // Validate the ROI (might reject if too small)
1005 selectedROI.Validate();
1006 selectedROI = null;
1007 UpdateView();
1008 }
1009 }

◆ ToolUp_Freeform()

void BioGTK.Tools.ToolUp_Freeform ( PointD e,
ButtonReleaseEventArgs buts )

Definition at line 1141 of file Tools.cs.

1142 {
1143 if (currentTool.type != Tool.Type.freeform || buts.Event.Button != 1)
1144 return;
1145
1146 if (selectedROI != null)
1147 {
1148 selectedROI.UpdateBoundingBox();
1149 //selectedROI = null;
1150 UpdateView();
1151 }
1152 }

◆ ToolUp_Line()

void BioGTK.Tools.ToolUp_Line ( PointD e,
ButtonReleaseEventArgs buts )

Definition at line 900 of file Tools.cs.

901 {
902 if (currentTool.type != Tool.Type.line || buts.Event.Button != 1)
903 return;
904
905 if (selectedROI != null && selectedROI.GetPointCount() >= 2)
906 {
907 selectedROI.UpdatePoint(new PointD(e.X, e.Y), 1);
908 selectedROI.UpdateBoundingBox();
909 selectedROI = null;
910 UpdateView();
911 }
912 }

◆ ToolUp_Magic()

void BioGTK.Tools.ToolUp_Magic ( PointD e,
ButtonReleaseEventArgs buts )

Definition at line 1560 of file Tools.cs.

1561 {
1562 if (!buts.Event.State.HasFlag(ModifierType.Button1Mask))
1563 return;
1564 // Define the rectangle from mouse coordinates
1565 RectangleD rectangle = new RectangleD(
1566 App.viewer.MouseDown.X,
1567 App.viewer.MouseDown.Y,
1568 Math.Abs(App.viewer.MouseUp.X - App.viewer.MouseDown.X),
1569 Math.Abs(App.viewer.MouseUp.Y - App.viewer.MouseDown.Y)
1570 );
1571
1572 // Convert to image space coordinates
1573 AForge.RectangleF rectInImageSpace = ImageView.SelectedImage.ToImageSpace(rectangle);
1574 ZCT coord = App.viewer.GetCoordinate();
1575 Bitmap bitmap;
1576
1577 // Check the number of RGB channels to choose filtering method
1578 if (ImageView.SelectedImage.Buffers[0].RGBChannelsCount > 1)
1579 {
1580 bitmap = ImageView.SelectedImage.GetFiltered(
1581 coord,
1582 new IntRange((int)ImageView.SelectedBuffer.Stats[0].Min, (int)ImageView.SelectedBuffer.Stats[0].Max),
1583 new IntRange((int)ImageView.SelectedBuffer.Stats[1].Min, (int)ImageView.SelectedBuffer.Stats[1].Max),
1584 new IntRange((int)ImageView.SelectedBuffer.Stats[2].Min, (int)ImageView.SelectedBuffer.Stats[2].Max)
1585 );
1586 }
1587 else
1588 {
1589 bitmap = ImageView.SelectedImage.GetFiltered(
1590 coord,
1591 new IntRange((int)ImageView.SelectedBuffer.Stats[0].Min, (int)ImageView.SelectedBuffer.Stats[0].Max),
1592 new IntRange((int)ImageView.SelectedBuffer.Stats[0].Min, (int)ImageView.SelectedBuffer.Stats[0].Max),
1593 new IntRange((int)ImageView.SelectedBuffer.Stats[0].Min, (int)ImageView.SelectedBuffer.Stats[0].Max)
1594 );
1595 }
1596
1597 // Crop the image to the selected rectangle
1598 bitmap.Crop(rectInImageSpace.ToRectangleInt());
1599 // Determine the threshold based on magicSelect settings
1600 Statistics[] st = Statistics.FromBytes(bitmap.Bytes, bitmap.SizeX, bitmap.Height, bitmap.RGBChannelsCount, bitmap.BitsPerPixel, bitmap.Stride, bitmap.PixelFormat);
1601 int threshold = magicSelect.Numeric ? magicSelect.Threshold : CalculateThreshold(magicSelect.Index, st[0]);
1602 BlobCounter blobCounter = new BlobCounter();
1603 OtsuThreshold th = new OtsuThreshold();
1604 bitmap.To8Bit();
1605 th.ApplyInPlace(bitmap);
1606 blobCounter.FilterBlobs = true;
1607 blobCounter.MinWidth = 2;
1608 blobCounter.MinHeight = 2;
1609 blobCounter.ProcessImage(bitmap);
1610 // Retrieve detected blobs
1611 Blob[] blobs = blobCounter.GetObjectsInformation();
1612 double pixelSizeX = ImageView.SelectedImage.PhysicalSizeX;
1613 double pixelSizeY = ImageView.SelectedImage.PhysicalSizeY;
1614 // Annotate detected blobs in the original image
1615 foreach (Blob blob in blobs)
1616 {
1617 AForge.RectangleD blobRectangle = new AForge.RectangleD(
1618 blob.Rectangle.X * pixelSizeX,
1619 blob.Rectangle.Y * pixelSizeY,
1620 blob.Rectangle.Width * pixelSizeX,
1621 blob.Rectangle.Height * pixelSizeY
1622 );
1623 // Calculate the location of the detected blob
1624 PointD location = new PointD(rectangle.X + blobRectangle.X, rectangle.Y + blobRectangle.Y);
1625 // Create and add ROI annotation
1626 ROI annotation = ROI.CreateRectangle(coord, location.X, location.Y, blobRectangle.W, blobRectangle.H);
1627 ImageView.SelectedImage.Annotations.Add(annotation);
1628 }
1629 App.viewer.UpdateView(true);
1630 }
static int CalculateThreshold(int index, Statistics stat)
Helper method to calculate threshold for magic select.
Definition Tools.cs:1826

◆ ToolUp_Move()

void BioGTK.Tools.ToolUp_Move ( PointD e,
ButtonReleaseEventArgs buts )

Definition at line 827 of file Tools.cs.

828 {
829 if (currentTool.type != Tool.Type.move || buts.Event.Button != 1)
830 return;
831
832 // Clear selection rectangle
833 Tools.GetTool(Tools.Tool.Type.move).Rectangle = new RectangleD(0, 0, 0, 0);
834 selectedROI?.UpdateBoundingBox();
835 App.viewer.UpdateView();
836 }

◆ ToolUp_Pan()

void BioGTK.Tools.ToolUp_Pan ( PointD e,
ButtonReleaseEventArgs buts )

Definition at line 1443 of file Tools.cs.

1444 {
1445 if (currentTool.type == Tool.Type.pan &&
1446 (buts.Event.Button == 1 || buts.Event.Button == 2))
1447 {
1448 currentTool = GetTool(Tool.Type.move);
1449 }
1450 }

◆ ToolUp_Rectangle()

void BioGTK.Tools.ToolUp_Rectangle ( PointD e,
ButtonReleaseEventArgs buts )

Definition at line 942 of file Tools.cs.

943 {
944 if (currentTool.type != Tool.Type.rect || buts.Event.Button != 1)
945 return;
946
947 if (selectedROI != null && selectedROI.type == ROI.Type.Rectangle)
948 {
949 // Update final rectangle bounds
950 selectedROI.BoundingBox = RectangleDExtensions.FromCorners(
951 new PointD(selectedROI.BoundingBox.X, selectedROI.BoundingBox.Y),
952 new PointD(e.X, e.Y));
953
954 // Validate the ROI (might reject if too small)
955 selectedROI.Validate();
956 selectedROI = null;
957 UpdateView();
958 }
959 }

Member Data Documentation

◆ applyToStack

bool BioGTK.Tools.applyToStack = false
static

Definition at line 57 of file Tools.cs.

◆ bEnabled

bool BioGTK.Tools.bEnabled = true
static

Definition at line 61 of file Tools.cs.

◆ colorOne

bool BioGTK.Tools.colorOne = true
static

Definition at line 239 of file Tools.cs.

◆ colorTool

ColorTool BioGTK.Tools.colorTool
static

Definition at line 58 of file Tools.cs.

◆ currentTool

Tool BioGTK.Tools.currentTool
static

Definition at line 1757 of file Tools.cs.

◆ drawColor

ColorS BioGTK.Tools.drawColor = new ColorS(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)
static

Definition at line 62 of file Tools.cs.

◆ eraseColor

ColorS BioGTK.Tools.eraseColor = new ColorS(0, 0, 0)
static

Definition at line 63 of file Tools.cs.

◆ gEnabled

bool BioGTK.Tools.gEnabled = true
static

Definition at line 60 of file Tools.cs.

◆ PanSpeed

double BioGTK.Tools.PanSpeed = 0.75
static

Definition at line 1369 of file Tools.cs.

◆ rEnabled

bool BioGTK.Tools.rEnabled = true
static

Definition at line 59 of file Tools.cs.

◆ selectionRect

RectangleD BioGTK.Tools.selectionRect
static

Definition at line 1800 of file Tools.cs.

◆ selectionRectangle

Rectangle BioGTK.Tools.selectionRectangle
static

Definition at line 85 of file Tools.cs.

◆ ti

TextInput BioGTK.Tools.ti = null
static

Definition at line 1801 of file Tools.cs.

◆ tolerance

ColorS BioGTK.Tools.tolerance = new ColorS(0, 0, 0)
static

Definition at line 64 of file Tools.cs.

◆ tools

Dictionary<string, Tool> BioGTK.Tools.tools = new Dictionary<string, Tool>()
static

Definition at line 86 of file Tools.cs.

Property Documentation

◆ DrawColor

ColorS BioGTK.Tools.DrawColor
staticgetset

Definition at line 1759 of file Tools.cs.

1760 {
1761 get
1762 {
1763 return drawColor;
1764 }
1765 set
1766 {
1767 drawColor = value;
1768 tools[Tool.Type.color1.ToString()].color = drawColor;
1769 }
1770 }

◆ EraseColor

ColorS BioGTK.Tools.EraseColor
staticgetset

Definition at line 1772 of file Tools.cs.

1773 {
1774 get
1775 {
1776 return eraseColor;
1777 }
1778 set
1779 {
1780 eraseColor = value;
1781 tools[Tool.Type.color2.ToString()].color = eraseColor;
1782 }
1783 }

◆ IsPanning

bool BioGTK.Tools.IsPanning
getset

Definition at line 1798 of file Tools.cs.

1798{ get; set; }

◆ selectedROI

ROI BioGTK.Tools.selectedROI
staticgetset

Definition at line 68 of file Tools.cs.

69 {
70 get
71 {
72 List<ROI> rs = new List<ROI>();
73 foreach (var item in GetSelectableRois(ImageView.SelectedImage))
74 if (item != null && item.Selected)
75 rs.Add(item);
76 if (rs.Count > 0)
77 roi = rs[0];
78 return roi;
79 }
80 set
81 {
82 roi = value;
83 }
84 }

◆ selectedROIs

List<ROI> BioGTK.Tools.selectedROIs
staticgetset

Definition at line 90 of file Tools.cs.

91 {
92 get
93 {
94 rois.Clear();
95 for (int i = 0; i < Images.images.Count; i++)
96 {
97 foreach (var item in GetSelectableRois(Images.images[i]))
98 if (item != null && item.Selected)
99 rois.Add(item);
100 }
101 return rois;
102 }
103 set
104 {
105 rois.Clear();
106 rois.AddRange(value);
107 }
108 }

◆ StrokeWidth

int BioGTK.Tools.StrokeWidth
staticgetset

Definition at line 1786 of file Tools.cs.

1787 {
1788 get
1789 {
1790 return width;
1791 }
1792 set
1793 {
1794 width = value;
1795 }
1796 }

The documentation for this class was generated from the following file: