Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiago Conceição <Tiago_caza@hotmail.com>2020-09-12 06:05:32 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2020-09-12 06:05:32 +0300
commit5cfd62d36e6ad9193a044bfca2a0e2dd4ae71928 (patch)
treea0516c7bfc3ad8098283be6f3bab7b358b0ff5b0
parent67c9d7139d19f8356b21a19f2b8062a5c107beab (diff)
v0.8.1.0v0.8.1.0
* (Add) Tools can now run inside a ROI (#49) * (Add) Layer preview: Hold-Shift + Left-drag to select an ROI (Region of interest) on image, that region will be used instead of whole image when running some tools * (Add) Layer preview: Hold-Shift + Hold-Alt + Left-drag to select and auto adjust the ROI to the contained objects, that region will be used instead of whole image when running some tools * (Add) Layer preview: Hold-Shift + Right-click on a object to select its bounding area, that region will be used instead of whole image when running some tools * (Add) Layer preview: ESC key to clear ROI * (Add) Layer preview: Overlay text with hints for current action * (Add) Tool - Move: Now possible to do a copy move instead of a cut move * (Add) Arrow wait cursor to progress loadings * (Change) Layer preview: Hold-Shift key to select issues and pick pixel position/brightness changed to Hold-Control key * (Change) Layer preview: Shift+click combination to zoom-in changed to Alt+click * (Fix) CTB v3: Bad file when re-encoding
-rw-r--r--CHANGELOG.md14
-rw-r--r--UVtools.Core/FileFormats/ChituboxFile.cs4
-rw-r--r--UVtools.Core/Layer/Layer.cs118
-rw-r--r--UVtools.Core/Layer/LayerManager.cs22
-rw-r--r--UVtools.Core/Operations/Operation.cs14
-rw-r--r--UVtools.Core/Operations/OperationMove.cs37
-rw-r--r--UVtools.Core/Operations/OperationPattern.cs31
-rw-r--r--UVtools.GUI/Controls/CtrlToolWindowContent.cs10
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolBlur.Designer.cs1
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolEditEditParameters.cs2
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolFlip.Designer.cs1
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolMask.Designer.cs2
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolMask.cs31
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolMorph.Designer.cs1
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolMorph.cs4
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolMove.Designer.cs33
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolMove.cs28
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolPattern.Designer.cs2
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolPattern.cs25
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolPixelDimming.Designer.cs2
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.cs4
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolResize.Designer.cs1
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolRotate.Designer.cs6
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolSolidify.Designer.cs48
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolSolidify.cs23
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolSolidify.resx123
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolThreshold.Designer.cs1
-rw-r--r--UVtools.GUI/Forms/FrmLoading.cs3
-rw-r--r--UVtools.GUI/Forms/FrmToolWindow.Designer.cs145
-rw-r--r--UVtools.GUI/Forms/FrmToolWindow.cs34
-rw-r--r--UVtools.GUI/Forms/FrmToolWindow.resx3
-rw-r--r--UVtools.GUI/FrmMain.Designer.cs32
-rw-r--r--UVtools.GUI/FrmMain.cs166
-rw-r--r--UVtools.GUI/FrmMain.resx2
-rw-r--r--UVtools.GUI/LayerCache.cs79
-rw-r--r--UVtools.GUI/UVtools.GUI.csproj10
36 files changed, 845 insertions, 217 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d01576c..2726bc4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,14 +1,20 @@
# Changelog
-## /08/2020 - v0.8.1.0
+## 12/09/2020 - v0.8.1.0
-* (Add) Layer preview: Hold-Shift key to select an ROI (Region of interest) on image, that region will be used instead of whole image when running some tools
+* (Add) Tools can now run inside a ROI (#49)
+* (Add) Layer preview: Hold-Shift + Left-drag to select an ROI (Region of interest) on image, that region will be used instead of whole image when running some tools
+* (Add) Layer preview: Hold-Shift + Hold-Alt + Left-drag to select and auto adjust the ROI to the contained objects, that region will be used instead of whole image when running some tools
+* (Add) Layer preview: Hold-Shift + Right-click on a object to select its bounding area, that region will be used instead of whole image when running some tools
* (Add) Layer preview: ESC key to clear ROI
* (Add) Layer preview: Overlay text with hints for current action
+* (Add) Tool - Move: Now possible to do a copy move instead of a cut move
+* (Add) Arrow wait cursor to progress loadings
* (Change) Layer preview: Hold-Shift key to select issues and pick pixel position/brightness changed to Hold-Control key
* (Change) Layer preview: Shift+click combination to zoom-in changed to Alt+click
+* (Fix) CTB v3: Bad file when re-encoding
-## 11/08/2020 - v0.8.0.0
+## 11/09/2020 - v0.8.0.0
* (Add) LGS and LGS30 file format for Longer Orange 10 and 30 (ezrec/uv3dp#105)
* (Add) CWS: Support the GRAY2RGB and RBG2GRAY encoding for Bene Mono
@@ -50,7 +56,7 @@ Less frequently used settings for gap and noise removal iterations have been mov
* (Fix) Mask: A crash when check "Invert" when mask is not loaded
* (Fix) Some text and phrases
-## 04/08/2020 - v0.7.0.0
+## 04/09/2020 - v0.7.0.0
* (Add) "Rebuild GCode" button
* (Add) Issues: Touching Bounds and Empty Layers to the detect button
diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs
index 6ff4e23..7880abc 100644
--- a/UVtools.Core/FileFormats/ChituboxFile.cs
+++ b/UVtools.Core/FileFormats/ChituboxFile.cs
@@ -1218,7 +1218,9 @@ namespace UVtools.Core.FileFormats
if (HeaderSettings.Version >= 3)
{
var layerDataEx = new LayerDataEx(layerData, layerIndex);
- layerData.DataAddress = layerDataCurrentOffset += Helpers.SerializeWriteFileStream(outputFile, layerDataEx);
+ layerDataCurrentOffset += (uint)Helpers.Serializer.SizeOf(layerDataEx);
+ layerData.DataAddress = layerDataCurrentOffset;
+ Helpers.SerializeWriteFileStream(outputFile, layerDataEx);
}
layerDataCurrentOffset += outputFile.WriteBytes(layerData.EncodedRle);
diff --git a/UVtools.Core/Layer/Layer.cs b/UVtools.Core/Layer/Layer.cs
index b0d8b95..4bbad16 100644
--- a/UVtools.Core/Layer/Layer.cs
+++ b/UVtools.Core/Layer/Layer.cs
@@ -444,35 +444,44 @@ namespace UVtools.Core
return result;
}
- public void MutateMove(OperationMove operation)
+ public void Move(OperationMove operation)
{
- using (var layer = LayerMat)
+ using (var mat = LayerMat)
{
- if (operation.ImageWidth == 0) operation.ImageWidth = (uint)layer.Width;
- if (operation.ImageHeight == 0) operation.ImageHeight = (uint)layer.Height;
+ if (operation.ImageWidth == 0) operation.ImageWidth = (uint)mat.Width;
+ if (operation.ImageHeight == 0) operation.ImageHeight = (uint)mat.Height;
/*layer.Transform(1.0, 1.0, move.MarginLeft - move.MarginRight, move.MarginTop-move.MarginBottom);
LayerMat = layer;*/
- using (var layerRoi = new Mat(layer, operation.SrcRoi))
+ /*using (var layerRoi = new Mat(layer, operation.SrcRoi))
+ using (var dstLayer = layer.CloneBlank())
+ using (var dstRoi = new Mat(dstLayer, operation.DstRoi))
{
- using (var dstLayer = layer.CloneBlank())
+ layerRoi.CopyTo(dstRoi);
+ LayerMat = dstLayer;
+ }*/
+
+ using (var srcRoi = new Mat(mat, operation.ROI))
+ using (var dstRoi = new Mat(mat, operation.DstRoi))
+ {
+ srcRoi.CopyTo(dstRoi);
+ if (operation.IsCutMove)
{
- using (var dstRoi = new Mat(dstLayer, operation.DstRoi))
- {
- layerRoi.CopyTo(dstRoi);
- LayerMat = dstLayer;
- }
+ srcRoi.SetTo(new MCvScalar(0));
}
+
+ LayerMat = mat;
}
}
}
- public void Resize(double xScale, double yScale)
+ public void Resize(double xScale, double yScale, OperationResize operation)
{
using (var mat = LayerMat)
{
- mat.TransformFromCenter(xScale, yScale);
+ Mat target = operation.GetRoiOrDefault(mat);
+ target.TransformFromCenter(xScale, yScale);
LayerMat = mat;
}
}
@@ -481,33 +490,20 @@ namespace UVtools.Core
{
using (var mat = LayerMat)
{
+ Mat target = operation.GetRoiOrDefault(mat);
+
if (operation.MakeCopy)
{
using (Mat dst = new Mat())
{
- CvInvoke.Flip(mat, dst, operation.FlipTypeOpenCV);
- CvInvoke.Add(mat, dst, mat);
- /*var spanSrc = mat.GetPixelSpan<byte>();
- var spanDst = dst.GetPixelSpan<byte>();
- for (int i = 0; i < spanSrc.Length; i++)
- {
- if (spanDst[i] == 0) continue;
- spanSrc[i] = spanDst[i];
- }*/
-
-
-
- LayerMat = mat;
+ CvInvoke.Flip(target, dst, operation.FlipTypeOpenCV);
+ CvInvoke.Add(target, dst, target);
}
}
else
{
- CvInvoke.Flip(mat, mat, operation.FlipTypeOpenCV);
- /*GpuMat gpumat = new GpuMat();
- gpumat.Upload(mat);
- CudaInvoke.Flip(gpumat, gpumat, flipType);
- gpumat.Download(mat);*/
+ CvInvoke.Flip(target, target, operation.FlipTypeOpenCV);
}
LayerMat = mat;
@@ -518,8 +514,10 @@ namespace UVtools.Core
{
using (var mat = LayerMat)
{
- var halfWidth = mat.Width / 2.0f;
- var halfHeight = mat.Height / 2.0f;
+ Mat target = operation.GetRoiOrDefault(mat);
+
+ var halfWidth = target.Width / 2.0f;
+ var halfHeight = target.Height / 2.0f;
using (var translateTransform = new Matrix<double>(2, 3))
{
CvInvoke.GetRotationMatrix2D(new PointF(halfWidth, halfHeight), (double) operation.AngleDegrees, 1.0, translateTransform);
@@ -537,20 +535,23 @@ namespace UVtools.Core
translateTransform[1, 2] += bound_h / 2 - halfHeight;*/
- CvInvoke.WarpAffine(mat, mat, translateTransform, mat.Size);
+ CvInvoke.WarpAffine(target, target, translateTransform, target.Size);
}
LayerMat = mat;
}
}
- public void MutateSolidify()
+ public void Solidify(OperationSolidify operation)
{
using (Mat mat = LayerMat)
{
using (Mat filteredMat = new Mat())
{
- CvInvoke.Threshold(mat, filteredMat, 254, 255, ThresholdType.Binary); // Clean AA
+ Mat target = operation.GetRoiOrDefault(mat);
+
+
+ CvInvoke.Threshold(target, filteredMat, 254, 255, ThresholdType.Binary); // Clean AA
using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
{
@@ -561,7 +562,7 @@ namespace UVtools.Core
for (int i = 0; i < contours.Size; i++)
{
if ((int)arr.GetValue(0, i, 2) != -1 || (int)arr.GetValue(0, i, 3) == -1) continue;
- CvInvoke.DrawContours(mat, contours, i, new MCvScalar(255), -1);
+ CvInvoke.DrawContours(target, contours, i, new MCvScalar(255), -1);
}
}
}
@@ -571,13 +572,13 @@ namespace UVtools.Core
}
}
- public void Mask(OperationMask mask) => Mask(mask.Mask);
-
- public void Mask(Mat mask)
+ public void Mask(OperationMask operation)
{
using (var mat = LayerMat)
{
- CvInvoke.BitwiseAnd(mat, mask, mat);
+ Mat target = operation.GetRoiOrDefault(mat);
+ if(operation.Mask.Size != target.Size) return;
+ CvInvoke.BitwiseAnd(target, operation.Mask, target);
LayerMat = mat;
}
}
@@ -655,17 +656,19 @@ namespace UVtools.Core
using (Mat erode = new Mat())
using (Mat diff = new Mat())
{
- CvInvoke.Erode(dst, erode, kernel, anchor, (int) operation.BorderSize, BorderType.Reflect101, default);
- CvInvoke.Subtract(dst, erode, diff);
+ Mat target = operation.GetRoiOrDefault(dst);
+
+ CvInvoke.Erode(target, erode, kernel, anchor, (int) operation.BorderSize, BorderType.Reflect101, default);
+ CvInvoke.Subtract(target, erode, diff);
if (operation.BordersOnly)
{
- CvInvoke.BitwiseAnd(diff, Index % 2 == 0 ? evenPatternMask : oddPatternMask, dst);
- CvInvoke.Add(erode, dst, dst);
+ CvInvoke.BitwiseAnd(diff, Index % 2 == 0 ? evenPatternMask : oddPatternMask, target);
+ CvInvoke.Add(erode, target, target);
}
else
{
- CvInvoke.BitwiseAnd(erode, Index % 2 == 0 ? evenPatternMask : oddPatternMask, dst);
- CvInvoke.Add(dst, diff, dst);
+ CvInvoke.BitwiseAnd(erode, Index % 2 == 0 ? evenPatternMask : oddPatternMask, target);
+ CvInvoke.Add(target, diff, target);
}
LayerMat = dst;
@@ -679,7 +682,8 @@ namespace UVtools.Core
using (Mat dst = LayerMat)
{
- CvInvoke.MorphologyEx(dst, dst, operation.MorphOperation, operation.Kernel.Matrix, operation.Kernel.Anchor, iterations, borderType, borderValue);
+ Mat target = operation.GetRoiOrDefault(dst);
+ CvInvoke.MorphologyEx(target, target, operation.MorphOperation, operation.Kernel.Matrix, operation.Kernel.Anchor, iterations, borderType, borderValue);
LayerMat = dst;
}
}
@@ -758,7 +762,8 @@ namespace UVtools.Core
{
using (Mat dst = LayerMat)
{
- CvInvoke.Threshold(dst, dst, operation.Threshold, operation.Maximum, operation.Type);
+ Mat target = operation.GetRoiOrDefault(dst);
+ CvInvoke.Threshold(target, target, operation.Threshold, operation.Maximum, operation.Type);
LayerMat = dst;
}
}
@@ -772,23 +777,24 @@ namespace UVtools.Core
//if (anchor.IsEmpty) anchor = new Point(-1, -1);
using (Mat dst = LayerMat)
{
+ Mat target = operation.GetRoiOrDefault(dst);
switch (operation.BlurOperation)
{
case OperationBlur.BlurAlgorithm.Blur:
- CvInvoke.Blur(dst, dst, size, operation.Kernel.Anchor);
+ CvInvoke.Blur(target, target, size, operation.Kernel.Anchor);
break;
case OperationBlur.BlurAlgorithm.Pyramid:
- CvInvoke.PyrDown(dst, dst);
- CvInvoke.PyrUp(dst, dst);
+ CvInvoke.PyrDown(target, target);
+ CvInvoke.PyrUp(target, target);
break;
case OperationBlur.BlurAlgorithm.MedianBlur:
- CvInvoke.MedianBlur(dst, dst, (int) operation.Size);
+ CvInvoke.MedianBlur(target, target, (int) operation.Size);
break;
case OperationBlur.BlurAlgorithm.GaussianBlur:
- CvInvoke.GaussianBlur(dst, dst, size, 0);
+ CvInvoke.GaussianBlur(target, target, size, 0);
break;
case OperationBlur.BlurAlgorithm.Filter2D:
- CvInvoke.Filter2D(dst, dst, operation.Kernel.Matrix, anchor);
+ CvInvoke.Filter2D(target, target, operation.Kernel.Matrix, anchor);
break;
default:
throw new ArgumentOutOfRangeException();
@@ -824,7 +830,7 @@ namespace UVtools.Core
public void Pattern(OperationPattern operation)
{
using (var layer = LayerMat)
- using (var layerRoi = new Mat(layer, operation.SrcRoi))
+ using (var layerRoi = new Mat(layer, operation.ROI))
using (var dstLayer = layer.CloneBlank())
{
for (ushort col = 0; col < operation.Cols; col++)
diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs
index 24cbbf3..0370ac1 100644
--- a/UVtools.Core/Layer/LayerManager.cs
+++ b/UVtools.Core/Layer/LayerManager.cs
@@ -247,13 +247,13 @@ namespace UVtools.Core
if (ReferenceEquals(progress, null)) progress = new OperationProgress();
progress.Reset(operation.ProgressAction, operation.LayerRangeCount);
- if (operation.SrcRoi == Rectangle.Empty) operation.SrcRoi = GetBoundingRectangle(progress);
+ if (operation.ROI == Rectangle.Empty) operation.ROI = GetBoundingRectangle(progress);
Parallel.For(operation.LayerIndexStart, operation.LayerIndexEnd + 1, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
- this[layerIndex].MutateMove(operation);
+ this[layerIndex].Move(operation);
lock (progress.Mutex)
{
@@ -322,7 +322,7 @@ namespace UVtools.Core
if (newX == 1.0m && newY == 1.0m) return;
- this[layerIndex].Resize((double) (newX / 100m), (double) (newY / 100m));
+ this[layerIndex].Resize((double) (newX / 100m), (double) (newY / 100m), operation);
});
progress.Token.ThrowIfCancellationRequested();
}
@@ -366,7 +366,7 @@ namespace UVtools.Core
Parallel.For(operation.LayerIndexStart, operation.LayerIndexEnd + 1, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
- this[layerIndex].MutateSolidify();
+ this[layerIndex].Solidify(operation);
lock (progress.Mutex)
{
progress++;
@@ -425,13 +425,15 @@ namespace UVtools.Core
using (Mat matEven = mat.CloneBlank())
using (Mat matOdd = mat.CloneBlank())
{
- CvInvoke.Repeat(operation.EvenPattern, mat.Rows / operation.EvenPattern.Rows + 1,
- mat.Cols / operation.EvenPattern.Cols + 1, matEven);
- CvInvoke.Repeat(operation.OddPattern, mat.Rows / operation.OddPattern.Rows + 1,
- mat.Cols / operation.OddPattern.Cols + 1, matOdd);
+ Mat target = operation.GetRoiOrDefault(mat);
- using (var evenPatternMask = new Mat(matEven, new Rectangle(0, 0, mat.Width, mat.Height)))
- using (var oddPatternMask = new Mat(matOdd, new Rectangle(0, 0, mat.Width, mat.Height)))
+ CvInvoke.Repeat(operation.EvenPattern, target.Rows / operation.EvenPattern.Rows + 1,
+ target.Cols / operation.EvenPattern.Cols + 1, matEven);
+ CvInvoke.Repeat(operation.OddPattern, target.Rows / operation.OddPattern.Rows + 1,
+ target.Cols / operation.OddPattern.Cols + 1, matOdd);
+
+ using (var evenPatternMask = new Mat(matEven, new Rectangle(0, 0, target.Width, target.Height)))
+ using (var oddPatternMask = new Mat(matOdd, new Rectangle(0, 0, target.Width, target.Height)))
{
Parallel.For(operation.LayerIndexStart, operation.LayerIndexEnd + 1, layerIndex =>
{
diff --git a/UVtools.Core/Operations/Operation.cs b/UVtools.Core/Operations/Operation.cs
index 3f656c0..1ed1cfb 100644
--- a/UVtools.Core/Operations/Operation.cs
+++ b/UVtools.Core/Operations/Operation.cs
@@ -6,7 +6,9 @@
* of this license document, but changing it is not allowed.
*/
+using System.Drawing;
using System.Runtime.CompilerServices;
+using Emgu.CV;
using UVtools.Core.Objects;
namespace UVtools.Core.Operations
@@ -78,5 +80,17 @@ namespace UVtools.Core.Operations
public virtual uint LayerIndexEnd { get; set; }
public uint LayerRangeCount => LayerIndexEnd - LayerIndexStart + 1;
+
+ /// <summary>
+ /// Gets or sets an ROI to process this operation
+ /// </summary>
+ public Rectangle ROI { get; set; } = Rectangle.Empty;
+
+ public bool HaveROI => !ROI.IsEmpty;
+
+ public Mat GetRoiOrDefault(Mat defaultMat)
+ {
+ return HaveROI ? new Mat(defaultMat, ROI) : defaultMat;
+ }
}
}
diff --git a/UVtools.Core/Operations/OperationMove.cs b/UVtools.Core/Operations/OperationMove.cs
index 77401ea..c663514 100644
--- a/UVtools.Core/Operations/OperationMove.cs
+++ b/UVtools.Core/Operations/OperationMove.cs
@@ -16,17 +16,17 @@ namespace UVtools.Core.Operations
{
public override string Title => "Move";
public override string Description =>
- "Change the position of the model on the build plate.";
+ "Change or copy the position of the model on the build plate.";
public override string ConfirmationText =>
- $"move model layers {LayerIndexStart} through {LayerIndexEnd} from " +
- $"location {{X={SrcRoi.X},Y={SrcRoi.Y}}} to " +
+ (IsCutMove ? "move" : "copy") + $" model layers {LayerIndexStart} through {LayerIndexEnd} from " +
+ $"location {{X={ROI.X},Y={ROI.Y}}} to " +
$"location {{X={DstRoi.X},Y={DstRoi.Y}}}?";
public override string ProgressTitle =>
- $"Moving model to {{X={DstRoi.X},Y={DstRoi.Y}}}";
+ (IsCutMove ? "Moving" : "Copying") +$" model to {{X={DstRoi.X},Y={DstRoi.Y}}}";
- public override string ProgressAction => "Moved layers";
+ public override string ProgressAction => (IsCutMove ? "Moved" : "Copied")+" layers";
public override StringTag Validate(params object[] parameters)
{
@@ -34,15 +34,12 @@ namespace UVtools.Core.Operations
if (!ValidateBounds())
{
- sb.AppendLine("Your parameters will put the model outside of build plate. Please adjust the location and margins.");
+ sb.AppendLine("Your parameters will put the model outside of build plate. Please adjust the location and margins.");
}
return new StringTag(sb.ToString());
}
-
- public Rectangle SrcRoi { get; set; }
-
private Rectangle _dstRoi = Rectangle.Empty;
public Rectangle DstRoi
{
@@ -57,7 +54,7 @@ namespace UVtools.Core.Operations
public void CalculateDstRoi()
{
- _dstRoi.Size = SrcRoi.Size;
+ _dstRoi.Size = ROI.Size;
switch (Anchor)
{
@@ -65,29 +62,29 @@ namespace UVtools.Core.Operations
_dstRoi.Location = new Point(0, 0);
break;
case Enumerations.Anchor.TopCenter:
- _dstRoi.Location = new Point((int)(ImageWidth / 2 - SrcRoi.Width / 2), 0);
+ _dstRoi.Location = new Point((int)(ImageWidth / 2 - ROI.Width / 2), 0);
break;
case Enumerations.Anchor.TopRight:
- _dstRoi.Location = new Point((int)(ImageWidth - SrcRoi.Width), 0);
+ _dstRoi.Location = new Point((int)(ImageWidth - ROI.Width), 0);
break;
case Enumerations.Anchor.MiddleLeft:
- _dstRoi.Location = new Point(0, (int)(ImageHeight / 2 - SrcRoi.Height / 2));
+ _dstRoi.Location = new Point(0, (int)(ImageHeight / 2 - ROI.Height / 2));
break;
case Enumerations.Anchor.MiddleCenter:
//case Anchor.None:
- _dstRoi.Location = new Point((int)(ImageWidth / 2 - SrcRoi.Width / 2), (int)(ImageHeight / 2 - SrcRoi.Height / 2));
+ _dstRoi.Location = new Point((int)(ImageWidth / 2 - ROI.Width / 2), (int)(ImageHeight / 2 - ROI.Height / 2));
break;
case Enumerations.Anchor.MiddleRight:
- _dstRoi.Location = new Point((int)(ImageWidth - SrcRoi.Width), (int)(ImageHeight / 2 - SrcRoi.Height / 2));
+ _dstRoi.Location = new Point((int)(ImageWidth - ROI.Width), (int)(ImageHeight / 2 - ROI.Height / 2));
break;
case Enumerations.Anchor.BottomLeft:
- _dstRoi.Location = new Point(0, (int)(ImageHeight - SrcRoi.Height));
+ _dstRoi.Location = new Point(0, (int)(ImageHeight - ROI.Height));
break;
case Enumerations.Anchor.BottomCenter:
- _dstRoi.Location = new Point((int)(ImageWidth / 2 - SrcRoi.Width / 2), (int)(ImageHeight - SrcRoi.Height));
+ _dstRoi.Location = new Point((int)(ImageWidth / 2 - ROI.Width / 2), (int)(ImageHeight - ROI.Height));
break;
case Enumerations.Anchor.BottomRight:
- _dstRoi.Location = new Point((int)(ImageWidth - SrcRoi.Width), (int)(ImageHeight - SrcRoi.Height));
+ _dstRoi.Location = new Point((int)(ImageWidth - ROI.Width), (int)(ImageHeight - ROI.Height));
break;
default:
throw new ArgumentOutOfRangeException();
@@ -110,13 +107,15 @@ namespace UVtools.Core.Operations
public int MarginRight { get; set; } = 0;
public int MarginBottom { get; set; } = 0;
+ public bool IsCutMove { get; set; } = true;
+
public OperationMove()
{
}
public OperationMove(Rectangle srcRoi, uint imageWidth = 0, uint imageHeight = 0, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter)
{
- SrcRoi = srcRoi;
+ ROI = srcRoi;
ImageWidth = imageWidth;
ImageHeight = imageHeight;
Anchor = anchor;
diff --git a/UVtools.Core/Operations/OperationPattern.cs b/UVtools.Core/Operations/OperationPattern.cs
index 039c0dd..e5d0e69 100644
--- a/UVtools.Core/Operations/OperationPattern.cs
+++ b/UVtools.Core/Operations/OperationPattern.cs
@@ -46,7 +46,6 @@ namespace UVtools.Core.Operations
#endregion
public Enumerations.Anchor Anchor { get; set; }
- public Rectangle SrcRoi { get; }
public uint ImageWidth { get; }
public uint ImageHeight { get; }
@@ -54,16 +53,16 @@ namespace UVtools.Core.Operations
public ushort MarginCol { get; set; }
public ushort MarginRow { get; set; }
- public ushort MaxMarginCol { get; }
- public ushort MaxMarginRow { get; }
+ public ushort MaxMarginCol { get; set; }
+ public ushort MaxMarginRow { get; set; }
public ushort Cols { get; set; } = 1;
public ushort Rows { get; set; } = 1;
- public ushort MaxCols { get; }
- public ushort MaxRows { get; }
+ public ushort MaxCols { get; set; }
+ public ushort MaxRows { get; set; }
- public Size GetPatternVolume => new Size(Cols * SrcRoi.Width + (Cols - 1) * MarginCol, Rows * SrcRoi.Height + (Rows - 1) * MarginRow);
+ public Size GetPatternVolume => new Size(Cols * ROI.Width + (Cols - 1) * MarginCol, Rows * ROI.Height + (Rows - 1) * MarginRow);
public OperationPattern()
{
@@ -71,12 +70,18 @@ namespace UVtools.Core.Operations
public OperationPattern(Rectangle srcRoi, Size resolution)
{
- SrcRoi = srcRoi;
ImageWidth = (uint) resolution.Width;
ImageHeight = (uint) resolution.Height;
- MaxCols = (ushort) (ImageWidth / srcRoi.Width);
- MaxRows = (ushort) (ImageHeight / srcRoi.Height);
+ SetRoi(srcRoi);
+ }
+
+ public void SetRoi(Rectangle srcRoi)
+ {
+ ROI = srcRoi;
+
+ MaxCols = (ushort)(ImageWidth / srcRoi.Width);
+ MaxRows = (ushort)(ImageHeight / srcRoi.Height);
MaxMarginCol = CalculateMarginCol(MaxCols);
MaxMarginRow = CalculateMarginRow(MaxRows);
@@ -141,13 +146,13 @@ namespace UVtools.Core.Operations
public ushort CalculateMarginCol(ushort cols)
{
if (cols <= 1) return 0;
- return (ushort)((ImageWidth - SrcRoi.Width * cols) / cols);
+ return (ushort)((ImageWidth - ROI.Width * cols) / cols);
}
public ushort CalculateMarginRow(ushort rows)
{
if (rows <= 1) return 0;
- return (ushort)((ImageHeight - SrcRoi.Height * rows) / rows);
+ return (ushort)((ImageHeight - ROI.Height * rows) / rows);
}
public Rectangle GetRoi(ushort col, ushort row)
@@ -155,8 +160,8 @@ namespace UVtools.Core.Operations
var patternVolume = GetPatternVolume;
return new Rectangle(new Point(
- (int) (col * SrcRoi.Width + col * MarginCol + (ImageWidth - patternVolume.Width) / 2),
- (int) (row * SrcRoi.Height + row * MarginRow + (ImageHeight - patternVolume.Height) / 2)), SrcRoi.Size);
+ (int) (col * ROI.Width + col * MarginCol + (ImageWidth - patternVolume.Width) / 2),
+ (int) (row * ROI.Height + row * MarginRow + (ImageHeight - patternVolume.Height) / 2)), ROI.Size);
}
public bool ValidateBounds()
diff --git a/UVtools.GUI/Controls/CtrlToolWindowContent.cs b/UVtools.GUI/Controls/CtrlToolWindowContent.cs
index e096821..bfaf348 100644
--- a/UVtools.GUI/Controls/CtrlToolWindowContent.cs
+++ b/UVtools.GUI/Controls/CtrlToolWindowContent.cs
@@ -81,6 +81,11 @@ namespace UVtools.GUI.Controls
[SettingsBindable(true)] public bool CanRun { get; set; } = true;
+ /// <summary>
+ /// Gets or sets if this control can make use of ROI
+ /// </summary>
+ [SettingsBindable(true)] public bool CanROI { get; set; } = false;
+
[Editor("System.ComponentModel.Design.MultilineStringEditor", typeof(UITypeEditor))]
[SettingsBindable(true)]
public string Description { get; set; }
@@ -161,6 +166,11 @@ namespace UVtools.GUI.Controls
if (ParentToolWindow is null) return true;
BaseOperation.LayerIndexStart = ParentToolWindow.LayerRangeStart;
BaseOperation.LayerIndexEnd = ParentToolWindow.LayerRangeEnd;
+ if (CanROI)
+ {
+ BaseOperation.ROI = Program.FrmMain.ROI;
+ }
+
return true;
}
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolBlur.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolBlur.Designer.cs
index ffe07fd..a70eeb9 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolBlur.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolBlur.Designer.cs
@@ -101,6 +101,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoSize = true;
+ this.CanROI = true;
this.Controls.Add(this.label1);
this.Controls.Add(this.cbBlurOperation);
this.Controls.Add(this.nmSize);
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolEditEditParameters.cs b/UVtools.GUI/Controls/Tools/CtrlToolEditEditParameters.cs
index c0e49f6..228fcf0 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolEditEditParameters.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolEditEditParameters.cs
@@ -159,7 +159,7 @@ namespace UVtools.GUI.Controls.Tools
public override void ExtraActionCall(object sender)
{
- if (sender is Button button)
+ if (ReferenceEquals(sender, ParentToolWindow.btnActionExtra))
{
foreach (var rowControl in RowControls)
{
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolFlip.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolFlip.Designer.cs
index 6d34da4..f319c53 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolFlip.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolFlip.Designer.cs
@@ -69,6 +69,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
+ this.CanROI = true;
this.Controls.Add(this.cbMakeCopy);
this.Controls.Add(this.cbFlipDirection);
this.Controls.Add(this.lbX);
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolMask.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolMask.Designer.cs
index c5ea3cf..0ef38f2 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolMask.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolMask.Designer.cs
@@ -225,8 +225,8 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
- this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ButtonOkEnabled = false;
+ this.CanROI = true;
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.cbInvertMask);
this.Controls.Add(this.lbMaskResolution);
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolMask.cs b/UVtools.GUI/Controls/Tools/CtrlToolMask.cs
index d5d8499..0a7009f 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolMask.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolMask.cs
@@ -30,6 +30,18 @@ namespace UVtools.GUI.Controls.Tools
lbPrinterResolution.Text = $"Printer Resolution: {Program.FrmMain.ActualLayerImage.Size}";
}
+ public override void ExtraActionCall(object sender)
+ {
+ if (ReferenceEquals(sender, ParentToolWindow.btnClearRoi))
+ {
+ Operation.Mask = null;
+ pbMask.Image = null;
+ lbMaskResolution.Text = "Mask resolution: (Unloaded)";
+ ButtonOkEnabled = false;
+ return;
+ }
+ }
+
private void EventClick(object sender, EventArgs e)
{
if (ReferenceEquals(sender, btnImportImageMask))
@@ -44,9 +56,20 @@ namespace UVtools.GUI.Controls.Tools
Operation.Mask = CvInvoke.Imread(fileOpen.FileName, ImreadModes.Grayscale);
- if (Operation.Mask.Size != Program.FrmMain.ActualLayerImage.Size)
+ var roi = Program.FrmMain.ROI;
+ if (roi.IsEmpty)
+ {
+ if (Operation.Mask.Size != Program.FrmMain.ActualLayerImage.Size)
+ {
+ CvInvoke.Resize(Operation.Mask, Operation.Mask, Program.FrmMain.ActualLayerImage.Size);
+ }
+ }
+ else
{
- CvInvoke.Resize(Operation.Mask, Operation.Mask, Program.FrmMain.ActualLayerImage.Size);
+ if (Operation.Mask.Size != roi.Size)
+ {
+ CvInvoke.Resize(Operation.Mask, Operation.Mask, roi.Size);
+ }
}
if (cbInvertMask.Checked)
@@ -72,7 +95,9 @@ namespace UVtools.GUI.Controls.Tools
if (ReferenceEquals(sender, btnMaskGenerate))
{
- Operation.Mask = Program.FrmMain.ActualLayerImage.CloneBlank();
+ var roi = Program.FrmMain.ROI;
+ Operation.Mask = roi.IsEmpty ? Program.FrmMain.ActualLayerImage.CloneBlank() : new Mat(roi.Size, DepthType.Cv8U, 1);
+
lbMaskResolution.Text = $"Mask Resolution: {Operation.Mask.Size}";
int radius = (int)nmGeneratorDiameter.Value;
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolMorph.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolMorph.Designer.cs
index 229e215..59aeccf 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolMorph.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolMorph.Designer.cs
@@ -145,6 +145,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoSize = true;
+ this.CanROI = true;
this.Controls.Add(this.label1);
this.Controls.Add(this.cbMorphOperation);
this.Controls.Add(this.ctrlKernel);
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolMorph.cs b/UVtools.GUI/Controls/Tools/CtrlToolMorph.cs
index 72b34eb..991f382 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolMorph.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolMorph.cs
@@ -45,9 +45,9 @@ namespace UVtools.GUI.Controls.Tools
public override void ExtraActionCall(object sender)
{
- if (sender is CheckBox checkbox)
+ if (ReferenceEquals(sender, ParentToolWindow.cbActionExtra))
{
- ctrlKernel.Visible = checkbox.Checked;
+ ctrlKernel.Visible = ParentToolWindow.cbActionExtra.Checked;
return;
}
}
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolMove.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolMove.Designer.cs
index c142242..3d10a55 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolMove.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolMove.Designer.cs
@@ -29,6 +29,8 @@
private void InitializeComponent()
{
this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.cbMoveType = new System.Windows.Forms.ComboBox();
+ this.label1 = new System.Windows.Forms.Label();
this.lbInsideBounds = new System.Windows.Forms.Label();
this.lbPlacementY = new System.Windows.Forms.Label();
this.lbPlacementX = new System.Windows.Forms.Label();
@@ -64,6 +66,8 @@
//
this.groupBox1.AutoSize = true;
this.groupBox1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.groupBox1.Controls.Add(this.cbMoveType);
+ this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Controls.Add(this.lbInsideBounds);
this.groupBox1.Controls.Add(this.lbPlacementY);
this.groupBox1.Controls.Add(this.lbPlacementX);
@@ -81,11 +85,33 @@
this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.groupBox1.Location = new System.Drawing.Point(0, 0);
this.groupBox1.Name = "groupBox1";
- this.groupBox1.Size = new System.Drawing.Size(570, 214);
+ this.groupBox1.Size = new System.Drawing.Size(570, 260);
this.groupBox1.TabIndex = 24;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Location && Margins";
//
+ // cbMoveType
+ //
+ this.cbMoveType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cbMoveType.FormattingEnabled = true;
+ this.cbMoveType.Items.AddRange(new object[] {
+ "Cut",
+ "Copy"});
+ this.cbMoveType.Location = new System.Drawing.Point(99, 207);
+ this.cbMoveType.Name = "cbMoveType";
+ this.cbMoveType.Size = new System.Drawing.Size(101, 28);
+ this.cbMoveType.TabIndex = 30;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(7, 211);
+ this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(85, 20);
+ this.label1.TabIndex = 29;
+ this.label1.Text = "Move type:";
+ //
// lbInsideBounds
//
this.lbInsideBounds.AutoSize = true;
@@ -392,12 +418,13 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
+ this.CanROI = true;
this.Controls.Add(this.groupBox1);
this.Description = "";
this.ExtraButtonVisible = true;
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Name = "CtrlToolMove";
- this.Size = new System.Drawing.Size(570, 214);
+ this.Size = new System.Drawing.Size(570, 260);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.tableAnchor.ResumeLayout(false);
@@ -437,5 +464,7 @@
private System.Windows.Forms.Label label4;
private System.Windows.Forms.NumericUpDown nmMarginRight;
private System.Windows.Forms.NumericUpDown nmMarginLeft;
+ private System.Windows.Forms.ComboBox cbMoveType;
+ private System.Windows.Forms.Label label1;
}
}
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolMove.cs b/UVtools.GUI/Controls/Tools/CtrlToolMove.cs
index 2ddda86..e9746e4 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolMove.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolMove.cs
@@ -21,26 +21,39 @@ namespace UVtools.GUI.Controls.Tools
public CtrlToolMove()
{
InitializeComponent();
- Operation = new OperationMove(Program.SlicerFile.LayerManager.BoundingRectangle, (uint)Program.FrmMain.ActualLayerImage.Width,
+
+ var roi = Program.FrmMain.ROI;
+
+ Operation = new OperationMove(roi.IsEmpty ? Program.SlicerFile.LayerManager.BoundingRectangle : roi, (uint)Program.FrmMain.ActualLayerImage.Width,
(uint)Program.FrmMain.ActualLayerImage.Height);
SetOperation(Operation);
- lbVolumeWidth.Text = $"Width: {Operation.SrcRoi.Width} / {Operation.ImageWidth}";
- lbVolumeHeight.Text = $"Height: {Operation.SrcRoi.Height} / {Operation.ImageHeight}";
-
+ cbMoveType.SelectedIndex = 0;
ExtraActionCall(this);
}
public override void ExtraActionCall(object sender)
{
- if (sender is Button || ReferenceEquals(sender, this))
+ if (ReferenceEquals(sender, this) || ReferenceEquals(sender, ParentToolWindow.btnActionExtra))
{
+ lbVolumeWidth.Text = $"Width: {Operation.ROI.Width} / {Operation.ImageWidth}";
+ lbVolumeHeight.Text = $"Height: {Operation.ROI.Height} / {Operation.ImageHeight}";
+
nmMarginLeft.Value = 0;
nmMarginTop.Value = 0;
nmMarginRight.Value = 0;
nmMarginBottom.Value = 0;
rbAnchorMiddleCenter.Checked = true;
EventValueChanged(this, EventArgs.Empty);
+
+ return;
+ }
+
+ if (ReferenceEquals(sender, ParentToolWindow.btnClearRoi))
+ {
+ Operation.ROI = Program.SlicerFile.LayerManager.BoundingRectangle;
+ ExtraActionCall(this);
+ return;
}
}
@@ -49,8 +62,8 @@ namespace UVtools.GUI.Controls.Tools
UpdateOperation();
var insideBounds = ButtonOkEnabled = Operation.ValidateBounds();
lbInsideBounds.Text = "Model within boundary: " + (insideBounds ? "Yes" : "No");
- lbPlacementX.Text = $"X: {Operation.DstRoi.X} / {Operation.ImageWidth - Operation.SrcRoi.Width}";
- lbPlacementY.Text = $"Y: {Operation.DstRoi.Y} / {Operation.ImageHeight - Operation.SrcRoi.Height}";
+ lbPlacementX.Text = $"X: {Operation.DstRoi.X} / {Operation.ImageWidth - Operation.ROI.Width}";
+ lbPlacementY.Text = $"Y: {Operation.DstRoi.Y} / {Operation.ImageHeight - Operation.ROI.Height}";
}
public override bool UpdateOperation()
@@ -77,6 +90,7 @@ namespace UVtools.GUI.Controls.Tools
Operation.MarginTop = (int)nmMarginTop.Value;
Operation.MarginRight = (int)nmMarginRight.Value;
Operation.MarginBottom = (int)nmMarginBottom.Value;
+ Operation.IsCutMove = cbMoveType.SelectedIndex == 0;
return true;
}
}
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolPattern.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolPattern.Designer.cs
index ac20b66..7d26dd5 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolPattern.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolPattern.Designer.cs
@@ -397,8 +397,8 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ButtonOkEnabled = false;
+ this.CanROI = true;
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.btnAutoMarginRow);
this.Controls.Add(this.btnAutoMarginCol);
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolPattern.cs b/UVtools.GUI/Controls/Tools/CtrlToolPattern.cs
index 240f6ef..3519d2b 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolPattern.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolPattern.cs
@@ -22,7 +22,9 @@ namespace UVtools.GUI.Controls.Tools
public CtrlToolPattern()
{
InitializeComponent();
- Operation = new OperationPattern(Program.SlicerFile.LayerManager.BoundingRectangle, Program.FrmMain.ActualLayerImage.Size);
+
+ var roi = Program.FrmMain.ROI;
+ Operation = new OperationPattern(roi.IsEmpty ? Program.SlicerFile.LayerManager.BoundingRectangle : roi, Program.FrmMain.ActualLayerImage.Size);
SetOperation(Operation);
if (Operation.MaxRows < 2 && Operation.MaxCols < 2)
@@ -34,22 +36,31 @@ namespace UVtools.GUI.Controls.Tools
return;
}
- nmCols.Maximum = Operation.MaxCols;
- nmRows.Maximum = Operation.MaxRows;
-
ExtraActionCall(this);
}
public override void ExtraActionCall(object sender)
{
- if (sender is Button || ReferenceEquals(sender, this))
+ if (ReferenceEquals(sender, this) || ReferenceEquals(sender, ParentToolWindow.btnActionExtra))
{
+ nmCols.Maximum = Operation.MaxCols;
+ nmRows.Maximum = Operation.MaxRows;
+
nmMarginCol.Value = Operation.MaxMarginCol;
nmMarginRow.Value = Operation.MaxMarginRow;
nmCols.Value = Operation.MaxCols;
nmRows.Value = Operation.MaxRows;
Operation.Fill();
EventValueChanged(this, EventArgs.Empty);
+
+ return;
+ }
+
+ if (ReferenceEquals(sender, ParentToolWindow.btnClearRoi))
+ {
+ Operation.SetRoi(Program.SlicerFile.LayerManager.BoundingRectangle);
+ ExtraActionCall(this);
+ return;
}
}
@@ -91,8 +102,8 @@ namespace UVtools.GUI.Controls.Tools
ButtonOkEnabled = insideBounds && (Operation.Cols > 1 || Operation.Rows > 1);
lbInsideBounds.Text = "Model within boundary: " + (insideBounds ? "Yes" : "No");
- lbVolumeWidth.Text = $"Width: {Operation.GetPatternVolume.Width} (Min:{Operation.SrcRoi.Width}, Max:{Operation.ImageWidth})";
- lbVolumeHeight.Text = $"Height: {Operation.GetPatternVolume.Height} (Min:{Operation.SrcRoi.Height}, Max:{Operation.ImageHeight})";
+ lbVolumeWidth.Text = $"Width: {Operation.GetPatternVolume.Width} (Min:{Operation.ROI.Width}, Max:{Operation.ImageWidth})";
+ lbVolumeHeight.Text = $"Height: {Operation.GetPatternVolume.Height} (Min:{Operation.ROI.Height}, Max:{Operation.ImageHeight})";
lbCols.Text = $"Columns: {nmCols.Value} / {Operation.MaxCols}";
lbRows.Text = $"Rows: {nmRows.Value} / {Operation.MaxRows}";
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolPixelDimming.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolPixelDimming.Designer.cs
index 0a175b7..ee58e5e 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolPixelDimming.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolPixelDimming.Designer.cs
@@ -508,7 +508,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
- this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.CanROI = true;
this.Controls.Add(this.cbDimsOnlyBorders);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.label5);
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.cs b/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.cs
index 8f6aae9..c8fe8a9 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.cs
@@ -47,9 +47,9 @@ namespace UVtools.GUI.Controls.Tools
public override void ExtraActionCall(object sender)
{
- if (sender is CheckBox checkbox)
+ if (ReferenceEquals(sender, ParentToolWindow.cbActionExtra))
{
- LayerRangeVisible = groupAdvancedSettings.Visible = checkbox.Checked;
+ LayerRangeVisible = groupAdvancedSettings.Visible = ParentToolWindow.cbActionExtra.Checked;
return;
}
}
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolResize.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolResize.Designer.cs
index 226becd..3a3f35d 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolResize.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolResize.Designer.cs
@@ -166,6 +166,7 @@
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.ButtonOkEnabled = false;
+ this.CanROI = true;
this.Controls.Add(this.cbFade);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolRotate.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolRotate.Designer.cs
index 135276c..94737a0 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolRotate.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolRotate.Designer.cs
@@ -52,8 +52,8 @@
this.nmDegrees.Name = "nmDegrees";
this.nmDegrees.Size = new System.Drawing.Size(101, 26);
this.nmDegrees.TabIndex = 23;
- this.toolTip.SetToolTip(this.nmDegrees, "Number of degrees to rotate the layers, where postive values are clockwise and" +
- " negative values are counter-clockwise.");
+ this.toolTip.SetToolTip(this.nmDegrees, "Number of degrees to rotate the layers, where postive values are clockwise and ne" +
+ "gative values are counter-clockwise.");
this.nmDegrees.Value = new decimal(new int[] {
90,
0,
@@ -85,7 +85,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.CanROI = true;
this.Controls.Add(this.label1);
this.Controls.Add(this.nmDegrees);
this.Controls.Add(this.lbX);
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolSolidify.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolSolidify.Designer.cs
new file mode 100644
index 0000000..9820f01
--- /dev/null
+++ b/UVtools.GUI/Controls/Tools/CtrlToolSolidify.Designer.cs
@@ -0,0 +1,48 @@
+namespace UVtools.GUI.Controls.Tools
+{
+ partial class CtrlToolSolidify
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ //
+ // CtrlToolSolidify
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.AutoSize = true;
+ this.CanROI = true;
+ this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.Name = "CtrlToolSolidify";
+ this.Size = new System.Drawing.Size(540, 0);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ }
+}
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolSolidify.cs b/UVtools.GUI/Controls/Tools/CtrlToolSolidify.cs
new file mode 100644
index 0000000..3f4b609
--- /dev/null
+++ b/UVtools.GUI/Controls/Tools/CtrlToolSolidify.cs
@@ -0,0 +1,23 @@
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+using System.Windows.Forms;
+using UVtools.Core.Operations;
+
+namespace UVtools.GUI.Controls.Tools
+{
+ public partial class CtrlToolSolidify : CtrlToolWindowContent
+ {
+ private OperationSolidify Operation { get; }
+ public CtrlToolSolidify()
+ {
+ InitializeComponent();
+ Operation = new OperationSolidify();
+ SetOperation(Operation);
+ }
+ }
+}
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolSolidify.resx b/UVtools.GUI/Controls/Tools/CtrlToolSolidify.resx
new file mode 100644
index 0000000..8766f29
--- /dev/null
+++ b/UVtools.GUI/Controls/Tools/CtrlToolSolidify.resx
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>17, 17</value>
+ </metadata>
+</root> \ No newline at end of file
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolThreshold.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolThreshold.Designer.cs
index 9e5ee5d..b1abf20 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolThreshold.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolThreshold.Designer.cs
@@ -132,6 +132,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
+ this.CanROI = true;
this.Controls.Add(this.label3);
this.Controls.Add(this.cbPresetHelpers);
this.Controls.Add(this.nmMaximum);
diff --git a/UVtools.GUI/Forms/FrmLoading.cs b/UVtools.GUI/Forms/FrmLoading.cs
index fb4204a..61cd510 100644
--- a/UVtools.GUI/Forms/FrmLoading.cs
+++ b/UVtools.GUI/Forms/FrmLoading.cs
@@ -66,6 +66,8 @@ namespace UVtools.GUI.Forms
btnCancel.Enabled = CanCancel;
btnCancel.Text = "Cancel";
+
+ Cursor = Cursors.AppStarting;
}
protected override void OnClosed(EventArgs e)
@@ -75,6 +77,7 @@ namespace UVtools.GUI.Forms
StopWatch.Stop();
Progress = null;
OperationLog.ElapsedTime = (uint) StopWatch.ElapsedMilliseconds / 1000m;
+ Cursor = Cursors.Arrow;
}
public OperationProgress RestartProgress(bool canCancel = true)
diff --git a/UVtools.GUI/Forms/FrmToolWindow.Designer.cs b/UVtools.GUI/Forms/FrmToolWindow.Designer.cs
index 469b5e9..fe732e0 100644
--- a/UVtools.GUI/Forms/FrmToolWindow.Designer.cs
+++ b/UVtools.GUI/Forms/FrmToolWindow.Designer.cs
@@ -41,7 +41,6 @@ namespace UVtools.GUI.Forms
this.lbLayerRangeFromMM = new System.Windows.Forms.Label();
this.lbLayerRangeToMM = new System.Windows.Forms.Label();
this.nmLayerRangeEnd = new System.Windows.Forms.NumericUpDown();
- this.btnLayerRangeSelect = new UVtools.GUI.Controls.SplitButton();
this.cmLayerRange = new System.Windows.Forms.ContextMenuStrip(this.components);
this.btnLayerRangeAllLayers = new System.Windows.Forms.ToolStripMenuItem();
this.btnLayerRangeCurrentLayer = new System.Windows.Forms.ToolStripMenuItem();
@@ -60,6 +59,13 @@ namespace UVtools.GUI.Forms
this.btnActionExtra = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.btnOk = new System.Windows.Forms.Button();
+ this.pnROI = new System.Windows.Forms.Panel();
+ this.gbROI = new System.Windows.Forms.GroupBox();
+ this.lbRoi = new System.Windows.Forms.Label();
+ this.btnClearRoi = new System.Windows.Forms.Button();
+ this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+ this.cbClearRoiAfterOperation = new System.Windows.Forms.CheckBox();
+ this.btnLayerRangeSelect = new UVtools.GUI.Controls.SplitButton();
this.pnDescription.SuspendLayout();
this.pnLayerRange.SuspendLayout();
this.gbLayerRange.SuspendLayout();
@@ -68,6 +74,8 @@ namespace UVtools.GUI.Forms
((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeStart)).BeginInit();
this.table.SuspendLayout();
this.pnActions.SuspendLayout();
+ this.pnROI.SuspendLayout();
+ this.gbROI.SuspendLayout();
this.SuspendLayout();
//
// pnDescription
@@ -102,7 +110,7 @@ namespace UVtools.GUI.Forms
this.pnContent.BackColor = System.Drawing.Color.White;
this.pnContent.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pnContent.Dock = System.Windows.Forms.DockStyle.Fill;
- this.pnContent.Location = new System.Drawing.Point(3, 191);
+ this.pnContent.Location = new System.Drawing.Point(3, 312);
this.pnContent.Name = "pnContent";
this.pnContent.Size = new System.Drawing.Size(548, 2);
this.pnContent.TabIndex = 9;
@@ -185,16 +193,6 @@ namespace UVtools.GUI.Forms
this.nmLayerRangeEnd.TabIndex = 14;
this.nmLayerRangeEnd.ValueChanged += new System.EventHandler(this.EventValueChanged);
//
- // btnLayerRangeSelect
- //
- this.btnLayerRangeSelect.Location = new System.Drawing.Point(359, 31);
- this.btnLayerRangeSelect.Menu = this.cmLayerRange;
- this.btnLayerRangeSelect.Name = "btnLayerRangeSelect";
- this.btnLayerRangeSelect.Size = new System.Drawing.Size(180, 26);
- this.btnLayerRangeSelect.TabIndex = 18;
- this.btnLayerRangeSelect.Text = "Select";
- this.btnLayerRangeSelect.UseVisualStyleBackColor = true;
- //
// cmLayerRange
//
this.cmLayerRange.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -314,18 +312,20 @@ namespace UVtools.GUI.Forms
this.table.ColumnCount = 1;
this.table.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.table.Controls.Add(this.pnDescription, 0, 0);
- this.table.Controls.Add(this.pnActions, 0, 3);
- this.table.Controls.Add(this.pnContent, 0, 2);
+ this.table.Controls.Add(this.pnActions, 0, 4);
+ this.table.Controls.Add(this.pnContent, 0, 3);
this.table.Controls.Add(this.pnLayerRange, 0, 1);
+ this.table.Controls.Add(this.pnROI, 0, 2);
this.table.Dock = System.Windows.Forms.DockStyle.Fill;
this.table.Location = new System.Drawing.Point(0, 0);
this.table.Name = "table";
- this.table.RowCount = 4;
+ this.table.RowCount = 5;
this.table.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.table.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.table.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.table.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.table.Size = new System.Drawing.Size(554, 281);
+ this.table.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.table.Size = new System.Drawing.Size(554, 404);
this.table.TabIndex = 10;
//
// pnActions
@@ -338,16 +338,15 @@ namespace UVtools.GUI.Forms
this.pnActions.Controls.Add(this.btnCancel);
this.pnActions.Controls.Add(this.btnOk);
this.pnActions.Dock = System.Windows.Forms.DockStyle.Fill;
- this.pnActions.Location = new System.Drawing.Point(3, 199);
+ this.pnActions.Location = new System.Drawing.Point(3, 320);
this.pnActions.Name = "pnActions";
- this.pnActions.Size = new System.Drawing.Size(548, 85);
+ this.pnActions.Size = new System.Drawing.Size(548, 86);
this.pnActions.TabIndex = 8;
//
// cbActionExtra
//
- this.cbActionExtra.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.cbActionExtra.AutoSize = true;
- this.cbActionExtra.Location = new System.Drawing.Point(10, 31);
+ this.cbActionExtra.Location = new System.Drawing.Point(10, 30);
this.cbActionExtra.Name = "cbActionExtra";
this.cbActionExtra.Size = new System.Drawing.Size(202, 24);
this.cbActionExtra.TabIndex = 26;
@@ -358,11 +357,10 @@ namespace UVtools.GUI.Forms
//
// btnActionExtra
//
- this.btnActionExtra.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnActionExtra.AutoSize = true;
this.btnActionExtra.Image = global::UVtools.GUI.Properties.Resources.undo_alt_16x16;
this.btnActionExtra.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
- this.btnActionExtra.Location = new System.Drawing.Point(4, 19);
+ this.btnActionExtra.Location = new System.Drawing.Point(4, 18);
this.btnActionExtra.Name = "btnActionExtra";
this.btnActionExtra.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0);
this.btnActionExtra.Size = new System.Drawing.Size(177, 48);
@@ -375,11 +373,12 @@ namespace UVtools.GUI.Forms
//
// btnCancel
//
- this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnCancel.AutoSize = true;
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Image = global::UVtools.GUI.Properties.Resources.Cancel_24x24;
this.btnCancel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
- this.btnCancel.Location = new System.Drawing.Point(430, 19);
+ this.btnCancel.Location = new System.Drawing.Point(430, 18);
this.btnCancel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0);
@@ -393,20 +392,98 @@ namespace UVtools.GUI.Forms
//
// btnOk
//
- this.btnOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnOk.AutoSize = true;
this.btnOk.Image = global::UVtools.GUI.Properties.Resources.Ok_24x24;
this.btnOk.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
- this.btnOk.Location = new System.Drawing.Point(330, 19);
+ this.btnOk.Location = new System.Drawing.Point(340, 18);
this.btnOk.Name = "btnOk";
this.btnOk.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0);
- this.btnOk.Size = new System.Drawing.Size(93, 48);
+ this.btnOk.Size = new System.Drawing.Size(83, 48);
this.btnOk.TabIndex = 5;
this.btnOk.Text = "&Ok";
this.btnOk.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
this.btnOk.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
this.btnOk.Click += new System.EventHandler(this.EventClick);
//
+ // pnROI
+ //
+ this.pnROI.AutoSize = true;
+ this.pnROI.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.pnROI.Controls.Add(this.gbROI);
+ this.pnROI.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.pnROI.Location = new System.Drawing.Point(3, 191);
+ this.pnROI.Name = "pnROI";
+ this.pnROI.Size = new System.Drawing.Size(548, 115);
+ this.pnROI.TabIndex = 10;
+ this.pnROI.Visible = false;
+ //
+ // gbROI
+ //
+ this.gbROI.AutoSize = true;
+ this.gbROI.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.gbROI.Controls.Add(this.cbClearRoiAfterOperation);
+ this.gbROI.Controls.Add(this.lbRoi);
+ this.gbROI.Controls.Add(this.btnClearRoi);
+ this.gbROI.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.gbROI.Location = new System.Drawing.Point(0, 0);
+ this.gbROI.Name = "gbROI";
+ this.gbROI.Size = new System.Drawing.Size(548, 115);
+ this.gbROI.TabIndex = 0;
+ this.gbROI.TabStop = false;
+ this.gbROI.Text = "ROI - Region of interest";
+ this.toolTip.SetToolTip(this.gbROI, "The impact of the operation will be limited to the ROI, which can be set directly" +
+ " from the layer preview window.");
+ //
+ // lbRoi
+ //
+ this.lbRoi.AutoSize = true;
+ this.lbRoi.Location = new System.Drawing.Point(7, 33);
+ this.lbRoi.Name = "lbRoi";
+ this.lbRoi.Size = new System.Drawing.Size(151, 20);
+ this.lbRoi.TabIndex = 2;
+ this.lbRoi.Text = "Region: (Rectangle)";
+ this.toolTip.SetToolTip(this.lbRoi, "The impact of the operation will be limited to the ROI, which can be set directly" +
+ " from the layer preview window.");
+ //
+ // btnClearRoi
+ //
+ this.btnClearRoi.Location = new System.Drawing.Point(309, 57);
+ this.btnClearRoi.Name = "btnClearRoi";
+ this.btnClearRoi.Size = new System.Drawing.Size(103, 33);
+ this.btnClearRoi.TabIndex = 1;
+ this.btnClearRoi.Text = "Clear ROI";
+ this.btnClearRoi.UseVisualStyleBackColor = true;
+ this.btnClearRoi.Click += new System.EventHandler(this.EventClick);
+ //
+ // toolTip
+ //
+ this.toolTip.AutoPopDelay = 32767;
+ this.toolTip.InitialDelay = 500;
+ this.toolTip.ReshowDelay = 100;
+ this.toolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info;
+ this.toolTip.ToolTipTitle = "Information";
+ //
+ // cbClearRoiAfterOperation
+ //
+ this.cbClearRoiAfterOperation.AutoSize = true;
+ this.cbClearRoiAfterOperation.Location = new System.Drawing.Point(11, 61);
+ this.cbClearRoiAfterOperation.Name = "cbClearRoiAfterOperation";
+ this.cbClearRoiAfterOperation.Size = new System.Drawing.Size(292, 24);
+ this.cbClearRoiAfterOperation.TabIndex = 3;
+ this.cbClearRoiAfterOperation.Text = "Clear ROI after perform the operation";
+ this.cbClearRoiAfterOperation.UseVisualStyleBackColor = true;
+ //
+ // btnLayerRangeSelect
+ //
+ this.btnLayerRangeSelect.Location = new System.Drawing.Point(359, 31);
+ this.btnLayerRangeSelect.Menu = this.cmLayerRange;
+ this.btnLayerRangeSelect.Name = "btnLayerRangeSelect";
+ this.btnLayerRangeSelect.Size = new System.Drawing.Size(180, 26);
+ this.btnLayerRangeSelect.TabIndex = 18;
+ this.btnLayerRangeSelect.Text = "Select";
+ this.btnLayerRangeSelect.UseVisualStyleBackColor = true;
+ //
// FrmToolWindow
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
@@ -415,7 +492,7 @@ namespace UVtools.GUI.Forms
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.BackColor = System.Drawing.Color.White;
this.CancelButton = this.btnCancel;
- this.ClientSize = new System.Drawing.Size(554, 281);
+ this.ClientSize = new System.Drawing.Size(554, 404);
this.Controls.Add(this.table);
this.DoubleBuffered = true;
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
@@ -444,6 +521,10 @@ namespace UVtools.GUI.Forms
this.table.PerformLayout();
this.pnActions.ResumeLayout(false);
this.pnActions.PerformLayout();
+ this.pnROI.ResumeLayout(false);
+ this.pnROI.PerformLayout();
+ this.gbROI.ResumeLayout(false);
+ this.gbROI.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@@ -477,6 +558,12 @@ namespace UVtools.GUI.Forms
private System.Windows.Forms.ToolStripMenuItem btnLayerRangeFirstLayer;
private System.Windows.Forms.ToolStripMenuItem btnLayerRangeLastLayer;
public System.Windows.Forms.Button btnActionExtra;
- private System.Windows.Forms.CheckBox cbActionExtra;
+ private System.Windows.Forms.Panel pnROI;
+ private System.Windows.Forms.GroupBox gbROI;
+ private System.Windows.Forms.Label lbRoi;
+ public System.Windows.Forms.ToolTip toolTip;
+ public System.Windows.Forms.CheckBox cbActionExtra;
+ public System.Windows.Forms.Button btnClearRoi;
+ public System.Windows.Forms.CheckBox cbClearRoiAfterOperation;
}
} \ No newline at end of file
diff --git a/UVtools.GUI/Forms/FrmToolWindow.cs b/UVtools.GUI/Forms/FrmToolWindow.cs
index f6e6502..f9a3875 100644
--- a/UVtools.GUI/Forms/FrmToolWindow.cs
+++ b/UVtools.GUI/Forms/FrmToolWindow.cs
@@ -149,6 +149,17 @@ namespace UVtools.GUI.Forms
pnContent.Visible = false;
}
+ var ROI = Program.FrmMain.ROI;
+ if (ROI != Rectangle.Empty)
+ {
+ pnROI.Visible = true;
+ lbRoi.Text = ROI.ToString();
+
+ /*lbDescription.Text +=
+ "\n\nNOTE: The operation will only be applied to the selected Region of Interest indicated below.\n" +
+ "The Region of Interest can be set directly from the layer preview window prior to running this tool.";*/
+ }
+
EventValueChanged(nmLayerRangeStart, EventArgs.Empty);
EventValueChanged(nmLayerRangeEnd, EventArgs.Empty);
}
@@ -172,6 +183,12 @@ namespace UVtools.GUI.Forms
ExtraCheckboxText = content.ExtraCheckboxText;
btnOk.Enabled = content.ButtonOkEnabled;
//content.AutoSize = true;
+
+ if (!content.CanROI)
+ {
+ pnROI.Visible = false;
+ }
+
Content = content;
content.PropertyChanged += ContentOnPropertyChanged;
@@ -318,6 +335,18 @@ namespace UVtools.GUI.Forms
return;
}
+ if (ReferenceEquals(sender, btnClearRoi))
+ {
+ if (MessageQuestionBox("Are you sure you want to clear the current ROI?\n" +
+ "This action can not be reverted, to select another ROI you must quit this window and select it on layer preview.",
+ "Clear the current ROI?") != DialogResult.Yes) return;
+ Program.FrmMain.pbLayer.SelectNone();
+ cbClearRoiAfterOperation.Checked = false;
+ pnROI.Visible = false;
+ ExtraActionCall(btnClearRoi);
+ return;
+ }
+
if (ReferenceEquals(sender, btnActionExtra) || ReferenceEquals(sender, cbActionExtra))
{
ExtraActionCall(sender);
@@ -351,6 +380,11 @@ namespace UVtools.GUI.Forms
DialogResult.Yes) return;
}
+ if (cbClearRoiAfterOperation.Checked)
+ {
+ Program.FrmMain.pbLayer.SelectNone();
+ }
+
DialogResult = DialogResult.OK;
Close();
diff --git a/UVtools.GUI/Forms/FrmToolWindow.resx b/UVtools.GUI/Forms/FrmToolWindow.resx
index 83a57f5..fa91044 100644
--- a/UVtools.GUI/Forms/FrmToolWindow.resx
+++ b/UVtools.GUI/Forms/FrmToolWindow.resx
@@ -120,6 +120,9 @@
<metadata name="cmLayerRange.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
+ <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>107, 17</value>
+ </metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
diff --git a/UVtools.GUI/FrmMain.Designer.cs b/UVtools.GUI/FrmMain.Designer.cs
index 8a22929..627849f 100644
--- a/UVtools.GUI/FrmMain.Designer.cs
+++ b/UVtools.GUI/FrmMain.Designer.cs
@@ -247,6 +247,7 @@ namespace UVtools.GUI
this.panelLayerNavigation = new System.Windows.Forms.Panel();
this.pbTrackerIssues = new System.Windows.Forms.PictureBox();
this.lbActualLayer = new System.Windows.Forms.Label();
+ this.tbLayer = new UVtools.GUI.Controls.TrackBarEx();
this.lbInitialLayer = new System.Windows.Forms.Label();
this.panel2 = new System.Windows.Forms.Panel();
this.btnFindLayer = new System.Windows.Forms.Button();
@@ -257,7 +258,6 @@ namespace UVtools.GUI
this.toolTipInformation = new System.Windows.Forms.ToolTip(this.components);
this.layerScrollTimer = new System.Windows.Forms.Timer(this.components);
this.mouseHoldTimer = new System.Windows.Forms.Timer(this.components);
- this.tbLayer = new UVtools.GUI.Controls.TrackBarEx();
this.menu.SuspendLayout();
this.mainTable.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.scCenter)).BeginInit();
@@ -316,8 +316,8 @@ namespace UVtools.GUI
this.tlRight.SuspendLayout();
this.panelLayerNavigation.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pbTrackerIssues)).BeginInit();
- this.panel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.tbLayer)).BeginInit();
+ this.panel2.SuspendLayout();
this.SuspendLayout();
//
// menu
@@ -2737,6 +2737,18 @@ namespace UVtools.GUI
this.lbActualLayer.TabIndex = 9;
this.lbActualLayer.Text = "?";
//
+ // tbLayer
+ //
+ this.tbLayer.Dock = System.Windows.Forms.DockStyle.Right;
+ this.tbLayer.Location = new System.Drawing.Point(93, 0);
+ this.tbLayer.Margin = new System.Windows.Forms.Padding(0);
+ this.tbLayer.Name = "tbLayer";
+ this.tbLayer.Orientation = System.Windows.Forms.Orientation.Vertical;
+ this.tbLayer.Size = new System.Drawing.Size(45, 557);
+ this.tbLayer.TabIndex = 8;
+ this.tbLayer.TickStyle = System.Windows.Forms.TickStyle.TopLeft;
+ this.tbLayer.ValueChanged += new System.EventHandler(this.ValueChanged);
+ //
// lbInitialLayer
//
this.lbInitialLayer.Dock = System.Windows.Forms.DockStyle.Fill;
@@ -2827,18 +2839,6 @@ namespace UVtools.GUI
this.mouseHoldTimer.Interval = 1000;
this.mouseHoldTimer.Tick += new System.EventHandler(this.EventTimerTick);
//
- // tbLayer
- //
- this.tbLayer.Dock = System.Windows.Forms.DockStyle.Right;
- this.tbLayer.Location = new System.Drawing.Point(93, 0);
- this.tbLayer.Margin = new System.Windows.Forms.Padding(0);
- this.tbLayer.Name = "tbLayer";
- this.tbLayer.Orientation = System.Windows.Forms.Orientation.Vertical;
- this.tbLayer.Size = new System.Drawing.Size(45, 557);
- this.tbLayer.TabIndex = 8;
- this.tbLayer.TickStyle = System.Windows.Forms.TickStyle.TopLeft;
- this.tbLayer.ValueChanged += new System.EventHandler(this.ValueChanged);
- //
// FrmMain
//
this.AllowDrop = true;
@@ -2945,8 +2945,8 @@ namespace UVtools.GUI
this.panelLayerNavigation.ResumeLayout(false);
this.panelLayerNavigation.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pbTrackerIssues)).EndInit();
- this.panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.tbLayer)).EndInit();
+ this.panel2.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
@@ -3000,7 +3000,6 @@ namespace UVtools.GUI
private System.Windows.Forms.ToolStripButton btnLayerImageRotate;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
private System.Windows.Forms.ToolStripButton btnLayerImageLayerDifference;
- private Cyotek.Windows.Forms.ImageBox pbLayer;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator7;
private System.Windows.Forms.ToolStripButton btnLayerImagePixelEdit;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator9;
@@ -3180,6 +3179,7 @@ namespace UVtools.GUI
private System.Windows.Forms.ToolStripSeparator toolStripSeparator26;
private System.Windows.Forms.ToolStripButton btnLogVerbose;
private System.Windows.Forms.Label lbLayerImageOverlay;
+ public Cyotek.Windows.Forms.ImageBox pbLayer;
}
}
diff --git a/UVtools.GUI/FrmMain.cs b/UVtools.GUI/FrmMain.cs
index 8ea093d..0d23959 100644
--- a/UVtools.GUI/FrmMain.cs
+++ b/UVtools.GUI/FrmMain.cs
@@ -15,6 +15,7 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
+using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -71,12 +72,24 @@ namespace UVtools.GUI
public FrmLoading FrmLoading { get; }
+ public Rectangle ROI
+ {
+ get
+ {
+ var rectangleF = pbLayer.SelectionRegion;
+ return rectangleF.IsEmpty ? Rectangle.Empty : GetTransposedRectangle(rectangleF, false);
+ }
+ set => pbLayer.SelectionRegion = value;
+ }
+
public static FileFormat SlicerFile
{
get => Program.SlicerFile;
set => Program.SlicerFile = value;
}
+ public LayerCache LayerCache { get; set; } = new LayerCache();
+
public uint ActualLayer { get; set; }
public Mat ActualLayerImage { get; private set; }
@@ -1338,6 +1351,14 @@ namespace UVtools.GUI
ShowLayer();
if (ReferenceEquals(sender, btnLayerImageRotate))
{
+ // Arrange selection rotation
+ var rectangleF = pbLayer.SelectionRegion;
+ if (!rectangleF.IsEmpty)
+ {
+ var rectangle = Rectangle.Round(rectangleF);
+ pbLayer.SelectionRegion = GetTransposedRectangle(rectangle, btnLayerImageRotate.Checked, true);
+ }
+
ZoomToFit();
}
@@ -1715,6 +1736,8 @@ namespace UVtools.GUI
// GUI CLEAN
pbThumbnail.Image = null;
pbLayer.Image = null;
+ pbLayer.SelectNone();
+ lbLayerImageOverlay.Visible = false;
pbThumbnail.Image = null;
tbGCode.Clear();
tabPageIssues.Tag = null;
@@ -2245,19 +2268,6 @@ namespace UVtools.GUI
var layer = SlicerFile[ActualLayer];
- VectorOfVectorOfPoint layerContours = null;
- Mat layerHierarchy = null;
- Array layerHierarchyJagged = null;
-
- void initContours()
- {
- if (!ReferenceEquals(layerContours, null)) return;
- layerContours = new VectorOfVectorOfPoint();
- layerHierarchy = new Mat();
- CvInvoke.FindContours(ActualLayerImage, layerContours, layerHierarchy, RetrType.Ccomp,
- ChainApproxMethod.ChainApproxSimple);
- layerHierarchyJagged = layerHierarchy.GetData();
- }
try
{
@@ -2273,6 +2283,7 @@ namespace UVtools.GUI
ActualLayerImage?.Dispose();
ActualLayerImage = SlicerFile[layerNum].LayerMat;
+ LayerCache.Image = ActualLayerImage;
CvInvoke.CvtColor(ActualLayerImage, ActualLayerImageBgr, ColorConversion.Gray2Bgr);
@@ -2475,7 +2486,6 @@ namespace UVtools.GUI
if (btnLayerImageLayerOutlineHollowAreas.Checked)
{
//CvInvoke.Threshold(ActualLayerImage, grayscale, 1, 255, ThresholdType.Binary);
- initContours();
/*
* hierarchy[i][0]: the index of the next contour of the same level
@@ -2483,14 +2493,14 @@ namespace UVtools.GUI
* hierarchy[i][2]: the index of the first child
* hierarchy[i][3]: the index of the parent
*/
- for (int i = 0; i < layerContours.Size; i++)
+ for (int i = 0; i < LayerCache.LayerContours.Size; i++)
{
- if ((int) layerHierarchyJagged.GetValue(0, i, 2) == -1 &&
- (int) layerHierarchyJagged.GetValue(0, i, 3) != -1)
+ if ((int)LayerCache.LayerHierarchyJagged.GetValue(0, i, 2) == -1 &&
+ (int)LayerCache.LayerHierarchyJagged.GetValue(0, i, 3) != -1)
{
//var r = CvInvoke.BoundingRectangle(contours[i]);
//CvInvoke.Rectangle(ActualLayerImageBgr, r, new MCvScalar(0, 0, 255), 2);
- CvInvoke.DrawContours(ActualLayerImageBgr, layerContours, i,
+ CvInvoke.DrawContours(ActualLayerImageBgr, LayerCache.LayerContours, i,
new MCvScalar(Settings.Default.OutlineHollowAreasColor.B,
Settings.Default.OutlineHollowAreasColor.G,
Settings.Default.OutlineHollowAreasColor.R),
@@ -2563,16 +2573,15 @@ namespace UVtools.GUI
}
else if (operation.OperationType == PixelOperation.PixelOperationType.Eraser)
{
- initContours();
if (imageSpan[ActualLayerImage.GetPixelPos(operation.Location)] < 10) continue;
var color = flvPixelHistory.SelectedObjects.Contains(operation)
? Settings.Default.PixelEditorRemovePixelHLColor
: Settings.Default.PixelEditorRemovePixelColor;
- for (int i = 0; i < layerContours.Size; i++)
+ for (int i = 0; i < LayerCache.LayerContours.Size; i++)
{
- if (CvInvoke.PointPolygonTest(layerContours[i], operation.Location, false) >= 0)
+ if (CvInvoke.PointPolygonTest(LayerCache.LayerContours[i], operation.Location, false) >= 0)
{
- CvInvoke.DrawContours(ActualLayerImageBgr, layerContours, i,
+ CvInvoke.DrawContours(ActualLayerImageBgr, LayerCache.LayerContours, i,
new MCvScalar(color.B, color.G, color.R), -1);
break;
}
@@ -2627,6 +2636,11 @@ namespace UVtools.GUI
if (btnLayerImageRotate.Checked)
{
CvInvoke.Rotate(ActualLayerImageBgr, ActualLayerImageBgr, RotateFlags.Rotate90Clockwise);
+ /*var roi = Rectangle.Round(pbLayer.SelectionRegion);
+ if (roi != Rectangle.Empty)
+ {
+ pbLayer.SelectionRegion = G
+ }*/
}
@@ -2650,10 +2664,6 @@ namespace UVtools.GUI
tsLayerInfo.Update();
tsLayerInfo.Refresh();
- layerContours?.Dispose();
- layerHierarchy?.Dispose();
-
-
watch.Stop();
tsLayerPreviewTime.Text = $"{watch.ElapsedMilliseconds}ms";
//lbLayers.Text = $"{SlicerFile.GetHeightFromLayer(layerNum)} / {SlicerFile.TotalHeight}mm\n{layerNum} / {SlicerFile.LayerCount-1}\n{percent}%";
@@ -2794,14 +2804,17 @@ namespace UVtools.GUI
{
pbLayer.Cursor = Cursors.Cross;
pbLayer.PanMode = ImageBoxPanMode.None;
- lbLayerImageOverlay.Text = "Pixel editing is on\n" +
- "Click to over a pixel to draw";
+ lbLayerImageOverlay.Text = "Pixel editing is on:\n" +
+ "» Click to over a pixel to draw";
}
else
{
+ pbLayer.Cursor = Cursors.Cross;
pbLayer.SelectionMode = ImageBoxSelectionMode.Rectangle;
- lbLayerImageOverlay.Text = "ROI selection mode\n" +
- "Click and drag to select an ROI\n" +
+ lbLayerImageOverlay.Text = "ROI selection mode:\n" +
+ "» Left-click and drag to select an ROI\n" +
+ "» Left-click + Alt and drag to select contained objects\n" +
+ "» Right click on an object to select its area\n" +
"Press Esc to clear the ROI";
}
@@ -2813,8 +2826,8 @@ namespace UVtools.GUI
{
pbLayer.Cursor = Cursors.Hand;
pbLayer.PanMode = ImageBoxPanMode.None;
- lbLayerImageOverlay.Text = "Issue selection mode\n" +
- "Click over a issue to select it";
+ lbLayerImageOverlay.Text = "Issue selection mode:\n" +
+ "» Click over a issue to select it";
lbLayerImageOverlay.Visible = true;
return;
@@ -3039,11 +3052,34 @@ namespace UVtools.GUI
// unconditionally stop any pending mouse timer here.
mouseHoldTimer.Stop();
+ if (!pbLayer.IsPointInImage(e.Location)) return;
+ Point location = pbLayer.PointToImage(e.Location);
+ if (pbLayer.SelectionMode == ImageBoxSelectionMode.Rectangle)
+ {
+ if (e.Button == MouseButtons.Left)
+ {
+ if ((ModifierKeys & Keys.Alt) != 0)
+ {
+ if (SelectObjectRoi(ROI) == 0) SelectObjectRoi(location);
+ return;
+ }
+ return;
+ }
+
+ if (e.Button == MouseButtons.Right)
+ {
+ if (!pbLayer.IsPointInImage(e.Location)) return;
+ SelectObjectRoi(location);
+
+ return;
+ }
+ }
+
// Shift must be pressed for any pixel edit action, middle button is ignored.
if (!btnLayerImagePixelEdit.Checked || (e.Button & MouseButtons.Middle) != 0 ||
(ModifierKeys & Keys.Shift) == 0) return;
- if (!pbLayer.IsPointInImage(e.Location)) return;
- var location = pbLayer.PointToImage(e.Location);
+ //if (!pbLayer.IsPointInImage(e.Location)) return;
+ //location = pbLayer.PointToImage(e.Location);
_lastPixelMouseLocation = Point.Empty;
// Left or Alt-Right Adds pixel, Right or Alt-Left removes pixel
@@ -3053,6 +3089,53 @@ namespace UVtools.GUI
}
}
+ public bool SelectObjectRoi(Point location)
+ {
+ var point = GetTransposedPoint(location);
+ var brightness = ActualLayerImage.GetByte(point);
+
+ if (brightness == 0) return false;
+ for (int i = 0; i < LayerCache.LayerContours.Size; i++)
+ {
+ if (CvInvoke.PointPolygonTest(LayerCache.LayerContours[i], point, false) >= 0)
+ {
+ var rectangle =
+ GetTransposedRectangle(CvInvoke.BoundingRectangle(LayerCache.LayerContours[i]));
+ ROI = rectangle;
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public uint SelectObjectRoi(Rectangle roiRectangle)
+ {
+ if (roiRectangle.IsEmpty) return 0;
+ List<Rectangle> rectangles = new List<Rectangle>();
+ for (int i = 0; i < LayerCache.LayerContours.Size; i++)
+ {
+ var rectangle = CvInvoke.BoundingRectangle(LayerCache.LayerContours[i]);
+ //roi.Intersect(rectangle);
+ if (roiRectangle.IntersectsWith(rectangle))
+ {
+ rectangles.Add(rectangle);
+ }
+
+ }
+ roiRectangle = rectangles.Count == 0 ? Rectangle.Empty : rectangles[0];
+ for (var i = 1; i < rectangles.Count; i++)
+ {
+ var rectangle = rectangles[i];
+ roiRectangle = Rectangle.Union(roiRectangle, rectangle);
+ }
+
+ ROI = GetTransposedRectangle(roiRectangle);
+
+ return (uint) rectangles.Count;
+ }
+
private void EventMouseLeave(object sender, EventArgs e)
{
// Toolstrip Buttons do not register mouseup events if the mouse is no longer over
@@ -3506,12 +3589,19 @@ namespace UVtools.GUI
: new Point(ActualLayerImage.Height - 1 - point.Y, point.X);
}
- public Rectangle GetTransposedRectangle(Rectangle rectangle)
+ public Rectangle GetTransposedRectangle(RectangleF rectangleF, bool clockWise = true, bool ignoreLayerRotation = false) =>
+ GetTransposedRectangle(Rectangle.Round(rectangleF), clockWise, ignoreLayerRotation);
+
+ public Rectangle GetTransposedRectangle(Rectangle rectangle, bool clockWise = true, bool ignoreLayerRotation = false)
{
- return btnLayerImageRotate.Checked
+ if (rectangle.IsEmpty || (!ignoreLayerRotation && !btnLayerImageRotate.Checked)) return rectangle;
+ return clockWise
? new Rectangle(ActualLayerImage.Height - rectangle.Bottom,
- rectangle.X, rectangle.Height, rectangle.Width)
- : rectangle;
+ rectangle.Left, rectangle.Height, rectangle.Width)
+ //: new Rectangle(ActualLayerImage.Width - rectangle.Bottom, rectangle.Left, rectangle.Width, rectangle.Height);
+ //: new Rectangle(ActualLayerImage.Width - rectangle.Bottom, ActualLayerImage.Height-rectangle.Right, rectangle.Width, rectangle.Height); // Rotate90FlipX: // = Rotate270FlipY
+ //: new Rectangle(rectangle.Top, rectangle.Left, rectangle.Width, rectangle.Height); // Rotate270FlipX: // = Rotate90FlipY
+ : new Rectangle(rectangle.Top, ActualLayerImage.Height - rectangle.Right, rectangle.Height, rectangle.Width); // Rotate90FlipNone: // = Rotate270FlipXY
}
/// <summary>
diff --git a/UVtools.GUI/FrmMain.resx b/UVtools.GUI/FrmMain.resx
index 881eac7..c0d3023 100644
--- a/UVtools.GUI/FrmMain.resx
+++ b/UVtools.GUI/FrmMain.resx
@@ -174,7 +174,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABk
- FAAAAk1TRnQBSQFMAgEBBgEAATABCwEwAQsBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
+ FAAAAk1TRnQBSQFMAgEBBgEAATgBCwE4AQsBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
AwABIAMAAQEBAAEgBgABIC4AAxgBIgMwAUsDMAFMAzIBUDMAAQEDJAE2AysBQqwAAyIBMQNWAbkDXQHi
AwAB/wMAAf8BKgEtASgB/gNTAawDTQGVAwABARgAAwkBDAMzAVIDUAGdA1cB6AMAAf4DKwH8Ay8BSqQA
AyEBMANZAewBKwEuASkB+gNRAfcDUgH0A1MB8QNIAfYDQQH5AwAB/wNPAZsDAAEBCAADFQEdAz8BbgNV
diff --git a/UVtools.GUI/LayerCache.cs b/UVtools.GUI/LayerCache.cs
new file mode 100644
index 0000000..07ef491
--- /dev/null
+++ b/UVtools.GUI/LayerCache.cs
@@ -0,0 +1,79 @@
+using System;
+using Emgu.CV;
+using Emgu.CV.CvEnum;
+using Emgu.CV.Util;
+
+namespace UVtools.GUI
+{
+ public sealed class LayerCache
+ {
+ private Mat _image;
+ private Array _layerHierarchyJagged;
+ private VectorOfVectorOfPoint _layerContours;
+ private Mat _layerHierarchy;
+
+ public Mat Image
+ {
+ get => _image;
+ set
+ {
+ Clear();
+ _image = value;
+ }
+ }
+
+ public VectorOfVectorOfPoint LayerContours
+ {
+ get
+ {
+ if (_layerContours is null) CacheContours();
+ return _layerContours;
+ }
+ private set => _layerContours = value;
+ }
+
+ public Mat LayerHierarchy
+ {
+ get
+ {
+ if (_layerHierarchy is null) CacheContours();
+ return _layerHierarchy;
+ }
+ private set => _layerHierarchy = value;
+ }
+
+ public Array LayerHierarchyJagged
+ {
+ get
+ {
+ if(_layerHierarchyJagged is null) CacheContours();
+ return _layerHierarchyJagged;
+ }
+ private set => _layerHierarchyJagged = value;
+ }
+
+ public void CacheContours(bool refresh = false)
+ {
+ if(refresh) Clear();
+ if (!ReferenceEquals(_layerContours, null)) return;
+ _layerContours = new VectorOfVectorOfPoint();
+ _layerHierarchy = new Mat();
+ CvInvoke.FindContours(Image, _layerContours, _layerHierarchy, RetrType.Ccomp,
+ ChainApproxMethod.ChainApproxSimple);
+ _layerHierarchyJagged = _layerHierarchy.GetData();
+ }
+
+
+ /// <summary>
+ /// Clears the cache
+ /// </summary>
+ public void Clear()
+ {
+ _layerContours?.Dispose();
+ _layerContours = null;
+ _layerHierarchy?.Dispose();
+ _layerHierarchy = null;
+ _layerHierarchyJagged = null;
+ }
+ }
+}
diff --git a/UVtools.GUI/UVtools.GUI.csproj b/UVtools.GUI/UVtools.GUI.csproj
index 85bfe97..636d9ce 100644
--- a/UVtools.GUI/UVtools.GUI.csproj
+++ b/UVtools.GUI/UVtools.GUI.csproj
@@ -188,6 +188,12 @@
<Compile Include="Controls\Tools\CtrlToolRepairLayers.Designer.cs">
<DependentUpon>CtrlToolRepairLayers.cs</DependentUpon>
</Compile>
+ <Compile Include="Controls\Tools\CtrlToolSolidify.cs">
+ <SubType>UserControl</SubType>
+ </Compile>
+ <Compile Include="Controls\Tools\CtrlToolSolidify.Designer.cs">
+ <DependentUpon>CtrlToolSolidify.cs</DependentUpon>
+ </Compile>
<Compile Include="Controls\Tools\CtrlToolThreshold.cs">
<SubType>UserControl</SubType>
</Compile>
@@ -327,6 +333,7 @@
<DependentUpon>FrmMain.cs</DependentUpon>
</Compile>
<Compile Include="Forms\PEProfileFolder.cs" />
+ <Compile Include="LayerCache.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\Annotations.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -345,6 +352,9 @@
<EmbeddedResource Include="Controls\Tools\CtrlToolRepairLayers.resx">
<DependentUpon>CtrlToolRepairLayers.cs</DependentUpon>
</EmbeddedResource>
+ <EmbeddedResource Include="Controls\Tools\CtrlToolSolidify.resx">
+ <DependentUpon>CtrlToolSolidify.cs</DependentUpon>
+ </EmbeddedResource>
<EmbeddedResource Include="Controls\Tools\CtrlToolThreshold.resx">
<DependentUpon>CtrlToolThreshold.cs</DependentUpon>
</EmbeddedResource>