diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-08-05 04:02:01 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-08-05 04:02:01 +0300 |
commit | fc3b789d29a5412d646a481ebb29c2057c63d58f (patch) | |
tree | 794f6a60a766fb837ece0dd6e1ca4d4a288ae6fe | |
parent | 384927dbef11b13993824198047b5c4a879fbb4b (diff) |
v0.6.4.2v0.6.4.2
* (Add) Hold "ALT" key when double clicking over items to invert AutoZoom setting, prevent or do zoom in issues or pixels, this will behave as !AutoZoom as long key is held
* (Improvement) Partial island update speed, huge boost performance over large files
-rw-r--r-- | CHANGELOG.md | 5 | ||||
-rw-r--r-- | UVtools.Core/Layer/LayerManager.cs | 274 | ||||
-rw-r--r-- | UVtools.Core/UVtools.Core.csproj | 6 | ||||
-rw-r--r-- | UVtools.GUI/FrmMain.cs | 8 | ||||
-rw-r--r-- | UVtools.GUI/Properties/AssemblyInfo.cs | 4 |
5 files changed, 155 insertions, 142 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e68efd..6784e82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 05/07/2020 - v0.6.4.2 + +* (Add) Hold "ALT" key when double clicking over items to invert AutoZoom setting, prevent or do zoom in issues or pixels, this will behave as !AutoZoom as long key is held +* (Improvement) Partial island update speed, huge boost performance over large files + ## 04/07/2020 - v0.6.4.1 * (Add) Partial update islands from current working layer and next layer when using pixel editor or island remove diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs index a3379c4..c588e10 100644 --- a/UVtools.Core/Layer/LayerManager.cs +++ b/UVtools.Core/Layer/LayerManager.cs @@ -10,7 +10,6 @@ using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; @@ -694,8 +693,6 @@ namespace UVtools.Core if(ReferenceEquals(touchBoundConfig, null)) touchBoundConfig = new TouchingBoundDetectionConfiguration(); if(ReferenceEquals(progress, null)) progress = new OperationProgress(); - const byte minTouchingBondsPixelColor = 200; - var result = new ConcurrentBag<LayerIssue>(); var layerHollowAreas = new ConcurrentDictionary<uint, List<LayerHollowArea>>(); @@ -717,168 +714,190 @@ namespace UVtools.Core layer => { if (progress.Token.IsCancellationRequested) return; - if (layer.NonZeroPixelCount > 0) + if (layer.NonZeroPixelCount == 0) + { + result.Add(new LayerIssue(layer, LayerIssue.IssueType.EmptyLayer)); + lock (progress.Mutex) + { + progress++; + } + + return; + } + + // Spare a decoding cycle + if (!resinTrapConfig.Enabled && + (layer.Index == 0 || + (!ReferenceEquals(islandConfig.WhiteListLayers, null) && !islandConfig.WhiteListLayers.Contains(layer.Index))) + ) { - using (var image = layer.LayerMat) + lock (progress.Mutex) { - int step = image.Step; - var span = image.GetPixelSpan<byte>(); + progress++; + } + return; + } - if (resinTrapConfig.Enabled) + using (var image = layer.LayerMat) + { + int step = image.Step; + var span = image.GetPixelSpan<byte>(); + + if (resinTrapConfig.Enabled) + { + // TouchingBounds Checker + List<Point> pixels = new List<Point>(); + for (int x = 0; x < image.Width; x++) // Check Top and Bottom bounds { - // TouchingBounds Checker - List<Point> pixels = new List<Point>(); - for (int x = 0; x < image.Width; x++) // Check Top and Bottom bounds + if (span[x] >= touchBoundConfig.MaximumPixelBrightness) // Top { - if (span[x] >= minTouchingBondsPixelColor) // Top - { - pixels.Add(new Point(x, 0)); - } - - if (span[step * image.Height - step + x] >= - minTouchingBondsPixelColor) // Bottom - { - pixels.Add(new Point(x, image.Height - 1)); - } + pixels.Add(new Point(x, 0)); } - for (int y = 0; y < image.Height; y++) // Check Left and Right bounds + if (span[step * image.Height - step + x] >= + touchBoundConfig.MaximumPixelBrightness) // Bottom { - if (span[y * step] >= minTouchingBondsPixelColor) // Left - { - pixels.Add(new Point(0, y)); - } + pixels.Add(new Point(x, image.Height - 1)); + } + } - if (span[y * step + step - 1] >= minTouchingBondsPixelColor) // Right - { - pixels.Add(new Point(step - 1, y)); - } + for (int y = 0; y < image.Height; y++) // Check Left and Right bounds + { + if (span[y * step] >= touchBoundConfig.MaximumPixelBrightness) // Left + { + pixels.Add(new Point(0, y)); } - if (pixels.Count > 0) + if (span[y * step + step - 1] >= touchBoundConfig.MaximumPixelBrightness) // Right { - result.Add(new LayerIssue(layer, LayerIssue.IssueType.TouchingBound, pixels.ToArray())); - /*result.TryAdd(layer.Index, new List<LayerIssue> + pixels.Add(new Point(step - 1, y)); + } + } + + if (pixels.Count > 0) + { + result.Add(new LayerIssue(layer, LayerIssue.IssueType.TouchingBound, + pixels.ToArray())); + /*result.TryAdd(layer.Index, new List<LayerIssue> { new LayerIssue(layer, LayerIssue.IssueType.TouchingBound, pixels.ToArray()) });*/ - } } + } - if (layer.Index == 0 || !islandConfig.Enabled) return; // No islands for layer 0 - - if (!ReferenceEquals(islandConfig.WhiteListLayers, null)) // Check white list + if (layer.Index == 0 || !islandConfig.Enabled) + { + lock (progress.Mutex) { - if (!islandConfig.WhiteListLayers.Contains(layer.Index)) return; + progress++; } + return; // No islands for layer 0 + } - VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); - Mat hierarchy = new Mat(); - - if (islandConfig.BinaryThreshold > 0) + if (!ReferenceEquals(islandConfig.WhiteListLayers, null)) // Check white list + { + if (!islandConfig.WhiteListLayers.Contains(layer.Index)) { - using (var thresholdImage = new Mat()) + lock (progress.Mutex) { - CvInvoke.Threshold(image, thresholdImage, 1, 255, ThresholdType.Binary); - CvInvoke.FindContours(thresholdImage, contours, hierarchy, RetrType.Ccomp, - ChainApproxMethod.ChainApproxSimple); + progress++; } + return; } - else + } + + VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); + Mat hierarchy = new Mat(); + + if (islandConfig.BinaryThreshold > 0) + { + using (var thresholdImage = new Mat()) { - CvInvoke.FindContours(image, contours, hierarchy, RetrType.Ccomp, + CvInvoke.Threshold(image, thresholdImage, 1, 255, ThresholdType.Binary); + CvInvoke.FindContours(thresholdImage, contours, hierarchy, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple); } + } + else + { + CvInvoke.FindContours(image, contours, hierarchy, RetrType.Ccomp, + ChainApproxMethod.ChainApproxSimple); + } - var arr = hierarchy.GetData(); - // - //hierarchy[i][0]: the index of the next contour of the same level - //hierarchy[i][1]: the index of the previous contour of the same level - //hierarchy[i][2]: the index of the first child - //hierarchy[i][3]: the index of the parent - // - - Mat previousImage = null; - Span<byte> previousSpan = null; - for (int i = 0; i < contours.Size; i++) - { + var arr = hierarchy.GetData(); + // + //hierarchy[i][0]: the index of the next contour of the same level + //hierarchy[i][1]: the index of the previous contour of the same level + //hierarchy[i][2]: the index of the first child + //hierarchy[i][3]: the index of the parent + // + + Mat previousImage = null; + Span<byte> previousSpan = null; + + for (int i = 0; i < contours.Size; i++) + { + if ((int) arr.GetValue(0, i, 2) == -1 && (int) arr.GetValue(0, i, 3) != -1) + continue; + var rect = CvInvoke.BoundingRectangle(contours[i]); + if (rect.GetArea() < islandConfig.RequiredAreaToProcessCheck) + continue; - if ((int) arr.GetValue(0, i, 2) == -1 && (int) arr.GetValue(0, i, 3) != -1) - continue; - var rect = CvInvoke.BoundingRectangle(contours[i]); - if (rect.GetArea() < islandConfig.RequiredAreaToProcessCheck) - continue; + if (ReferenceEquals(previousImage, null)) + { + previousImage = this[layer.Index - 1].LayerMat; + previousSpan = previousImage.GetPixelSpan<byte>(); + } - if (ReferenceEquals(previousImage, null)) - { - previousImage = this[layer.Index - 1].LayerMat; - previousSpan = previousImage.GetPixelSpan<byte>(); - } + List<Point> points = new List<Point>(); + uint pixelsSupportingIsland = 0; - List<Point> points = new List<Point>(); - uint pixelsSupportingIsland = 0; + using (Mat contourImage = image.CloneBlank()) + { + CvInvoke.DrawContours(contourImage, contours, i, new MCvScalar(255), -1); + var contourImageSpan = contourImage.GetPixelSpan<byte>(); - using (Mat contourImage = image.CloneBlank()) + for (int y = rect.Y; y < rect.Bottom; y++) { - CvInvoke.DrawContours(contourImage, contours, i, new MCvScalar(255), -1); - var contourImageSpan = contourImage.GetPixelSpan<byte>(); - - for (int y = rect.Y; y < rect.Bottom; y++) + for (int x = rect.X; x < rect.Right; x++) { - for (int x = rect.X; x < rect.Right; x++) + int pixel = step * y + x; + if (span[pixel] < islandConfig.RequiredPixelBrightnessToProcessCheck) + continue; // Low brightness, ignore + if (contourImageSpan[pixel] != 255) + continue; // Not inside contour, ignore + + //if (CvInvoke.PointPolygonTest(contours[i], new PointF(x, y), false) < 0) continue; // Out of contour SLOW! + //Debug.WriteLine($"Layer: {layer.Index}, Coutour: {i}, X:{x} Y:{y}"); + points.Add(new Point(x, y)); + + if (previousSpan[pixel] >= + islandConfig.RequiredPixelBrightnessToSupport) { - int pixel = step * y + x; - if (span[pixel] < islandConfig.RequiredPixelBrightnessToProcessCheck) - continue; // Low brightness, ignore - if (contourImageSpan[pixel] != 255) - continue; // Not inside contour, ignore - - //if (CvInvoke.PointPolygonTest(contours[i], new PointF(x, y), false) < 0) continue; // Out of contour SLOW! - //Debug.WriteLine($"Layer: {layer.Index}, Coutour: {i}, X:{x} Y:{y}"); - points.Add(new Point(x, y)); - - if (previousSpan[pixel] >= - islandConfig.RequiredPixelBrightnessToSupport) - { - pixelsSupportingIsland++; - } + pixelsSupportingIsland++; } } } + } - if (points.Count == 0) continue; - if (pixelsSupportingIsland >= islandConfig.RequiredPixelsToSupport) - continue; // Not a island, bounding is strong, i think... - if (pixelsSupportingIsland > 0 && - points.Count < islandConfig.RequiredPixelsToSupport && - pixelsSupportingIsland >= Math.Max(1, points.Count / 2)) - continue; // Not a island, but maybe weak bounding... + if (points.Count == 0) continue; + if (pixelsSupportingIsland >= islandConfig.RequiredPixelsToSupport) + continue; // Not a island, bounding is strong, i think... + if (pixelsSupportingIsland > 0 && + points.Count < islandConfig.RequiredPixelsToSupport && + pixelsSupportingIsland >= Math.Max(1, points.Count / 2)) + continue; // Not a island, but maybe weak bounding... - var issue = new LayerIssue(layer, LayerIssue.IssueType.Island, points.ToArray(), - rect); - result.Add(issue); - /*result.AddOrUpdate(layer.Index, new List<LayerIssue> {issue}, - (layerIndex, list) => - { - list.Add(issue); - return list; - });*/ - } - - contours.Dispose(); - hierarchy.Dispose(); - previousImage?.Dispose(); + var issue = new LayerIssue(layer, LayerIssue.IssueType.Island, points.ToArray(), + rect); + result.Add(issue); } - } - else - { - result.Add(new LayerIssue(layer, LayerIssue.IssueType.EmptyLayer)); - /*result.TryAdd(layer.Index, new List<LayerIssue> - { - new LayerIssue(layer, LayerIssue.IssueType.EmptyLayer) - });*/ + + contours.Dispose(); + hierarchy.Dispose(); + previousImage?.Dispose(); } lock (progress.Mutex) @@ -1146,20 +1165,9 @@ namespace UVtools.Core select new LayerIssue(this[layerIndex], LayerIssue.IssueType.ResinTrap, area.Contour, area.BoundingRectangle)) { result.Add(issue); - /*result.AddOrUpdate(layerIndex, new List<LayerIssue> {issue}, (u, listIssues) => - { - listIssues.Add(issue); - return listIssues; - });*/ } } - //resultSorted = resultSorted.OrderBy(issue => issue.Type).ThenBy(issue => issue.LayerIndex); - /*resultSorted.Sort((issue, layerIssue) => - { - int ret = issue.Type.CompareTo(layerIssue.Type); - return ret != 0 ? ret : issue.LayerIndex.CompareTo(layerIssue.LayerIndex); - });*/ return result.OrderBy(issue => issue.Type).ThenBy(issue => issue.LayerIndex).ThenBy(issue => issue.PixelsCount).ToList(); } diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index e3a2ef8..f3e307b 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.1</Version> + <Version>0.6.4.2</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> <Platforms>AnyCPU;x64</Platforms> - <AssemblyVersion>0.6.4.1</AssemblyVersion> - <FileVersion>0.6.4.1</FileVersion> + <AssemblyVersion>0.6.4.2</AssemblyVersion> + <FileVersion>0.6.4.2</FileVersion> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> diff --git a/UVtools.GUI/FrmMain.cs b/UVtools.GUI/FrmMain.cs index 7e2ac2f..07f925b 100644 --- a/UVtools.GUI/FrmMain.cs +++ b/UVtools.GUI/FrmMain.cs @@ -1860,7 +1860,7 @@ namespace UVtools.GUI y = issue.X; } - if (Settings.Default.AutoZoomIssues) + if (Settings.Default.AutoZoomIssues ^ (ModifierKeys & Keys.Alt) != 0) { pbLayer.ZoomToRegion(x, y, 5, 5); pbLayer.ZoomOut(true); @@ -1876,7 +1876,7 @@ namespace UVtools.GUI ? ActualLayerImage.Height - 1 - issue.BoundingRectangle.Bottom : issue.BoundingRectangle.X; int y = tsLayerImageRotate.Checked ? issue.BoundingRectangle.X : issue.BoundingRectangle.Y; - if (Settings.Default.AutoZoomIssues) + if (Settings.Default.AutoZoomIssues ^ (ModifierKeys & Keys.Alt) != 0) { pbLayer.ZoomToRegion( @@ -1921,8 +1921,8 @@ namespace UVtools.GUI x = ActualLayerImage.Height - 1 - operation.Location.Y; y = operation.Location.X; } - - if (Settings.Default.AutoZoomIssues) + + if (Settings.Default.AutoZoomIssues ^ (ModifierKeys & Keys.Alt) != 0) { pbLayer.ZoomToRegion(x, y, operation.Size.Width, operation.Size.Height); pbLayer.ZoomOut(true); diff --git a/UVtools.GUI/Properties/AssemblyInfo.cs b/UVtools.GUI/Properties/AssemblyInfo.cs index 98b4453..da3ac3d 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.1")] -[assembly: AssemblyFileVersion("0.6.4.1")] +[assembly: AssemblyVersion("0.6.4.2")] +[assembly: AssemblyFileVersion("0.6.4.2")] |