From 2f848af71837bfe36b35040b8847d456b778d84a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Tue, 22 Sep 2020 23:44:35 +0100 Subject: v0.8.2.4 * (Add) Layer Importer: Option to merge images * (Improvement) Layer difference computation time, faster render --- CHANGELOG.md | 5 + UVtools.Core/FileFormats/FileFormat.cs | 4 +- UVtools.Core/FileFormats/IFileFormat.cs | 5 + UVtools.Core/Layer/LayerManager.cs | 10 ++ UVtools.Core/Operations/OperationLayerImport.cs | 1 + UVtools.Core/UVtools.Core.csproj | 6 +- .../Controls/Tools/CtrlToolLayerImport.Designer.cs | 18 ++- UVtools.GUI/Controls/Tools/CtrlToolLayerImport.cs | 5 +- UVtools.GUI/FrmMain.cs | 101 +++++---------- UVtools.GUI/Properties/AssemblyInfo.cs | 4 +- UVtools.GUI/UVtools.GUI.csproj | 4 + UVtools.WPF/MainWindow.axaml | 144 +++++++++++++++++---- UVtools.WPF/MainWindow.axaml.cs | 83 +++++++++++- UVtools.WPF/Structures/SlicerProperty.cs | 41 ++++++ 14 files changed, 331 insertions(+), 100 deletions(-) create mode 100644 UVtools.WPF/Structures/SlicerProperty.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index a729c1f..f431d41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 22/09/2020 - v0.8.2.4 + +* (Add) Layer Importer: Option to merge images +* (Improvement) Layer difference computation time, faster render + ## 19/09/2020 - v0.8.2.3 * (Add) Tooltip for next and previous layer buttons with associated shortcut (#61) diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs index 7c72f15..3f245f2 100644 --- a/UVtools.Core/FileFormats/FileFormat.cs +++ b/UVtools.Core/FileFormats/FileFormat.cs @@ -354,7 +354,9 @@ namespace UVtools.Core.FileFormats public abstract float PrintTime { get; } - + + public float PrintTimeHours => (float) Math.Round(PrintTime / 3600, 2); + public abstract float UsedMaterial { get; } public abstract float MaterialCost { get; } diff --git a/UVtools.Core/FileFormats/IFileFormat.cs b/UVtools.Core/FileFormats/IFileFormat.cs index e166b55..3b77858 100644 --- a/UVtools.Core/FileFormats/IFileFormat.cs +++ b/UVtools.Core/FileFormats/IFileFormat.cs @@ -185,6 +185,11 @@ namespace UVtools.Core.FileFormats /// float PrintTime { get; } + /// + /// Gets the estimate print time in hours + /// + float PrintTimeHours { get; } + /// /// Gets the estimate used material in ml /// diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs index ad3e149..183a333 100644 --- a/UVtools.Core/Layer/LayerManager.cs +++ b/UVtools.Core/Layer/LayerManager.cs @@ -1343,6 +1343,16 @@ namespace UVtools.Core { var mat = CvInvoke.Imread(operation.Files[i], ImreadModes.Grayscale); uint layerIndex = (uint) (startIndex + i); + if (operation.MergeImages) + { + if (!(this[layerIndex] is null)) + { + using (var oldMat = this[layerIndex].LayerMat) + { + CvInvoke.Add(oldMat, mat, mat); + } + } + } this[layerIndex] = new Layer(layerIndex, mat); lock (progress.Mutex) diff --git a/UVtools.Core/Operations/OperationLayerImport.cs b/UVtools.Core/Operations/OperationLayerImport.cs index 89e3159..b7c8502 100644 --- a/UVtools.Core/Operations/OperationLayerImport.cs +++ b/UVtools.Core/Operations/OperationLayerImport.cs @@ -80,6 +80,7 @@ namespace UVtools.Core.Operations public bool ReplaceStartLayer { get; set; } public bool ReplaceSubsequentLayers { get; set; } public bool DiscardRemainingLayers { get; set; } + public bool MergeImages { get; set; } public List Files { get; } = new List(); diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 9d1d0f1..df16c45 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,12 +10,12 @@ https://github.com/sn4k3/UVtools https://github.com/sn4k3/UVtools MSLA/DLP, file analysis, repair, conversion and manipulation - 0.8.2.3 + 0.8.2.4 Copyright © 2020 PTRTECH UVtools.png AnyCPU;x64 - 0.8.2.3 - 0.8.2.3 + 0.8.2.4 + 0.8.2.4 diff --git a/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.Designer.cs index 66a17c1..371dff4 100644 --- a/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.Designer.cs +++ b/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.Designer.cs @@ -48,6 +48,7 @@ this.pbSelectedImage = new System.Windows.Forms.PictureBox(); this.cbReplaceSubsequentLayers = new System.Windows.Forms.CheckBox(); this.cbDiscardRemainingLayers = new System.Windows.Forms.CheckBox(); + this.cbMergeImages = new System.Windows.Forms.CheckBox(); ((System.ComponentModel.ISupportInitialize)(this.nmInsertAfterLayer)).BeginInit(); this.tsBar.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); @@ -276,11 +277,25 @@ this.cbDiscardRemainingLayers.UseVisualStyleBackColor = true; this.cbDiscardRemainingLayers.CheckedChanged += new System.EventHandler(this.EventClick); // + // cbMergeImages + // + this.cbMergeImages.AutoSize = true; + this.cbMergeImages.Enabled = false; + this.cbMergeImages.Location = new System.Drawing.Point(244, 83); + this.cbMergeImages.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.cbMergeImages.Name = "cbMergeImages"; + this.cbMergeImages.Size = new System.Drawing.Size(128, 24); + this.cbMergeImages.TabIndex = 41; + this.cbMergeImages.Text = "Merge images"; + this.toolTip.SetToolTip(this.cbMergeImages, "Merge source layer with target layer\r\n(Require \"Replace subsequent layers\")"); + this.cbMergeImages.UseVisualStyleBackColor = true; + this.cbMergeImages.CheckedChanged += new System.EventHandler(this.EventClick); + // // CtrlToolLayerImport // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.Controls.Add(this.cbMergeImages); this.Controls.Add(this.cbDiscardRemainingLayers); this.Controls.Add(this.cbReplaceSubsequentLayers); this.Controls.Add(this.lbResult); @@ -330,5 +345,6 @@ private System.Windows.Forms.PictureBox pbSelectedImage; private System.Windows.Forms.CheckBox cbReplaceSubsequentLayers; private System.Windows.Forms.CheckBox cbDiscardRemainingLayers; + private System.Windows.Forms.CheckBox cbMergeImages; } } diff --git a/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.cs b/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.cs index 41b591a..53090af 100644 --- a/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.cs +++ b/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.cs @@ -40,6 +40,7 @@ namespace UVtools.GUI.Controls.Tools Operation.ReplaceStartLayer = cbReplaceStartLayer.Checked; Operation.ReplaceSubsequentLayers = cbReplaceSubsequentLayers.Checked; Operation.DiscardRemainingLayers = cbDiscardRemainingLayers.Checked; + Operation.MergeImages = cbMergeImages.Checked; return true; } @@ -79,10 +80,12 @@ namespace UVtools.GUI.Controls.Tools { if (ReferenceEquals(sender, cbReplaceSubsequentLayers)) { - cbDiscardRemainingLayers.Enabled = cbReplaceSubsequentLayers.Checked; + cbDiscardRemainingLayers.Enabled = cbDiscardRemainingLayers.Enabled = cbReplaceSubsequentLayers.Checked; + cbMergeImages.Enabled = cbReplaceSubsequentLayers.Checked; if (!cbReplaceSubsequentLayers.Checked) { cbDiscardRemainingLayers.Checked = false; + cbMergeImages.Checked = false; } } diff --git a/UVtools.GUI/FrmMain.cs b/UVtools.GUI/FrmMain.cs index 12867f6..ac3fe8c 100644 --- a/UVtools.GUI/FrmMain.cs +++ b/UVtools.GUI/FrmMain.cs @@ -2275,7 +2275,7 @@ namespace UVtools.GUI /// Shows a layer number /// /// Layer number - void ShowLayer(uint layerNum) + unsafe void ShowLayer(uint layerNum) { if (SlicerFile is null) return; @@ -2316,8 +2316,10 @@ namespace UVtools.GUI CvInvoke.CvtColor(ActualLayerImage, ActualLayerImageBgr, ColorConversion.Gray2Bgr); - var imageSpan = ActualLayerImage.GetPixelSpan(); - var imageBgrSpan = ActualLayerImageBgr.GetPixelSpan(); + //var imageSpan = ActualLayerImage.GetPixelSpan(); + //var imageBgrSpan = ActualLayerImageBgr.GetPixelSpan(); + var imageSpan = ActualLayerImage.GetBytePointer(); + var imageBgrSpan = ActualLayerImageBgr.GetBytePointer(); if (btnLayerImageLayerOutlineEdgeDetection.Checked) @@ -2332,71 +2334,30 @@ namespace UVtools.GUI { if (layerNum > 0 && layerNum < SlicerFile.LayerCount - 1) { - using (var previousImage = SlicerFile[layerNum - 1].LayerMat) - using (var nextImage = SlicerFile[layerNum + 1].LayerMat) + Mat previousImage = null; + Mat nextImage = null; + + // Can improve performance on >4K images? + Parallel.Invoke( + () => { previousImage = SlicerFile[ActualLayer - 1].LayerMat; }, + () => { nextImage = SlicerFile[ActualLayer + 1].LayerMat; }); + + /*using (var previousImage = SlicerFile[_actualLayer - 1].LayerMat) + using (var nextImage = SlicerFile[_actualLayer + 1].LayerMat) + {*/ + //var previousSpan = previousImage.GetPixelSpan(); + //var nextSpan = nextImage.GetPixelSpan(); + + var previousSpan = previousImage.GetBytePointer(); + var nextSpan = nextImage.GetBytePointer(); + + int width = ActualLayerImage.Width; + int channels = ActualLayerImageBgr.NumberOfChannels; + Parallel.For(0, ActualLayerImageBgr.Height, y => { - var previousSpan = previousImage.GetPixelSpan(); - var nextSpan = nextImage.GetPixelSpan(); - - /*Parallel.For(0, imageSpan.Length, i => - { - var currentByte = ActualLayerImage.GetSinglePixelSpan(i); - var previousByte = previousImage.GetSinglePixelSpan(i); - var nextByte = nextImage.GetSinglePixelSpan(i); - - if (currentByte[0] != 0) return; - Color color = Color.Empty; - if (previousByte[0] > 0 && nextByte[0] > 0) - { - color = Settings.Default.PreviousNextLayerColor; - } - else if (previousByte[0] > 0) - { - color = Settings.Default.PreviousLayerColor; - } - else if (nextByte[0] > 0) - { - color = Settings.Default.NextLayerColor; - } - - if (color.IsEmpty) return; - ActualLayerImageBgr.SetByte(i * 3, new[]{ color.B , color.G, color.R }); - });*/ - - /*Parallel.For(0, ActualLayerImage.Height, y => - { - var currentSpan = ActualLayerImage.GetPixelRowSpan(y); - var currentRGBSpan = ActualLayerImageBgr.GetPixelRowSpan(y); - var previousSpan = previousImage.GetPixelRowSpan(y); - var nextSpan = nextImage.GetPixelRowSpan(y); - - for (int x = 0; x < currentSpan.Length; x++) - { - if (currentSpan[x] != 0) continue; - Color color = Color.Empty; - if (previousSpan[x] > 0 && nextSpan[x] > 0) - { - color = Settings.Default.PreviousNextLayerColor; - } - else if (previousSpan[x] > 0) - { - color = Settings.Default.PreviousLayerColor; - } - else if (nextSpan[x] > 0) - { - color = Settings.Default.NextLayerColor; - } - - if (color.IsEmpty) continue; - var bgrPixel = x * 3; - currentRGBSpan[bgrPixel] = color.B; // B - currentRGBSpan[++bgrPixel] = color.G; // G - currentRGBSpan[++bgrPixel] = color.R; // R - } - });*/ - - for (int pixel = 0; pixel < imageSpan.Length; pixel++) + for (int x = 0; x < width; x++) { + int pixel = y * width + x; if (imageSpan[pixel] != 0) continue; Color color = Color.Empty; if (previousSpan[pixel] > 0 && nextSpan[pixel] > 0) @@ -2413,12 +2374,16 @@ namespace UVtools.GUI } if (color.IsEmpty) continue; - var bgrPixel = pixel * 3; + var bgrPixel = pixel * channels; imageBgrSpan[bgrPixel] = color.B; // B imageBgrSpan[++bgrPixel] = color.G; // G imageBgrSpan[++bgrPixel] = color.R; // R + //imageBgrSpan[++bgrPixel] = color.A; // A } - } + }); + + previousImage.Dispose(); + nextImage.Dispose(); } } diff --git a/UVtools.GUI/Properties/AssemblyInfo.cs b/UVtools.GUI/Properties/AssemblyInfo.cs index e011fe6..dd226f7 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.8.2.3")] -[assembly: AssemblyFileVersion("0.8.2.3")] +[assembly: AssemblyVersion("0.8.2.4")] +[assembly: AssemblyFileVersion("0.8.2.4")] diff --git a/UVtools.GUI/UVtools.GUI.csproj b/UVtools.GUI/UVtools.GUI.csproj index b1269db..4b2b1c5 100644 --- a/UVtools.GUI/UVtools.GUI.csproj +++ b/UVtools.GUI/UVtools.GUI.csproj @@ -41,6 +41,7 @@ prompt 4 false + true AnyCPU @@ -51,6 +52,7 @@ prompt 4 false + true UVtools.ico @@ -67,6 +69,7 @@ 7.3 prompt MinimumRecommendedRules.ruleset + true bin\x64\Release\ @@ -77,6 +80,7 @@ 7.3 prompt MinimumRecommendedRules.ruleset + true false diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml index 76f60c1..b18591d 100644 --- a/UVtools.WPF/MainWindow.axaml +++ b/UVtools.WPF/MainWindow.axaml @@ -108,35 +108,135 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + SelectedIndex="{Binding TabSelectedIndex}"> + Information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -146,7 +246,7 @@ - + @@ -275,7 +375,6 @@ Name="Layer.Navigation.Slider" Minimum="0" Maximum="{Binding SliderMaximumValue}" - Ticks="{Binding SliderMaximumValue}" Value="{Binding ActualLayer}" TickFrequency="1" TickPlacement="Outside" @@ -357,7 +456,7 @@ @@ -397,10 +496,11 @@