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>2021-05-29 06:14:03 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2021-05-29 06:14:03 +0300
commitd90f7e6f75873f40dcfe807752522b4c1baa751e (patch)
tree3fab7b5faca785983f0444b0654d6314351f6d36
parentff4e0dfe28572b151b4831f905110eeeaf57fb62 (diff)
v2.13.1v2.13.1
- (Add) Layer preview - Outline: Skeletonize - (Add) Actions - Export layers to skeleton: Export a layer range to a skeletonized image that is the sum of each layer skeleton - (Add) Pixel editor - Text: Allow to rotate text placement by any angle (#206) - (Add) Calibrate - XYZ Accuracy: Drain hole diameter (#205)
-rw-r--r--CHANGELOG.md7
-rw-r--r--UVtools.Core/Extensions/EmguExtensions.cs175
-rw-r--r--UVtools.Core/Extensions/PointExtensions.cs27
-rw-r--r--UVtools.Core/Extensions/SizeExtensions.cs64
-rw-r--r--UVtools.Core/FileFormats/GR1File.cs2
-rw-r--r--UVtools.Core/FileFormats/MDLPFile.cs2
-rw-r--r--UVtools.Core/Layer/LayerManager.cs4
-rw-r--r--UVtools.Core/Operations/Operation.cs2
-rw-r--r--UVtools.Core/Operations/OperationCalibrateElephantFoot.cs14
-rw-r--r--UVtools.Core/Operations/OperationCalibrateExposureFinder.cs76
-rw-r--r--UVtools.Core/Operations/OperationCalibrateGrayscale.cs16
-rw-r--r--UVtools.Core/Operations/OperationCalibrateStressTower.cs12
-rw-r--r--UVtools.Core/Operations/OperationCalibrateTolerance.cs30
-rw-r--r--UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs64
-rw-r--r--UVtools.Core/Operations/OperationLayerExportHeatMap.cs4
-rw-r--r--UVtools.Core/Operations/OperationLayerExportSkeleton.cs139
-rw-r--r--UVtools.Core/Operations/OperationPixelArithmetic.cs6
-rw-r--r--UVtools.Core/Operations/OperationRepairLayers.cs2
-rw-r--r--UVtools.Core/Operations/OperationSolidify.cs2
-rw-r--r--UVtools.Core/PixelEditor/PixelText.cs10
-rw-r--r--UVtools.Core/UVtools.Core.csproj2
-rw-r--r--UVtools.ScriptSample/ScriptTestPerLayerSettingsSample.cs16
-rw-r--r--UVtools.ScriptSample/ScriptVATClean.cs6
-rw-r--r--UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml54
-rw-r--r--UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml.cs2
-rw-r--r--UVtools.WPF/Controls/Tools/ToolLayerExportSkeletonControl.axaml30
-rw-r--r--UVtools.WPF/Controls/Tools/ToolLayerExportSkeletonControl.axaml.cs36
-rw-r--r--UVtools.WPF/MainWindow.LayerPreview.cs37
-rw-r--r--UVtools.WPF/MainWindow.PixelEditor.cs2
-rw-r--r--UVtools.WPF/MainWindow.axaml42
-rw-r--r--UVtools.WPF/MainWindow.axaml.cs8
-rw-r--r--UVtools.WPF/UVtools.WPF.csproj2
32 files changed, 702 insertions, 193 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed9c89d..4bf3cbb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## 29/05/2021 - v2.13.1
+
+- (Add) Layer preview - Outline: Skeletonize
+- (Add) Actions - Export layers to skeleton: Export a layer range to a skeletonized image that is the sum of each layer skeleton
+- (Add) Pixel editor - Text: Allow to rotate text placement by any angle (#206)
+- (Add) Calibrate - XYZ Accuracy: Drain hole diameter (#205)
+
## 23/05/2021 - v2.13.0
- (Add) Tool - Light bleed compensation: Compensate the over-curing and light bleed from clear resins by dimming the sequential pixels
diff --git a/UVtools.Core/Extensions/EmguExtensions.cs b/UVtools.Core/Extensions/EmguExtensions.cs
index 3a55047..4240372 100644
--- a/UVtools.Core/Extensions/EmguExtensions.cs
+++ b/UVtools.Core/Extensions/EmguExtensions.cs
@@ -8,23 +8,20 @@
using System;
using System.Drawing;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace UVtools.Core.Extensions
{
public static class EmguExtensions
{
- public static readonly MCvScalar WhiteByte = new(255);
- public static readonly MCvScalar White3Byte = new(255, 255, 255);
- public static readonly MCvScalar BlackByte = new(0);
- public static readonly MCvScalar Black3Byte = new(0, 0, 0);
- public static readonly MCvScalar Transparent4Byte = new(0, 0, 0, 0);
- public static readonly MCvScalar Black4Byte = new(0, 0, 0, 255);
+ public static readonly MCvScalar WhiteColor = new(255, 255, 255, 255);
+ public static readonly MCvScalar BlackColor = new(0, 0, 0, 255);
+ //public static readonly MCvScalar TransparentColor = new();
public static unsafe byte* GetBytePointer(this Mat mat)
{
@@ -72,7 +69,7 @@ namespace UVtools.Core.Extensions
public static unsafe Span<T> GetPixelColSpan<T>(this Mat mat, int x, int length = 0, int offset = 0)
{
var colMat = mat.Col(x);
- return new(IntPtr.Add(mat.DataPointer, offset).ToPointer(), length <= 0 ? mat.Height : length);
+ return new(IntPtr.Add(colMat.DataPointer, offset).ToPointer(), length <= 0 ? mat.Height : length);
}
/// <summary>
@@ -95,25 +92,89 @@ namespace UVtools.Core.Extensions
public static void Transform(this Mat src, double xScale, double yScale, double xTrans = 0, double yTrans = 0, Size dstSize = default, Inter interpolation = Inter.Linear)
{
//var dst = new Mat(src.Size, src.Depth, src.NumberOfChannels);
- using (var translateTransform = new Matrix<double>(2, 3)
+ using var translateTransform = new Matrix<double>(2, 3)
{
[0, 0] = xScale, // xScale
[1, 1] = yScale, // yScale
[0, 2] = xTrans, //x translation + compensation of x scaling
[1, 2] = yTrans // y translation + compensation of y scaling
- })
+ };
+ CvInvoke.WarpAffine(src, src, translateTransform, dstSize.IsEmpty ? src.Size : dstSize, interpolation);
+ }
+
+ /// <summary>
+ /// Rotates a Mat by an angle while keeping the image size
+ /// </summary>
+ /// <param name="src"></param>
+ /// <param name="angle"></param>
+ /// <param name="scale"></param>
+ public static void Rotate(this Mat src, double angle, Size newSize = default, double scale = 1.0) => Rotate(src, src, angle, newSize, scale);
+
+ /// <summary>
+ /// Rotates a Mat by an angle while keeping the image size
+ /// </summary>
+ /// <param name="src"></param>
+ /// <param name="dst"></param>
+ /// <param name="angle"></param>
+ /// <param name="scale"></param>
+ public static void Rotate(this Mat src, Mat dst, double angle, Size newSize = default, double scale = 1.0)
+ {
+ if (angle % 360 == 0 && scale == 1.0) return;
+ if (newSize.IsEmpty)
+ {
+ newSize = src.Size;
+ }
+
+ var halfWidth = src.Width / 2.0f;
+ var halfHeight = src.Height / 2.0f;
+ using var translateTransform = new Matrix<double>(2, 3);
+ CvInvoke.GetRotationMatrix2D(new PointF(halfWidth, halfHeight), -angle, scale, translateTransform);
+
+ if (src.Size != newSize)
{
- CvInvoke.WarpAffine(src, src, translateTransform, dstSize.IsEmpty ? src.Size : dstSize, interpolation);
+ // adjust the rotation matrix to take into account translation
+ translateTransform[0, 2] += newSize.Width / 2.0 - halfWidth;
+ translateTransform[1, 2] += newSize.Height / 2.0 - halfHeight;
}
+
+ CvInvoke.WarpAffine(src, dst, translateTransform, newSize);
}
- public static void Rotate(this Mat src, double angle)
+ /// <summary>
+ /// Rotates a Mat by an angle while adjusting bounds to fit the rotated content
+ /// </summary>
+ /// <param name="src"></param>
+ /// <param name="angle"></param>
+ /// <param name="scale"></param>
+ public static void RotateAdjustBounds(this Mat src, double angle, double scale = 1.0) => RotateAdjustBounds(src, src, angle, scale);
+
+ /// <summary>
+ /// Rotates a Mat by an angle while adjusting bounds to fit the rotated content
+ /// </summary>
+ /// <param name="src"></param>
+ /// <param name="dst"></param>
+ /// <param name="angle"></param>
+ /// <param name="scale"></param>
+ public static void RotateAdjustBounds(this Mat src, Mat dst, double angle, double scale = 1.0)
{
+ if (angle % 360 == 0 && scale == 1.0) return;
var halfWidth = src.Width / 2.0f;
var halfHeight = src.Height / 2.0f;
using var translateTransform = new Matrix<double>(2, 3);
- CvInvoke.GetRotationMatrix2D(new PointF(halfWidth, halfHeight), -angle, 1.0, translateTransform);
- CvInvoke.WarpAffine(src, src, translateTransform, src.Size);
+ CvInvoke.GetRotationMatrix2D(new PointF(halfWidth, halfHeight), -angle, scale, translateTransform);
+ var cos = Math.Abs(translateTransform[0, 0]);
+ var sin = Math.Abs(translateTransform[0, 1]);
+
+ // compute the new bounding dimensions of the image
+ int newWidth = (int) (src.Height * sin + src.Width * cos);
+ int newHeight = (int) (src.Height * cos + src.Width * sin);
+
+ // adjust the rotation matrix to take into account translation
+ translateTransform[0, 2] += newWidth / 2.0 - halfWidth;
+ translateTransform[1, 2] += newHeight / 2.0 - halfHeight;
+
+
+ CvInvoke.WarpAffine(src, dst, translateTransform, new Size(newWidth, newHeight));
}
/// <summary>
@@ -134,6 +195,85 @@ namespace UVtools.Core.Extensions
yTrans + (src.Height - src.Height * yScale) / 2.0, dstSize, interpolation);
}
+ public static void PutTextRotated(this Mat src, string text, Point org, FontFace fontFace, double fontScale, MCvScalar color,
+ int thickness = 1, LineType lineType = LineType.EightConnected, bool bottomLeftOrigin = false, double angle = 0)
+ {
+ if (angle % 360 == 0) // No rotation needed, cheaper cycle
+ {
+ CvInvoke.PutText(src, text, org, fontFace, fontScale, color, thickness, lineType, bottomLeftOrigin);
+ return;
+ }
+
+ using var rotatedSrc = src.Clone();
+ rotatedSrc.RotateAdjustBounds(-angle);
+ var sizeDifference = (rotatedSrc.Size - src.Size).Half();
+ org.Offset(sizeDifference.ToPoint());
+ org = org.Rotate(-angle, new Point(rotatedSrc.Size.Width / 2, rotatedSrc.Size.Height / 2));
+ CvInvoke.PutText(rotatedSrc, text, org, fontFace, fontScale, color, thickness, lineType, bottomLeftOrigin);
+
+ using var mask = rotatedSrc.CloneBlank();
+ CvInvoke.PutText(mask, text, org, fontFace, fontScale, WhiteColor, thickness, lineType, bottomLeftOrigin);
+
+ rotatedSrc.Rotate(angle, src.Size);
+ mask.Rotate(angle, src.Size);
+
+ rotatedSrc.CopyTo(src, mask);
+ }
+
+ /// <summary>
+ /// Determine the area (i.e. total number of pixels in the image),
+ /// initialize the output skeletonized image, and construct the
+ /// morphological structuring element
+ /// </summary>
+ /// <param name="src"></param>
+ /// <param name="iterations">Number of iterations required to perform the skeletoize</param>
+ /// <param name="ksize"></param>
+ /// <param name="elementShape"></param>
+ public static Mat Skeletonize(this Mat src, out int iterations, Size ksize = default, ElementShape elementShape = ElementShape.Rectangle)
+ {
+ if (ksize.IsEmpty) ksize = new Size(3, 3);
+ Point anchor = new(-1, -1);
+ var skeleton = src.CloneBlank();
+ using var kernel = CvInvoke.GetStructuringElement(elementShape, ksize, anchor);
+
+ var image = src;
+ using var temp = new Mat();
+ iterations = 0;
+ while (true)
+ {
+ iterations++;
+
+ // erode and dilate the image using the structuring element
+ using var eroded = new Mat();
+ CvInvoke.Erode(image, eroded, kernel, anchor, 1, BorderType.Reflect101, default);
+ CvInvoke.Dilate(eroded, temp, kernel, anchor, 1, BorderType.Reflect101, default);
+
+ // subtract the temporary image from the original, eroded
+ // image, then take the bitwise 'or' between the skeleton
+ // and the temporary image
+ CvInvoke.Subtract(image, temp, temp);
+ CvInvoke.BitwiseOr(skeleton, temp, skeleton);
+ image = eroded.Clone();
+
+ // if there are no more 'white' pixels in the image, then
+ // break from the loop
+ if (CvInvoke.CountNonZero(image) == 0) break;
+ }
+
+ return skeleton;
+ }
+
+ /// <summary>
+ /// Determine the area (i.e. total number of pixels in the image),
+ /// initialize the output skeletonized image, and construct the
+ /// morphological structuring element
+ /// </summary>
+ /// <param name="src"></param>
+ /// <param name="ksize"></param>
+ /// <param name="elementShape"></param>
+ public static Mat Skeletonize(this Mat src, Size ksize = default, ElementShape elementShape = ElementShape.Rectangle)
+ => src.Skeletonize(out _, ksize, elementShape);
+
/// <summary>
/// Copy a <see cref="Mat"/> to center of other <see cref="Mat"/>
/// </summary>
@@ -226,6 +366,13 @@ namespace UVtools.Core.Extensions
return new(mat.Rows, mat.Cols, mat.Depth, mat.NumberOfChannels);
}
+ public static Mat New(this Mat src, MCvScalar color)
+ {
+ Mat mat = new(src.Rows, src.Cols, src.Depth, src.NumberOfChannels);
+ mat.SetTo(color);
+ return mat;
+ }
+
/// <summary>
/// Clone this <see cref="Mat"/> blanked (All zeros)
/// </summary>
diff --git a/UVtools.Core/Extensions/PointExtensions.cs b/UVtools.Core/Extensions/PointExtensions.cs
index 8b0056c..8d9820f 100644
--- a/UVtools.Core/Extensions/PointExtensions.cs
+++ b/UVtools.Core/Extensions/PointExtensions.cs
@@ -16,7 +16,7 @@ namespace UVtools.Core.Extensions
public static Point Rotate(this Point point, double angleDegree, Point pivot = default)
{
- if (angleDegree is 0 or 360) return point;
+ if (angleDegree % 360 == 0) return point;
double angle = angleDegree * Math.PI / 180;
double cos = Math.Cos(angle);
double sin = Math.Sin(angle);
@@ -25,9 +25,30 @@ namespace UVtools.Core.Extensions
double x = cos * dx - sin * dy + pivot.X;
double y = sin * dx + cos * dy + pivot.Y;
- Point rotated = new((int)Math.Round(x), (int)Math.Round(y));
- return rotated;
+ return new((int)Math.Round(x), (int)Math.Round(y));
}
+ public static PointF Rotate(this PointF point, double angleDegree, PointF pivot = default)
+ {
+ if (angleDegree % 360 == 0) return point;
+ double angle = angleDegree * Math.PI / 180;
+ double cos = Math.Cos(angle);
+ double sin = Math.Sin(angle);
+ double dx = point.X - pivot.X;
+ double dy = point.Y - pivot.Y;
+ double x = cos * dx - sin * dy + pivot.X;
+ double y = sin * dx + cos * dy + pivot.Y;
+
+ return new((float) x, (float) y);
+ }
+
+ public static Point Half(this Point point)=> new(point.X / 2, point.Y / 2);
+
+ public static PointF Half(this PointF point) => new(point.X / 2, point.Y / 2);
+
+ public static Size ToSize(this Point point) => new(point.X, point.Y);
+
+ public static SizeF ToSize(this PointF point) => new(point.X, point.Y);
+
}
}
diff --git a/UVtools.Core/Extensions/SizeExtensions.cs b/UVtools.Core/Extensions/SizeExtensions.cs
index e16893c..8bbc547 100644
--- a/UVtools.Core/Extensions/SizeExtensions.cs
+++ b/UVtools.Core/Extensions/SizeExtensions.cs
@@ -43,6 +43,8 @@ namespace UVtools.Core.Extensions
SizeSuffixes[mag]);
}
+ public static Size Inflate(this Size size, Size otherSize) => new (size.Width + otherSize.Width, size.Height + otherSize.Height);
+ public static Size Inflate(this Size size) => size.Inflate(size);
public static Size Inflate(this Size size, int pixels) => new (size.Width + pixels, size.Height + pixels);
public static Size Inflate(this Size size, int width, int height) => new (size.Width + width, size.Height + height);
@@ -51,10 +53,7 @@ namespace UVtools.Core.Extensions
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
- public static bool HaveZero(this Size size)
- {
- return size.Width <= 0 && size.Height <= 0;
- }
+ public static bool HaveZero(this Size size) => size.Width <= 0 && size.Height <= 0;
/// <summary>
/// Exchange width with height
@@ -63,45 +62,50 @@ namespace UVtools.Core.Extensions
/// <returns></returns>
public static Size Invert(this Size size) => new(size.Height, size.Width);
- public static int Area(this Rectangle rect)
- {
- return rect.Width * rect.Height;
- }
+ public static int Area(this Rectangle rect) => rect.Width * rect.Height;
- public static int Area(this Size size)
- {
- return size.Width * size.Height;
- }
+ public static int Area(this Size size) => size.Width * size.Height;
- public static int Max(this Size size)
- {
- return Math.Max(size.Width, size.Height);
- }
+ public static int Max(this Size size) => Math.Max(size.Width, size.Height);
- public static float Area(this RectangleF rect, int round = -1)
- {
- return round >= 0 ? (float) Math.Round(rect.Width * rect.Height, round) : rect.Width * rect.Height;
- }
+ public static float Area(this RectangleF rect, int round = -1) => round >= 0 ? (float) Math.Round(rect.Width * rect.Height, round) : rect.Width * rect.Height;
/// <summary>
/// Gets if this size have a zero value on width or height
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
- public static bool HaveZero(this SizeF size)
- {
- return size.Width <= 0 && size.Height <= 0;
- }
+ public static bool HaveZero(this SizeF size) => size.Width <= 0 && size.Height <= 0;
- public static float Area(this SizeF size, int round = -1)
- {
- return round >= 0 ? (float)Math.Round(size.Width * size.Height, round) : size.Width * size.Height;
- }
+ public static float Area(this SizeF size, int round = -1) => round >= 0 ? (float)Math.Round(size.Width * size.Height, round) : size.Width * size.Height;
+
+ public static float Max(this SizeF size) => Math.Max(size.Width, size.Height);
+
+ public static Size Half(this Size size) => new(size.Width / 2, size.Height / 2);
+
+ public static SizeF Half(this SizeF size) => new(size.Width / 2, size.Height / 2);
+
+ public static Point ToPoint(this Size size) => new(size.Width, size.Height);
+ public static PointF ToPoint(this SizeF size) => new(size.Width, size.Height);
- public static float Max(this SizeF size)
+ public static Size Rotate(this Size size, double angleDegree)
{
- return Math.Max(size.Width, size.Height);
+ if (angleDegree % 360 == 0) return size;
+ var sizeHalf = size.Half();
+ double angle = angleDegree * Math.PI / 180;
+ double cos = Math.Cos(angle);
+ double sin = Math.Sin(angle);
+ // var newImgWidth = + (float)(x0 + Math.Abs((x - x0) * Math.Cos(rad)) + Math.Abs((y - y0) * Math.Sin(rad)));
+ //var newImgHeight = -(float)(y0 + Math.Abs((x - x0) * Math.Sin(rad)) + Math.Abs((y - y0) * Math.Cos(rad)));
+ int dx = size.Width - sizeHalf.Width;
+ int dy = size.Height - sizeHalf.Height;
+ //double width = sizeHalf.Width + Math.Abs(dx * cos) + Math.Abs(dy * sin);
+ //double height = sizeHalf.Height + Math.Abs(dx * sin) + Math.Abs(dy * cos);
+ double width = Math.Abs(cos * dx) - Math.Abs(sin * dy) + sizeHalf.Width;
+ double height = Math.Abs(sin * dx) + Math.Abs(cos * dy) + sizeHalf.Height;
+
+ return new((int)Math.Round(width), (int)Math.Round(height));
}
}
diff --git a/UVtools.Core/FileFormats/GR1File.cs b/UVtools.Core/FileFormats/GR1File.cs
index 4374b38..7a227b1 100644
--- a/UVtools.Core/FileFormats/GR1File.cs
+++ b/UVtools.Core/FileFormats/GR1File.cs
@@ -489,7 +489,7 @@ namespace UVtools.Core.FileFormats
using var mat = EmguExtensions.InitMat(Resolution);
foreach (var line in layerDefs[layerIndex].Lines)
{
- CvInvoke.Line(mat, new Point(line.StartX, line.StartY), new Point(line.StartX, line.EndY), EmguExtensions.WhiteByte);
+ CvInvoke.Line(mat, new Point(line.StartX, line.StartY), new Point(line.StartX, line.EndY), EmguExtensions.WhiteColor);
}
this[layerIndex] = new Layer((uint) layerIndex, mat, this);
diff --git a/UVtools.Core/FileFormats/MDLPFile.cs b/UVtools.Core/FileFormats/MDLPFile.cs
index 7530199..73af073 100644
--- a/UVtools.Core/FileFormats/MDLPFile.cs
+++ b/UVtools.Core/FileFormats/MDLPFile.cs
@@ -454,7 +454,7 @@ namespace UVtools.Core.FileFormats
using var mat = EmguExtensions.InitMat(Resolution);
foreach (var line in layerDefs[layerIndex].Lines)
{
- CvInvoke.Line(mat, new Point(line.StartX, line.StartY), new Point(line.StartX, line.EndY), EmguExtensions.WhiteByte);
+ CvInvoke.Line(mat, new Point(line.StartX, line.StartY), new Point(line.StartX, line.EndY), EmguExtensions.WhiteColor);
}
this[layerIndex] = new Layer((uint) layerIndex, mat, this);
diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs
index e7b9c7d..773e728 100644
--- a/UVtools.Core/Layer/LayerManager.cs
+++ b/UVtools.Core/Layer/LayerManager.cs
@@ -1432,7 +1432,7 @@ namespace UVtools.Core
using (var vec =
new VectorOfVectorOfPoint(new VectorOfPoint(checkArea.Contour)))
{
- CvInvoke.DrawContours(emguImage, vec, -1, EmguExtensions.WhiteByte, -1);
+ CvInvoke.DrawContours(emguImage, vec, -1, EmguExtensions.WhiteColor, -1);
}
using (var intersectingAreasMat = image.CloneBlank())
@@ -1638,7 +1638,7 @@ namespace UVtools.Core
var operationText = (PixelText)operation;
var mat = modifiedLayers.GetOrAdd(operation.LayerIndex, u => this[operation.LayerIndex].LayerMat);
- CvInvoke.PutText(mat, operationText.Text, operationText.Location, operationText.Font, operationText.FontScale, new MCvScalar(operationText.Brightness), operationText.Thickness, operationText.LineType, operationText.Mirror);
+ mat.PutTextRotated(operationText.Text, operationText.Location, operationText.Font, operationText.FontScale, new MCvScalar(operationText.Brightness), operationText.Thickness, operationText.LineType, operationText.Mirror, operationText.Angle);
}
else if (operation.OperationType == PixelOperation.PixelOperationType.Eraser)
{
diff --git a/UVtools.Core/Operations/Operation.cs b/UVtools.Core/Operations/Operation.cs
index acf78b2..d4abaf1 100644
--- a/UVtools.Core/Operations/Operation.cs
+++ b/UVtools.Core/Operations/Operation.cs
@@ -415,7 +415,7 @@ namespace UVtools.Core.Operations
var mask = EmguExtensions.InitMat(mat.Size);
using VectorOfVectorOfPoint vec = new(points);
- CvInvoke.DrawContours(mask, vec, -1, EmguExtensions.WhiteByte, -1);
+ CvInvoke.DrawContours(mask, vec, -1, EmguExtensions.WhiteColor, -1);
return GetRoiOrDefault(mask);
}
diff --git a/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs b/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs
index eaa3c5f..8903780 100644
--- a/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs
+++ b/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs
@@ -489,11 +489,11 @@ namespace UVtools.Core.Operations
maxY += ellipseHeight;
using Mat shape = EmguExtensions.InitMat(new Size(maxX + startX, maxY + startY));
- CvInvoke.FillPoly(shape, new VectorOfPoint(pointList.ToArray()), EmguExtensions.WhiteByte, lineType);
- CvInvoke.Circle(shape, new Point(0, 0), length / 4, EmguExtensions.BlackByte, -1, lineType);
+ CvInvoke.FillPoly(shape, new VectorOfPoint(pointList.ToArray()), EmguExtensions.WhiteColor, lineType);
+ CvInvoke.Circle(shape, new Point(0, 0), length / 4, EmguExtensions.BlackColor, -1, lineType);
CvInvoke.Ellipse(shape, new Point(maxX / 2, maxY - ellipseHeight), new Size(maxX / 3, ellipseHeight), 0, 0, 360,
- EmguExtensions.WhiteByte, -1, lineType);
- CvInvoke.Circle(shape, new Point(length / 2, (int) (maxY - 100 * _partScale)), length / 5, EmguExtensions.BlackByte, -1, lineType);
+ EmguExtensions.WhiteColor, -1, lineType);
+ CvInvoke.Circle(shape, new Point(length / 2, (int) (maxY - 100 * _partScale)), length / 5, EmguExtensions.BlackColor, -1, lineType);
int currentX = 0;
int currentY = 0;
@@ -510,7 +510,7 @@ namespace UVtools.Core.Operations
void addText(Mat mat, ushort number, params string[] text)
{
- var color = _extrudeText ? EmguExtensions.WhiteByte : EmguExtensions.BlackByte;
+ var color = _extrudeText ? EmguExtensions.WhiteColor : EmguExtensions.BlackColor;
CvInvoke.PutText(mat, number.ToString(), new Point((int) (100 * _partScale), (int) (55 * _partScale)), font, 1.5 * (double) _partScale, color, (int) (4 * _partScale), lineType);
CvInvoke.PutText(mat, "UVtools EP", new Point(fontStartX, fontStartY), font, 0.8 * (double) _partScale, color, (int) (2 * _partScale), lineType);
CvInvoke.PutText(mat, $"{Microns}um", new Point(fontStartX, fontStartY + fontMargin), font, fontScale, color, fontThickness, lineType);
@@ -679,8 +679,8 @@ namespace UVtools.Core.Operations
CvInvoke.Line(thumbnail, new Point(xSpacing, ySpacing + 5), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.Line(thumbnail, new Point(thumbnail.Width - xSpacing, 0), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.PutText(thumbnail, "Elephant Foot Cal.", new Point(xSpacing, ySpacing * 2), fontFace, fontScale, new MCvScalar(0, 255, 255), fontThickness);
- CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
- CvInvoke.PutText(thumbnail, $"{ObjectCount} Objects", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
+ CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
+ CvInvoke.PutText(thumbnail, $"{ObjectCount} Objects", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
/*thumbnail.SetTo(EmguExtensions.Black3Byte);
diff --git a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs
index 3f1d0f2..8430fe5 100644
--- a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs
+++ b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs
@@ -1236,13 +1236,13 @@ namespace UVtools.Core.Operations
var layers = new Mat[2];
layers[0] = EmguExtensions.InitMat(rect.Size);
- CvInvoke.Rectangle(layers[0], rect, EmguExtensions.WhiteByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.Rectangle(layers[0], rect, EmguExtensions.WhiteColor, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
layers[1] = layers[0].CloneBlank();
if (holes.Length > 0)
{
CvInvoke.Rectangle(layers[1],
new Rectangle(rect.Size.Width - holePanelWidth, 0, rect.Size.Width, layers[0].Height),
- EmguExtensions.WhiteByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ EmguExtensions.WhiteColor, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
@@ -1254,7 +1254,7 @@ namespace UVtools.Core.Operations
{
CvInvoke.Rectangle(layers[1],
new Rectangle(0, 0, layers[1].Size.Width-holePanelWidth, _staircaseThickness),
- EmguExtensions.WhiteByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ EmguExtensions.WhiteColor, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
// Print holes
@@ -1297,13 +1297,13 @@ namespace UVtools.Core.Operations
case CalibrateExposureFinderShapes.Square:
CvInvoke.Rectangle(layers[layerIndex],
new Rectangle(new Point(xPos, yPos), new Size(diameter-1, diameter-1)),
- EmguExtensions.WhiteByte, -1,
+ EmguExtensions.WhiteColor, -1,
_enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
break;
case CalibrateExposureFinderShapes.Circle:
CvInvoke.Circle(layers[layerIndex],
new Point(xPos, yPos),
- radius, EmguExtensions.WhiteByte, -1,
+ radius, EmguExtensions.WhiteColor, -1,
_enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
break;
}
@@ -1334,13 +1334,13 @@ namespace UVtools.Core.Operations
case CalibrateExposureFinderShapes.Square:
CvInvoke.Rectangle(layers[layerIndex],
new Rectangle(new Point(xPos, yPos), new Size(diameter-1, diameter-1)),
- EmguExtensions.BlackByte, -1,
+ EmguExtensions.BlackColor, -1,
_enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
break;
case CalibrateExposureFinderShapes.Circle:
CvInvoke.Circle(layers[layerIndex],
new Point(xPos, yPos),
- radius, EmguExtensions.BlackByte, -1,
+ radius, EmguExtensions.BlackColor, -1,
_enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
break;
}
@@ -1374,17 +1374,17 @@ namespace UVtools.Core.Operations
{
// Print positive bottom
CvInvoke.Rectangle(layers[1], new Rectangle(xPos, yPos, barLengthPx - 1, barSpacingPx - 1),
- EmguExtensions.WhiteByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ EmguExtensions.WhiteColor, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
// Print positive top
yPos += barSpacingPx;
CvInvoke.Rectangle(layers[1], new Rectangle(xPos + barLengthPx + _barVerticalSplitter, yPos, barLengthPx - 1, bars[i] - 1),
- EmguExtensions.WhiteByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ EmguExtensions.WhiteColor, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
yPos += bars[i];
}
// Left over
CvInvoke.Rectangle(layers[1], new Rectangle(xPos, yPos, barLengthPx - 1, barSpacingPx - 1),
- EmguExtensions.WhiteByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ EmguExtensions.WhiteColor, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
yPos += barSpacingPx;
@@ -1395,7 +1395,7 @@ namespace UVtools.Core.Operations
yStartPos - 1,
barsPanelWidth - _barFenceThickness + 1,
yPos - yStartPos + _barFenceThickness / 2 + _barFenceOffset + 1),
- EmguExtensions.WhiteByte, _barFenceThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ EmguExtensions.WhiteColor, _barFenceThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
yPos += _barFenceThickness * 2 + _barFenceOffset * 2;
}
@@ -1406,7 +1406,7 @@ namespace UVtools.Core.Operations
if (!textSize.IsEmpty)
{
CvInvoke.Rotate(layers[1], layers[1], RotateFlags.Rotate90CounterClockwise);
- CvInvoke.PutText(layers[1], _text, new Point(_staircaseThickness + featuresMarginX, layers[1].Height - barsPanelWidth - featuresMarginX * (barsPanelWidth > 0 ? 2 : 1)), _textFont, _textScale, EmguExtensions.WhiteByte, _textThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(layers[1], _text, new Point(_staircaseThickness + featuresMarginX, layers[1].Height - barsPanelWidth - featuresMarginX * (barsPanelWidth > 0 ? 2 : 1)), _textFont, _textScale, EmguExtensions.WhiteColor, _textThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
CvInvoke.Rotate(layers[1], layers[1], RotateFlags.Rotate90Clockwise);
}
@@ -1416,7 +1416,7 @@ namespace UVtools.Core.Operations
yPos = bullseyeYPos;
foreach (var circle in bulleyes)
{
- CvInvoke.Circle(layers[1], new Point(bullseyeXPos, yPos), circle.Radius, EmguExtensions.WhiteByte, circle.Thickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.Circle(layers[1], new Point(bullseyeXPos, yPos), circle.Radius, EmguExtensions.WhiteColor, circle.Thickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
if (_bullsEyeInvertQuadrants)
@@ -1442,7 +1442,7 @@ namespace UVtools.Core.Operations
new Size(
bulleyesDiameter + 10 + _bullsEyeFenceOffset*2 + _bullsEyeFenceThickness,
bulleyesDiameter + 10 + _bullsEyeFenceOffset*2 + _bullsEyeFenceThickness)),
- EmguExtensions.WhiteByte,
+ EmguExtensions.WhiteColor,
_bullsEyeFenceThickness,
_enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
@@ -1454,14 +1454,14 @@ namespace UVtools.Core.Operations
if (isPreview)
{
var textHeightStart = layers[1].Height - featuresMarginY - TextMarkingSpacing;
- CvInvoke.PutText(layers[1], $"{Microns}u", new Point(TextMarkingStartX, textHeightStart), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
- CvInvoke.PutText(layers[1], $"{_bottomExposure}s", new Point(TextMarkingStartX, textHeightStart + TextMarkingLineBreak), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
- CvInvoke.PutText(layers[1], $"{_normalExposure}s", new Point(TextMarkingStartX, textHeightStart + TextMarkingLineBreak * 2), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(layers[1], $"{Microns}u", new Point(TextMarkingStartX, textHeightStart), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(layers[1], $"{_bottomExposure}s", new Point(TextMarkingStartX, textHeightStart + TextMarkingLineBreak), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(layers[1], $"{_normalExposure}s", new Point(TextMarkingStartX, textHeightStart + TextMarkingLineBreak * 2), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
if (holes.Length > 0)
{
- CvInvoke.PutText(layers[1], $"{Microns}u", new Point(layers[1].Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
- CvInvoke.PutText(layers[1], $"{_bottomExposure}s", new Point(layers[1].Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart + TextMarkingLineBreak), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
- CvInvoke.PutText(layers[1], $"{_normalExposure}s", new Point(layers[1].Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart + TextMarkingLineBreak * 2), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(layers[1], $"{Microns}u", new Point(layers[1].Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(layers[1], $"{_bottomExposure}s", new Point(layers[1].Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart + TextMarkingLineBreak), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(layers[1], $"{_normalExposure}s", new Point(layers[1].Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart + TextMarkingLineBreak * 2), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
}
@@ -1508,7 +1508,7 @@ namespace UVtools.Core.Operations
foreach (var triangle in triangles)
{
using var vec = new VectorOfPoint(triangle);
- CvInvoke.FillPoly(layers[1], vec, EmguExtensions.WhiteByte,
+ CvInvoke.FillPoly(layers[1], vec, EmguExtensions.WhiteColor,
_enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
@@ -1528,7 +1528,7 @@ namespace UVtools.Core.Operations
CvInvoke.Rectangle(layers[1], new Rectangle(
new Point(triangles[0][0].X - 0, triangles[0][0].Y - 0),
new Size(triangleWidth * 2 + 0, triangleHeight + 0)
- ), EmguExtensions.WhiteByte, outlineThickness,
+ ), EmguExtensions.WhiteColor, outlineThickness,
_enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
}
@@ -1587,14 +1587,14 @@ namespace UVtools.Core.Operations
CvInvoke.Line(thumbnail, new Point(xSpacing, ySpacing + 5), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.Line(thumbnail, new Point(thumbnail.Width - xSpacing, 0), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.PutText(thumbnail, "Exposure Time Cal.", new Point(xSpacing, ySpacing * 2), fontFace, fontScale, new MCvScalar(0, 255, 255), fontThickness);
- CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
+ CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
if (_patternModel)
{
- CvInvoke.PutText(thumbnail, $"Patterned Model", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
+ CvInvoke.PutText(thumbnail, $"Patterned Model", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
}
else
{
- CvInvoke.PutText(thumbnail, $"Features: {(_staircaseThickness > 0 ? 1 : 0) + Holes.Length + Bars.Length + BullsEyes.Length + (_counterTrianglesEnabled ? 1 : 0)}", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
+ CvInvoke.PutText(thumbnail, $"Features: {(_staircaseThickness > 0 ? 1 : 0) + Holes.Length + Bars.Length + BullsEyes.Length + (_counterTrianglesEnabled ? 1 : 0)}", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
}
@@ -1679,7 +1679,7 @@ namespace UVtools.Core.Operations
{
if (_patternModelGlueBottomLayers)
{
- newMatRoi.SetTo(EmguExtensions.WhiteByte);
+ newMatRoi.SetTo(EmguExtensions.WhiteColor);
}
}
@@ -1697,11 +1697,11 @@ namespace UVtools.Core.Operations
if (_multipleBrightness)
{
- CvInvoke.PutText(newMatRoi, brightness.ToString(), new(xHalf - 60, yHalf + 20 - TextMarkingLineBreak * 4), TextMarkingFontFace, 2, EmguExtensions.BlackByte, 3, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(newMatRoi, brightness.ToString(), new(xHalf - 60, yHalf + 20 - TextMarkingLineBreak * 4), TextMarkingFontFace, 2, EmguExtensions.BlackColor, 3, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
- CvInvoke.PutText(newMatRoi, $"{microns}u", new(xHalf - 60, yHalf + 20 - TextMarkingLineBreak * 2), TextMarkingFontFace, 2, EmguExtensions.BlackByte, 3, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
- CvInvoke.PutText(newMatRoi, $"{group.Key.BottomExposure}s", new(xHalf - 60, yHalf + 20), TextMarkingFontFace, 2, EmguExtensions.BlackByte, 3, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
- CvInvoke.PutText(newMatRoi, $"{group.Key.Exposure}s", new(xHalf - 60, yHalf + 20 + TextMarkingLineBreak * 2), TextMarkingFontFace, 2, EmguExtensions.BlackByte, 3, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(newMatRoi, $"{microns}u", new(xHalf - 60, yHalf + 20 - TextMarkingLineBreak * 2), TextMarkingFontFace, 2, EmguExtensions.BlackColor, 3, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(newMatRoi, $"{group.Key.BottomExposure}s", new(xHalf - 60, yHalf + 20), TextMarkingFontFace, 2, EmguExtensions.BlackColor, 3, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(newMatRoi, $"{group.Key.Exposure}s", new(xHalf - 60, yHalf + 20 + TextMarkingLineBreak * 2), TextMarkingFontFace, 2, EmguExtensions.BlackColor, 3, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
if (brightness < 255)
@@ -1863,7 +1863,7 @@ namespace UVtools.Core.Operations
{
CvInvoke.Rectangle(matRoi,
new Rectangle(staircaseWidth - staircaseWidthForLayer, 0, staircaseWidthForLayer, _staircaseThickness),
- EmguExtensions.WhiteByte, -1,
+ EmguExtensions.WhiteColor, -1,
_enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
}
@@ -1890,19 +1890,19 @@ namespace UVtools.Core.Operations
}
var textHeightStart = matRoi.Height - featuresMarginY - TextMarkingSpacing;
- CvInvoke.PutText(matRoi, $"{microns}u", new Point(TextMarkingStartX, textHeightStart), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
- CvInvoke.PutText(matRoi, $"{bottomExposureTemp}s", new Point(TextMarkingStartX, textHeightStart + TextMarkingLineBreak), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
- CvInvoke.PutText(matRoi, $"{normalExposureTemp}s", new Point(TextMarkingStartX, textHeightStart + TextMarkingLineBreak * 2), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(matRoi, $"{microns}u", new Point(TextMarkingStartX, textHeightStart), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(matRoi, $"{bottomExposureTemp}s", new Point(TextMarkingStartX, textHeightStart + TextMarkingLineBreak), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(matRoi, $"{normalExposureTemp}s", new Point(TextMarkingStartX, textHeightStart + TextMarkingLineBreak * 2), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
if (holes.Length > 0)
{
- CvInvoke.PutText(matRoi, $"{microns}u", new Point(matRoi.Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
- CvInvoke.PutText(matRoi, $"{bottomExposureTemp}s", new Point(matRoi.Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart + TextMarkingLineBreak), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
- CvInvoke.PutText(matRoi, $"{normalExposureTemp}s", new Point(matRoi.Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart + TextMarkingLineBreak * 2), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(matRoi, $"{microns}u", new Point(matRoi.Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(matRoi, $"{bottomExposureTemp}s", new Point(matRoi.Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart + TextMarkingLineBreak), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(matRoi, $"{normalExposureTemp}s", new Point(matRoi.Width - featuresMarginX * 2 - holes[^1] + TextMarkingStartX, textHeightStart + TextMarkingLineBreak * 2), TextMarkingFontFace, TextMarkingScale, EmguExtensions.BlackColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
if (_multipleBrightness)
{
- CvInvoke.PutText(matRoi, brightness.ToString(), new Point(matRoi.Width / 3, 35), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteByte, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.PutText(matRoi, brightness.ToString(), new Point(matRoi.Width / 3, 35), TextMarkingFontFace, TextMarkingScale, EmguExtensions.WhiteColor, TextMarkingThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
if (brightness < 255 &&
(_multipleBrightnessExcludeFrom == CalibrateExposureFinderMultipleBrightnessExcludeFrom.None ||
_multipleBrightnessExcludeFrom == CalibrateExposureFinderMultipleBrightnessExcludeFrom.Bottom && !isBottomLayer ||
diff --git a/UVtools.Core/Operations/OperationCalibrateGrayscale.cs b/UVtools.Core/Operations/OperationCalibrateGrayscale.cs
index db8dce4..dd9e6b5 100644
--- a/UVtools.Core/Operations/OperationCalibrateGrayscale.cs
+++ b/UVtools.Core/Operations/OperationCalibrateGrayscale.cs
@@ -362,7 +362,7 @@ namespace UVtools.Core.Operations
int innerRadius = Math.Max(100, radius - _innerMargin);
double topLineLength = 0;
- CvInvoke.Circle(layers[0], center, radius, EmguExtensions.WhiteByte, -1, LineType.AntiAlias);
+ CvInvoke.Circle(layers[0], center, radius, EmguExtensions.WhiteColor, -1, LineType.AntiAlias);
layers[1] = layers[0].Clone();
layers[2] = layers[0].Clone();
@@ -414,7 +414,7 @@ namespace UVtools.Core.Operations
{
text = $"{Math.Round(brightness * _normalExposure / byte.MaxValue, 2)}s";
}
- CvInvoke.PutText(layers[2], text, fontPoint, fontFace, fontScale, EmguExtensions.BlackByte, fontThickness, lineType);
+ CvInvoke.PutText(layers[2], text, fontPoint, fontFace, fontScale, EmguExtensions.BlackColor, fontThickness, lineType);
rotatedAngle += AngleStep;
layers[2].Rotate(AngleStep);
}
@@ -426,12 +426,12 @@ namespace UVtools.Core.Operations
var holeRadius = Math.Min(radius, _centerHoleDiameter) / 2;
if (_innerMargin > 0)
{
- CvInvoke.Circle(layers[2], center, holeRadius + _innerMargin, EmguExtensions.WhiteByte, -1, lineType);
+ CvInvoke.Circle(layers[2], center, holeRadius + _innerMargin, EmguExtensions.WhiteColor, -1, lineType);
}
foreach (var layer in layers)
{
- CvInvoke.Circle(layer, center, holeRadius, EmguExtensions.BlackByte, -1, lineType);
+ CvInvoke.Circle(layer, center, holeRadius, EmguExtensions.BlackColor, -1, lineType);
}
}
@@ -439,11 +439,11 @@ namespace UVtools.Core.Operations
fontThickness = 3;
CvInvoke.PutText(layers[0], $"{Microns}um at {_bottomExposure}s/{_normalExposure}s",
new Point(center.X - radius / 2, center.Y + radius / 2 +40),
- fontFace, fontScale, EmguExtensions.BlackByte, fontThickness, lineType, true);
+ fontFace, fontScale, EmguExtensions.BlackColor, fontThickness, lineType, true);
CvInvoke.PutText(layers[0], $"{_startBrightness}-{_endBrightness} S:{_brightnessSteps}",
new Point(center.X - radius / 2, center.Y + radius / 2 - 40),
- fontFace, fontScale, EmguExtensions.BlackByte, fontThickness, lineType, true);
+ fontFace, fontScale, EmguExtensions.BlackColor, fontThickness, lineType, true);
if (_mirrorOutput)
{
@@ -466,8 +466,8 @@ namespace UVtools.Core.Operations
CvInvoke.Line(thumbnail, new Point(xSpacing, ySpacing + 5), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.Line(thumbnail, new Point(thumbnail.Width - xSpacing, 0), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.PutText(thumbnail, "Grayscale Cal.", new Point(xSpacing, ySpacing * 2), fontFace, fontScale, new MCvScalar(0, 255, 255), fontThickness);
- CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
- CvInvoke.PutText(thumbnail, $"Divs:{Divisions} Angle:{AngleStep}", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
+ CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
+ CvInvoke.PutText(thumbnail, $"Divs:{Divisions} Angle:{AngleStep}", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
return thumbnail;
}
diff --git a/UVtools.Core/Operations/OperationCalibrateStressTower.cs b/UVtools.Core/Operations/OperationCalibrateStressTower.cs
index 314b753..f9f5fa2 100644
--- a/UVtools.Core/Operations/OperationCalibrateStressTower.cs
+++ b/UVtools.Core/Operations/OperationCalibrateStressTower.cs
@@ -341,7 +341,7 @@ namespace UVtools.Core.Operations
Parallel.For(0, baseLayers, layerIndex =>
{
int chamferOffset = (int) Math.Max(0, _chamferLayers - layerIndex);
- CvInvoke.Circle(layers[layerIndex], center, (int) baseRadius - chamferOffset, EmguExtensions.WhiteByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.Circle(layers[layerIndex], center, (int) baseRadius - chamferOffset, EmguExtensions.WhiteColor, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
});
@@ -363,11 +363,11 @@ namespace UVtools.Core.Operations
for (uint spiralLayerIndex = (uint) layerIndex; spiralLayerIndex < maxLayer; spiralLayerIndex++)
{
- CvInvoke.Circle(layers[spiralLayerIndex], locationCW, (int)spiralRadius, EmguExtensions.WhiteByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.Circle(layers[spiralLayerIndex], locationCW, (int)spiralRadius, EmguExtensions.WhiteColor, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
if (_spiralDirection == SpiralDirections.Both)
{
spiralAngle = -spiralAngle;
- CvInvoke.Circle(layers[spiralLayerIndex], locationCCW, (int)spiralRadius, EmguExtensions.WhiteByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.Circle(layers[spiralLayerIndex], locationCCW, (int)spiralRadius, EmguExtensions.WhiteColor, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
}
}
}
@@ -378,7 +378,7 @@ namespace UVtools.Core.Operations
Parallel.For(0, ceilLayers, i =>
{
uint layerIndex = (uint)(currrentlayer + i);
- CvInvoke.Circle(layers[layerIndex], center, (int)baseRadius, EmguExtensions.WhiteByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
+ CvInvoke.Circle(layers[layerIndex], center, (int)baseRadius, EmguExtensions.WhiteColor, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected);
});
@@ -404,8 +404,8 @@ namespace UVtools.Core.Operations
CvInvoke.Line(thumbnail, new Point(xSpacing, ySpacing + 5), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.Line(thumbnail, new Point(thumbnail.Width - xSpacing, 0), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.PutText(thumbnail, "Stress Tower", new Point(xSpacing, ySpacing * 2), fontFace, fontScale, new MCvScalar(0, 255, 255), fontThickness);
- CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
- CvInvoke.PutText(thumbnail, $"{_spirals} Spirals @ {_spiralAngleStepPerLayer}deg", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
+ CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
+ CvInvoke.PutText(thumbnail, $"{_spirals} Spirals @ {_spiralAngleStepPerLayer}deg", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
return thumbnail;
}
diff --git a/UVtools.Core/Operations/OperationCalibrateTolerance.cs b/UVtools.Core/Operations/OperationCalibrateTolerance.cs
index 6681186..87f7f03 100644
--- a/UVtools.Core/Operations/OperationCalibrateTolerance.cs
+++ b/UVtools.Core/Operations/OperationCalibrateTolerance.cs
@@ -523,16 +523,16 @@ namespace UVtools.Core.Operations
case Shapes.Circle:
currentX += (int) FemaleDiameterXPixels / 2;
currentY += (int) FemaleDiameterXPixels / 2;
- CvInvoke.Circle(layer, new Point(currentX, currentY), (int) (FemaleDiameterXPixels / 2), EmguExtensions.WhiteByte, -1, lineType);
- CvInvoke.Circle(layer, new Point(currentX, currentY), (int) (FemaleHoleDiameterXPixels / 2), EmguExtensions.BlackByte, -1, lineType);
+ CvInvoke.Circle(layer, new Point(currentX, currentY), (int) (FemaleDiameterXPixels / 2), EmguExtensions.WhiteColor, -1, lineType);
+ CvInvoke.Circle(layer, new Point(currentX, currentY), (int) (FemaleHoleDiameterXPixels / 2), EmguExtensions.BlackColor, -1, lineType);
currentX += (int) FemaleDiameterXPixels / 2 + PartMargin;
break;
case Shapes.Square:
int offsetX = (int) ((FemaleDiameterXPixels - FemaleHoleDiameterXPixels) / 2);
int offsetY = (int) ((FemaleDiameterYPixels - FemaleHoleDiameterYPixels) / 2);
- CvInvoke.Rectangle(layer, new Rectangle(currentX, currentY, (int) FemaleDiameterXPixels, (int) FemaleDiameterXPixels), EmguExtensions.WhiteByte, -1, lineType);
- CvInvoke.Rectangle(layer, new Rectangle(currentX + offsetX, currentY + offsetY, (int) FemaleHoleDiameterXPixels, (int) FemaleHoleDiameterYPixels), EmguExtensions.BlackByte, -1, lineType);
+ CvInvoke.Rectangle(layer, new Rectangle(currentX, currentY, (int) FemaleDiameterXPixels, (int) FemaleDiameterXPixels), EmguExtensions.WhiteColor, -1, lineType);
+ CvInvoke.Rectangle(layer, new Rectangle(currentX + offsetX, currentY + offsetY, (int) FemaleHoleDiameterXPixels, (int) FemaleHoleDiameterYPixels), EmguExtensions.BlackColor, -1, lineType);
currentX += (int)FemaleDiameterXPixels + PartMargin;
currentY = startY + (int) FemaleDiameterYPixels / 2;
break;
@@ -567,18 +567,18 @@ namespace UVtools.Core.Operations
switch (Shape)
{
case Shapes.Circle:
- CvInvoke.Circle(layer, new Point(currentX + halfDiameterX, currentY + halfDiameterY), (int)(FemaleDiameterXPixels / 2), EmguExtensions.WhiteByte, -1, lineType);
- CvInvoke.Circle(layer, new Point(currentX + halfDiameterX, currentY + halfDiameterY), (int)(FemaleHoleDiameterXPixels / 2), EmguExtensions.BlackByte, -1, lineType);
- CvInvoke.Circle(layer, new Point(currentX + halfDiameterX, currentY + halfDiameterY), xPixels / 2, EmguExtensions.WhiteByte, -1, lineType);
+ CvInvoke.Circle(layer, new Point(currentX + halfDiameterX, currentY + halfDiameterY), (int)(FemaleDiameterXPixels / 2), EmguExtensions.WhiteColor, -1, lineType);
+ CvInvoke.Circle(layer, new Point(currentX + halfDiameterX, currentY + halfDiameterY), (int)(FemaleHoleDiameterXPixels / 2), EmguExtensions.BlackColor, -1, lineType);
+ CvInvoke.Circle(layer, new Point(currentX + halfDiameterX, currentY + halfDiameterY), xPixels / 2, EmguExtensions.WhiteColor, -1, lineType);
break;
case Shapes.Square:
int offsetX = (int)((FemaleDiameterXPixels - FemaleHoleDiameterXPixels) / 2);
int offsetY = (int)((FemaleDiameterYPixels - FemaleHoleDiameterYPixels) / 2);
- CvInvoke.Rectangle(layer, new Rectangle(currentX, currentY, (int)FemaleDiameterXPixels, (int)FemaleDiameterXPixels), EmguExtensions.WhiteByte, -1, lineType);
- CvInvoke.Rectangle(layer, new Rectangle(currentX + offsetX, currentY + offsetY, (int)FemaleHoleDiameterXPixels, (int)FemaleHoleDiameterYPixels), EmguExtensions.BlackByte, -1, lineType);
+ CvInvoke.Rectangle(layer, new Rectangle(currentX, currentY, (int)FemaleDiameterXPixels, (int)FemaleDiameterXPixels), EmguExtensions.WhiteColor, -1, lineType);
+ CvInvoke.Rectangle(layer, new Rectangle(currentX + offsetX, currentY + offsetY, (int)FemaleHoleDiameterXPixels, (int)FemaleHoleDiameterYPixels), EmguExtensions.BlackColor, -1, lineType);
offsetX = (int)((FemaleDiameterXPixels - xPixels) / 2);
offsetY = (int)((FemaleDiameterYPixels - yPixels) / 2);
- CvInvoke.Rectangle(layer, new Rectangle(currentX + offsetX, currentY + offsetY, xPixels, yPixels), EmguExtensions.WhiteByte, -1, lineType);
+ CvInvoke.Rectangle(layer, new Rectangle(currentX + offsetX, currentY + offsetY, xPixels, yPixels), EmguExtensions.WhiteColor, -1, lineType);
break;
}
@@ -604,10 +604,10 @@ namespace UVtools.Core.Operations
switch (Shape)
{
case Shapes.Circle:
- CvInvoke.Circle(layer, new Point(currentX + halfDiameterX, currentY + halfDiameterY), halfDiameterX, EmguExtensions.WhiteByte, -1, lineType);
+ CvInvoke.Circle(layer, new Point(currentX + halfDiameterX, currentY + halfDiameterY), halfDiameterX, EmguExtensions.WhiteColor, -1, lineType);
break;
case Shapes.Square:
- CvInvoke.Rectangle(layer, new Rectangle(currentX, currentY, xPixels, yPixels), EmguExtensions.WhiteByte, -1, lineType);
+ CvInvoke.Rectangle(layer, new Rectangle(currentX, currentY, xPixels, yPixels), EmguExtensions.WhiteColor, -1, lineType);
break;
}
@@ -680,7 +680,7 @@ namespace UVtools.Core.Operations
{
foreach (var keyValuePair in pointTextList)
{
- CvInvoke.PutText(layers[layerIndex], keyValuePair.Value, keyValuePair.Key, fontFace, fontScale, EmguExtensions.BlackByte, fontThickness, lineType);
+ CvInvoke.PutText(layers[layerIndex], keyValuePair.Value, keyValuePair.Key, fontFace, fontScale, EmguExtensions.BlackColor, fontThickness, lineType);
}
});
@@ -705,8 +705,8 @@ namespace UVtools.Core.Operations
CvInvoke.Line(thumbnail, new Point(xSpacing, ySpacing + 5), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.Line(thumbnail, new Point(thumbnail.Width - xSpacing, 0), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.PutText(thumbnail, "Tolerance Cal.", new Point(xSpacing, ySpacing * 2), fontFace, fontScale, new MCvScalar(0, 255, 255), fontThickness);
- CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
- CvInvoke.PutText(thumbnail, $"Objects: {OutputObjects}", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
+ CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
+ CvInvoke.PutText(thumbnail, $"Objects: {OutputObjects}", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
/*thumbnail.SetTo(EmguExtensions.Black3Byte);
diff --git a/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs b/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs
index 8784f5b..00d78e3 100644
--- a/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs
+++ b/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs
@@ -49,6 +49,7 @@ namespace UVtools.Core.Operations
private bool _outputBLObject;
private bool _outputBCObject;
private bool _outputBRObject;
+ private decimal _drainHoleArea = 3;
#endregion
@@ -252,6 +253,12 @@ namespace UVtools.Core.Operations
public uint LayerCount => (uint) Math.Floor(ZSize / LayerHeight);
+ public decimal DrainHoleArea
+ {
+ get => _drainHoleArea;
+ set => RaiseAndSetIfChanged(ref _drainHoleArea, value);
+ }
+
public bool CenterHoleRelief
{
get => _centerHoleRelief;
@@ -602,7 +609,7 @@ namespace UVtools.Core.Operations
public Mat[] GetLayers()
{
- var layers = new Mat[2];
+ var layers = new Mat[3];
for (byte i = 0; i < layers.Length; i++)
{
layers[i] = EmguExtensions.InitMat(SlicerFile.Resolution);
@@ -620,6 +627,9 @@ namespace UVtools.Core.Operations
const double fontScale = 1.3;
const byte fontThickness = 3;
+ var xPixels = XPixels;
+ var yPixels = YPixels;
+
for (int y = 0; y < 3; y++)
{
switch (y)
@@ -629,11 +639,11 @@ namespace UVtools.Core.Operations
positionYStr = "T";
break;
case 1:
- currentY = (int)(SlicerFile.Resolution.Height / 2 - YPixels / 2);
+ currentY = (int)(SlicerFile.Resolution.Height / 2 - yPixels / 2);
positionYStr = "M";
break;
case 2:
- currentY = (int)(SlicerFile.Resolution.Height - YPixels - _topBottomMargin);
+ currentY = (int)(SlicerFile.Resolution.Height - yPixels - _topBottomMargin);
positionYStr = "B";
break;
}
@@ -646,11 +656,11 @@ namespace UVtools.Core.Operations
positionStr = $"{positionYStr}L";
break;
case 1:
- currentX = (int)(SlicerFile.Resolution.Width / 2 - XPixels / 2);
+ currentX = (int)(SlicerFile.Resolution.Width / 2 - xPixels / 2);
positionStr = $"{positionYStr}C";
break;
case 2:
- currentX = (int)(SlicerFile.Resolution.Width - XPixels - _leftRightMargin);
+ currentX = (int)(SlicerFile.Resolution.Width - xPixels - _leftRightMargin);
positionStr = $"{positionYStr}R";
break;
}
@@ -669,31 +679,39 @@ namespace UVtools.Core.Operations
if(y == 2 && x == 2 && !_outputBRObject) continue;
var layer = layers[i];
CvInvoke.Rectangle(layer,
- new Rectangle(currentX, currentY, (int) XPixels, (int) YPixels),
- EmguExtensions.WhiteByte, -1);
+ new Rectangle(currentX, currentY, (int)xPixels, (int) yPixels),
+ EmguExtensions.WhiteColor, -1);
CvInvoke.PutText(layer, positionStr,
new Point(currentX + fontStartX, currentY + fontStartY), fontFace, fontScale,
- EmguExtensions.BlackByte, fontThickness);
+ EmguExtensions.BlackColor, fontThickness);
CvInvoke.PutText(layer, $"{XSize},{YSize},{ZSize}",
- new Point(currentX + fontStartX, (int) (currentY + YPixels - fontStartY + 25)), fontFace, fontScale,
- EmguExtensions.BlackByte, fontThickness);
+ new Point(currentX + fontStartX, (int) (currentY + yPixels - fontStartY + 25)), fontFace, fontScale,
+ EmguExtensions.BlackColor, fontThickness);
if (CenterHoleRelief)
{
CvInvoke.Circle(layer,
- new Point((int) (currentX + XPixels / 2), (int) (currentY + YPixels / 2)),
- (int) (Math.Min(XPixels, YPixels) / 4),
- EmguExtensions.Black3Byte, -1);
+ new Point((int) (currentX + xPixels / 2), (int) (currentY + yPixels / 2)),
+ (int) (Math.Min(xPixels, yPixels) / 4),
+ EmguExtensions.BlackColor, -1);
}
- if (_hollowModel && i != 0 && _wallThickness > 0)
+ if (_hollowModel && i > 0 && _wallThickness > 0)
{
- Size rectSize = new((int) (XPixels - WallThicknessXPixels * 2), (int) (YPixels - WallThicknessYPixels * 2));
+ Size rectSize = new((int) (xPixels - WallThicknessXPixels * 2), (int) (yPixels - WallThicknessYPixels * 2));
Point rectLocation = new((int) (currentX + WallThicknessXPixels), (int) (currentY + WallThicknessYPixels));
CvInvoke.Rectangle(layers[i], new Rectangle(rectLocation, rectSize),
- EmguExtensions.Black3Byte, -1);
+ EmguExtensions.BlackColor, -1);
+ }
+
+ if (i == 2 && _drainHoleArea > 0)
+ {
+ Size rectSize = new((int)xPixels, (int)(Yppmm * _drainHoleArea));
+ Point rectLocation = new(currentX, (int)(currentY + xPixels / 2 - rectSize.Height / 2));
+ CvInvoke.Rectangle(layers[i], new Rectangle(rectLocation, rectSize),
+ EmguExtensions.BlackColor, -1);
}
}
}
@@ -720,8 +738,8 @@ namespace UVtools.Core.Operations
CvInvoke.Line(thumbnail, new Point(xSpacing, ySpacing + 5), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.Line(thumbnail, new Point(thumbnail.Width - xSpacing, 0), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.PutText(thumbnail, "XYZ Accuracy Cal.", new Point(xSpacing, ySpacing * 2), fontFace, fontScale, new MCvScalar(0, 255, 255), fontThickness);
- CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
- CvInvoke.PutText(thumbnail, $"{XSize} x {YSize} x {ZSize} mm", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
+ CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
+ CvInvoke.PutText(thumbnail, $"{XSize} x {YSize} x {ZSize} mm", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
/*thumbnail.SetTo(EmguExtensions.Black3Byte);
@@ -752,10 +770,18 @@ namespace UVtools.Core.Operations
{
IsModified = true
};
+ var ventLayer = new Layer(0, layers[2], SlicerFile.LayerManager)
+ {
+ IsModified = true
+ };
+
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
- newLayers[layerIndex] = SlicerFile.GetInitialLayerValueOrNormal(layerIndex, bottomLayer.Clone(), layer.Clone());
+ newLayers[layerIndex] = SlicerFile.GetInitialLayerValueOrNormal(layerIndex, bottomLayer.Clone(),
+ (_hollowModel || _centerHoleRelief) && _drainHoleArea > 0 && layerIndex <= _bottomLayers + (int)Math.Floor(_drainHoleArea / _layerHeight)
+ ? ventLayer.Clone() : layer.Clone());
+
progress++;
}
diff --git a/UVtools.Core/Operations/OperationLayerExportHeatMap.cs b/UVtools.Core/Operations/OperationLayerExportHeatMap.cs
index 2c0bccb..3817514 100644
--- a/UVtools.Core/Operations/OperationLayerExportHeatMap.cs
+++ b/UVtools.Core/Operations/OperationLayerExportHeatMap.cs
@@ -28,10 +28,10 @@ namespace UVtools.Core.Operations
#region Overrides
public override bool CanHaveProfiles => false;
- public override string Title => "Export layers to heat map.";
+ public override string Title => "Export layers to heat map";
public override string Description =>
- "Export a layer range to a grayscale heat map image that represents the median of the mass in the Z depth/perception\n" +
+ "Export a layer range to a grayscale heat map image that represents the median of the mass in the Z depth/perception.\n" +
"The pixel brightness/intensity shows where the most mass are concentrated.";
public override string ConfirmationText =>
diff --git a/UVtools.Core/Operations/OperationLayerExportSkeleton.cs b/UVtools.Core/Operations/OperationLayerExportSkeleton.cs
new file mode 100644
index 0000000..0fd56d0
--- /dev/null
+++ b/UVtools.Core/Operations/OperationLayerExportSkeleton.cs
@@ -0,0 +1,139 @@
+/*
+ * 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.Threading.Tasks;
+using Emgu.CV;
+using UVtools.Core.Extensions;
+using UVtools.Core.FileFormats;
+
+namespace UVtools.Core.Operations
+{
+ [Serializable]
+ public sealed class OperationLayerExportSkeleton : Operation
+ {
+ #region Members
+ private string _filePath;
+ private bool _cropByRoi = true;
+
+ #endregion
+
+ #region Overrides
+
+ public override bool CanHaveProfiles => false;
+ public override string Title => "Export layers to skeleton";
+
+ public override string Description =>
+ "Export a layer range to a skeletonized image that is the sum of each layer skeleton.";
+
+ public override string ConfirmationText =>
+ $"skeletonize from layers {LayerIndexStart} through {LayerIndexEnd}?";
+
+ public override string ProgressTitle =>
+ $"Skeletonizing from layers {LayerIndexStart} through {LayerIndexEnd}";
+
+ public override string ProgressAction => "Skeletonized layers";
+
+ public override string ToString()
+ {
+ var result = $"[Crop by ROI: {_cropByRoi}]" +
+ LayerRangeString;
+ if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
+ return result;
+ }
+
+ #endregion
+
+ #region Properties
+
+ public string FilePath
+ {
+ get => _filePath;
+ set => RaiseAndSetIfChanged(ref _filePath, value);
+ }
+
+ public bool CropByROI
+ {
+ get => _cropByRoi;
+ set => RaiseAndSetIfChanged(ref _cropByRoi, value);
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public OperationLayerExportSkeleton()
+ { }
+
+ public OperationLayerExportSkeleton(FileFormat slicerFile) : base(slicerFile)
+ {
+ _filePath = SlicerFile.FileFullPath + ".skeleton.png";
+ }
+
+ #endregion
+
+ #region Methods
+
+ protected override bool ExecuteInternally(OperationProgress progress)
+ {
+ using var skeletonSum = EmguExtensions.InitMat(SlicerFile.Resolution);
+ var skeletonSumRoi = GetRoiOrDefault(skeletonSum);
+ using var mask = GetMask(skeletonSum);
+
+
+ Parallel.For(LayerIndexStart, LayerIndexEnd+1, layerIndex =>
+ {
+ if (progress.Token.IsCancellationRequested) return;
+
+ using var mat = SlicerFile[layerIndex].LayerMat;
+ var matRoi = GetRoiOrDefault(mat);
+ using var skeletonRoi = matRoi.Skeletonize();
+ lock (progress.Mutex)
+ {
+ CvInvoke.Add(skeletonSumRoi, skeletonRoi, skeletonSumRoi, mask);
+ progress++;
+ }
+ });
+
+ if (!progress.Token.IsCancellationRequested)
+ {
+ if (_cropByRoi && HaveROI)
+ {
+ skeletonSumRoi.Save(_filePath);
+ }
+ else
+ {
+ skeletonSum.Save(_filePath);
+ }
+ }
+
+ return !progress.Token.IsCancellationRequested;
+ }
+
+ #endregion
+
+ #region Equality
+
+ private bool Equals(OperationLayerExportSkeleton other)
+ {
+ return _filePath == other._filePath && _cropByRoi == other._cropByRoi;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return ReferenceEquals(this, obj) || obj is OperationLayerExportSkeleton other && Equals(other);
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(_filePath, _cropByRoi);
+ }
+
+ #endregion
+ }
+}
diff --git a/UVtools.Core/Operations/OperationPixelArithmetic.cs b/UVtools.Core/Operations/OperationPixelArithmetic.cs
index 427d7be..ff1ca0e 100644
--- a/UVtools.Core/Operations/OperationPixelArithmetic.cs
+++ b/UVtools.Core/Operations/OperationPixelArithmetic.cs
@@ -295,13 +295,13 @@ namespace UVtools.Core.Operations
case PixelArithmeticOperators.KeepRegion:
{
using var targetClone = target.Clone();
- original.SetTo(EmguExtensions.BlackByte);
- mat.SetTo(EmguExtensions.BlackByte);
+ original.SetTo(EmguExtensions.BlackColor);
+ mat.SetTo(EmguExtensions.BlackColor);
targetClone.CopyTo(target);
break;
}
case PixelArithmeticOperators.DiscardRegion:
- target.SetTo(EmguExtensions.BlackByte);
+ target.SetTo(EmguExtensions.BlackColor);
break;
default:
throw new NotImplementedException();
diff --git a/UVtools.Core/Operations/OperationRepairLayers.cs b/UVtools.Core/Operations/OperationRepairLayers.cs
index 2ba34f0..3e9c29d 100644
--- a/UVtools.Core/Operations/OperationRepairLayers.cs
+++ b/UVtools.Core/Operations/OperationRepairLayers.cs
@@ -255,7 +255,7 @@ namespace UVtools.Core.Operations
CvInvoke.DrawContours(image,
vec,
-1,
- EmguExtensions.WhiteByte,
+ EmguExtensions.WhiteColor,
-1);
}
}
diff --git a/UVtools.Core/Operations/OperationSolidify.cs b/UVtools.Core/Operations/OperationSolidify.cs
index ea5e389..0990182 100644
--- a/UVtools.Core/Operations/OperationSolidify.cs
+++ b/UVtools.Core/Operations/OperationSolidify.cs
@@ -127,7 +127,7 @@ namespace UVtools.Core.Operations
}
- CvInvoke.DrawContours(target, contours, i, EmguExtensions.WhiteByte, -1);
+ CvInvoke.DrawContours(target, contours, i, EmguExtensions.WhiteColor, -1);
}
ApplyMask(original, target);
diff --git a/UVtools.Core/PixelEditor/PixelText.cs b/UVtools.Core/PixelEditor/PixelText.cs
index beab7e6..5a420a9 100644
--- a/UVtools.Core/PixelEditor/PixelText.cs
+++ b/UVtools.Core/PixelEditor/PixelText.cs
@@ -19,6 +19,7 @@ namespace UVtools.Core.PixelEditor
private ushort _thickness = 1;
private string _text;
private bool _mirror;
+ private double _angle;
private byte _removePixelBrightness;
public override PixelOperationType OperationType => PixelOperationType.Text;
@@ -54,6 +55,12 @@ namespace UVtools.Core.PixelEditor
set => RaiseAndSetIfChanged(ref _mirror, value);
}
+ public double Angle
+ {
+ get => _angle;
+ set => RaiseAndSetIfChanged(ref _angle, value);
+ }
+
public byte RemovePixelBrightness
{
get => _removePixelBrightness;
@@ -74,13 +81,14 @@ namespace UVtools.Core.PixelEditor
public PixelText(){}
- public PixelText(uint layerIndex, Point location, LineType lineType, FontFace font, double fontScale, ushort thickness, string text, bool mirror, byte removePixelBrightness, byte pixelBrightness, bool isAdd) : base(layerIndex, location, lineType, pixelBrightness)
+ public PixelText(uint layerIndex, Point location, LineType lineType, FontFace font, double fontScale, ushort thickness, string text, bool mirror, double angle, byte removePixelBrightness, byte pixelBrightness, bool isAdd) : base(layerIndex, location, lineType, pixelBrightness)
{
_font = font;
_fontScale = fontScale;
_thickness = thickness;
_text = text;
_mirror = mirror;
+ _angle = angle;
IsAdd = isAdd;
_removePixelBrightness = removePixelBrightness;
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index 4a97b3d..d0f18c5 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -10,7 +10,7 @@
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
- <Version>2.13.0</Version>
+ <Version>2.13.1</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
diff --git a/UVtools.ScriptSample/ScriptTestPerLayerSettingsSample.cs b/UVtools.ScriptSample/ScriptTestPerLayerSettingsSample.cs
index 70e283c..5e1dbde 100644
--- a/UVtools.ScriptSample/ScriptTestPerLayerSettingsSample.cs
+++ b/UVtools.ScriptSample/ScriptTestPerLayerSettingsSample.cs
@@ -89,27 +89,27 @@ namespace UVtools.ScriptSample
// Do the left eye
x = xCenter - noseThickness/2 - faceSpacing - eyeDiameter/2;
y = faceSpacing;
- CvInvoke.Circle(mats[0], new Point(x, y), eyeDiameter/2, EmguExtensions.WhiteByte, -1, lineType);
- CvInvoke.Circle(mats[1], new Point(x, y), eyeDiameter/2, EmguExtensions.WhiteByte, -1, lineType);
+ CvInvoke.Circle(mats[0], new Point(x, y), eyeDiameter/2, EmguExtensions.WhiteColor, -1, lineType);
+ CvInvoke.Circle(mats[1], new Point(x, y), eyeDiameter/2, EmguExtensions.WhiteColor, -1, lineType);
Progress++;
// Do the right eye, the mirror of left...
x = (int)(SlicerFile.ResolutionX - x);
- CvInvoke.Circle(mats[0], new Point(x, y), eyeDiameter / 2, EmguExtensions.WhiteByte, -1, lineType);
- CvInvoke.Circle(mats[3], new Point(x, y), eyeDiameter / 2, EmguExtensions.WhiteByte, -1, lineType);
+ CvInvoke.Circle(mats[0], new Point(x, y), eyeDiameter / 2, EmguExtensions.WhiteColor, -1, lineType);
+ CvInvoke.Circle(mats[3], new Point(x, y), eyeDiameter / 2, EmguExtensions.WhiteColor, -1, lineType);
Progress++;
// Do the noose
x = xCenter - noseThickness / 2;
- CvInvoke.Rectangle(mats[0], new Rectangle(x, y, noseThickness, noseHeight), EmguExtensions.WhiteByte, -1, lineType);
- CvInvoke.Rectangle(mats[2], new Rectangle(x, y, noseThickness, noseHeight), EmguExtensions.WhiteByte, -1, lineType);
+ CvInvoke.Rectangle(mats[0], new Rectangle(x, y, noseThickness, noseHeight), EmguExtensions.WhiteColor, -1, lineType);
+ CvInvoke.Rectangle(mats[2], new Rectangle(x, y, noseThickness, noseHeight), EmguExtensions.WhiteColor, -1, lineType);
Progress++;
// Do the mouth
x = xCenter;
y += noseHeight + faceSpacing;
- CvInvoke.Ellipse(mats[0], new Point(x, y), new Size(eyeDiameter+faceSpacing+noseThickness/2, mouthHeight), 0, 0, 180, EmguExtensions.WhiteByte, -1, lineType);
- CvInvoke.Ellipse(mats[4], new Point(x, y), new Size(eyeDiameter+faceSpacing+noseThickness/2, mouthHeight), 0, 0, 180, EmguExtensions.WhiteByte, -1, lineType);
+ CvInvoke.Ellipse(mats[0], new Point(x, y), new Size(eyeDiameter+faceSpacing+noseThickness/2, mouthHeight), 0, 0, 180, EmguExtensions.WhiteColor, -1, lineType);
+ CvInvoke.Ellipse(mats[4], new Point(x, y), new Size(eyeDiameter+faceSpacing+noseThickness/2, mouthHeight), 0, 0, 180, EmguExtensions.WhiteColor, -1, lineType);
SlicerFile.LayerManager.AllocateAndSetFromMat(mats); // Replace layers and rebuild properties
diff --git a/UVtools.ScriptSample/ScriptVATClean.cs b/UVtools.ScriptSample/ScriptVATClean.cs
index aefee4c..bd769b5 100644
--- a/UVtools.ScriptSample/ScriptVATClean.cs
+++ b/UVtools.ScriptSample/ScriptVATClean.cs
@@ -91,7 +91,7 @@ namespace UVtools.ScriptSample
CvInvoke.Rectangle(mat, new Rectangle(
new Point(InputInset.Value, InputInset.Value),
new Size((int) (SlicerFile.ResolutionX - InputInset.Value*2)-1, (int) (SlicerFile.ResolutionY - InputInset.Value*2)-1)
- ), EmguExtensions.WhiteByte, -1, LineType.FourConnected);
+ ), EmguExtensions.WhiteColor, -1, LineType.FourConnected);
layer.LayerMat = mat;
SlicerFile.SuppressRebuildPropertiesWork(() =>
@@ -132,8 +132,8 @@ namespace UVtools.ScriptSample
CvInvoke.Line(thumbnail, new Point(xSpacing, ySpacing + 5), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.Line(thumbnail, new Point(thumbnail.Width - xSpacing, 0), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3);
CvInvoke.PutText(thumbnail, "VAT Clean Utility", new Point(xSpacing, ySpacing * 2), fontFace, fontScale, new MCvScalar(0, 255, 255), fontThickness);
- CvInvoke.PutText(thumbnail, $"Exposure time: {SlicerFile.ExposureTime}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
- CvInvoke.PutText(thumbnail, $"Use the spatula in!", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness);
+ CvInvoke.PutText(thumbnail, $"Exposure time: {SlicerFile.ExposureTime}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
+ CvInvoke.PutText(thumbnail, $"Use the spatula in!", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.WhiteColor, fontThickness);
return thumbnail;
}
diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml b/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml
index 97d2126..d95b166 100644
--- a/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml
+++ b/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml
@@ -200,16 +200,45 @@
VerticalAlignment="Center"
Text="px"/>
- <CheckBox Grid.Row="12" Grid.Column="2" Grid.ColumnSpan="2"
- Content="Hollow model"
- IsChecked="{Binding Operation.HollowModel}"/>
+ <TextBlock Grid.Row="12" Grid.Column="0"
+ VerticalAlignment="Center"
+ Text="Drain hole diameter:">
+ <TextBlock.IsEnabled>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="Operation.HollowModel"/>
+ <Binding Path="Operation.CenterHoleRelief"/>
+ </MultiBinding>
+ </TextBlock.IsEnabled>
+ </TextBlock>
+ <NumericUpDown Grid.Row="12" Grid.Column="2"
+ Increment="0.5"
+ Minimum="0"
+ Maximum="100"
+ FormatString="F2"
+ Value="{Binding Operation.DrainHoleArea}">
+ <NumericUpDown.IsEnabled>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="Operation.HollowModel"/>
+ <Binding Path="Operation.CenterHoleRelief"/>
+ </MultiBinding>
+ </NumericUpDown.IsEnabled>
+ </NumericUpDown>
+ <TextBlock Grid.Row="12" Grid.Column="4"
+ VerticalAlignment="Center"
+ Text="mm³">
+ <TextBlock.IsEnabled>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="Operation.HollowModel"/>
+ <Binding Path="Operation.CenterHoleRelief"/>
+ </MultiBinding>
+ </TextBlock.IsEnabled>
+ </TextBlock>
<TextBlock Grid.Row="12" Grid.Column="6" Grid.ColumnSpan="3"
Text="Wall thickness:"
VerticalAlignment="Center"
IsEnabled="{Binding Operation.HollowModel}"/>
<NumericUpDown Grid.Row="12" Grid.Column="8"
-
Increment="0.5"
Minimum="0"
Maximum="100"
@@ -221,16 +250,21 @@
IsEnabled="{Binding Operation.HollowModel}"
Text="mm"/>
+ <CheckBox Grid.Row="14" Grid.Column="0"
+ Grid.ColumnSpan="2"
+ ToolTip.Tip="Most of the printers requires a mirror output to print with the correct orientation"
+ IsChecked="{Binding Operation.MirrorOutput}"
+ Content="Mirror output" />
+
<CheckBox Grid.Row="14" Grid.Column="2" Grid.ColumnSpan="4"
VerticalAlignment="Center"
IsChecked="{Binding Operation.CenterHoleRelief}"
- Content="Relief with a center hole"/>
+ Content="Relief base with a center hole"/>
- <CheckBox Grid.Row="14" Grid.Column="8"
- Grid.ColumnSpan="3"
- ToolTip.Tip="Most of the printers requires a mirror output to print with the correct orientation"
- IsChecked="{Binding Operation.MirrorOutput}"
- Content="Mirror output" />
+
+ <CheckBox Grid.Row="14" Grid.Column="8" Grid.ColumnSpan="3"
+ Content="Hollow model"
+ IsChecked="{Binding Operation.HollowModel}"/>
<TextBlock Grid.Row="16" Grid.Column="0"
VerticalAlignment="Center"
diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml.cs b/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml.cs
index 04f256e..c3ded15 100644
--- a/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml.cs
+++ b/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml.cs
@@ -62,7 +62,7 @@ namespace UVtools.WPF.Controls.Calibrators
{
_timer.Stop();
_timer.Start();
- if (e.PropertyName == nameof(Operation.ScaleXFactor) || e.PropertyName == nameof(Operation.ScaleYFactor))
+ if (e.PropertyName is nameof(Operation.ScaleXFactor) or nameof(Operation.ScaleYFactor))
{
RaisePropertyChanged(nameof(IsProfileAddEnabled));
return;
diff --git a/UVtools.WPF/Controls/Tools/ToolLayerExportSkeletonControl.axaml b/UVtools.WPF/Controls/Tools/ToolLayerExportSkeletonControl.axaml
new file mode 100644
index 0000000..df056b9
--- /dev/null
+++ b/UVtools.WPF/Controls/Tools/ToolLayerExportSkeletonControl.axaml
@@ -0,0 +1,30 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+ x:Class="UVtools.WPF.Controls.Tools.ToolLayerExportSkeletonControl">
+ <StackPanel Spacing="10">
+
+ <StackPanel Orientation="Horizontal" Spacing="5">
+ <TextBox
+ Watermark="Output filepath"
+ UseFloatingWatermark="True"
+ VerticalAlignment="Center"
+ IsReadOnly="True"
+ Width="500"
+ Text="{Binding Operation.FilePath}"/>
+ <Button
+ VerticalAlignment="Stretch"
+ Command="{Binding ChooseFilePath}">
+ <Image Source="/Assets/Icons/open-16x16.png"/>
+ </Button>
+ </StackPanel>
+
+ <CheckBox
+ Content="Crop image by selected ROI"
+ IsVisible="{Binding ParentWindow.IsROIVisible}"
+ IsChecked="{Binding Operation.CropByROI}"/>
+
+ </StackPanel>
+</UserControl>
diff --git a/UVtools.WPF/Controls/Tools/ToolLayerExportSkeletonControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolLayerExportSkeletonControl.axaml.cs
new file mode 100644
index 0000000..02091f4
--- /dev/null
+++ b/UVtools.WPF/Controls/Tools/ToolLayerExportSkeletonControl.axaml.cs
@@ -0,0 +1,36 @@
+using System.IO;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using UVtools.Core.Operations;
+
+namespace UVtools.WPF.Controls.Tools
+{
+ public partial class ToolLayerExportSkeletonControl : ToolControl
+ {
+ public OperationLayerExportSkeleton Operation => BaseOperation as OperationLayerExportSkeleton;
+ public ToolLayerExportSkeletonControl()
+ {
+ InitializeComponent();
+ BaseOperation = new OperationLayerExportSkeleton(SlicerFile);
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public async void ChooseFilePath()
+ {
+ var dialog = new SaveFileDialog
+ {
+ Filters = Helpers.ImagesFullFileFilter,
+ InitialFileName = Path.GetFileName(SlicerFile.FileFullPath) + ".skeleton.png",
+ Directory = Path.GetDirectoryName(SlicerFile.FileFullPath),
+ };
+ var file = await dialog.ShowAsync(ParentWindow);
+ if (string.IsNullOrWhiteSpace(file)) return;
+ Operation.FilePath = file;
+ }
+ }
+}
diff --git a/UVtools.WPF/MainWindow.LayerPreview.cs b/UVtools.WPF/MainWindow.LayerPreview.cs
index 49ed2d8..f781800 100644
--- a/UVtools.WPF/MainWindow.LayerPreview.cs
+++ b/UVtools.WPF/MainWindow.LayerPreview.cs
@@ -74,6 +74,8 @@ namespace UVtools.WPF
private bool _showLayerOutlineLayerBoundary;
private bool _showLayerOutlineHollowAreas;
private bool _showLayerOutlineEdgeDetection;
+ private bool _showLayerOutlineSkeletonize;
+
private bool _isTooltipOverlayVisible;
private string _tooltipOverlayText;
@@ -379,6 +381,16 @@ namespace UVtools.WPF
}
}
+ public bool ShowLayerOutlineSkeletonize
+ {
+ get => _showLayerOutlineSkeletonize;
+ set
+ {
+ if (!RaiseAndSetIfChanged(ref _showLayerOutlineSkeletonize, value)) return;
+ ShowLayer();
+ }
+ }
+
public bool IsPixelEditorActive
{
get => _isPixelEditorActive;
@@ -693,7 +705,12 @@ namespace UVtools.WPF
{
using var canny = new Mat();
CvInvoke.Canny(LayerCache.Image, canny, 80, 40, 3, true);
- CvInvoke.CvtColor(canny, LayerCache.ImageBgr, ColorConversion.Gray2Bgra);
+ CvInvoke.CvtColor(canny, LayerCache.ImageBgr, ColorConversion.Gray2Bgr);
+ }
+ else if (_showLayerOutlineSkeletonize)
+ {
+ using var skeletonize = LayerCache.Image.Skeletonize();
+ CvInvoke.CvtColor(skeletonize, LayerCache.ImageBgr, ColorConversion.Gray2Bgr);
}
else if (_showLayerImageDifference)
{
@@ -1000,9 +1017,14 @@ namespace UVtools.WPF
? Settings.PixelEditor.RemovePixelHighlightColor
: Settings.PixelEditor.RemovePixelColor);
- CvInvoke.PutText(LayerCache.ImageBgr, operationText.Text, operationText.Location,
+
+
+ /*CvInvoke.PutText(LayerCache.ImageBgr, operationText.Text, operationText.Location,
operationText.Font, operationText.FontScale, new MCvScalar(color.B, color.G, color.R),
- operationText.Thickness, operationText.LineType, operationText.Mirror);
+ operationText.Thickness, operationText.LineType, operationText.Mirror);*/
+ LayerCache.ImageBgr.PutTextRotated(operationText.Text, operationText.Location,
+ operationText.Font, operationText.FontScale, new MCvScalar(color.B, color.G, color.R),
+ operationText.Thickness, operationText.LineType, operationText.Mirror, operationText.Angle);
}
else if (operation.OperationType == PixelOperation.PixelOperationType.Eraser)
{
@@ -1876,12 +1898,17 @@ namespace UVtools.WPF
int baseLine = 0;
var size = CvInvoke.GetTextSize(text, DrawingPixelText.Font, DrawingPixelText.FontScale, DrawingPixelText.Thickness, ref baseLine);
- cursor = EmguExtensions.InitMat(new Size(size.Width * 2, size.Height * 2), 4);
+ //var rotatedSize = size.Rotate(DrawingPixelText.Angle);
+ //Point point = (rotatedSize.Inflate(rotatedSize)).Rotate(DrawingPixelText.Angle, rotatedSize.ToPoint());
+ cursor = EmguExtensions.InitMat(size.Inflate(), 4);
//CvInvoke.Rectangle(cursor, new Rectangle(Point.Empty, size), _pixelEditorCursorColor, -1, DrawingPixelText.LineType);
//_pixelEditorCursorColor.V3 = 255;
//CvInvoke.Rectangle(cursor, new Rectangle(new Point(size.Width, 0), size), _pixelEditorCursorColor, 1, DrawingPixelText.LineType);
- CvInvoke.PutText(cursor, text, new Point(size.Width, size.Height), DrawingPixelText.Font, DrawingPixelText.FontScale, _pixelEditorCursorColor, DrawingPixelText.Thickness, DrawingPixelText.LineType, DrawingPixelText.Mirror);
+ CvInvoke.PutText(cursor, text, size.ToPoint(), DrawingPixelText.Font, DrawingPixelText.FontScale, _pixelEditorCursorColor, DrawingPixelText.Thickness, DrawingPixelText.LineType, DrawingPixelText.Mirror);
+ cursor.RotateAdjustBounds(DrawingPixelText.Angle);
+ //cursor.Rotate(DrawingPixelText.Angle);
+ //cursor.PutTextRotated(text, cursor.Size.ToPoint().Half(), DrawingPixelText.Font, DrawingPixelText.FontScale, _pixelEditorCursorColor, DrawingPixelText.Thickness, DrawingPixelText.LineType, DrawingPixelText.Mirror, DrawingPixelText.Angle);
if (_showLayerImageFlipped)
{
var flipType = FlipType.None;
diff --git a/UVtools.WPF/MainWindow.PixelEditor.cs b/UVtools.WPF/MainWindow.PixelEditor.cs
index 1a4d9b0..80f127a 100644
--- a/UVtools.WPF/MainWindow.PixelEditor.cs
+++ b/UVtools.WPF/MainWindow.PixelEditor.cs
@@ -262,7 +262,7 @@ namespace UVtools.WPF
{
var operationText = new PixelText(layerIndex, realLocation, DrawingPixelText.LineType,
DrawingPixelText.Font, DrawingPixelText.FontScale, DrawingPixelText.Thickness,
- DrawingPixelText.Text, DrawingPixelText.Mirror, DrawingPixelText.RemovePixelBrightness, DrawingPixelText.PixelBrightness, isAdd);
+ DrawingPixelText.Text, DrawingPixelText.Mirror, DrawingPixelText.Angle, DrawingPixelText.RemovePixelBrightness, DrawingPixelText.PixelBrightness, isAdd);
//if (PixelHistory.Contains(operation)) continue;
//PixelHistory.Add(operation);
diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml
index 50fd61d..89f1090 100644
--- a/UVtools.WPF/MainWindow.axaml
+++ b/UVtools.WPF/MainWindow.axaml
@@ -982,7 +982,7 @@
</Border>
<Grid
- RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto"
+ RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto"
ColumnDefinitions="Auto,10,130,5,40">
<TextBlock
@@ -1063,46 +1063,64 @@
Grid.Row="12"
Grid.Column="0"
VerticalAlignment="Center"
- Text="Remove pixel brightness:" />
+ Text="Rotation angle:" />
<NumericUpDown
Grid.Row="12"
Grid.Column="2"
+ FormatString="F2"
+ Minimum="-360"
+ Maximum="360"
+ Value="{Binding DrawingPixelText.Angle}"/>
+ <TextBlock
+ Grid.Row="12"
+ Grid.Column="4"
+ VerticalAlignment="Center"
+ Text="º" />
+
+ <TextBlock
+ Grid.Row="14"
+ Grid.Column="0"
+ VerticalAlignment="Center"
+ Text="Remove pixel brightness:" />
+ <NumericUpDown
+ Grid.Row="14"
+ Grid.Column="2"
Minimum="0"
Maximum="255"
Value="{Binding DrawingPixelText.RemovePixelBrightness}"/>
<TextBlock
- Grid.Row="12"
+ Grid.Row="14"
Grid.Column="4"
VerticalAlignment="Center"
Text="{Binding DrawingPixelText.RemovePixelBrightnessPercent, StringFormat=\{0:0\}%}" />
<TextBlock
- Grid.Row="14"
+ Grid.Row="16"
Grid.Column="0"
VerticalAlignment="Center"
Text="Add pixel brightness:" />
<NumericUpDown
- Grid.Row="14"
+ Grid.Row="16"
Grid.Column="2"
Minimum="1"
Maximum="255"
Value="{Binding DrawingPixelText.PixelBrightness}"/>
<TextBlock
- Grid.Row="14"
+ Grid.Row="16"
Grid.Column="4"
VerticalAlignment="Center"
Text="{Binding DrawingPixelText.PixelBrightnessPercent, StringFormat=\{0:0\}%}" />
<TextBlock
- Grid.Row="16"
+ Grid.Row="18"
Grid.Column="0"
VerticalAlignment="Center"
Text="Layers depth below:" />
<NumericUpDown
- Grid.Row="16"
+ Grid.Row="18"
Grid.Column="2"
Grid.ColumnSpan="3"
Minimum="0"
@@ -1111,12 +1129,12 @@
<TextBlock
- Grid.Row="18"
+ Grid.Row="20"
Grid.Column="0"
VerticalAlignment="Center"
Text="Layers depth above:" />
<NumericUpDown
- Grid.Row="18"
+ Grid.Row="20"
Grid.Column="2"
Grid.ColumnSpan="3"
Minimum="0"
@@ -1824,6 +1842,10 @@
<CheckBox
IsChecked="{Binding ShowLayerOutlineEdgeDetection}"
Content="Edge detection"/>
+ <CheckBox
+ IsChecked="{Binding ShowLayerOutlineSkeletonize}"
+ IsEnabled="{Binding !ShowLayerOutlineEdgeDetection}"
+ Content="Skeletonize"/>
</ContextMenu>
</Button.ContextMenu>
<StackPanel Orientation="Horizontal">
diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs
index d146014..67fc9b7 100644
--- a/UVtools.WPF/MainWindow.axaml.cs
+++ b/UVtools.WPF/MainWindow.axaml.cs
@@ -351,6 +351,14 @@ namespace UVtools.WPF
},
new()
{
+ Tag = new OperationLayerExportSkeleton(),
+ Icon = new Avalonia.Controls.Image
+ {
+ Source = new Bitmap(App.GetAsset("/Assets/Icons/file-image-16x16.png"))
+ }
+ },
+ new()
+ {
Tag = new OperationLayerExportHeatMap(),
Icon = new Avalonia.Controls.Image
{
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index 16f4847..eeab339 100644
--- a/UVtools.WPF/UVtools.WPF.csproj
+++ b/UVtools.WPF/UVtools.WPF.csproj
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
- <Version>2.13.0</Version>
+ <Version>2.13.1</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">