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-06-25 01:37:57 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2020-06-25 01:37:57 +0300
commit6d401eb774bc4d9a0014e24b2d48c4f5e156d912 (patch)
treef1c248691362d61f2052fc8709df4524f38c0b02 /UVtools.Core
parent625b736ad725d8b91576d4a511149a1f8920930e (diff)
Droped Parser and create UVtoolsCmd
Diffstat (limited to 'UVtools.Core')
-rw-r--r--UVtools.Core/CWSFile.cs1
-rw-r--r--UVtools.Core/ChituboxFile.cs1
-rw-r--r--UVtools.Core/ChituboxZipFile.cs1
-rw-r--r--UVtools.Core/FileExtension.cs3
-rw-r--r--UVtools.Core/FileFormat.cs46
-rw-r--r--UVtools.Core/IFileFormat.cs11
-rw-r--r--UVtools.Core/ImageFile.cs1
-rw-r--r--UVtools.Core/LayerManager.cs890
-rw-r--r--UVtools.Core/PHZFile.cs1
-rw-r--r--UVtools.Core/PWSFile.cs1
-rw-r--r--UVtools.Core/SL1File.cs1
-rw-r--r--UVtools.Core/UVtools.Core.csproj6
-rw-r--r--UVtools.Core/ZCodexFile.cs1
13 files changed, 663 insertions, 301 deletions
diff --git a/UVtools.Core/CWSFile.cs b/UVtools.Core/CWSFile.cs
index 1743a9e..14e948d 100644
--- a/UVtools.Core/CWSFile.cs
+++ b/UVtools.Core/CWSFile.cs
@@ -14,7 +14,6 @@ using System.Linq;
using System.Reflection;
using System.Text;
using UVtools.Core.Extensions;
-using UVtools.Parser;
namespace UVtools.Core
{
diff --git a/UVtools.Core/ChituboxFile.cs b/UVtools.Core/ChituboxFile.cs
index 05f5397..0aed6ce 100644
--- a/UVtools.Core/ChituboxFile.cs
+++ b/UVtools.Core/ChituboxFile.cs
@@ -19,7 +19,6 @@ using BinarySerialization;
using Emgu.CV;
using Emgu.CV.CvEnum;
using UVtools.Core.Extensions;
-using UVtools.Parser;
namespace UVtools.Core
{
diff --git a/UVtools.Core/ChituboxZipFile.cs b/UVtools.Core/ChituboxZipFile.cs
index ec57188..9507b77 100644
--- a/UVtools.Core/ChituboxZipFile.cs
+++ b/UVtools.Core/ChituboxZipFile.cs
@@ -18,7 +18,6 @@ using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
using UVtools.Core.Extensions;
-using UVtools.Parser;
namespace UVtools.Core
{
diff --git a/UVtools.Core/FileExtension.cs b/UVtools.Core/FileExtension.cs
index cb56563..7838211 100644
--- a/UVtools.Core/FileExtension.cs
+++ b/UVtools.Core/FileExtension.cs
@@ -5,9 +5,10 @@
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
+
using System.Collections.Generic;
-namespace UVtools.Parser
+namespace UVtools.Core
{
/// <summary>
/// Represents a file extension for slicer file formats
diff --git a/UVtools.Core/FileFormat.cs b/UVtools.Core/FileFormat.cs
index 812e7ae..110cfac 100644
--- a/UVtools.Core/FileFormat.cs
+++ b/UVtools.Core/FileFormat.cs
@@ -16,7 +16,6 @@ using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using UVtools.Core.Extensions;
-using UVtools.Parser;
namespace UVtools.Core
{
@@ -638,51 +637,6 @@ namespace UVtools.Core
return Convert(to.GetType(), fileFullPath);
}
- public void Resize(uint startLayerIndex, uint endLayerIndex, double x, double y, bool fade)
- {
- if (x == 1.0 && y == 1.0) return;
-
- Parallel.For(startLayerIndex, endLayerIndex+1, /*new ParallelOptions { MaxDegreeOfParallelism = 1 },*/ layerIndex =>
- {
- var newX = x;
- var newY = y;
- if (fade)
- {
- if (newX != 1.0)
- {
- double steps = Math.Abs(newX - 1.0) / (endLayerIndex - startLayerIndex);
- //maxIteration = Math.Max(iterationsStart, iterationsEnd);
-
- newX = (float) (newX < 1.0
- ? newX + (layerIndex - startLayerIndex) * steps
- : newX - (layerIndex - startLayerIndex) * steps);
-
- // constrain
- //iterations = Math.Min(Math.Max(1, iterations), maxIteration);
- }
-
- if (y != 1.0)
- {
- double steps = Math.Abs(newY - 1.0) / (endLayerIndex - startLayerIndex);
- //maxIteration = Math.Max(iterationsStart, iterationsEnd);
-
- newY = (float) (newY < 1.0
- ? newY + (layerIndex - startLayerIndex) * steps
- : newY - (layerIndex - startLayerIndex) * steps);
-
- // constrain
- //iterations = Math.Min(Math.Max(1, iterations), maxIteration);
- }
- }
-
- if (newX == 1.0 && newY == 1.0) return;
-
-
-
- this[layerIndex].Resize(newX, newY);
- });
- }
-
public byte ValidateAntiAliasingLevel()
{
if (AntiAliasing < 2) return 1;
diff --git a/UVtools.Core/IFileFormat.cs b/UVtools.Core/IFileFormat.cs
index 89c5a09..825804b 100644
--- a/UVtools.Core/IFileFormat.cs
+++ b/UVtools.Core/IFileFormat.cs
@@ -9,7 +9,6 @@
using System;
using System.Text;
using Emgu.CV;
-using UVtools.Parser;
namespace UVtools.Core
{
@@ -338,16 +337,6 @@ namespace UVtools.Core
bool Convert(FileFormat to, string fileFullPath);
/// <summary>
- /// Resizes layer images in x and y factor, starting at 1 = 100%
- /// </summary>
- /// <param name="startLayerIndex">Layer index to start</param>
- /// <param name="endLayerIndex">Layer index to end</param>
- /// <param name="x">X factor, starts at 1</param>
- /// <param name="y">Y factor, starts at 1</param>
- /// <param name="fade">Fade X/Y towards 100%</param>
- void Resize(uint startLayerIndex, uint endLayerIndex, double x, double y, bool fade);
-
- /// <summary>
/// Validate AntiAlias Level
/// </summary>
byte ValidateAntiAliasingLevel();
diff --git a/UVtools.Core/ImageFile.cs b/UVtools.Core/ImageFile.cs
index 462aa75..4d351b5 100644
--- a/UVtools.Core/ImageFile.cs
+++ b/UVtools.Core/ImageFile.cs
@@ -4,7 +4,6 @@ using System.Net.Mime;
using Emgu.CV;
using Emgu.CV.CvEnum;
using UVtools.Core.Extensions;
-using UVtools.Parser;
using Size = System.Drawing.Size;
namespace UVtools.Core
diff --git a/UVtools.Core/LayerManager.cs b/UVtools.Core/LayerManager.cs
index b8b2d6b..12792fa 100644
--- a/UVtools.Core/LayerManager.cs
+++ b/UVtools.Core/LayerManager.cs
@@ -5,6 +5,7 @@
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
+
using System;
using System.Collections;
using System.Collections.Concurrent;
@@ -12,8 +13,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
+using System.Linq;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.CV.CvEnum;
@@ -21,7 +21,7 @@ using Emgu.CV.Structure;
using Emgu.CV.Util;
using UVtools.Core.Extensions;
-namespace UVtools.Parser
+namespace UVtools.Core
{
#region LayerIssue Class
@@ -115,7 +115,7 @@ namespace UVtools.Parser
public override string ToString()
{
- return $"{nameof(Type)}: {Type}";
+ return $"{nameof(Type)}: {Type}, Layer: {Layer.Index}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Size)}: {Size}";
}
}
#endregion
@@ -565,13 +565,8 @@ namespace UVtools.Parser
return result;
}
- public Layer Clone()
- {
- return new Layer(Index, CompressedBytes, Filename, ParentLayerManager);
- }
- #endregion
- public void Resize(double xScale, double yScale)
+ public void MutateResize(double xScale, double yScale)
{
using (var mat = LayerMat)
{
@@ -579,6 +574,144 @@ namespace UVtools.Parser
LayerMat = mat;
}
}
+
+ public void MutateSolidify()
+ {
+ using (Mat mat = LayerMat)
+ {
+ using (Mat filteredMat = new Mat())
+ {
+ CvInvoke.Threshold(mat, filteredMat, 254, 255, ThresholdType.Binary); // Clean AA
+
+ using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
+ {
+ using (Mat hierarchy = new Mat())
+ {
+ CvInvoke.FindContours(filteredMat, contours, hierarchy, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);
+ var arr = hierarchy.GetData();
+ for (int i = 0; i < contours.Size; i++)
+ {
+ if ((int) arr.GetValue(0, i, 2) != -1 || (int) arr.GetValue(0, i, 3) == -1) continue;
+ CvInvoke.DrawContours(mat, contours, i, new MCvScalar(255), -1);
+ }
+ }
+ }
+ }
+
+ LayerMat = mat;
+ }
+ }
+
+ public void MutateErode(int iterations = 1, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default)
+ {
+ 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.Erode(dst, dst, kernel, anchor, iterations, borderType, borderValue);
+ LayerMat = dst;
+ }
+ }
+
+ public void MutateDilate(int iterations = 1, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default)
+ {
+ 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.Dilate(dst, dst, kernel, anchor, iterations, borderType, borderValue);
+ LayerMat = dst;
+ }
+ }
+
+ public void MutateOpen(int iterations = 1, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default)
+ {
+ 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.MorphologyEx(dst, dst, MorphOp.Open, kernel, anchor, iterations, borderType, borderValue);
+ LayerMat = dst;
+ }
+ }
+
+ public void MutateClose(int iterations = 1, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default)
+ {
+ 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.MorphologyEx(dst, dst, MorphOp.Close, kernel, anchor, iterations, borderType, borderValue);
+ LayerMat = dst;
+ }
+ }
+
+ public void MutateGradient(int iterations = 1, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default)
+ {
+ if (anchor.IsEmpty) anchor = new Point(-1, -1);
+ if (ReferenceEquals(kernel, null))
+ {
+ kernel = CvInvoke.GetStructuringElement(ElementShape.Cross, new Size(3, 3), anchor);
+ }
+ using (Mat dst = LayerMat)
+ {
+ CvInvoke.MorphologyEx(dst, dst, MorphOp.Gradient, kernel, anchor, iterations, borderType, borderValue);
+ LayerMat = dst;
+ }
+ }
+
+ public void MutatePyrDownUp(BorderType borderType = BorderType.Reflect101)
+ {
+ using (Mat dst = LayerMat)
+ {
+ CvInvoke.PyrDown(dst, dst, borderType);
+ CvInvoke.PyrUp(dst, dst, borderType);
+ LayerMat = dst;
+ }
+ }
+
+ public void MutateMedianBlur(int aperture = 1)
+ {
+ using (Mat dst = LayerMat)
+ {
+ CvInvoke.MedianBlur(dst, dst, aperture);
+ LayerMat = dst;
+ }
+ }
+
+ public void MutateGaussianBlur(Size size = default, int sigmaX = 0, int sigmaY = 0, BorderType borderType = BorderType.Reflect101)
+ {
+ if(size.IsEmpty) size = new Size(5, 5);
+
+ using (Mat dst = LayerMat)
+ {
+ CvInvoke.GaussianBlur(dst, dst, size, sigmaX, sigmaY, borderType);
+ LayerMat = dst;
+ }
+ }
+
+
+
+ public Layer Clone()
+ {
+ return new Layer(Index, CompressedBytes, Filename, ParentLayerManager);
+ }
+
+
+
+ #endregion
}
#endregion
@@ -728,6 +861,219 @@ namespace UVtools.Parser
return Layers[index];
}
+ /// <summary>
+ /// Resizes layer images in x and y factor, starting at 1 = 100%
+ /// </summary>
+ /// <param name="startLayerIndex">Layer index to start</param>
+ /// <param name="endLayerIndex">Layer index to end</param>
+ /// <param name="x">X factor, starts at 1</param>
+ /// <param name="y">Y factor, starts at 1</param>
+ /// <param name="isFade">Fade X/Y towards 100%</param>
+ public void MutateResize(uint startLayerIndex, uint endLayerIndex, double x, double y, bool isFade)
+ {
+ if (x == 1.0 && y == 1.0) return;
+
+ double xSteps = Math.Abs(x - 1.0) / (endLayerIndex - startLayerIndex);
+ double ySteps = Math.Abs(y - 1.0) / (endLayerIndex - startLayerIndex);
+
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ var newX = x;
+ var newY = y;
+ if (isFade)
+ {
+ if (newX != 1.0)
+ {
+
+ //maxIteration = Math.Max(iterationsStart, iterationsEnd);
+
+ newX = (float)(newX < 1.0
+ ? newX + (layerIndex - startLayerIndex) * xSteps
+ : newX - (layerIndex - startLayerIndex) * xSteps);
+
+ // constrain
+ //iterations = Math.Min(Math.Max(1, iterations), maxIteration);
+ }
+
+ if (y != 1.0)
+ {
+
+ //maxIteration = Math.Max(iterationsStart, iterationsEnd);
+
+ newY = (float)(newY < 1.0
+ ? newY + (layerIndex - startLayerIndex) * ySteps
+ : newY - (layerIndex - startLayerIndex) * ySteps);
+
+ // constrain
+ //iterations = Math.Min(Math.Max(1, iterations), maxIteration);
+ }
+ }
+
+ if (newX == 1.0 && newY == 1.0) return;
+
+ this[layerIndex].MutateResize(newX, newY);
+ });
+ }
+
+ public void MutateSolidify(uint startLayerIndex, uint endLayerIndex)
+ {
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ this[layerIndex].MutateSolidify();
+ });
+ }
+
+ private void MutateGetVarsIterationFade(uint startLayerIndex, uint endLayerIndex, int iterationsStart, int iterationsEnd, ref bool isFade, out int iterationSteps, out int maxIteration)
+ {
+ iterationSteps = 0;
+ maxIteration = 0;
+ isFade = isFade && startLayerIndex != endLayerIndex && iterationsStart != iterationsEnd;
+ if (!isFade) return;
+ iterationSteps = (int)Math.Abs((double)(iterationsStart - iterationsEnd) / (endLayerIndex - startLayerIndex));
+ maxIteration = Math.Max(iterationsStart, iterationsEnd);
+ }
+
+ private int MutateGetIterationVar(bool isFade, int iterationsStart, int iterationsEnd, int iterationSteps, int maxIteration, uint startLayerIndex, uint layerIndex)
+ {
+ if(!isFade) return iterationsStart;
+ // calculate iterations based on range
+ int iterations = (int)(iterationsStart < iterationsEnd
+ ? iterationsStart + (layerIndex - startLayerIndex) * iterationSteps
+ : iterationsStart - (layerIndex - startLayerIndex) * iterationSteps);
+
+ // constrain
+ return Math.Min(Math.Max(1, iterations), maxIteration);
+ }
+
+ public void MutateErode(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false,
+ IInputArray kernel = null, Point anchor = default,
+ BorderType borderType = BorderType.Default, MCvScalar borderValue = default)
+ {
+ MutateGetVarsIterationFade(
+ startLayerIndex,
+ endLayerIndex,
+ iterationsStart,
+ iterationsEnd,
+ ref isFade,
+ out var iterationSteps,
+ out var maxIteration
+ );
+
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ int iterations = MutateGetIterationVar(isFade, iterationsStart, iterationsEnd, iterationSteps, maxIteration, startLayerIndex, (uint) layerIndex);
+ this[layerIndex].MutateErode(iterations, kernel, anchor, borderType, borderValue);
+ });
+ }
+
+ public void MutateDilate(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false,
+ IInputArray kernel = null, Point anchor = default,
+ BorderType borderType = BorderType.Default, MCvScalar borderValue = default)
+ {
+ MutateGetVarsIterationFade(
+ startLayerIndex,
+ endLayerIndex,
+ iterationsStart,
+ iterationsEnd,
+ ref isFade,
+ out var iterationSteps,
+ out var maxIteration
+ );
+
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ int iterations = MutateGetIterationVar(isFade, iterationsStart, iterationsEnd, iterationSteps, maxIteration, startLayerIndex, (uint)layerIndex);
+ this[layerIndex].MutateDilate(iterations, kernel, anchor, borderType, borderValue);
+ });
+ }
+
+ public void MutateOpen(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false,
+ IInputArray kernel = null, Point anchor = default,
+ BorderType borderType = BorderType.Default, MCvScalar borderValue = default)
+ {
+ MutateGetVarsIterationFade(
+ startLayerIndex,
+ endLayerIndex,
+ iterationsStart,
+ iterationsEnd,
+ ref isFade,
+ out var iterationSteps,
+ out var maxIteration
+ );
+
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ int iterations = MutateGetIterationVar(isFade, iterationsStart, iterationsEnd, iterationSteps, maxIteration, startLayerIndex, (uint)layerIndex);
+ this[layerIndex].MutateOpen(iterations, kernel, anchor, borderType, borderValue);
+ });
+ }
+
+ public void MutateClose(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false,
+ IInputArray kernel = null, Point anchor = default,
+ BorderType borderType = BorderType.Default, MCvScalar borderValue = default)
+ {
+ MutateGetVarsIterationFade(
+ startLayerIndex,
+ endLayerIndex,
+ iterationsStart,
+ iterationsEnd,
+ ref isFade,
+ out var iterationSteps,
+ out var maxIteration
+ );
+
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ int iterations = MutateGetIterationVar(isFade, iterationsStart, iterationsEnd, iterationSteps, maxIteration, startLayerIndex, (uint)layerIndex);
+ this[layerIndex].MutateClose(iterations, kernel, anchor, borderType, borderValue);
+ });
+ }
+
+ public void MutateGradient(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false,
+ IInputArray kernel = null, Point anchor = default,
+ BorderType borderType = BorderType.Default, MCvScalar borderValue = default)
+ {
+ MutateGetVarsIterationFade(
+ startLayerIndex,
+ endLayerIndex,
+ iterationsStart,
+ iterationsEnd,
+ ref isFade,
+ out var iterationSteps,
+ out var maxIteration
+ );
+
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ int iterations = MutateGetIterationVar(isFade, iterationsStart, iterationsEnd, iterationSteps, maxIteration, startLayerIndex, (uint)layerIndex);
+ this[layerIndex].MutateGradient(iterations, kernel, anchor, borderType, borderValue);
+ });
+ }
+
+ public void MutatePyrDownUp(uint startLayerIndex, uint endLayerIndex, BorderType borderType = BorderType.Default)
+ {
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ this[layerIndex].MutatePyrDownUp(borderType);
+ });
+ }
+
+ public void MutateMedianBlur(uint startLayerIndex, uint endLayerIndex, int aperture = 1)
+ {
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ this[layerIndex].MutateMedianBlur(aperture);
+ });
+ }
+
+ public void MutateGaussianBlur(uint startLayerIndex, uint endLayerIndex, Size size = default, int sigmaX = 0, int sigmaY = 0, BorderType borderType = BorderType.Reflect101)
+ {
+ Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex =>
+ {
+ this[layerIndex].MutateGaussianBlur(size, sigmaX, sigmaY, borderType);
+ });
+ }
+
public ConcurrentDictionary<uint, List<LayerIssue>> GetAllIssues()
{
const byte requiredPixelsToSupportIsland = 10;
@@ -749,296 +1095,370 @@ namespace UVtools.Parser
}
});*/
- var layerHollowAreas = new ConcurrentDictionary<uint, List<LayerHollowArea>>();
-
- // Detect contours
- Parallel.ForEach(this,
- //new ParallelOptions{MaxDegreeOfParallelism = 1},
- layer =>
+ var task1 = new TaskFactory().StartNew(() =>
{
- using (var image = layer.LayerMat)
- {
- int step = image.Step;
- CvInvoke.Threshold(image, image, 1, 255, ThresholdType.Binary);
-
- var span = image.GetPixelSpan<byte>();
-
- // TouchingBounds Checker
- List<Point> pixels = new List<Point>();
- for (int x = 0; x < image.Width; x++) // Check Top and Bottom bounds
+ // Detect contours
+ Parallel.ForEach(this,
+ //new ParallelOptions{MaxDegreeOfParallelism = 1},
+ layer =>
{
- if (span[x] >= minTouchingBondsPixelColor) // Top
+ using (var image = layer.LayerMat)
{
- pixels.Add(new Point(x, 0));
- }
+ int step = image.Step;
+ var span = image.GetPixelSpan<byte>();
- if (span[step * image.Height - step + x] >= minTouchingBondsPixelColor) // Bottom
- {
- pixels.Add(new Point(x, image.Height - 1));
- }
- }
-
- for (int y = 0; y < image.Height; y++) // Check Left and Right bounds
- {
- if (span[y * step] >= minTouchingBondsPixelColor) // Left
- {
- pixels.Add(new Point(0, y));
- }
-
- if (span[y * step + step - 1] >= minTouchingBondsPixelColor) // Right
- {
- pixels.Add(new Point(step - 1, y));
- }
- }
-
- if (pixels.Count > 0)
- {
- result.TryAdd(layer.Index, new List<LayerIssue>
- {
- new LayerIssue(layer, LayerIssue.IssueType.TouchingBound, pixels.ToArray())
- });
- }
+ // TouchingBounds Checker
+ List<Point> pixels = new List<Point>();
+ for (int x = 0; x < image.Width; x++) // Check Top and Bottom bounds
+ {
+ 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));
+ }
+ }
+ for (int y = 0; y < image.Height; y++) // Check Left and Right bounds
+ {
+ if (span[y * step] >= minTouchingBondsPixelColor) // Left
+ {
+ pixels.Add(new Point(0, y));
+ }
+ if (span[y * step + step - 1] >= minTouchingBondsPixelColor) // Right
+ {
+ pixels.Add(new Point(step - 1, y));
+ }
+ }
+ if (pixels.Count > 0)
+ {
+ result.TryAdd(layer.Index, new List<LayerIssue>
+ {
+ new LayerIssue(layer, LayerIssue.IssueType.TouchingBound, pixels.ToArray())
+ });
+ }
+ if (layer.Index == 0) return; // No inslands for layer 0
- var listHollowArea = new List<LayerHollowArea>();
+ CvInvoke.Threshold(image, image, 1, 255, ThresholdType.Binary);
+ VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
+ Mat hierarchy = new Mat();
- VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
- Mat hierarchy = new Mat();
+ CvInvoke.FindContours(image, contours, hierarchy, RetrType.Ccomp,
+ ChainApproxMethod.ChainApproxSimple);
- 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
+ //
- 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;
- Span<byte> imageSpan = null;
- for (int i = 0; i < contours.Size; i++)
- {
- if ((int) arr.GetValue(0, i, 2) != -1 || (int) arr.GetValue(0, i, 3) == -1) // Island
- {
- if(layer.Index == 0) continue;
- if (ReferenceEquals(previousImage, null))
+ Mat previousImage = null;
+ Span<byte> previousSpan = null;
+ Span<byte> imageSpan = null;
+ for (int i = 0; i < contours.Size; i++)
{
- previousImage = this[layer.Index - 1].LayerMat;
- previousSpan = previousImage.GetPixelSpan<byte>();
- imageSpan = image.GetPixelSpan<byte>();
- }
-
- var rect = CvInvoke.BoundingRectangle(contours[i]);
- List<Point> points = new List<Point>();
- uint pixelsSupportingIsland = 0;
+ if ((int) arr.GetValue(0, i, 2) == -1 && (int) arr.GetValue(0, i, 3) != -1) continue;
+ if (ReferenceEquals(previousImage, null))
+ {
+ previousImage = this[layer.Index - 1].LayerMat;
+ previousSpan = previousImage.GetPixelSpan<byte>();
+ imageSpan = image.GetPixelSpan<byte>();
+ }
- using (Mat contourImage = image.CloneBlank())
- {
- CvInvoke.DrawContours(contourImage, contours, i, new MCvScalar(255), -1);
- var contourImageSpan = contourImage.GetPixelSpan<byte>();
+ var rect = CvInvoke.BoundingRectangle(contours[i]);
+ List<Point> points = new List<Point>();
+ uint pixelsSupportingIsland = 0;
- for (int y = rect.Y; y < rect.Bottom; y++)
+ using (Mat contourImage = image.CloneBlank())
{
- for (int x = rect.X; x < rect.Right; x++)
- {
- //int pixel = image.GetPixelPos(x, y);
- int pixel = step * y + x;
- if (imageSpan[pixel] < minIslandPixelToCheck)
- 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));
+ CvInvoke.DrawContours(contourImage, contours, i, new MCvScalar(255), -1);
+ var contourImageSpan = contourImage.GetPixelSpan<byte>();
- if (previousSpan[pixel] >= minIslandSupportPixelColor)
+ for (int y = rect.Y; y < rect.Bottom; y++)
+ {
+ for (int x = rect.X; x < rect.Right; x++)
{
- pixelsSupportingIsland++;
+ //int pixel = image.GetPixelPos(x, y);
+ int pixel = step * y + x;
+ if (imageSpan[pixel] < minIslandPixelToCheck)
+ 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] >= minIslandSupportPixelColor)
+ {
+ pixelsSupportingIsland++;
+ }
}
}
}
- }
- if (points.Count == 0) continue;
- if (pixelsSupportingIsland >= requiredPixelsToSupportIsland) continue; // Not a island, bounding is strong, i think...
- if (pixelsSupportingIsland > 0 && points.Count < requiredPixelsToSupportIsland &&
- pixelsSupportingIsland >= Math.Max(1, points.Count / 2)) continue; // Not a island, but maybe weak bounding...
+ if (points.Count == 0) continue;
+ if (pixelsSupportingIsland >= requiredPixelsToSupportIsland)
+ continue; // Not a island, bounding is strong, i think...
+ if (pixelsSupportingIsland > 0 && points.Count < requiredPixelsToSupportIsland &&
+ 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.AddOrUpdate(layer.Index, new List<LayerIssue>{ issue },
- (layerIndex, list) =>
- {
- list.Add(issue);
- return list;
- });
- }
- else //if ((int) arr.GetValue(0, i, 2) == -1 && (int) arr.GetValue(0, i, 3) != -1) // Hollow area
- {
- listHollowArea.Add(new LayerHollowArea(contours[i].ToArray(),
- CvInvoke.BoundingRectangle(contours[i]),
- layer.Index == 0 || layer.Index == Count - 1
- ? LayerHollowArea.AreaType.Drain
- : LayerHollowArea.AreaType.Unknown));
-
- if (listHollowArea.Count > 0)
- layerHollowAreas.TryAdd(layer.Index, listHollowArea);
+ var issue = new LayerIssue(layer, LayerIssue.IssueType.Island, points.ToArray(), rect);
+ result.AddOrUpdate(layer.Index, new List<LayerIssue> {issue},
+ (layerIndex, list) =>
+ {
+ list.Add(issue);
+ return list;
+ });
+ }
+
+ contours.Dispose();
+ hierarchy.Dispose();
+ previousImage?.Dispose();
}
- }
- hierarchy.Dispose();
- previousImage?.Dispose();
- }
+ });
});
- for (uint layerIndex = 1; layerIndex < Count - 1; layerIndex++) // Ignore first and last layers, always drains
+ var layerHollowAreas = new ConcurrentDictionary<uint, List<LayerHollowArea>>();
+ var task2 = new TaskFactory().StartNew(() =>
{
- if (!layerHollowAreas.TryGetValue(layerIndex, out var areas)) continue; // No hollow areas in this layer, ignore
+ // Detect contours
+ Parallel.ForEach(this,
+ //new ParallelOptions{MaxDegreeOfParallelism = 1},
+ layer =>
+ {
+ using (var image = layer.LayerMat)
+ {
+ CvInvoke.Threshold(image, image, 254, 255, ThresholdType.Binary);
- byte areaCount = 0;
- //foreach (var area in areas)
- Parallel.ForEach(areas, area =>
- {
- if (area.Type != LayerHollowArea.AreaType.Unknown) return; // processed, ignore
- area.Type = LayerHollowArea.AreaType.Trap;
+ var listHollowArea = new List<LayerHollowArea>();
- areaCount++;
+ using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
+ {
+ using (Mat hierarchy = new Mat())
+ {
+
+ CvInvoke.FindContours(image, contours, hierarchy, RetrType.Ccomp,
+ ChainApproxMethod.ChainApproxSimple);
- List<LayerHollowArea> linkedAreas = new List<LayerHollowArea>();
+ 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
+ //
+
+ for (int i = 0; i < contours.Size; i++)
+ {
+ if ((int) arr.GetValue(0, i, 2) != -1 || (int) arr.GetValue(0, i, 3) == -1)
+ continue;
+ listHollowArea.Add(new LayerHollowArea(contours[i].ToArray(),
+ CvInvoke.BoundingRectangle(contours[i]),
+ layer.Index == 0 || layer.Index == Count - 1
+ ? LayerHollowArea.AreaType.Drain
+ : LayerHollowArea.AreaType.Unknown));
+
+ if (listHollowArea.Count > 0)
+ layerHollowAreas.TryAdd(layer.Index, listHollowArea);
+ }
+ }
+ }
+ }
+ });
- for (sbyte dir = 1; dir >= -1 && area.Type != LayerHollowArea.AreaType.Drain; dir -= 2)
- //Parallel.ForEach(dirs, new ParallelOptions {MaxDegreeOfParallelism = 2}, dir =>
+
+ for (uint layerIndex = 1; layerIndex < Count - 1; layerIndex++) // Ignore first and last layers, always drains
+ {
+ if (!layerHollowAreas.TryGetValue(layerIndex, out var areas))
+ continue; // No hollow areas in this layer, ignore
+
+ byte areaCount = 0;
+ //foreach (var area in areas)
+
+ Parallel.ForEach(from t in areas where t.Type == LayerHollowArea.AreaType.Unknown select t, area =>
{
- Queue<LayerHollowArea> queue = new Queue<LayerHollowArea>();
- queue.Enqueue(area);
- area.Processed = false;
- int nextLayerIndex = (int)layerIndex;
- while (queue.Count > 0 && area.Type != LayerHollowArea.AreaType.Drain)
+ //if (area.Type != LayerHollowArea.AreaType.Unknown) return; // processed, ignore
+ area.Type = LayerHollowArea.AreaType.Trap;
+
+ areaCount++;
+
+ List<LayerHollowArea> linkedAreas = new List<LayerHollowArea>();
+
+ for (sbyte dir = 1; dir >= -1 && area.Type != LayerHollowArea.AreaType.Drain; dir -= 2)
+ //Parallel.ForEach(new sbyte[] {1, -1}, new ParallelOptions {MaxDegreeOfParallelism = 2}, dir =>
{
- LayerHollowArea checkArea = queue.Dequeue();
- if (checkArea.Processed) continue;
- checkArea.Processed = true;
- nextLayerIndex += dir;
- //Debug.WriteLine($"Area Count: {areaCount} | Layer: {layerIndex} | Next Layer: {nextLayerIndex} | Dir: {dir}");
- if (nextLayerIndex < 0 && nextLayerIndex >= Count)
- break; // Exhausted layers
- bool haveNextAreas =
- layerHollowAreas.TryGetValue((uint)nextLayerIndex, out var nextAreas);
-
- using (var image = this[nextLayerIndex].LayerMat)
+ Queue<LayerHollowArea> queue = new Queue<LayerHollowArea>();
+ queue.Enqueue(area);
+ area.Processed = false;
+ int nextLayerIndex = (int) layerIndex;
+ while (queue.Count > 0 && area.Type != LayerHollowArea.AreaType.Drain)
{
- var span = image.GetPixelSpan<byte>();
- using (var emguImage = image.CloneBlank())
+ LayerHollowArea checkArea = queue.Dequeue();
+ if (checkArea.Processed) continue;
+ checkArea.Processed = true;
+ nextLayerIndex += dir;
+ Debug.WriteLine($"Area Count: {areaCount} | Layer: {layerIndex} | Next Layer: {nextLayerIndex} | Dir: {dir}");
+ if (nextLayerIndex < 0 && nextLayerIndex >= Count)
+ break; // Exhausted layers
+ bool haveNextAreas = layerHollowAreas.TryGetValue((uint) nextLayerIndex, out var nextAreas);
+ List<LayerHollowArea> intersectingAreas = new List<LayerHollowArea>();
+
+ using (var image = this[nextLayerIndex].LayerMat)
{
- //emguImage.FillConvexPoly(checkArea.Contour, new Gray(255));
- CvInvoke.DrawContours(emguImage, new VectorOfVectorOfPoint(new VectorOfPoint(checkArea.Contour)), -1, new MCvScalar(255), -1);
+ var span = image.GetPixelSpan<byte>();
+ using (var emguImage = image.CloneBlank())
+ {
+ using(var vec = new VectorOfVectorOfPoint(new VectorOfPoint(checkArea.Contour)))
+ {
+ CvInvoke.DrawContours(emguImage, vec, -1, new MCvScalar(255), -1);
+ }
- bool exitPixelLoop = false;
- uint blackCount = 0;
+ if (haveNextAreas)
+ {
+ foreach (var nextArea in nextAreas)
+ {
+ if (!checkArea.BoundingRectangle.IntersectsWith(nextArea.BoundingRectangle)) continue;
- var spanContour = emguImage.GetPixelSpan<byte>();
- for (int y = checkArea.BoundingRectangle.Y;
- y <= checkArea.BoundingRectangle.Bottom &&
- area.Type != LayerHollowArea.AreaType.Drain && !exitPixelLoop;
- y++)
- {
- for (int x = checkArea.BoundingRectangle.X;
- x <= checkArea.BoundingRectangle.Right &&
+ intersectingAreas.Add(nextArea);
+ /*CvInvoke.DrawContours(emguImage,
+ new VectorOfVectorOfPoint(new VectorOfPoint(nextArea.Contour)),
+ -1,
+ new MCvScalar(intersectingAreas.Count), -1);*/
+ }
+ if (intersectingAreas.Count == 0)
+ {
+ haveNextAreas = false;
+ }
+ }
+
+ bool exitPixelLoop = false;
+ uint blackCount = 0;
+
+ var spanContour = emguImage.GetPixelSpan<byte>();
+ for (int y = checkArea.BoundingRectangle.Y;
+ y <= checkArea.BoundingRectangle.Bottom &&
area.Type != LayerHollowArea.AreaType.Drain && !exitPixelLoop;
- x++)
+ y++)
{
- int pixelPos = image.GetPixelPos(x, y);
+ int pixelPos = image.GetPixelPos(checkArea.BoundingRectangle.X, y)-1;
+ for (int x = checkArea.BoundingRectangle.X;
+ x <= checkArea.BoundingRectangle.Right &&
+ area.Type != LayerHollowArea.AreaType.Drain && !exitPixelLoop;
+ x++)
+ {
+ pixelPos++;
- if (spanContour[pixelPos] != 255) continue;
- if (span[pixelPos] > 30) continue;
- blackCount++;
+ if (spanContour[pixelPos] == 0) continue; // No contour
+ if (span[pixelPos] > 30) continue; // Threshold to ignore white area
+ blackCount++;
- if (haveNextAreas
- ) // Have areas, can be on same area path or not
- {
- foreach (var nextArea in nextAreas)
+ if (haveNextAreas) // Have areas, can be on same area path or not
{
- if (!(CvInvoke.PointPolygonTest(
- new VectorOfPoint(nextArea.Contour),
- new PointF(x, y), false) >= 0)) continue;
- if (nextArea.Type == LayerHollowArea.AreaType.Drain
- ) // Found a drain, stop query
+ /*int i = spanContour[pixelPos] - 1;
+ if (i == -1 || i >= 254)
+ continue;
+
+ //if(queue.Contains(intersectingAreas[i])) continue;
+ //Debug.WriteLine($"BlackCount: {blackCount}, pixel color: {i}, layerindex: {layerIndex}");
+
+ if (intersectingAreas[i].Type == LayerHollowArea.AreaType.Drain) // Found a drain, stop query
{
area.Type = LayerHollowArea.AreaType.Drain;
}
else
{
- queue.Enqueue(nextArea);
+ queue.Enqueue(intersectingAreas[i]);
}
- linkedAreas.Add(nextArea);
+ linkedAreas.Add(intersectingAreas[i]);
exitPixelLoop = true;
+ break;*/
+ foreach (var nextAreaCheck in intersectingAreas)
+ {
+ using (var vec = new VectorOfPoint(nextAreaCheck.Contour))
+ {
+ //Debug.WriteLine(CvInvoke.PointPolygonTest(vec, new PointF(x, y), false));
+ if (CvInvoke.PointPolygonTest(vec, new PointF(x, y), false) < 0) continue;
+ }
+
+ if (nextAreaCheck.Type == LayerHollowArea.AreaType.Drain
+ ) // Found a drain, stop query
+ {
+ area.Type = LayerHollowArea.AreaType.Drain;
+ exitPixelLoop = true;
+ }
+ else
+ {
+ queue.Enqueue(area);
+ }
+
+ linkedAreas.Add(nextAreaCheck);
+ intersectingAreas.Remove(nextAreaCheck);
+ haveNextAreas = intersectingAreas.Count > 0;
+ break;
+ //exitPixelLoop = true;
+ //break;
+
+ }
+ }
+ else if (blackCount > Math.Min(checkArea.Contour.Length / 2, 10)) // Black pixel without next areas = Drain
+ {
+ area.Type = LayerHollowArea.AreaType.Drain;
+ exitPixelLoop = true;
break;
}
- }
- else if (blackCount > Math.Min(checkArea.Contour.Length / 2, 10)) // Black pixel without next areas = Drain
- {
- area.Type = LayerHollowArea.AreaType.Drain;
- exitPixelLoop = true;
- break;
- }
- } // X loop
- } // Y loop
+ } // X loop
+ } // Y loop
- if (queue.Count == 0 && blackCount > Math.Min(checkArea.Contour.Length / 2, 10))
- {
+ if (queue.Count == 0 && blackCount > Math.Min(checkArea.Contour.Length / 2, 10))
+ {
- area.Type = LayerHollowArea.AreaType.Drain;
- }
+ area.Type = LayerHollowArea.AreaType.Drain;
+ }
- } // Dispose emgu image
- } // Dispose image
- } // Areas loop
- } // Dir layer loop
+ } // Dispose emgu image
+ } // Dispose image
+ } // Areas loop
+ } // Dir layer loop
- foreach (var linkedArea in linkedAreas) // Update linked areas
- {
- linkedArea.Type = area.Type;
- }
- });
- }
+ foreach (var linkedArea in linkedAreas) // Update linked areas
+ {
+ linkedArea.Type = area.Type;
+ }
+ });
+ }
+ });
+
+ task1.Wait(); // Islands & bounds
+ task2.Wait(); // Resin trap
for (uint layerIndex = 0; layerIndex < Count; layerIndex++)
{
if (!layerHollowAreas.TryGetValue(layerIndex, out var list)) continue;
- if (list.Count > 0)
+ if (list.Count == 0) continue;
+ foreach (var issue in
+ from area
+ in list
+ where area.Type == LayerHollowArea.AreaType.Trap
+ select new LayerIssue(this[layerIndex], LayerIssue.IssueType.ResinTrap, area.Contour, area.BoundingRectangle))
{
- foreach (var area in list)
+ result.AddOrUpdate(layerIndex, new List<LayerIssue> {issue}, (u, listIssues) =>
{
- if (area.Type == LayerHollowArea.AreaType.Trap)
- {
- var issue = new LayerIssue(this[layerIndex], LayerIssue.IssueType.ResinTrap, area.Contour, area.BoundingRectangle);
- result.AddOrUpdate(layerIndex, new List<LayerIssue> {issue}, (u, listIssues) =>
- {
- listIssues.Add(issue);
- return listIssues;
- });
- //issuesHollow.Add();
- }
- }
-
- /*if (issuesHollow.Count > 0)
- {
- if (Issues.TryGetValue(layerIndex, out var currentIssue))
- {
- currentIssue.AddRange(issuesHollow);
- }
- else
- {
- Issues.Add(layerIndex, issuesHollow);
- }
- }*/
+ listIssues.Add(issue);
+ return listIssues;
+ });
}
}
diff --git a/UVtools.Core/PHZFile.cs b/UVtools.Core/PHZFile.cs
index 966ea1f..34487a1 100644
--- a/UVtools.Core/PHZFile.cs
+++ b/UVtools.Core/PHZFile.cs
@@ -20,7 +20,6 @@ using BinarySerialization;
using Emgu.CV;
using Emgu.CV.CvEnum;
using UVtools.Core.Extensions;
-using UVtools.Parser;
namespace UVtools.Core
{
diff --git a/UVtools.Core/PWSFile.cs b/UVtools.Core/PWSFile.cs
index 342c59d..2cf034a 100644
--- a/UVtools.Core/PWSFile.cs
+++ b/UVtools.Core/PWSFile.cs
@@ -16,7 +16,6 @@ using BinarySerialization;
using Emgu.CV;
using Emgu.CV.CvEnum;
using UVtools.Core.Extensions;
-using UVtools.Parser;
namespace UVtools.Core
{
diff --git a/UVtools.Core/SL1File.cs b/UVtools.Core/SL1File.cs
index bf3d4bd..0ddafbd 100644
--- a/UVtools.Core/SL1File.cs
+++ b/UVtools.Core/SL1File.cs
@@ -16,7 +16,6 @@ using System.Reflection;
using Emgu.CV;
using Emgu.CV.CvEnum;
using UVtools.Core.Extensions;
-using UVtools.Parser;
namespace UVtools.Core
{
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index 7de4af6..7f4291a 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -11,6 +11,8 @@
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, repair, conversion and manipulation</Description>
<Version>0.6</Version>
+ <Copyright>Copyright © 2020 PTRTECH</Copyright>
+ <PackageIcon>UVtools.png</PackageIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -30,6 +32,10 @@
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
+ <None Include="..\UVtools.GUI\UVtools.png">
+ <Pack>True</Pack>
+ <PackagePath></PackagePath>
+ </None>
<None Include="MatBytes.cs" />
</ItemGroup>
diff --git a/UVtools.Core/ZCodexFile.cs b/UVtools.Core/ZCodexFile.cs
index 7a2eda5..7cee01b 100644
--- a/UVtools.Core/ZCodexFile.cs
+++ b/UVtools.Core/ZCodexFile.cs
@@ -17,7 +17,6 @@ using Emgu.CV.CvEnum;
using Emgu.CV.Util;
using Newtonsoft.Json;
using UVtools.Core.Extensions;
-using UVtools.Parser;
namespace UVtools.Core
{