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-08-08 05:10:16 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2020-08-08 05:10:16 +0300
commit292db4090fad93a5cecbeb63de1e56dd2b95b164 (patch)
treeecb4ca44430760caaf877d38aa302fedf0285fb1
parentf53dc038818c487120de1915b563b1f1f6ec0818 (diff)
v0.6.5.0v0.6.5.0
* (Add) Mutators: Custom kernels, auto kernels and anchor where applicable * (Add) Mutator - Blur: Box Blur * (Add) Mutator - Blur: Filter2D * (Improvement) Mutator: Group all blurs into one window * (Fix) Mutators: Sample images was gone * (Fix) Mutator - Solidify: Remove the disabled input box * (Fix) Mutator - Pixel Dimming: Disable word wrap on pattern text box
-rw-r--r--CHANGELOG.md10
-rw-r--r--UVtools.Core/Layer/Layer.cs26
-rw-r--r--UVtools.Core/Layer/LayerManager.cs317
-rw-r--r--UVtools.Core/UVtools.Core.csproj6
-rw-r--r--UVtools.GUI/Controls/CtrlKernel.Designer.cs307
-rw-r--r--UVtools.GUI/Controls/CtrlKernel.cs133
-rw-r--r--UVtools.GUI/Controls/CtrlKernel.resx120
-rw-r--r--UVtools.GUI/Forms/FrmMutation.Designer.cs48
-rw-r--r--UVtools.GUI/Forms/FrmMutation.cs36
-rw-r--r--UVtools.GUI/Forms/FrmMutationBlur.Designer.cs367
-rw-r--r--UVtools.GUI/Forms/FrmMutationBlur.cs248
-rw-r--r--UVtools.GUI/Forms/FrmMutationBlur.resx136
-rw-r--r--UVtools.GUI/Forms/FrmMutationPixelDimming.Designer.cs146
-rw-r--r--UVtools.GUI/Forms/FrmToolEmpty.cs15
-rw-r--r--UVtools.GUI/FrmMain.cs93
-rw-r--r--UVtools.GUI/Mutation.cs1
-rw-r--r--UVtools.GUI/Properties/AssemblyInfo.cs4
-rw-r--r--UVtools.GUI/UVtools.GUI.csproj18
18 files changed, 1749 insertions, 282 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ec4a91..57f6d62 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
# Changelog
+## 08/08/2020 - v0.6.5.0
+
+* (Add) Mutators: Custom kernels, auto kernels and anchor where applicable
+* (Add) Mutator - Blur: Box Blur
+* (Add) Mutator - Blur: Filter2D
+* (Improvement) Mutator: Group all blurs into one window
+* (Fix) Mutators: Sample images was gone
+* (Fix) Mutator - Solidify: Remove the disabled input box
+* (Fix) Mutator - Pixel Dimming: Disable word wrap on pattern text box
+
## 06/08/2020 - v0.6.4.3
* (Add) Pixel Editor - Supports and Drain holes: AntiAliasing
diff --git a/UVtools.Core/Layer/Layer.cs b/UVtools.Core/Layer/Layer.cs
index 3056d4c..b9401a7 100644
--- a/UVtools.Core/Layer/Layer.cs
+++ b/UVtools.Core/Layer/Layer.cs
@@ -732,6 +732,18 @@ namespace UVtools.Core
}
}
+ public void MutateBlur(Size size = default, Point anchor = default, BorderType borderType = BorderType.Reflect101)
+ {
+ if (size.IsEmpty) size = new Size(3, 3);
+ if (anchor.IsEmpty) anchor = new Point(-1, -1);
+ using (Mat dst = LayerMat)
+ {
+ CvInvoke.Blur(dst, dst, size, anchor, borderType);
+ LayerMat = dst;
+ }
+ }
+
+
public void MutatePyrDownUp(BorderType borderType = BorderType.Reflect101)
{
using (Mat dst = LayerMat)
@@ -762,6 +774,20 @@ namespace UVtools.Core
}
}
+ public void MutateFilter2D(IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Reflect101)
+ {
+ if (anchor.IsEmpty) anchor = new Point(-1, -1);
+ if (ReferenceEquals(kernel, null))
+ {
+ kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor);
+ }
+ using (Mat dst = LayerMat)
+ {
+ CvInvoke.Filter2D(dst, dst, kernel, anchor, 0, borderType);
+ LayerMat = dst;
+ }
+ }
+
public void ChangeResolution(uint newResolutionX, uint newResolutionY, Rectangle roi)
{
using (var mat = LayerMat)
diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs
index 4818b1b..77efb72 100644
--- a/UVtools.Core/Layer/LayerManager.cs
+++ b/UVtools.Core/Layer/LayerManager.cs
@@ -45,9 +45,10 @@ namespace UVtools.Core
BlackHat,
HitMiss,
ThresholdPixels,
- PyrDownUp,
+ Blur
+ /*PyrDownUp,
SmoothMedian,
- SmoothGaussian,
+ SmoothGaussian,*/
}
#endregion
@@ -635,7 +636,23 @@ namespace UVtools.Core
progress.Token.ThrowIfCancellationRequested();
}
- public void MutatePyrDownUp(uint startLayerIndex, uint endLayerIndex, BorderType borderType = BorderType.Default, OperationProgress progress = null)
+ public void MutateBlur(uint startLayerIndex, uint endLayerIndex, Size size, Point kernelAnchor = default, BorderType borderType = BorderType.Reflect101, OperationProgress progress = null)
+ {
+ if (ReferenceEquals(progress, null)) progress = new OperationProgress();
+ progress.Reset("Box Blur", endLayerIndex - startLayerIndex + 1);
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ if (progress.Token.IsCancellationRequested) return;
+ this[layerIndex].MutateBlur(size, kernelAnchor, borderType);
+ lock (progress.Mutex)
+ {
+ progress++;
+ }
+ });
+ progress.Token.ThrowIfCancellationRequested();
+ }
+
+ public void MutatePyrDownUp(uint startLayerIndex, uint endLayerIndex, BorderType borderType = BorderType.Reflect101, OperationProgress progress = null)
{
if (ReferenceEquals(progress, null)) progress = new OperationProgress();
progress.Reset("PryDownUp", endLayerIndex - startLayerIndex+1);
@@ -683,6 +700,22 @@ namespace UVtools.Core
progress.Token.ThrowIfCancellationRequested();
}
+ public void MutateFilter2D(uint startLayerIndex, uint endLayerIndex, IInputArray kernel = null, Point kernelAnchor = default, BorderType borderType = BorderType.Reflect101, OperationProgress progress = null)
+ {
+ if (ReferenceEquals(progress, null)) progress = new OperationProgress();
+ progress.Reset("Filter 2D", endLayerIndex - startLayerIndex + 1);
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ if (progress.Token.IsCancellationRequested) return;
+ this[layerIndex].MutateFilter2D(kernel, kernelAnchor, borderType);
+ lock (progress.Mutex)
+ {
+ progress++;
+ }
+ });
+ progress.Token.ThrowIfCancellationRequested();
+ }
+
public List<LayerIssue> GetAllIssues(
IslandDetectionConfiguration islandConfig = null, ResinTrapDetectionConfiguration resinTrapConfig = null,
TouchingBoundDetectionConfiguration touchBoundConfig = null,
@@ -1281,6 +1314,145 @@ namespace UVtools.Core
progress.Token.ThrowIfCancellationRequested();
}
+ public void RemoveLayer(uint layerIndex) => RemoveLayer(layerIndex, layerIndex);
+
+ public void RemoveLayer(uint layerIndexStart, uint layerIndexEnd)
+ {
+ var layersRemove = new List<uint>();
+ for (uint layerIndex = layerIndexStart; layerIndex <= layerIndexEnd; layerIndex++)
+ {
+ layersRemove.Add(layerIndex);
+ }
+
+ RemoveLayer(layersRemove);
+ }
+
+ public void RemoveLayer(List<uint> layersRemove)
+ {
+ if (layersRemove.Count == 0) return;
+
+ var oldLayers = Layers;
+ float layerHeight = SlicerFile.LayerHeight;
+
+ Layers = new Layer[Count - layersRemove.Count];
+
+ // Re-set
+ uint newLayerIndex = 0;
+ for (uint layerIndex = 0; layerIndex < oldLayers.Length; layerIndex++)
+ {
+ if (layersRemove.Contains(layerIndex)) continue;
+ Layers[newLayerIndex] = oldLayers[layerIndex];
+ Layers[newLayerIndex].Index = newLayerIndex;
+
+ // Re-Z
+ float posZ = layerHeight;
+ if (newLayerIndex > 0)
+ {
+ if (oldLayers[layerIndex - 1].PositionZ == oldLayers[layerIndex].PositionZ)
+ {
+ posZ = Layers[newLayerIndex - 1].PositionZ;
+ }
+ else
+ {
+ posZ = (float)Math.Round(Layers[newLayerIndex - 1].PositionZ + layerHeight, 2);
+ }
+ }
+
+ Layers[newLayerIndex].PositionZ = posZ;
+ Layers[newLayerIndex].IsModified = true;
+
+ newLayerIndex++;
+ }
+
+ SlicerFile.LayerCount = Count;
+ BoundingRectangle = Rectangle.Empty;
+ SlicerFile.RequireFullEncode = true;
+ }
+
+ public void ReHeight(OperationLayerReHeight operation, OperationProgress progress = null)
+ {
+ if (ReferenceEquals(progress, null)) progress = new OperationProgress();
+ progress.Reset("Re-Height", operation.LayerCount);
+
+ var oldLayers = Layers;
+
+ Layers = new Layer[operation.LayerCount];
+
+ uint newLayerIndex = 0;
+ for (uint layerIndex = 0; layerIndex < oldLayers.Length; layerIndex++)
+ {
+ var oldLayer = oldLayers[layerIndex];
+ if (operation.IsDivision)
+ {
+ for (byte i = 0; i < operation.Modifier; i++)
+ {
+ Layers[newLayerIndex] =
+ new Layer(newLayerIndex, oldLayer.CompressedBytes, null, this)
+ {
+ PositionZ = (float)(operation.LayerHeight * (newLayerIndex + 1)),
+ ExposureTime = oldLayer.ExposureTime,
+ BoundingRectangle = oldLayer.BoundingRectangle,
+ NonZeroPixelCount = oldLayer.NonZeroPixelCount
+
+ };
+ newLayerIndex++;
+ progress++;
+ }
+ }
+ else
+ {
+ using (var mat = oldLayers[layerIndex++].LayerMat)
+ {
+ for (byte i = 1; i < operation.Modifier; i++)
+ {
+ using (var nextMat = oldLayers[layerIndex++].LayerMat)
+ {
+ CvInvoke.Add(mat, nextMat, mat);
+ }
+ }
+
+ Layers[newLayerIndex] = new Layer(newLayerIndex, mat, null, this)
+ {
+ PositionZ = (float)(operation.LayerHeight * (newLayerIndex + 1)),
+ ExposureTime = oldLayer.ExposureTime
+ };
+ newLayerIndex++;
+ layerIndex--;
+ progress++;
+ }
+ }
+ }
+
+
+ SlicerFile.LayerHeight = (float)operation.LayerHeight;
+ SlicerFile.LayerCount = Count;
+ BoundingRectangle = Rectangle.Empty;
+ SlicerFile.RequireFullEncode = true;
+ }
+
+ public void ChangeResolution(uint newResolutionX, uint newResolutionY, OperationProgress progress)
+ {
+ if (ReferenceEquals(progress, null)) progress = new OperationProgress();
+ progress.Reset("Resolution", Count);
+
+ var bounds = BoundingRectangle;
+
+ Parallel.For(0, Count, layerIndex =>
+ {
+ if (progress.Token.IsCancellationRequested) return;
+
+ this[layerIndex].ChangeResolution(newResolutionX, newResolutionY, bounds);
+
+ lock (progress.Mutex)
+ {
+ progress++;
+ }
+ });
+
+ SlicerFile.ResolutionX = newResolutionX;
+ SlicerFile.ResolutionY = newResolutionY;
+ }
+
public void ToolPattern(uint startLayerIndex, uint endLayerIndex, OperationPattern settings, OperationProgress progress = null)
{
if (ReferenceEquals(progress, null)) progress = new OperationProgress();
@@ -1462,144 +1634,5 @@ namespace UVtools.Core
#endregion
-
- public void RemoveLayer(uint layerIndex) => RemoveLayer(layerIndex, layerIndex);
-
- public void RemoveLayer(uint layerIndexStart, uint layerIndexEnd)
- {
- var layersRemove = new List<uint>();
- for (uint layerIndex = layerIndexStart; layerIndex <= layerIndexEnd; layerIndex++)
- {
- layersRemove.Add(layerIndex);
- }
-
- RemoveLayer(layersRemove);
- }
-
- public void RemoveLayer(List<uint> layersRemove)
- {
- if (layersRemove.Count == 0) return;
-
- var oldLayers = Layers;
- float layerHeight = SlicerFile.LayerHeight;
-
- Layers = new Layer[Count - layersRemove.Count];
-
- // Re-set
- uint newLayerIndex = 0;
- for (uint layerIndex = 0; layerIndex < oldLayers.Length; layerIndex++)
- {
- if (layersRemove.Contains(layerIndex)) continue;
- Layers[newLayerIndex] = oldLayers[layerIndex];
- Layers[newLayerIndex].Index = newLayerIndex;
-
- // Re-Z
- float posZ = layerHeight;
- if (newLayerIndex > 0)
- {
- if (oldLayers[layerIndex - 1].PositionZ == oldLayers[layerIndex].PositionZ)
- {
- posZ = Layers[newLayerIndex - 1].PositionZ;
- }
- else
- {
- posZ = (float)Math.Round(Layers[newLayerIndex - 1].PositionZ + layerHeight, 2);
- }
- }
-
- Layers[newLayerIndex].PositionZ = posZ;
- Layers[newLayerIndex].IsModified = true;
-
- newLayerIndex++;
- }
-
- SlicerFile.LayerCount = Count;
- BoundingRectangle = Rectangle.Empty;
- SlicerFile.RequireFullEncode = true;
- }
-
- public void ReHeight(OperationLayerReHeight operation, OperationProgress progress = null)
- {
- if (ReferenceEquals(progress, null)) progress = new OperationProgress();
- progress.Reset("Re-Height", operation.LayerCount);
-
- var oldLayers = Layers;
-
- Layers = new Layer[operation.LayerCount];
-
- uint newLayerIndex = 0;
- for (uint layerIndex = 0; layerIndex < oldLayers.Length; layerIndex++)
- {
- var oldLayer = oldLayers[layerIndex];
- if (operation.IsDivision)
- {
- for (byte i = 0; i < operation.Modifier; i++)
- {
- Layers[newLayerIndex] =
- new Layer(newLayerIndex, oldLayer.CompressedBytes, null, this)
- {
- PositionZ = (float) (operation.LayerHeight * (newLayerIndex + 1)),
- ExposureTime = oldLayer.ExposureTime,
- BoundingRectangle = oldLayer.BoundingRectangle,
- NonZeroPixelCount = oldLayer.NonZeroPixelCount
-
- };
- newLayerIndex++;
- progress++;
- }
- }
- else
- {
- using (var mat = oldLayers[layerIndex++].LayerMat)
- {
- for (byte i = 1; i < operation.Modifier; i++)
- {
- using (var nextMat = oldLayers[layerIndex++].LayerMat)
- {
- CvInvoke.Add(mat, nextMat, mat);
- }
- }
-
- Layers[newLayerIndex] = new Layer(newLayerIndex, mat, null, this)
- {
- PositionZ = (float)(operation.LayerHeight * (newLayerIndex + 1)),
- ExposureTime = oldLayer.ExposureTime
- };
- newLayerIndex++;
- layerIndex--;
- progress++;
- }
- }
- }
-
-
- SlicerFile.LayerHeight = (float) operation.LayerHeight;
- SlicerFile.LayerCount = Count;
- BoundingRectangle = Rectangle.Empty;
- SlicerFile.RequireFullEncode = true;
- }
-
- public void ChangeResolution(uint newResolutionX, uint newResolutionY, OperationProgress progress)
- {
- if (ReferenceEquals(progress, null)) progress = new OperationProgress();
- progress.Reset("Resolution", Count);
-
- var bounds = BoundingRectangle;
-
- Parallel.For(0, Count, layerIndex =>
- {
- if (progress.Token.IsCancellationRequested) return;
-
- this[layerIndex].ChangeResolution(newResolutionX, newResolutionY, bounds);
-
- lock (progress.Mutex)
- {
- progress++;
- }
- });
-
- SlicerFile.ResolutionX = newResolutionX;
- SlicerFile.ResolutionY = newResolutionY;
- }
}
}
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index b87f305..8a7c465 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -10,12 +10,12 @@
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, repair, conversion and manipulation</Description>
- <Version>0.6.4.3</Version>
+ <Version>0.6.5.0</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
- <AssemblyVersion>0.6.4.3</AssemblyVersion>
- <FileVersion>0.6.4.3</FileVersion>
+ <AssemblyVersion>0.6.5.0</AssemblyVersion>
+ <FileVersion>0.6.5.0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
diff --git a/UVtools.GUI/Controls/CtrlKernel.Designer.cs b/UVtools.GUI/Controls/CtrlKernel.Designer.cs
new file mode 100644
index 0000000..eb7e35b
--- /dev/null
+++ b/UVtools.GUI/Controls/CtrlKernel.Designer.cs
@@ -0,0 +1,307 @@
+namespace UVtools.GUI.Controls
+{
+ partial class CtrlKernel
+ {
+ /// <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.tbKernel = new System.Windows.Forms.TextBox();
+ this.cbShape = new System.Windows.Forms.ComboBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.nmSizeX = new System.Windows.Forms.NumericUpDown();
+ this.label2 = new System.Windows.Forms.Label();
+ this.label3 = new System.Windows.Forms.Label();
+ this.nmSizeY = new System.Windows.Forms.NumericUpDown();
+ this.btnGen = new System.Windows.Forms.Button();
+ this.btnReset = new System.Windows.Forms.Button();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.label4 = new System.Windows.Forms.Label();
+ this.nmAnchorY = new System.Windows.Forms.NumericUpDown();
+ this.nmAnchorX = new System.Windows.Forms.NumericUpDown();
+ this.label5 = new System.Windows.Forms.Label();
+ this.label6 = new System.Windows.Forms.Label();
+ ((System.ComponentModel.ISupportInitialize)(this.nmSizeX)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmSizeY)).BeginInit();
+ this.groupBox1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.nmAnchorY)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmAnchorX)).BeginInit();
+ this.SuspendLayout();
+ //
+ // tbKernel
+ //
+ this.tbKernel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.tbKernel.Location = new System.Drawing.Point(6, 25);
+ this.tbKernel.Multiline = true;
+ this.tbKernel.Name = "tbKernel";
+ this.tbKernel.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.tbKernel.Size = new System.Drawing.Size(210, 178);
+ this.tbKernel.TabIndex = 1;
+ this.tbKernel.WordWrap = false;
+ //
+ // cbShape
+ //
+ this.cbShape.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.cbShape.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cbShape.FormattingEnabled = true;
+ this.cbShape.Location = new System.Drawing.Point(308, 24);
+ this.cbShape.Name = "cbShape";
+ this.cbShape.Size = new System.Drawing.Size(133, 28);
+ this.cbShape.TabIndex = 2;
+ //
+ // label1
+ //
+ this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(248, 28);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(60, 20);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "Shape:";
+ //
+ // nmSizeX
+ //
+ this.nmSizeX.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.nmSizeX.Location = new System.Drawing.Point(308, 58);
+ this.nmSizeX.Maximum = new decimal(new int[] {
+ 65535,
+ 0,
+ 0,
+ 0});
+ this.nmSizeX.Minimum = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.nmSizeX.Name = "nmSizeX";
+ this.nmSizeX.Size = new System.Drawing.Size(50, 26);
+ this.nmSizeX.TabIndex = 3;
+ this.nmSizeX.Value = new decimal(new int[] {
+ 3,
+ 0,
+ 0,
+ 0});
+ //
+ // label2
+ //
+ this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(258, 61);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(44, 20);
+ this.label2.TabIndex = 4;
+ this.label2.Text = "Size:";
+ //
+ // label3
+ //
+ this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(366, 61);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(16, 20);
+ this.label3.TabIndex = 5;
+ this.label3.Text = "x";
+ //
+ // nmSizeY
+ //
+ this.nmSizeY.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.nmSizeY.Location = new System.Drawing.Point(392, 58);
+ this.nmSizeY.Maximum = new decimal(new int[] {
+ 65535,
+ 0,
+ 0,
+ 0});
+ this.nmSizeY.Minimum = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.nmSizeY.Name = "nmSizeY";
+ this.nmSizeY.Size = new System.Drawing.Size(50, 26);
+ this.nmSizeY.TabIndex = 6;
+ this.nmSizeY.Value = new decimal(new int[] {
+ 3,
+ 0,
+ 0,
+ 0});
+ //
+ // btnGen
+ //
+ this.btnGen.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnGen.Location = new System.Drawing.Point(226, 147);
+ this.btnGen.Name = "btnGen";
+ this.btnGen.Size = new System.Drawing.Size(131, 56);
+ this.btnGen.TabIndex = 7;
+ this.btnGen.Text = "Generate";
+ this.btnGen.UseVisualStyleBackColor = true;
+ this.btnGen.Click += new System.EventHandler(this.EventClick);
+ //
+ // btnReset
+ //
+ this.btnReset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnReset.Location = new System.Drawing.Point(367, 147);
+ this.btnReset.Name = "btnReset";
+ this.btnReset.Size = new System.Drawing.Size(74, 56);
+ this.btnReset.TabIndex = 8;
+ this.btnReset.Text = "Reset";
+ this.btnReset.UseVisualStyleBackColor = true;
+ this.btnReset.Click += new System.EventHandler(this.EventClick);
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.label6);
+ this.groupBox1.Controls.Add(this.label5);
+ this.groupBox1.Controls.Add(this.nmAnchorY);
+ this.groupBox1.Controls.Add(this.nmAnchorX);
+ this.groupBox1.Controls.Add(this.label4);
+ this.groupBox1.Controls.Add(this.btnReset);
+ this.groupBox1.Controls.Add(this.btnGen);
+ this.groupBox1.Controls.Add(this.tbKernel);
+ this.groupBox1.Controls.Add(this.nmSizeY);
+ this.groupBox1.Controls.Add(this.cbShape);
+ this.groupBox1.Controls.Add(this.label3);
+ this.groupBox1.Controls.Add(this.label1);
+ this.groupBox1.Controls.Add(this.label2);
+ this.groupBox1.Controls.Add(this.nmSizeX);
+ 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(448, 215);
+ this.groupBox1.TabIndex = 0;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "Kernel";
+ //
+ // label4
+ //
+ this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(223, 93);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(79, 20);
+ this.label4.TabIndex = 9;
+ this.label4.Text = "Anchor X:";
+ //
+ // nmAnchorY
+ //
+ this.nmAnchorY.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.nmAnchorY.Location = new System.Drawing.Point(392, 90);
+ this.nmAnchorY.Maximum = new decimal(new int[] {
+ 65535,
+ 0,
+ 0,
+ 0});
+ this.nmAnchorY.Minimum = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ -2147483648});
+ this.nmAnchorY.Name = "nmAnchorY";
+ this.nmAnchorY.Size = new System.Drawing.Size(50, 26);
+ this.nmAnchorY.TabIndex = 11;
+ this.nmAnchorY.Value = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ -2147483648});
+ //
+ // nmAnchorX
+ //
+ this.nmAnchorX.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.nmAnchorX.Location = new System.Drawing.Point(308, 90);
+ this.nmAnchorX.Maximum = new decimal(new int[] {
+ 65535,
+ 0,
+ 0,
+ 0});
+ this.nmAnchorX.Minimum = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ -2147483648});
+ this.nmAnchorX.Name = "nmAnchorX";
+ this.nmAnchorX.Size = new System.Drawing.Size(50, 26);
+ this.nmAnchorX.TabIndex = 10;
+ this.nmAnchorX.Value = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ -2147483648});
+ //
+ // label5
+ //
+ this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(363, 93);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(24, 20);
+ this.label5.TabIndex = 12;
+ this.label5.Text = "Y:";
+ //
+ // label6
+ //
+ this.label6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(222, 123);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(218, 20);
+ this.label6.TabIndex = 13;
+ this.label6.Text = "Note: Anchor auto center = -1";
+ //
+ // CtrlKernel
+ //
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
+ this.Controls.Add(this.groupBox1);
+ this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.Name = "CtrlKernel";
+ this.Size = new System.Drawing.Size(448, 215);
+ ((System.ComponentModel.ISupportInitialize)(this.nmSizeX)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmSizeY)).EndInit();
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.nmAnchorY)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmAnchorX)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ private System.Windows.Forms.ComboBox cbShape;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.NumericUpDown nmSizeX;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.NumericUpDown nmSizeY;
+ private System.Windows.Forms.Button btnGen;
+ private System.Windows.Forms.Button btnReset;
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.NumericUpDown nmAnchorY;
+ private System.Windows.Forms.NumericUpDown nmAnchorX;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.Label label6;
+ public System.Windows.Forms.TextBox tbKernel;
+ }
+}
diff --git a/UVtools.GUI/Controls/CtrlKernel.cs b/UVtools.GUI/Controls/CtrlKernel.cs
new file mode 100644
index 0000000..7653f5b
--- /dev/null
+++ b/UVtools.GUI/Controls/CtrlKernel.cs
@@ -0,0 +1,133 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+using Emgu.CV;
+using Emgu.CV.CvEnum;
+using UVtools.Core.Extensions;
+
+namespace UVtools.GUI.Controls
+{
+ public partial class CtrlKernel : UserControl
+ {
+ public ElementShape AutoShape => (ElementShape)cbShape.SelectedItem;
+ public Size AutoKernelSize => new Size((int) nmSizeX.Value, (int) nmSizeY.Value);
+ public Point KernelAnchor => new Point((int) nmAnchorX.Value, (int) nmAnchorY.Value);
+ public CtrlKernel()
+ {
+ InitializeComponent();
+ if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) return;
+
+ foreach (var element in (ElementShape[])Enum.GetValues(
+ typeof(ElementShape)))
+ {
+ if (element == ElementShape.Custom) continue;
+ cbShape.Items.Add(element);
+ }
+
+ cbShape.SelectedItem = ElementShape.Rectangle;
+ Reset();
+ }
+
+ private void EventClick(object sender, EventArgs e)
+ {
+ if (ReferenceEquals(sender, btnGen))
+ {
+ if (nmSizeX.Value <= nmAnchorX.Value || nmSizeY.Value <= nmAnchorY.Value)
+ {
+ MessageBox.Show("Anchor position X/Y can't be higher or equal than size X/Y\nPlease fix the values.",
+ "Invalid anchor position", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+
+ using (var kernel = CvInvoke.GetStructuringElement(AutoShape, AutoKernelSize, KernelAnchor))
+ {
+ string text = string.Empty;
+ for (int y = 0; y < kernel.Height; y++)
+ {
+ var span = kernel.GetPixelRowSpan<byte>(y);
+ var line = string.Empty;
+ for (int x = 0; x < span.Length; x++)
+ {
+ line += $" {span[x]}";
+ }
+
+ line = line.Remove(0, 1);
+ text += line;
+ if (y < kernel.Height - 1)
+ {
+ text += Environment.NewLine;
+ }
+ }
+
+ tbKernel.Text = text;
+ }
+ return;
+ }
+
+ if (ReferenceEquals(sender, btnReset))
+ {
+ Reset();
+ }
+ }
+
+ public void Reset()
+ {
+ nmSizeX.Value = 3;
+ nmSizeY.Value = 3;
+ nmAnchorX.Value = -1;
+ nmAnchorY.Value = -1;
+ cbShape.SelectedItem = ElementShape.Rectangle;
+ btnGen.PerformClick();
+ }
+
+ public Matrix<byte> GetMatrix()
+ {
+ if (string.IsNullOrEmpty(tbKernel.Text))
+ {
+ MessageBox.Show("Kernel can't be empty.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return null;
+ }
+ Matrix<byte> matrix = null;
+ for (var row = 0; row < tbKernel.Lines.Length; row++)
+ {
+ var bytes = tbKernel.Lines[row].Trim().Split(' ');
+ if (row == 0)
+ {
+ matrix = new Matrix<byte>(tbKernel.Lines.Length, bytes.Length);
+ }
+ else
+ {
+ if (matrix.Cols != bytes.Length)
+ {
+ MessageBox.Show($"Row {row + 1} have invalid number of columns, the matrix must have equal columns count per line, per defined on line 1", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ matrix.Dispose();
+ return null;
+ }
+ }
+
+ for (int col = 0; col < bytes.Length; col++)
+ {
+ if (byte.TryParse(bytes[col], out var value))
+ {
+ matrix[row, col] = value;
+ }
+ else
+ {
+ MessageBox.Show($"{bytes[col]} is a invalid number, use values from 0 to 255", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ matrix.Dispose();
+ return null;
+ }
+ }
+ }
+ if (matrix.Cols <= nmAnchorX.Value || matrix.Rows <= nmAnchorY.Value)
+ {
+ MessageBox.Show("Anchor position X/Y can't be higher or equal than kernel columns/rows\nPlease fix the values.",
+ "Invalid anchor position", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ matrix.Dispose();
+ return null;
+ }
+ return matrix;
+ }
+ }
+}
diff --git a/UVtools.GUI/Controls/CtrlKernel.resx b/UVtools.GUI/Controls/CtrlKernel.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/UVtools.GUI/Controls/CtrlKernel.resx
@@ -0,0 +1,120 @@
+<?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>
+</root> \ No newline at end of file
diff --git a/UVtools.GUI/Forms/FrmMutation.Designer.cs b/UVtools.GUI/Forms/FrmMutation.Designer.cs
index 8d32fc0..15f3f04 100644
--- a/UVtools.GUI/Forms/FrmMutation.Designer.cs
+++ b/UVtools.GUI/Forms/FrmMutation.Designer.cs
@@ -48,11 +48,12 @@ namespace UVtools.GUI.Forms
this.nmIterationsEnd = new System.Windows.Forms.NumericUpDown();
this.cbIterationsFade = new System.Windows.Forms.CheckBox();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
- this.btnLayerRangeSelect = new UVtools.GUI.Controls.SplitButton();
this.btnCancel = new System.Windows.Forms.Button();
this.btnPreview = new System.Windows.Forms.Button();
this.pbInfo = new System.Windows.Forms.PictureBox();
this.btnMutate = new System.Windows.Forms.Button();
+ this.ctrlKernel = new UVtools.GUI.Controls.CtrlKernel();
+ this.btnLayerRangeSelect = new UVtools.GUI.Controls.SplitButton();
((System.ComponentModel.ISupportInitialize)(this.numIterationsStart)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeStart)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeEnd)).BeginInit();
@@ -69,7 +70,7 @@ namespace UVtools.GUI.Forms
this.lbDescription.Location = new System.Drawing.Point(13, 14);
this.lbDescription.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbDescription.Name = "lbDescription";
- this.lbDescription.Size = new System.Drawing.Size(584, 128);
+ this.lbDescription.Size = new System.Drawing.Size(584, 323);
this.lbDescription.TabIndex = 0;
this.lbDescription.Text = "Description";
//
@@ -245,23 +246,13 @@ namespace UVtools.GUI.Forms
this.toolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info;
this.toolTip.ToolTipTitle = "Information";
//
- // btnLayerRangeSelect
- //
- this.btnLayerRangeSelect.Location = new System.Drawing.Point(484, 147);
- this.btnLayerRangeSelect.Menu = this.cmLayerRange;
- this.btnLayerRangeSelect.Name = "btnLayerRangeSelect";
- this.btnLayerRangeSelect.Size = new System.Drawing.Size(114, 26);
- this.btnLayerRangeSelect.TabIndex = 2;
- this.btnLayerRangeSelect.Text = "Select";
- this.btnLayerRangeSelect.UseVisualStyleBackColor = true;
- //
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
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(447, 230);
+ this.btnCancel.Location = new System.Drawing.Point(447, 451);
this.btnCancel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(150, 48);
@@ -277,7 +268,7 @@ namespace UVtools.GUI.Forms
this.btnPreview.Enabled = false;
this.btnPreview.Image = global::UVtools.GUI.Properties.Resources.eye_24x24;
this.btnPreview.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
- this.btnPreview.Location = new System.Drawing.Point(131, 230);
+ this.btnPreview.Location = new System.Drawing.Point(131, 451);
this.btnPreview.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.btnPreview.Name = "btnPreview";
this.btnPreview.Size = new System.Drawing.Size(150, 48);
@@ -289,11 +280,10 @@ namespace UVtools.GUI.Forms
//
// pbInfo
//
- this.pbInfo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
- | System.Windows.Forms.AnchorStyles.Right)));
+ this.pbInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.pbInfo.Location = new System.Drawing.Point(604, 14);
this.pbInfo.Name = "pbInfo";
- this.pbInfo.Size = new System.Drawing.Size(311, 264);
+ this.pbInfo.Size = new System.Drawing.Size(311, 323);
this.pbInfo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pbInfo.TabIndex = 7;
this.pbInfo.TabStop = false;
@@ -304,7 +294,7 @@ namespace UVtools.GUI.Forms
this.btnMutate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnMutate.Image = global::UVtools.GUI.Properties.Resources.Ok_24x24;
this.btnMutate.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
- this.btnMutate.Location = new System.Drawing.Point(289, 230);
+ this.btnMutate.Location = new System.Drawing.Point(289, 451);
this.btnMutate.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.btnMutate.Name = "btnMutate";
this.btnMutate.Size = new System.Drawing.Size(150, 48);
@@ -314,12 +304,31 @@ namespace UVtools.GUI.Forms
this.btnMutate.UseVisualStyleBackColor = true;
this.btnMutate.Click += new System.EventHandler(this.ItemClicked);
//
+ // ctrlKernel
+ //
+ this.ctrlKernel.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.ctrlKernel.Location = new System.Drawing.Point(12, 221);
+ this.ctrlKernel.Name = "ctrlKernel";
+ this.ctrlKernel.Size = new System.Drawing.Size(585, 217);
+ this.ctrlKernel.TabIndex = 16;
+ //
+ // btnLayerRangeSelect
+ //
+ this.btnLayerRangeSelect.Location = new System.Drawing.Point(484, 147);
+ this.btnLayerRangeSelect.Menu = this.cmLayerRange;
+ this.btnLayerRangeSelect.Name = "btnLayerRangeSelect";
+ this.btnLayerRangeSelect.Size = new System.Drawing.Size(114, 26);
+ this.btnLayerRangeSelect.TabIndex = 2;
+ this.btnLayerRangeSelect.Text = "Select";
+ this.btnLayerRangeSelect.UseVisualStyleBackColor = true;
+ //
// FrmMutation
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
- this.ClientSize = new System.Drawing.Size(927, 292);
+ this.ClientSize = new System.Drawing.Size(927, 513);
+ this.Controls.Add(this.ctrlKernel);
this.Controls.Add(this.cbIterationsFade);
this.Controls.Add(this.nmIterationsEnd);
this.Controls.Add(this.lbIterationsStop);
@@ -380,5 +389,6 @@ namespace UVtools.GUI.Forms
private System.Windows.Forms.NumericUpDown nmIterationsEnd;
private System.Windows.Forms.CheckBox cbIterationsFade;
private System.Windows.Forms.ToolTip toolTip;
+ public CtrlKernel ctrlKernel;
}
} \ No newline at end of file
diff --git a/UVtools.GUI/Forms/FrmMutation.cs b/UVtools.GUI/Forms/FrmMutation.cs
index 24035e4..16b2a49 100644
--- a/UVtools.GUI/Forms/FrmMutation.cs
+++ b/UVtools.GUI/Forms/FrmMutation.cs
@@ -7,7 +7,9 @@
*/
using System;
+using System.Drawing;
using System.Windows.Forms;
+using Emgu.CV;
using UVtools.Core;
namespace UVtools.GUI.Forms
@@ -47,6 +49,9 @@ namespace UVtools.GUI.Forms
get => cbIterationsFade.Checked;
set => cbIterationsFade.Checked = value;
}
+
+ public Matrix<byte> KernelMatrix { get; private set; }
+ public Point KernelAnchor => ctrlKernel.KernelAnchor;
#endregion
#region Constructors
@@ -62,9 +67,7 @@ namespace UVtools.GUI.Forms
Mutation = mutation;
DialogResult = DialogResult.Cancel;
- if (defaultIterations == 0 ||
- mutation.Mutate == LayerManager.Mutate.PyrDownUp ||
- mutation.Mutate == LayerManager.Mutate.Solidify)
+ if (defaultIterations == 0)
{
lbIterationsStart.Enabled =
numIterationsStart.Enabled =
@@ -79,15 +82,6 @@ namespace UVtools.GUI.Forms
numIterationsStart.Select();
}
- if (Mutation.Mutate == LayerManager.Mutate.SmoothGaussian ||
- Mutation.Mutate == LayerManager.Mutate.SmoothMedian)
- {
- lbIterationsStop.Enabled =
- nmIterationsEnd.Enabled =
- cbIterationsFade.Enabled =
- false;
- }
-
Text = $"Mutate: {mutation.MenuName}";
lbDescription.Text = Mutation.Description;
@@ -112,6 +106,7 @@ namespace UVtools.GUI.Forms
base.OnKeyUp(e);
if (e.KeyCode == Keys.Enter)
{
+ if (ctrlKernel.tbKernel.ContainsFocus) return;
btnMutate.PerformClick();
e.Handled = true;
return;
@@ -192,20 +187,9 @@ namespace UVtools.GUI.Forms
return;
}
- if (Mutation.Mutate == LayerManager.Mutate.SmoothGaussian ||
- Mutation.Mutate == LayerManager.Mutate.SmoothMedian)
- {
- if (IterationsFade)
- {
- MessageBox.Show("Smooth doesn't support fading.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
- return;
- }
- if (Iterations % 2 != 1)
- {
- MessageBox.Show("Iterations must be a odd number.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
- return;
- }
- }
+ KernelMatrix = ctrlKernel.GetMatrix();
+ if (ReferenceEquals(KernelMatrix, null)) return;
+
var operationName = string.IsNullOrEmpty(Mutation.MenuName) ? Mutation.Mutate.ToString() : Mutation.MenuName;
if (MessageBox.Show($"Are you sure you want to {operationName}?", Text, MessageBoxButtons.YesNo,
diff --git a/UVtools.GUI/Forms/FrmMutationBlur.Designer.cs b/UVtools.GUI/Forms/FrmMutationBlur.Designer.cs
new file mode 100644
index 0000000..9ccf143
--- /dev/null
+++ b/UVtools.GUI/Forms/FrmMutationBlur.Designer.cs
@@ -0,0 +1,367 @@
+using UVtools.GUI.Controls;
+
+namespace UVtools.GUI.Forms
+{
+ partial class FrmMutationBlur
+ {
+ /// <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 Windows Form 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.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmMutationBlur));
+ this.lbDescription = new System.Windows.Forms.Label();
+ this.lbIterationsStart = new System.Windows.Forms.Label();
+ this.nmSize = new System.Windows.Forms.NumericUpDown();
+ this.lbLayerRange = new System.Windows.Forms.Label();
+ this.nmLayerRangeStart = new System.Windows.Forms.NumericUpDown();
+ this.nmLayerRangeEnd = new System.Windows.Forms.NumericUpDown();
+ this.lbLayerRangeTo = new System.Windows.Forms.Label();
+ this.cmLayerRange = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.btnLayerRangeAllLayers = new System.Windows.Forms.ToolStripMenuItem();
+ this.btnLayerRangeCurrentLayer = new System.Windows.Forms.ToolStripMenuItem();
+ this.btnLayerRangeBottomLayers = new System.Windows.Forms.ToolStripMenuItem();
+ this.btnLayerRangeNormalLayers = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+ this.btnCancel = new System.Windows.Forms.Button();
+ this.btnPreview = new System.Windows.Forms.Button();
+ this.pbInfo = new System.Windows.Forms.PictureBox();
+ this.btnMutate = new System.Windows.Forms.Button();
+ this.cbAlgorithm = new System.Windows.Forms.ComboBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.ctrlKernel = new UVtools.GUI.Controls.CtrlKernel();
+ this.btnLayerRangeSelect = new UVtools.GUI.Controls.SplitButton();
+ ((System.ComponentModel.ISupportInitialize)(this.nmSize)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeStart)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeEnd)).BeginInit();
+ this.cmLayerRange.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.pbInfo)).BeginInit();
+ this.SuspendLayout();
+ //
+ // lbDescription
+ //
+ this.lbDescription.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.lbDescription.Location = new System.Drawing.Point(13, 14);
+ this.lbDescription.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.lbDescription.Name = "lbDescription";
+ this.lbDescription.Size = new System.Drawing.Size(584, 128);
+ this.lbDescription.TabIndex = 0;
+ this.lbDescription.Text = "Description";
+ //
+ // lbIterationsStart
+ //
+ this.lbIterationsStart.AutoSize = true;
+ this.lbIterationsStart.Location = new System.Drawing.Point(66, 220);
+ this.lbIterationsStart.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.lbIterationsStart.Name = "lbIterationsStart";
+ this.lbIterationsStart.Size = new System.Drawing.Size(44, 20);
+ this.lbIterationsStart.TabIndex = 3;
+ this.lbIterationsStart.Text = "Size:";
+ this.toolTip.SetToolTip(this.lbIterationsStart, resources.GetString("lbIterationsStart.ToolTip"));
+ //
+ // nmSize
+ //
+ this.nmSize.Location = new System.Drawing.Point(118, 217);
+ this.nmSize.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.nmSize.Minimum = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.nmSize.Name = "nmSize";
+ this.nmSize.Size = new System.Drawing.Size(149, 26);
+ this.nmSize.TabIndex = 3;
+ this.nmSize.Value = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ //
+ // lbLayerRange
+ //
+ this.lbLayerRange.AutoSize = true;
+ this.lbLayerRange.Location = new System.Drawing.Point(13, 150);
+ this.lbLayerRange.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.lbLayerRange.Name = "lbLayerRange";
+ this.lbLayerRange.Size = new System.Drawing.Size(97, 20);
+ this.lbLayerRange.TabIndex = 9;
+ this.lbLayerRange.Text = "Layer range:";
+ this.toolTip.SetToolTip(this.lbLayerRange, resources.GetString("lbLayerRange.ToolTip"));
+ //
+ // nmLayerRangeStart
+ //
+ this.nmLayerRangeStart.Location = new System.Drawing.Point(118, 147);
+ this.nmLayerRangeStart.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.nmLayerRangeStart.Maximum = new decimal(new int[] {
+ 100000,
+ 0,
+ 0,
+ 0});
+ this.nmLayerRangeStart.Name = "nmLayerRangeStart";
+ this.nmLayerRangeStart.Size = new System.Drawing.Size(149, 26);
+ this.nmLayerRangeStart.TabIndex = 0;
+ //
+ // nmLayerRangeEnd
+ //
+ this.nmLayerRangeEnd.Location = new System.Drawing.Point(314, 147);
+ this.nmLayerRangeEnd.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.nmLayerRangeEnd.Maximum = new decimal(new int[] {
+ 100000,
+ 0,
+ 0,
+ 0});
+ this.nmLayerRangeEnd.Name = "nmLayerRangeEnd";
+ this.nmLayerRangeEnd.Size = new System.Drawing.Size(149, 26);
+ this.nmLayerRangeEnd.TabIndex = 1;
+ //
+ // lbLayerRangeTo
+ //
+ this.lbLayerRangeTo.AutoSize = true;
+ this.lbLayerRangeTo.Location = new System.Drawing.Point(275, 150);
+ this.lbLayerRangeTo.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.lbLayerRangeTo.Name = "lbLayerRangeTo";
+ this.lbLayerRangeTo.Size = new System.Drawing.Size(31, 20);
+ this.lbLayerRangeTo.TabIndex = 12;
+ this.lbLayerRangeTo.Text = "To:";
+ //
+ // cmLayerRange
+ //
+ this.cmLayerRange.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.btnLayerRangeAllLayers,
+ this.btnLayerRangeCurrentLayer,
+ this.btnLayerRangeBottomLayers,
+ this.btnLayerRangeNormalLayers});
+ this.cmLayerRange.Name = "cmLayerRange";
+ this.cmLayerRange.Size = new System.Drawing.Size(226, 92);
+ //
+ // btnLayerRangeAllLayers
+ //
+ this.btnLayerRangeAllLayers.Name = "btnLayerRangeAllLayers";
+ this.btnLayerRangeAllLayers.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)
+ | System.Windows.Forms.Keys.A)));
+ this.btnLayerRangeAllLayers.Size = new System.Drawing.Size(225, 22);
+ this.btnLayerRangeAllLayers.Text = "&All Layers";
+ this.btnLayerRangeAllLayers.Click += new System.EventHandler(this.ItemClicked);
+ //
+ // btnLayerRangeCurrentLayer
+ //
+ this.btnLayerRangeCurrentLayer.Name = "btnLayerRangeCurrentLayer";
+ this.btnLayerRangeCurrentLayer.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)
+ | System.Windows.Forms.Keys.C)));
+ this.btnLayerRangeCurrentLayer.Size = new System.Drawing.Size(225, 22);
+ this.btnLayerRangeCurrentLayer.Text = "&Current Layer";
+ this.btnLayerRangeCurrentLayer.Click += new System.EventHandler(this.ItemClicked);
+ //
+ // btnLayerRangeBottomLayers
+ //
+ this.btnLayerRangeBottomLayers.Name = "btnLayerRangeBottomLayers";
+ this.btnLayerRangeBottomLayers.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)
+ | System.Windows.Forms.Keys.B)));
+ this.btnLayerRangeBottomLayers.Size = new System.Drawing.Size(225, 22);
+ this.btnLayerRangeBottomLayers.Text = "&Bottom Layers";
+ this.btnLayerRangeBottomLayers.Click += new System.EventHandler(this.ItemClicked);
+ //
+ // btnLayerRangeNormalLayers
+ //
+ this.btnLayerRangeNormalLayers.Name = "btnLayerRangeNormalLayers";
+ this.btnLayerRangeNormalLayers.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)
+ | System.Windows.Forms.Keys.N)));
+ this.btnLayerRangeNormalLayers.Size = new System.Drawing.Size(225, 22);
+ this.btnLayerRangeNormalLayers.Text = "&Normal Layers";
+ this.btnLayerRangeNormalLayers.Click += new System.EventHandler(this.ItemClicked);
+ //
+ // toolTip
+ //
+ this.toolTip.AutoPopDelay = 32767;
+ this.toolTip.InitialDelay = 500;
+ this.toolTip.IsBalloon = true;
+ this.toolTip.ReshowDelay = 100;
+ this.toolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info;
+ this.toolTip.ToolTipTitle = "Information";
+ //
+ // btnCancel
+ //
+ this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ 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(447, 476);
+ this.btnCancel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Size = new System.Drawing.Size(150, 48);
+ this.btnCancel.TabIndex = 6;
+ this.btnCancel.Text = "&Cancel";
+ this.btnCancel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ this.btnCancel.UseVisualStyleBackColor = true;
+ this.btnCancel.Click += new System.EventHandler(this.ItemClicked);
+ //
+ // btnPreview
+ //
+ this.btnPreview.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.btnPreview.Enabled = false;
+ this.btnPreview.Image = global::UVtools.GUI.Properties.Resources.eye_24x24;
+ this.btnPreview.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ this.btnPreview.Location = new System.Drawing.Point(131, 476);
+ this.btnPreview.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.btnPreview.Name = "btnPreview";
+ this.btnPreview.Size = new System.Drawing.Size(150, 48);
+ this.btnPreview.TabIndex = 4;
+ this.btnPreview.Text = "&Preview";
+ this.btnPreview.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ this.btnPreview.UseVisualStyleBackColor = true;
+ this.btnPreview.Visible = false;
+ //
+ // pbInfo
+ //
+ this.pbInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.pbInfo.Location = new System.Drawing.Point(604, 14);
+ this.pbInfo.Name = "pbInfo";
+ this.pbInfo.Size = new System.Drawing.Size(311, 323);
+ this.pbInfo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.pbInfo.TabIndex = 7;
+ this.pbInfo.TabStop = false;
+ this.pbInfo.Visible = false;
+ //
+ // btnMutate
+ //
+ this.btnMutate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.btnMutate.Image = global::UVtools.GUI.Properties.Resources.Ok_24x24;
+ this.btnMutate.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ this.btnMutate.Location = new System.Drawing.Point(289, 476);
+ this.btnMutate.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.btnMutate.Name = "btnMutate";
+ this.btnMutate.Size = new System.Drawing.Size(150, 48);
+ this.btnMutate.TabIndex = 5;
+ this.btnMutate.Text = "&Mutate";
+ this.btnMutate.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ this.btnMutate.UseVisualStyleBackColor = true;
+ this.btnMutate.Click += new System.EventHandler(this.ItemClicked);
+ //
+ // cbAlgorithm
+ //
+ this.cbAlgorithm.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cbAlgorithm.DropDownWidth = 600;
+ this.cbAlgorithm.FormattingEnabled = true;
+ this.cbAlgorithm.Location = new System.Drawing.Point(118, 181);
+ this.cbAlgorithm.Name = "cbAlgorithm";
+ this.cbAlgorithm.Size = new System.Drawing.Size(479, 28);
+ this.cbAlgorithm.TabIndex = 17;
+ this.cbAlgorithm.SelectedIndexChanged += new System.EventHandler(this.EventSelectedIndexChanged);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(30, 185);
+ this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(80, 20);
+ this.label1.TabIndex = 18;
+ this.label1.Text = "Algorithm:";
+ //
+ // ctrlKernel
+ //
+ this.ctrlKernel.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.ctrlKernel.Location = new System.Drawing.Point(12, 251);
+ this.ctrlKernel.Name = "ctrlKernel";
+ this.ctrlKernel.Size = new System.Drawing.Size(586, 217);
+ this.ctrlKernel.TabIndex = 16;
+ //
+ // btnLayerRangeSelect
+ //
+ this.btnLayerRangeSelect.Location = new System.Drawing.Point(470, 147);
+ this.btnLayerRangeSelect.Menu = this.cmLayerRange;
+ this.btnLayerRangeSelect.Name = "btnLayerRangeSelect";
+ this.btnLayerRangeSelect.Size = new System.Drawing.Size(128, 26);
+ this.btnLayerRangeSelect.TabIndex = 2;
+ this.btnLayerRangeSelect.Text = "Select";
+ this.btnLayerRangeSelect.UseVisualStyleBackColor = true;
+ //
+ // FrmMutationBlur
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this.btnCancel;
+ this.ClientSize = new System.Drawing.Size(927, 538);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.cbAlgorithm);
+ this.Controls.Add(this.ctrlKernel);
+ this.Controls.Add(this.btnLayerRangeSelect);
+ this.Controls.Add(this.lbLayerRangeTo);
+ this.Controls.Add(this.nmLayerRangeEnd);
+ this.Controls.Add(this.nmLayerRangeStart);
+ this.Controls.Add(this.lbLayerRange);
+ this.Controls.Add(this.btnPreview);
+ this.Controls.Add(this.pbInfo);
+ this.Controls.Add(this.btnMutate);
+ this.Controls.Add(this.btnCancel);
+ this.Controls.Add(this.nmSize);
+ this.Controls.Add(this.lbIterationsStart);
+ this.Controls.Add(this.lbDescription);
+ this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.KeyPreview = true;
+ this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FrmMutationBlur";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Form1";
+ this.TopMost = true;
+ ((System.ComponentModel.ISupportInitialize)(this.nmSize)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeStart)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeEnd)).EndInit();
+ this.cmLayerRange.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.pbInfo)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label lbDescription;
+ private System.Windows.Forms.Label lbIterationsStart;
+ private System.Windows.Forms.NumericUpDown nmSize;
+ private System.Windows.Forms.Button btnCancel;
+ private System.Windows.Forms.Button btnMutate;
+ private System.Windows.Forms.PictureBox pbInfo;
+ private System.Windows.Forms.Button btnPreview;
+ private System.Windows.Forms.Label lbLayerRange;
+ private System.Windows.Forms.NumericUpDown nmLayerRangeStart;
+ private System.Windows.Forms.NumericUpDown nmLayerRangeEnd;
+ private System.Windows.Forms.Label lbLayerRangeTo;
+ private Controls.SplitButton btnLayerRangeSelect;
+ private System.Windows.Forms.ContextMenuStrip cmLayerRange;
+ private System.Windows.Forms.ToolStripMenuItem btnLayerRangeAllLayers;
+ private System.Windows.Forms.ToolStripMenuItem btnLayerRangeCurrentLayer;
+ private System.Windows.Forms.ToolStripMenuItem btnLayerRangeBottomLayers;
+ private System.Windows.Forms.ToolStripMenuItem btnLayerRangeNormalLayers;
+ private System.Windows.Forms.ToolTip toolTip;
+ public CtrlKernel ctrlKernel;
+ private System.Windows.Forms.ComboBox cbAlgorithm;
+ private System.Windows.Forms.Label label1;
+ }
+} \ No newline at end of file
diff --git a/UVtools.GUI/Forms/FrmMutationBlur.cs b/UVtools.GUI/Forms/FrmMutationBlur.cs
new file mode 100644
index 0000000..0f58441
--- /dev/null
+++ b/UVtools.GUI/Forms/FrmMutationBlur.cs
@@ -0,0 +1,248 @@
+/*
+ * 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;
+using System.Drawing;
+using System.Windows.Forms;
+using Emgu.CV;
+using UVtools.Core;
+
+namespace UVtools.GUI.Forms
+{
+ public partial class FrmMutationBlur : Form
+ {
+ public enum BlurAlgorithm
+ {
+ Blur,
+ Pyramid,
+ MedianBlur,
+ GaussianBlur,
+ Filter2D
+ }
+ public struct BlurAlgorithmDescription
+ {
+ public BlurAlgorithm BlurAlgorithm;
+ public string Description;
+
+ public BlurAlgorithmDescription(BlurAlgorithm blurAlgorithm, string description)
+ {
+ BlurAlgorithm = blurAlgorithm;
+ Description = description;
+ }
+
+ public override string ToString()
+ {
+ return Description;
+ }
+ }
+ #region Properties
+
+ private Mutation Mutation { get; }
+
+ public uint LayerRangeStart
+ {
+ get => (uint) nmLayerRangeStart.Value;
+ set => nmLayerRangeStart.Value = value;
+ }
+
+ public uint LayerRangeEnd
+ {
+ get => (uint)Math.Min(nmLayerRangeEnd.Value, Program.SlicerFile.LayerCount-1);
+ set => nmLayerRangeEnd.Value = value;
+ }
+
+ public BlurAlgorithm BlurAlgorithmType => ((BlurAlgorithmDescription) cbAlgorithm.SelectedItem).BlurAlgorithm;
+
+ public uint KSize
+ {
+ get => (uint) nmSize.Value;
+ set => nmSize.Value = value;
+ }
+
+ public Matrix<byte> KernelMatrix { get; private set; }
+ public Point KernelAnchor => ctrlKernel.KernelAnchor;
+ #endregion
+
+ #region Constructors
+
+ public FrmMutationBlur()
+ {
+ InitializeComponent();
+ nmLayerRangeEnd.Value = Program.SlicerFile.LayerCount - 1;
+ cbAlgorithm.Items.AddRange(new object[]
+ {
+ new BlurAlgorithmDescription(BlurAlgorithm.Blur, "Blur: Normalized box filter"),
+ new BlurAlgorithmDescription(BlurAlgorithm.Pyramid, "Pyramid: Down/up-sampling step of Gaussian pyramid decomposition"),
+ new BlurAlgorithmDescription(BlurAlgorithm.MedianBlur, "Median Blur: Each pixel becomes the median of its surrounding pixels"),
+ new BlurAlgorithmDescription(BlurAlgorithm.GaussianBlur, "Gaussian Blur: Each pixel is a sum of fractions of each pixel in its neighborhood"),
+ new BlurAlgorithmDescription(BlurAlgorithm.Filter2D, "Filter 2D: Applies an arbitrary linear filter to an image"),
+ });
+ cbAlgorithm.SelectedIndex = 0;
+ }
+
+ public FrmMutationBlur(Mutation mutation) : this()
+ {
+
+ Mutation = mutation;
+
+ Text = $"Mutate: {mutation.MenuName}";
+ lbDescription.Text = Mutation.Description;
+
+ if (ReferenceEquals(mutation.Image, null))
+ {
+ Width = pbInfo.Location.X+25;
+ }
+ else
+ {
+ pbInfo.Image = mutation.Image;
+ pbInfo.Visible = true;
+ }
+ }
+ #endregion
+
+ #region Overrides
+ protected override void OnKeyUp(KeyEventArgs e)
+ {
+ base.OnKeyUp(e);
+ if (e.KeyCode == Keys.Enter)
+ {
+ if (ctrlKernel.tbKernel.ContainsFocus) return;
+ btnMutate.PerformClick();
+ e.Handled = true;
+ return;
+ }
+
+ if ((ModifierKeys & Keys.Shift) == Keys.Shift && (ModifierKeys & Keys.Control) == Keys.Control)
+ {
+ if (e.KeyCode == Keys.A)
+ {
+ btnLayerRangeAllLayers.PerformClick();
+ e.Handled = true;
+ return;
+ }
+
+ if (e.KeyCode == Keys.C)
+ {
+ btnLayerRangeCurrentLayer.PerformClick();
+ e.Handled = true;
+ return;
+ }
+
+ if (e.KeyCode == Keys.B)
+ {
+ btnLayerRangeBottomLayers.PerformClick();
+ e.Handled = true;
+ return;
+ }
+
+ if (e.KeyCode == Keys.N)
+ {
+ btnLayerRangeNormalLayers.PerformClick();
+ e.Handled = true;
+ return;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Events
+ private void ItemClicked(object sender, EventArgs e)
+ {
+ if (ReferenceEquals(sender, btnLayerRangeAllLayers))
+ {
+ nmLayerRangeStart.Value = 0;
+ nmLayerRangeEnd.Value = Program.SlicerFile.LayerCount-1;
+ return;
+ }
+
+ if (ReferenceEquals(sender, btnLayerRangeCurrentLayer))
+ {
+ nmLayerRangeStart.Value = Program.FrmMain.ActualLayer;
+ nmLayerRangeEnd.Value = Program.FrmMain.ActualLayer;
+ return;
+ }
+
+ if (ReferenceEquals(sender, btnLayerRangeBottomLayers))
+ {
+ nmLayerRangeStart.Value = 0;
+ nmLayerRangeEnd.Value = Program.SlicerFile.InitialLayerCount-1;
+ return;
+ }
+
+ if (ReferenceEquals(sender, btnLayerRangeNormalLayers))
+ {
+ nmLayerRangeStart.Value = Program.SlicerFile.InitialLayerCount - 1;
+ nmLayerRangeEnd.Value = Program.SlicerFile.LayerCount - 1;
+ return;
+ }
+
+ if (ReferenceEquals(sender, btnMutate))
+ {
+ if (!btnMutate.Enabled) return;
+ if (LayerRangeStart > LayerRangeEnd)
+ {
+ MessageBox.Show("Layer range start can't be higher than layer end.\nPlease fix and try again.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ nmLayerRangeStart.Select();
+ return;
+ }
+
+ if (BlurAlgorithmType == BlurAlgorithm.GaussianBlur ||
+ BlurAlgorithmType == BlurAlgorithm.MedianBlur)
+ {
+ if (KSize % 2 != 1)
+ {
+ MessageBox.Show("Size must be a odd number", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ }
+
+ if (BlurAlgorithmType == BlurAlgorithm.Filter2D)
+ {
+ KernelMatrix = ctrlKernel.GetMatrix();
+ if (ReferenceEquals(KernelMatrix, null)) return;
+ }
+
+
+ var operationName = string.IsNullOrEmpty(Mutation.MenuName) ? Mutation.Mutate.ToString() : Mutation.MenuName;
+ if (MessageBox.Show($"Are you sure you want to {operationName}?", Text, MessageBoxButtons.YesNo,
+ MessageBoxIcon.Question) == DialogResult.Yes)
+ {
+ DialogResult = DialogResult.OK;
+ if (KSize <= 0) // Should never happen!
+ {
+ DialogResult = DialogResult.Cancel;
+ }
+ Close();
+ }
+
+ return;
+ }
+
+ if (ReferenceEquals(sender, btnCancel))
+ {
+ DialogResult = DialogResult.Cancel;
+ return;
+ }
+ }
+
+ private void EventSelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (ReferenceEquals(sender, cbAlgorithm))
+ {
+ ctrlKernel.Enabled = BlurAlgorithmType == BlurAlgorithm.Filter2D;
+ nmSize.Enabled = BlurAlgorithmType != BlurAlgorithm.Pyramid && BlurAlgorithmType != BlurAlgorithm.Filter2D;
+ return;
+ }
+ }
+
+ #endregion
+
+
+ }
+}
diff --git a/UVtools.GUI/Forms/FrmMutationBlur.resx b/UVtools.GUI/Forms/FrmMutationBlur.resx
new file mode 100644
index 0000000..40776f4
--- /dev/null
+++ b/UVtools.GUI/Forms/FrmMutationBlur.resx
@@ -0,0 +1,136 @@
+<?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>148, 17</value>
+ </metadata>
+ <data name="lbIterationsStart.ToolTip" xml:space="preserve">
+ <value>Selects the number of iterations/passes to perform on each layer using this mutator.
+Enable the "Fade in/out" to fade the iteration over layers, you can use a start iteration higher than end to perform a inverse fade.
+WARNING: Using high iteration values can destroy your model depending on the mutator being used, please use low values or with caution!</value>
+ </data>
+ <data name="lbLayerRange.ToolTip" xml:space="preserve">
+ <value>Selects the layers range within start layer and end layer where mutator will operate.
+Select same layer start as end to operate only within that layer.
+Note: "Layer Start" start can't be higher than "Layer End".</value>
+ </data>
+ <metadata name="cmLayerRange.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/Forms/FrmMutationPixelDimming.Designer.cs b/UVtools.GUI/Forms/FrmMutationPixelDimming.Designer.cs
index 55114be..4e06213 100644
--- a/UVtools.GUI/Forms/FrmMutationPixelDimming.Designer.cs
+++ b/UVtools.GUI/Forms/FrmMutationPixelDimming.Designer.cs
@@ -45,11 +45,11 @@ namespace UVtools.GUI.Forms
this.btnLayerRangeNormalLayers = new System.Windows.Forms.ToolStripMenuItem();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.label1 = new System.Windows.Forms.Label();
+ this.label6 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
- this.label6 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.btnCancel = new System.Windows.Forms.Button();
this.btnMutate = new System.Windows.Forms.Button();
@@ -68,6 +68,10 @@ namespace UVtools.GUI.Forms
this.btnDimPatternChessBoard = new System.Windows.Forms.Button();
this.tbOddPattern = new System.Windows.Forms.TextBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.label13 = new System.Windows.Forms.Label();
+ this.label11 = new System.Windows.Forms.Label();
+ this.nmInfillSpacing = new System.Windows.Forms.NumericUpDown();
+ this.label12 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.btnInfillPatternWaves = new System.Windows.Forms.Button();
this.btnInfillPatternSquareGrid = new System.Windows.Forms.Button();
@@ -75,10 +79,6 @@ namespace UVtools.GUI.Forms
this.nmInfillThickness = new System.Windows.Forms.NumericUpDown();
this.label9 = new System.Windows.Forms.Label();
this.label10 = new System.Windows.Forms.Label();
- this.label11 = new System.Windows.Forms.Label();
- this.nmInfillSpacing = new System.Windows.Forms.NumericUpDown();
- this.label12 = new System.Windows.Forms.Label();
- this.label13 = new System.Windows.Forms.Label();
this.btnLayerRangeSelect = new UVtools.GUI.Controls.SplitButton();
((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeStart)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeEnd)).BeginInit();
@@ -87,8 +87,8 @@ namespace UVtools.GUI.Forms
((System.ComponentModel.ISupportInitialize)(this.nmPixelDimBrightness)).BeginInit();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.nmInfillThickness)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nmInfillSpacing)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmInfillThickness)).BeginInit();
this.SuspendLayout();
//
// lbDescription
@@ -225,6 +225,17 @@ namespace UVtools.GUI.Forms
this.label1.Text = "px";
this.toolTip.SetToolTip(this.label1, resources.GetString("label1.ToolTip"));
//
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(19, 478);
+ this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(548, 20);
+ this.label6.TabIndex = 25;
+ this.label6.Text = "(Leave this field empty to use only the even layer pattern for the layers range)";
+ this.toolTip.SetToolTip(this.label6, resources.GetString("label6.ToolTip"));
+ //
// label2
//
this.label2.AutoSize = true;
@@ -265,17 +276,6 @@ namespace UVtools.GUI.Forms
this.label5.TabIndex = 24;
this.label5.Text = "Odd Layer\r\nPattern:\r\n0 = Black\r\n255 = White\r\n(Optional)";
//
- // label6
- //
- this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(19, 478);
- this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label6.Name = "label6";
- this.label6.Size = new System.Drawing.Size(548, 20);
- this.label6.TabIndex = 25;
- this.label6.Text = "(Leave this field empty to use only the even layer pattern for the layers range)";
- this.toolTip.SetToolTip(this.label6, resources.GetString("label6.ToolTip"));
- //
// label7
//
this.label7.AutoSize = true;
@@ -344,6 +344,7 @@ namespace UVtools.GUI.Forms
this.tbEvenPattern.Size = new System.Drawing.Size(469, 124);
this.tbEvenPattern.TabIndex = 17;
this.tbEvenPattern.Text = "127 255 255 255\r\n255 255 127 255";
+ this.tbEvenPattern.WordWrap = false;
//
// nmPixelDimBrightness
//
@@ -485,6 +486,7 @@ namespace UVtools.GUI.Forms
this.tbOddPattern.Size = new System.Drawing.Size(469, 124);
this.tbOddPattern.TabIndex = 23;
this.tbOddPattern.Text = "255 255 127 255\r\n127 255 255 255";
+ this.tbOddPattern.WordWrap = false;
//
// groupBox2
//
@@ -506,6 +508,60 @@ namespace UVtools.GUI.Forms
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Infill generator";
//
+ // label13
+ //
+ this.label13.Location = new System.Drawing.Point(7, 22);
+ this.label13.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label13.Name = "label13";
+ this.label13.Size = new System.Drawing.Size(561, 46);
+ this.label13.TabIndex = 34;
+ this.label13.Text = "The infill function can create a ton of resin traps, use only this tool if you kn" +
+ "ow what are you doing or for specific parts. You always need to ensure the drain" +
+ "s.";
+ //
+ // label11
+ //
+ this.label11.AutoSize = true;
+ this.label11.Location = new System.Drawing.Point(543, 76);
+ this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label11.Name = "label11";
+ this.label11.Size = new System.Drawing.Size(25, 20);
+ this.label11.TabIndex = 33;
+ this.label11.Text = "px";
+ //
+ // nmInfillSpacing
+ //
+ this.nmInfillSpacing.Location = new System.Drawing.Point(422, 73);
+ this.nmInfillSpacing.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.nmInfillSpacing.Maximum = new decimal(new int[] {
+ 10000,
+ 0,
+ 0,
+ 0});
+ this.nmInfillSpacing.Minimum = new decimal(new int[] {
+ 5,
+ 0,
+ 0,
+ 0});
+ this.nmInfillSpacing.Name = "nmInfillSpacing";
+ this.nmInfillSpacing.Size = new System.Drawing.Size(113, 26);
+ this.nmInfillSpacing.TabIndex = 31;
+ this.nmInfillSpacing.Value = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ 0});
+ //
+ // label12
+ //
+ this.label12.AutoSize = true;
+ this.label12.Location = new System.Drawing.Point(343, 76);
+ this.label12.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label12.Name = "label12";
+ this.label12.Size = new System.Drawing.Size(71, 20);
+ this.label12.TabIndex = 32;
+ this.label12.Text = "Spacing:";
+ //
// label8
//
this.label8.AutoSize = true;
@@ -589,60 +645,6 @@ namespace UVtools.GUI.Forms
this.label10.TabIndex = 21;
this.label10.Text = "Thickness:";
//
- // label11
- //
- this.label11.AutoSize = true;
- this.label11.Location = new System.Drawing.Point(543, 76);
- this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label11.Name = "label11";
- this.label11.Size = new System.Drawing.Size(25, 20);
- this.label11.TabIndex = 33;
- this.label11.Text = "px";
- //
- // nmInfillSpacing
- //
- this.nmInfillSpacing.Location = new System.Drawing.Point(422, 73);
- this.nmInfillSpacing.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
- this.nmInfillSpacing.Maximum = new decimal(new int[] {
- 10000,
- 0,
- 0,
- 0});
- this.nmInfillSpacing.Minimum = new decimal(new int[] {
- 5,
- 0,
- 0,
- 0});
- this.nmInfillSpacing.Name = "nmInfillSpacing";
- this.nmInfillSpacing.Size = new System.Drawing.Size(113, 26);
- this.nmInfillSpacing.TabIndex = 31;
- this.nmInfillSpacing.Value = new decimal(new int[] {
- 20,
- 0,
- 0,
- 0});
- //
- // label12
- //
- this.label12.AutoSize = true;
- this.label12.Location = new System.Drawing.Point(343, 76);
- this.label12.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label12.Name = "label12";
- this.label12.Size = new System.Drawing.Size(71, 20);
- this.label12.TabIndex = 32;
- this.label12.Text = "Spacing:";
- //
- // label13
- //
- this.label13.Location = new System.Drawing.Point(7, 22);
- this.label13.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label13.Name = "label13";
- this.label13.Size = new System.Drawing.Size(561, 46);
- this.label13.TabIndex = 34;
- this.label13.Text = "The infill function can create a ton of resin traps, use only this tool if you kn" +
- "ow what are you doing or for specific parts. You always need to ensure the drain" +
- "s.";
- //
// btnLayerRangeSelect
//
this.btnLayerRangeSelect.Location = new System.Drawing.Point(446, 146);
@@ -697,8 +699,8 @@ namespace UVtools.GUI.Forms
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
- ((System.ComponentModel.ISupportInitialize)(this.nmInfillThickness)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nmInfillSpacing)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmInfillThickness)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
diff --git a/UVtools.GUI/Forms/FrmToolEmpty.cs b/UVtools.GUI/Forms/FrmToolEmpty.cs
index 29d89cc..9c91473 100644
--- a/UVtools.GUI/Forms/FrmToolEmpty.cs
+++ b/UVtools.GUI/Forms/FrmToolEmpty.cs
@@ -33,11 +33,22 @@ namespace UVtools.GUI.Forms
#endregion
#region Constructors
- public FrmToolEmpty(uint layerIndex, string text, string description, string btnOkText)
+ public FrmToolEmpty()
{
InitializeComponent();
- DialogResult = DialogResult.Cancel;
+ }
+
+ public FrmToolEmpty(Mutation mutation) : this()
+ {
+ btnOk.Text = "Mutate";
+ Text = $"Mutate: {mutation.MenuName}";
+ lbDescription.Text = mutation.Description;
+ nmLayerRangeEnd.Value = Program.SlicerFile.LayerCount - 1;
+ }
+
+ public FrmToolEmpty(uint layerIndex, string text, string description, string btnOkText) : this()
+ {
nmLayerRangeStart.Value = layerIndex;
nmLayerRangeEnd.Value = layerIndex;
diff --git a/UVtools.GUI/FrmMain.cs b/UVtools.GUI/FrmMain.cs
index fb2aa3b..8f0d0aa 100644
--- a/UVtools.GUI/FrmMain.cs
+++ b/UVtools.GUI/FrmMain.cs
@@ -109,7 +109,12 @@ namespace UVtools.GUI
"If a pixel brightness is less or equal to the threshold value, set this pixel to 0, otherwise set to defined maximum value.\n" +
"More info: https://docs.opencv.org/master/d7/d4d/tutorial_py_thresholding.html"
)},
- {LayerManager.Mutate.PyrDownUp, new Mutation(LayerManager.Mutate.PyrDownUp, "Big Blur", Resources.blur_16x16,
+ {LayerManager.Mutate.Blur, new Mutation(LayerManager.Mutate.Blur, "Blur", Resources.blur_16x16,
+ "Blur and averaging images with various low pass filters\n" +
+ "Note: Printer must support AntiAliasing on firmware to able to use this function\n" +
+ "More information: https://docs.opencv.org/master/d4/d13/tutorial_py_filtering.html "
+ )},
+ /*{LayerManager.Mutate.PyrDownUp, new Mutation(LayerManager.Mutate.PyrDownUp, "Big Blur", Resources.blur_16x16,
"Performs down/up-sampling step of Gaussian pyramid decomposition.\n" +
"First down-samples the image by rejecting even rows and columns, after performs up-sampling step of Gaussian pyramid decomposition.\n" +
"This operation will add a big blur to edges, creating a over-exaggerated anti-aliasing and as result can make edges smoother\n" +
@@ -127,7 +132,7 @@ namespace UVtools.GUI
"Very fast, but does not preserve sharp edges well.\n" +
"Note 1: Printer must support AntiAliasing on firmware to able to use this function.\n" +
"Note 2: Iterations must be a odd number."
- )},
+ )},*/
};
@@ -3103,6 +3108,9 @@ namespace UVtools.GUI
uint iterationsEnd = 0;
bool fade = false;
+ Matrix<byte> kernel = null;
+ Point kernelAnchor = Point.Empty;
+
ThresholdType thresholdType = ThresholdType.Binary;
OperationMove operationMove = null;
@@ -3113,6 +3121,8 @@ namespace UVtools.GUI
Matrix<byte> evenPattern = null;
Matrix<byte> oddPattern = null;
+ FrmMutationBlur.BlurAlgorithm blurAlgorithm = FrmMutationBlur.BlurAlgorithm.Blur;
+
switch (mutator)
{
case LayerManager.Mutate.Move:
@@ -3156,6 +3166,14 @@ namespace UVtools.GUI
x = (double) inputBox.Value;
}
break;
+ case LayerManager.Mutate.Solidify:
+ using (FrmToolEmpty inputBox = new FrmToolEmpty(Mutations[mutator]))
+ {
+ if (inputBox.ShowDialog() != DialogResult.OK) return;
+ layerStart = inputBox.LayerRangeStart;
+ layerEnd = inputBox.LayerRangeEnd;
+ }
+ break;
case LayerManager.Mutate.PixelDimming:
using (FrmMutationPixelDimming inputBox = new FrmMutationPixelDimming(Mutations[mutator]))
{
@@ -3178,6 +3196,25 @@ namespace UVtools.GUI
thresholdType = inputBox.ThresholdTypeValue;
}
break;
+ case LayerManager.Mutate.Blur:
+ using (FrmMutationBlur inputBox = new FrmMutationBlur(Mutations[mutator]))
+ {
+ if (inputBox.ShowDialog() != DialogResult.OK) return;
+ iterationsStart = inputBox.KSize;
+ if (iterationsStart == 0) return;
+ layerStart = inputBox.LayerRangeStart;
+ layerEnd = inputBox.LayerRangeEnd;
+
+ blurAlgorithm = inputBox.BlurAlgorithmType;
+
+ if (blurAlgorithm == FrmMutationBlur.BlurAlgorithm.Filter2D)
+ {
+ kernel = inputBox.KernelMatrix;
+ kernelAnchor = inputBox.KernelAnchor;
+ }
+ }
+
+ break;
default:
using (FrmMutation inputBox = new FrmMutation(Mutations[mutator]))
{
@@ -3187,6 +3224,9 @@ namespace UVtools.GUI
layerStart = inputBox.LayerRangeStart;
layerEnd = inputBox.LayerRangeEnd;
iterationsEnd = inputBox.IterationsEnd;
+
+ kernel = inputBox.KernelMatrix;
+ kernelAnchor = inputBox.KernelAnchor;
}
break;
@@ -3234,19 +3274,19 @@ namespace UVtools.GUI
SlicerFile.LayerManager.MutatePixelDimming(layerStart, layerEnd, evenPattern, oddPattern, (ushort) iterationsStart, progress);
break;
case LayerManager.Mutate.Erode:
- SlicerFile.LayerManager.MutateErode(layerStart, layerEnd, (int) iterationsStart, (int) iterationsEnd, fade, progress);
+ SlicerFile.LayerManager.MutateErode(layerStart, layerEnd, (int) iterationsStart, (int) iterationsEnd, fade, progress, kernel, kernelAnchor);
break;
case LayerManager.Mutate.Dilate:
- SlicerFile.LayerManager.MutateDilate(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress);
+ SlicerFile.LayerManager.MutateDilate(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress, kernel, kernelAnchor);
break;
case LayerManager.Mutate.Opening:
- SlicerFile.LayerManager.MutateOpen(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress);
+ SlicerFile.LayerManager.MutateOpen(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress, kernel, kernelAnchor);
break;
case LayerManager.Mutate.Closing:
- SlicerFile.LayerManager.MutateClose(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress);
+ SlicerFile.LayerManager.MutateClose(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress, kernel, kernelAnchor);
break;
case LayerManager.Mutate.Gradient:
- SlicerFile.LayerManager.MutateGradient(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress);
+ SlicerFile.LayerManager.MutateGradient(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress, kernel, kernelAnchor);
break;
/*case Mutation.Mutates.TopHat:
kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(9, 9),
@@ -3267,21 +3307,42 @@ namespace UVtools.GUI
case LayerManager.Mutate.ThresholdPixels:
SlicerFile.LayerManager.MutateThresholdPixels(layerStart, layerEnd, (byte) iterationsStart, (byte) iterationsEnd, thresholdType, progress);
break;
- case LayerManager.Mutate.PyrDownUp:
- SlicerFile.LayerManager.MutatePyrDownUp(layerStart, layerEnd, BorderType.Default, progress);
- break;
- case LayerManager.Mutate.SmoothMedian:
- SlicerFile.LayerManager.MutateMedianBlur(layerStart, layerEnd, (int)iterationsStart, progress);
- break;
- case LayerManager.Mutate.SmoothGaussian:
- SlicerFile.LayerManager.MutateGaussianBlur(layerStart, layerEnd, new Size((int) iterationsStart, (int) iterationsStart), 0,0, BorderType.Default, progress);
+ case LayerManager.Mutate.Blur:
+ switch (blurAlgorithm)
+ {
+ case FrmMutationBlur.BlurAlgorithm.Blur:
+ SlicerFile.LayerManager.MutateBlur(layerStart, layerEnd, new Size((int)iterationsStart, (int)iterationsStart), kernelAnchor, BorderType.Reflect101, progress);
+ break;
+ case FrmMutationBlur.BlurAlgorithm.Pyramid:
+ SlicerFile.LayerManager.MutatePyrDownUp(layerStart, layerEnd, BorderType.Default, progress);
+ break;
+ case FrmMutationBlur.BlurAlgorithm.MedianBlur:
+ SlicerFile.LayerManager.MutateMedianBlur(layerStart, layerEnd, (int) iterationsStart, progress);
+ break;
+ case FrmMutationBlur.BlurAlgorithm.GaussianBlur:
+ SlicerFile.LayerManager.MutateGaussianBlur(layerStart, layerEnd, new Size((int)iterationsStart, (int)iterationsStart), 0, 0, BorderType.Reflect101, progress);
+ break;
+ case FrmMutationBlur.BlurAlgorithm.Filter2D:
+ SlicerFile.LayerManager.MutateFilter2D(layerStart, layerEnd, kernel, kernelAnchor, BorderType.Reflect101, progress);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
break;
+ /*case LayerManager.Mutate.PyrDownUp:
+ SlicerFile.LayerManager.MutatePyrDownUp(layerStart, layerEnd, BorderType.Default, progress);
+ break;
+ case LayerManager.Mutate.SmoothMedian:
+ SlicerFile.LayerManager.MutateMedianBlur(layerStart, layerEnd, (int)iterationsStart, progress);
+ break;
+ case LayerManager.Mutate.SmoothGaussian:
+ SlicerFile.LayerManager.MutateGaussianBlur(layerStart, layerEnd, new Size((int) iterationsStart, (int) iterationsStart), 0,0, BorderType.Default, progress);
+ break;*/
}
}
catch (OperationCanceledException)
{
-
}
catch (Exception ex)
{
diff --git a/UVtools.GUI/Mutation.cs b/UVtools.GUI/Mutation.cs
index 323faf3..b56fb91 100644
--- a/UVtools.GUI/Mutation.cs
+++ b/UVtools.GUI/Mutation.cs
@@ -31,6 +31,7 @@ namespace UVtools.GUI
MenuName = menuName ?? mutate.ToString();
Description = description;
MenuImage = menuImage ?? Properties.Resources.filter_filled_16x16;
+ Image = image;
}
#endregion
diff --git a/UVtools.GUI/Properties/AssemblyInfo.cs b/UVtools.GUI/Properties/AssemblyInfo.cs
index 8100aa2..ebfa840 100644
--- a/UVtools.GUI/Properties/AssemblyInfo.cs
+++ b/UVtools.GUI/Properties/AssemblyInfo.cs
@@ -35,5 +35,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.6.4.3")]
-[assembly: AssemblyFileVersion("0.6.4.3")]
+[assembly: AssemblyVersion("0.6.5.0")]
+[assembly: AssemblyFileVersion("0.6.5.0")]
diff --git a/UVtools.GUI/UVtools.GUI.csproj b/UVtools.GUI/UVtools.GUI.csproj
index d93fd0a..229ff2c 100644
--- a/UVtools.GUI/UVtools.GUI.csproj
+++ b/UVtools.GUI/UVtools.GUI.csproj
@@ -145,6 +145,12 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="Controls\CtrlKernel.cs">
+ <SubType>UserControl</SubType>
+ </Compile>
+ <Compile Include="Controls\CtrlKernel.Designer.cs">
+ <DependentUpon>CtrlKernel.cs</DependentUpon>
+ </Compile>
<Compile Include="Controls\Log.cs" />
<Compile Include="Controls\SlicerPropertyItem.cs" />
<Compile Include="Controls\SplitButton.cs">
@@ -156,6 +162,12 @@
<Compile Include="Forms\FrmInstallPEProfiles.Designer.cs">
<DependentUpon>FrmInstallPEProfiles.cs</DependentUpon>
</Compile>
+ <Compile Include="Forms\FrmMutationBlur.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="Forms\FrmMutationBlur.Designer.cs">
+ <DependentUpon>FrmMutationBlur.cs</DependentUpon>
+ </Compile>
<Compile Include="Forms\FrmMutationThreshold.cs">
<SubType>Form</SubType>
</Compile>
@@ -262,12 +274,18 @@
<Compile Include="Mutation.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <EmbeddedResource Include="Controls\CtrlKernel.resx">
+ <DependentUpon>CtrlKernel.cs</DependentUpon>
+ </EmbeddedResource>
<EmbeddedResource Include="Forms\FrmAbout.resx">
<DependentUpon>FrmAbout.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\FrmInstallPEProfiles.resx">
<DependentUpon>FrmInstallPEProfiles.cs</DependentUpon>
</EmbeddedResource>
+ <EmbeddedResource Include="Forms\FrmMutationBlur.resx">
+ <DependentUpon>FrmMutationBlur.cs</DependentUpon>
+ </EmbeddedResource>
<EmbeddedResource Include="Forms\FrmMutationThreshold.resx">
<DependentUpon>FrmMutationThreshold.cs</DependentUpon>
</EmbeddedResource>