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:
-rw-r--r--CHANGELOG.md8
-rw-r--r--UVtools.Core/Extensions/PointExtensions.cs2
-rw-r--r--UVtools.Core/Operations/Operation.cs8
-rw-r--r--UVtools.Core/Operations/OperationBlur.cs6
-rw-r--r--UVtools.Core/Operations/OperationChangeResolution.cs3
-rw-r--r--UVtools.Core/Operations/OperationDynamicLifts.cs2
-rw-r--r--UVtools.Core/Operations/OperationInfill.cs158
-rw-r--r--UVtools.Core/Operations/OperationLayerExportGif.cs2
-rw-r--r--UVtools.Core/Operations/OperationLayerExportHeatMap.cs2
-rw-r--r--UVtools.Core/Operations/OperationLayerReHeight.cs3
-rw-r--r--UVtools.Core/Operations/OperationLightBleedCompensation.cs277
-rw-r--r--UVtools.Core/Operations/OperationPixelArithmetic.cs2
-rw-r--r--UVtools.Core/Operations/OperationScripting.cs3
-rw-r--r--UVtools.Core/UVtools.Core.csproj2
-rw-r--r--UVtools.Platforms/AppImage/AppDir/AppRun5
-rw-r--r--UVtools.Platforms/AppImage/AppDir/UVtools.desktop12
-rw-r--r--UVtools.Platforms/AppImage/AppDir/UVtools.pngbin0 -> 6632 bytes
-rw-r--r--UVtools.Platforms/AppImage/appimagetool-x86_64.AppImagebin0 -> 2172096 bytes
-rw-r--r--UVtools.ScriptSample/ScriptLightBleedCompensationSample.cs125
-rw-r--r--UVtools.WPF/Assets/Icons/lightbulb-solid-16x16.pngbin0 -> 199 bytes
-rw-r--r--UVtools.WPF/Controls/Tools/ToolLightBleedCompensationControl.axaml42
-rw-r--r--UVtools.WPF/Controls/Tools/ToolLightBleedCompensationControl.axaml.cs20
-rw-r--r--UVtools.WPF/Extensions/WindowExtensions.cs2
-rw-r--r--UVtools.WPF/MainWindow.axaml.cs8
-rw-r--r--UVtools.WPF/UVtools.WPF.csproj4
-rw-r--r--build/CreateRelease.WPF.ps126
26 files changed, 652 insertions, 70 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6702ea2..ed9c89d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,12 @@
# Changelog
-## /05/2021 - v2.12.2
+## 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
+- (Add) Infill: Honeycomb infill type
+- (Upgrade) MessageBox from 1.2.0 to 1.3.1 to fix the small size messages
+
+## 20/05/2021 - v2.12.2
- (Add) Layer action - Export layers to heat map: Export a layer range to a grayscale heat map image that represents the median of the mass in the Z depth/perception. The pixel brightness/intensity shows where the most mass are concentrated.
diff --git a/UVtools.Core/Extensions/PointExtensions.cs b/UVtools.Core/Extensions/PointExtensions.cs
index 4ba31d8..8b0056c 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 == 0 || angleDegree == 360) return point;
+ if (angleDegree is 0 or 360) return point;
double angle = angleDegree * Math.PI / 180;
double cos = Math.Cos(angle);
double sin = Math.Sin(angle);
diff --git a/UVtools.Core/Operations/Operation.cs b/UVtools.Core/Operations/Operation.cs
index f8b9b10..acf78b2 100644
--- a/UVtools.Core/Operations/Operation.cs
+++ b/UVtools.Core/Operations/Operation.cs
@@ -383,6 +383,14 @@ namespace UVtools.Core.Operations
ROI = roi;
}
+ public Size GetRoiSizeOrDefault() => GetRoiSizeOrDefault(SlicerFile.Resolution);
+ public Size GetRoiSizeOrDefault(Mat defaultMat) => GetRoiSizeOrDefault(defaultMat.Size);
+
+ public Size GetRoiSizeOrDefault(Size defaultSize)
+ {
+ return HaveROI && defaultSize != _roi.Size ? _roi.Size : defaultSize;
+ }
+
public Mat GetRoiOrDefault(Mat defaultMat)
{
return HaveROI && defaultMat.Size != _roi.Size ? new Mat(defaultMat, _roi) : defaultMat;
diff --git a/UVtools.Core/Operations/OperationBlur.cs b/UVtools.Core/Operations/OperationBlur.cs
index 255c57f..9642812 100644
--- a/UVtools.Core/Operations/OperationBlur.cs
+++ b/UVtools.Core/Operations/OperationBlur.cs
@@ -21,15 +21,17 @@ namespace UVtools.Core.Operations
[Serializable]
public sealed class OperationBlur : Operation
{
+ #region Members
private BlurAlgorithm _blurOperation = BlurAlgorithm.Blur;
private uint _size = 1;
+ #endregion
#region Overrides
public override string Title => "Blur";
public override string Description =>
- $"Blur layer images by applying a low pass filter\n\n" +
- "NOTE: Target printer must support AntiAliasing in order to use this function.\n\n" +
+ $"Blur layer images by applying a low pass filter.\n\n" +
+ "NOTE: Target printer must support AntiAliasing in order to use this function.\n" +
"See https://docs.opencv.org/master/d4/d13/tutorial_py_filtering.html";
public override string ConfirmationText =>
diff --git a/UVtools.Core/Operations/OperationChangeResolution.cs b/UVtools.Core/Operations/OperationChangeResolution.cs
index 4982cd4..c40d3f7 100644
--- a/UVtools.Core/Operations/OperationChangeResolution.cs
+++ b/UVtools.Core/Operations/OperationChangeResolution.cs
@@ -12,7 +12,6 @@ using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using UVtools.Core.FileFormats;
-using UVtools.Core.Objects;
namespace UVtools.Core.Operations
{
@@ -58,7 +57,7 @@ namespace UVtools.Core.Operations
public override bool CanROI => false;
public override string Title => "Change print resolution";
public override string Description =>
- "Crops or resizes all layer images to fit an alternate print resolution\n" +
+ "Crops or resizes all layer images to fit an alternate print resolution.\n" +
"Useful to make files printable on a different printer than they were originally sliced for without the need to re-slice.\n\n" +
"NOTE: Please ensure that the actual model will fit within the new print resolution. The operation will be aborted if it will result in any of the actual model being clipped.\n" +
"Only use this tool if both source and target printer have the same pixel pitch spec, otherwise the model size will be invalidated and result in a different size than the originally sliced for. " +
diff --git a/UVtools.Core/Operations/OperationDynamicLifts.cs b/UVtools.Core/Operations/OperationDynamicLifts.cs
index 7444f0f..5fab1d9 100644
--- a/UVtools.Core/Operations/OperationDynamicLifts.cs
+++ b/UVtools.Core/Operations/OperationDynamicLifts.cs
@@ -54,7 +54,7 @@ namespace UVtools.Core.Operations
public override string Title => "Dynamic lifts";
public override string Description =>
- "Generate dynamic lift height and speeds for each layer given it mass\n" +
+ "Generate dynamic lift height and speeds for each layer given it mass.\n" +
"Larger masses requires more lift height and less speed while smaller masses can go with shorter lift height and more speed.\n" +
"If you have a raft, start after it layer number to not influence the calculations.\n" +
"Note: Only few printers support this. Running this on an unsupported printer will cause no harm.";
diff --git a/UVtools.Core/Operations/OperationInfill.cs b/UVtools.Core/Operations/OperationInfill.cs
index b07ba06..01b3ae9 100644
--- a/UVtools.Core/Operations/OperationInfill.cs
+++ b/UVtools.Core/Operations/OperationInfill.cs
@@ -33,7 +33,7 @@ namespace UVtools.Core.Operations
public override string Title => "Infill";
public override string Description =>
- $"Generate infill patterns in the model\n\nNOTES:\n1) You must exclude floor and ceil layers from the range.\n2) You must take care of drain holes after the operation.";
+ $"Generate infill patterns in the model.\n\nNOTES:\n1) You must exclude floor and ceil layers from the range.\n2) You must take care of drain holes after the operation.";
public override string ConfirmationText =>
$"infill model with {InfillType} from layers {LayerIndexStart} through {LayerIndexEnd}?";
@@ -53,6 +53,7 @@ namespace UVtools.Core.Operations
CubicCenterLink,
CubicDynamicLink,
CubicInterlinked,
+ Honeycomb
}
#endregion
@@ -128,17 +129,23 @@ namespace UVtools.Core.Operations
protected override bool ExecuteInternally(OperationProgress progress)
{
+ Mat mask = null;
+ if (_infillType == InfillAlgorithm.Honeycomb)
+ {
+ mask = GetHoneycombMask(GetRoiSizeOrDefault());
+ }
+
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using var mat = SlicerFile[layerIndex].LayerMat;
- Execute(mat, layerIndex);
+ Execute(mat, layerIndex, mask);
SlicerFile[layerIndex].LayerMat = mat;
progress.LockAndIncrement();
});
-
+ mask?.Dispose();
return !progress.Token.IsCancellationRequested;
}
@@ -149,22 +156,22 @@ namespace UVtools.Core.Operations
var kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor);
uint index = Convert.ToUInt32(arguments[0]);
uint layerIndex = index - LayerIndexStart;
- var infillColor = new MCvScalar(InfillBrightness);
+ var infillColor = new MCvScalar(_infillBrightness);
Mat patternMask = null;
using Mat erode = new ();
using Mat diff = new ();
- Mat target = GetRoiOrDefault(mat);
+ var target = GetRoiOrDefault(mat);
using var mask = GetMask(mat);
-
+ bool disposeTargetMask = true;
- if (InfillType == InfillAlgorithm.Cubic ||
- InfillType == InfillAlgorithm.CubicCenterLink ||
- InfillType == InfillAlgorithm.CubicDynamicLink ||
- InfillType == InfillAlgorithm.CubicInterlinked)
+ if (_infillType is InfillAlgorithm.Cubic
+ or InfillAlgorithm.CubicCenterLink
+ or InfillAlgorithm.CubicDynamicLink
+ or InfillAlgorithm.CubicInterlinked)
{
- using var infillPattern = EmguExtensions.InitMat(new Size(InfillSpacing, InfillSpacing));
- using Mat matPattern = mat.CloneBlank();
+ using var infillPattern = EmguExtensions.InitMat(new Size(_infillSpacing, _infillSpacing));
+ using var matPattern = mat.CloneBlank();
bool firstPattern = true;
uint accumulator = 0;
bool dynamicCenter = false;
@@ -172,16 +179,16 @@ namespace UVtools.Core.Operations
{
dynamicCenter = !dynamicCenter;
firstPattern = true;
- accumulator += InfillSpacing;
+ accumulator += _infillSpacing;
if (accumulator >= layerIndex) break;
firstPattern = false;
- accumulator += InfillThickness;
+ accumulator += _infillThickness;
}
if (firstPattern)
{
- int thickness = InfillThickness / 2;
+ int thickness = _infillThickness / 2;
// Top Left
CvInvoke.Rectangle(infillPattern,
new Rectangle(0, 0, thickness, thickness),
@@ -207,106 +214,159 @@ namespace UVtools.Core.Operations
int margin = (int) (InfillSpacing - accumulator + layerIndex) - thickness;
int marginInv = (int) (accumulator - layerIndex) - thickness;
- if (InfillType == InfillAlgorithm.CubicCenterLink ||
- (InfillType == InfillAlgorithm.CubicDynamicLink &&
+ if (_infillType == InfillAlgorithm.CubicCenterLink ||
+ (_infillType == InfillAlgorithm.CubicDynamicLink &&
dynamicCenter) ||
- InfillType == InfillAlgorithm.CubicInterlinked)
+ _infillType == InfillAlgorithm.CubicInterlinked)
{
CvInvoke.Rectangle(infillPattern,
- new Rectangle(margin, margin, InfillThickness, InfillThickness),
+ new Rectangle(margin, margin, _infillThickness, _infillThickness),
infillColor, -1);
CvInvoke.Rectangle(infillPattern,
- new Rectangle(marginInv, marginInv, InfillThickness,
- InfillThickness),
+ new Rectangle(marginInv, marginInv, _infillThickness,
+ _infillThickness),
infillColor, -1);
CvInvoke.Rectangle(infillPattern,
- new Rectangle(margin, marginInv, InfillThickness,
- InfillThickness),
+ new Rectangle(margin, marginInv, _infillThickness,
+ _infillThickness),
infillColor, -1);
CvInvoke.Rectangle(infillPattern,
- new Rectangle(marginInv, margin, InfillThickness,
- InfillThickness),
+ new Rectangle(marginInv, margin, _infillThickness,
+ _infillThickness),
infillColor, -1);
}
- if (InfillType == InfillAlgorithm.CubicInterlinked ||
- (InfillType == InfillAlgorithm.CubicDynamicLink &&
+ if (_infillType == InfillAlgorithm.CubicInterlinked ||
+ (_infillType == InfillAlgorithm.CubicDynamicLink &&
!dynamicCenter))
{
CvInvoke.Rectangle(infillPattern,
- new Rectangle(margin, -thickness, InfillThickness,
- InfillThickness),
+ new Rectangle(margin, -thickness, _infillThickness,
+ _infillThickness),
infillColor, -1);
CvInvoke.Rectangle(infillPattern,
- new Rectangle(marginInv, -thickness, InfillThickness,
- InfillThickness),
+ new Rectangle(marginInv, -thickness, _infillThickness,
+ _infillThickness),
infillColor, -1);
CvInvoke.Rectangle(infillPattern,
- new Rectangle(-thickness, margin, InfillThickness,
- InfillThickness),
+ new Rectangle(-thickness, margin, _infillThickness,
+ _infillThickness),
infillColor, -1);
CvInvoke.Rectangle(infillPattern,
- new Rectangle(-thickness, marginInv, InfillThickness,
- InfillThickness),
+ new Rectangle(-thickness, marginInv, _infillThickness,
+ _infillThickness),
infillColor, -1);
CvInvoke.Rectangle(infillPattern,
new Rectangle(InfillSpacing - thickness, margin,
- InfillThickness, InfillThickness),
+ _infillThickness, _infillThickness),
infillColor, -1);
CvInvoke.Rectangle(infillPattern,
new Rectangle(InfillSpacing - thickness, marginInv,
- InfillThickness, InfillThickness),
+ _infillThickness, _infillThickness),
infillColor, -1);
CvInvoke.Rectangle(infillPattern,
new Rectangle(margin, InfillSpacing - thickness,
- InfillThickness, InfillThickness),
+ _infillThickness, _infillThickness),
infillColor, -1);
CvInvoke.Rectangle(infillPattern,
new Rectangle(marginInv, InfillSpacing - thickness,
- InfillThickness, InfillThickness),
+ _infillThickness, _infillThickness),
infillColor, -1);
}
-
-
}
else
{
CvInvoke.Rectangle(infillPattern,
- new Rectangle(0, 0, InfillSpacing, InfillSpacing),
- infillColor, InfillThickness);
+ new Rectangle(0, 0, _infillSpacing, _infillSpacing),
+ infillColor, _infillThickness);
}
+ CvInvoke.Repeat(infillPattern, target.Rows / infillPattern.Rows + 1,
+ target.Cols / infillPattern.Cols + 1, matPattern);
+ patternMask = new Mat(matPattern, new Rectangle(0, 0, target.Width, target.Height));
+ disposeTargetMask = true;
+ }
+ else if (_infillType == InfillAlgorithm.Honeycomb)
+ {
+ if (arguments.Length >= 2)
+ {
+ patternMask = (Mat)arguments[1];
+ disposeTargetMask = false;
+ }
+ else
{
- CvInvoke.Repeat(infillPattern, target.Rows / infillPattern.Rows + 1,
- target.Cols / infillPattern.Cols + 1, matPattern);
- patternMask = new Mat(matPattern, new Rectangle(0, 0, target.Width, target.Height));
+ patternMask = GetHoneycombMask(target.Size);
+ disposeTargetMask = true;
}
}
-
+ //patternMask.Save("D:\\pattern.png");
CvInvoke.Erode(target, erode, kernel, anchor, WallThickness, BorderType.Reflect101,
default);
CvInvoke.Subtract(target, erode, diff);
-
+
CvInvoke.BitwiseAnd(erode, patternMask, target, mask);
CvInvoke.Add(target, diff, target, mask);
- patternMask?.Dispose();
+
+ if (disposeTargetMask)
+ {
+ patternMask.Dispose();
+ }
return true;
}
+ public Mat GetHoneycombMask(Size targetSize)
+ {
+ var patternMask = EmguExtensions.InitMat(targetSize);
+
+ var halfInfillSpacing = _infillSpacing / 2;
+ var halfThickenss = _infillThickness / 2;
+ int width = (int)Math.Round(4 * (_infillSpacing / 2.0 / Math.Sqrt(3)));
+ var infillColor = new MCvScalar(_infillBrightness);
+
+ for (int col = 0; col <= targetSize.Width / _infillSpacing; col++)
+ {
+ for (int row = 0; row <= targetSize.Height / _infillSpacing; row++)
+ {
+ // Move over for the column number.
+ int x = (int)Math.Round(col * (width * 0.75f));
+
+ // Move down the required number of rows.
+ int y = row * _infillSpacing;
+
+ // If the column is odd, move down half a hex more.
+ if (col % 2 == 1) y += halfInfillSpacing;
+
+ var points = new Point[]
+ {
+ new(x, y),
+ new((int) Math.Round(x + width * 0.25f), y - _infillSpacing / 2),
+ new((int) Math.Round(x + width * 0.75f), y - _infillSpacing / 2),
+ new(x + width, y),
+ new((int) Math.Round(x + width * 0.75f), y + _infillSpacing / 2),
+ new((int) Math.Round(x + width * 0.25f), y + _infillSpacing / 2),
+ };
+
+ CvInvoke.Polylines(patternMask, points, true, infillColor, _infillThickness);
+ }
+ }
+
+ return patternMask;
+ }
+
#endregion
}
}
diff --git a/UVtools.Core/Operations/OperationLayerExportGif.cs b/UVtools.Core/Operations/OperationLayerExportGif.cs
index e863f89..d0a0d24 100644
--- a/UVtools.Core/Operations/OperationLayerExportGif.cs
+++ b/UVtools.Core/Operations/OperationLayerExportGif.cs
@@ -65,7 +65,7 @@ namespace UVtools.Core.Operations
public override string Title => "Export layers to GIF";
public override string Description =>
- "Export a layer range to an animated GIF file\n" +
+ "Export a layer range to an animated GIF file.\n" +
"Note: This process is slow, optimize the parameters to output few layers as possible and/or scale them down.";
public override string ConfirmationText =>
diff --git a/UVtools.Core/Operations/OperationLayerExportHeatMap.cs b/UVtools.Core/Operations/OperationLayerExportHeatMap.cs
index eb6482c..2c0bccb 100644
--- a/UVtools.Core/Operations/OperationLayerExportHeatMap.cs
+++ b/UVtools.Core/Operations/OperationLayerExportHeatMap.cs
@@ -28,7 +28,7 @@ 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" +
diff --git a/UVtools.Core/Operations/OperationLayerReHeight.cs b/UVtools.Core/Operations/OperationLayerReHeight.cs
index 1aee091..548c25c 100644
--- a/UVtools.Core/Operations/OperationLayerReHeight.cs
+++ b/UVtools.Core/Operations/OperationLayerReHeight.cs
@@ -34,6 +34,7 @@ namespace UVtools.Core.Operations
Average
}
#endregion
+
#region Members
private OperationLayerReHeightItem _selectedItem;
private OperationLayerReHeightAntiAliasingType _antiAliasingType;
@@ -46,7 +47,7 @@ namespace UVtools.Core.Operations
public override bool CanROI => false;
public override string Title => "Adjust layer height";
public override string Description =>
- "Adjust the layer height of the model\n\n" +
+ "Adjust the layer height of the model.\n\n" +
"Adjusting to values lower than current height will reduce layer lines, adjusting to values higher" +
" than current height will reduce model detail.\n\n" +
"Note: Using dedicated slicer software to re-slice will usually yeild better results.";
diff --git a/UVtools.Core/Operations/OperationLightBleedCompensation.cs b/UVtools.Core/Operations/OperationLightBleedCompensation.cs
new file mode 100644
index 0000000..c3175af
--- /dev/null
+++ b/UVtools.Core/Operations/OperationLightBleedCompensation.cs
@@ -0,0 +1,277 @@
+/*
+ * 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.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Emgu.CV;
+using Emgu.CV.Structure;
+using UVtools.Core.Extensions;
+using UVtools.Core.FileFormats;
+
+namespace UVtools.Core.Operations
+{
+ [Serializable]
+ public class OperationLightBleedCompensation : Operation
+ {
+ #region Enums
+
+ public enum LightBleedCompensationLookupMode : byte
+ {
+ [Description("Previous: Look for sequential pixels relative to the previous layers")]
+ Previous,
+
+ [Description("Next: Look for sequential pixels relative to the next layers")]
+ Next,
+
+ [Description("Both: Look for sequential pixels relative to the previous and next layers")]
+ Both
+ }
+
+ #endregion
+
+ #region Members
+
+ private LightBleedCompensationLookupMode _lookupMode = LightBleedCompensationLookupMode.Next;
+ private string _dimBy = "25,15,10,5";
+
+ #endregion
+
+ #region Overrides
+
+ public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.Normal;
+
+ public override string Title => "Light bleed compensation";
+ public override string Description =>
+ "Compensate the over-curing and light bleed from clear resins by dimming the sequential pixels.\n" +
+ "Note: You need to find the optimal minimum pixel brightness that such resin can print in order to optimize this process.\n" +
+ "With more translucent resins you can go with lower brightness but stick to a limit that can form the layer without loss." +
+ " Tiny details can be lost when using low brightness level.\n" +
+ "After apply a light bleed compensation, do not apply or re-run this tool over.";
+
+ public override string ConfirmationText =>
+ $"compensate layers {LayerIndexStart} through {LayerIndexEnd}?";
+
+ public override string ProgressTitle =>
+ $"Compensate layers {LayerIndexStart} through {LayerIndexEnd}";
+
+ public override string ProgressAction => "Compensated layers";
+
+ public override string ValidateInternally()
+ {
+ StringBuilder sb = new();
+
+ if (DimByArray.Length == 0)
+ {
+ sb.AppendLine($"The dim levels are invalid or not set.");
+ }
+
+ if (MaximumSubtraction >= byte.MaxValue)
+ {
+ sb.AppendLine($"The sum of dim levels are producing black pixels.");
+ }
+
+ return sb.ToString();
+ }
+
+ public override string ToString()
+ {
+ var result = $"[Lookup: {_lookupMode}]" +
+ $" [Dim by: {_dimBy}]" + LayerRangeString;
+ if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
+ return result;
+ }
+ #endregion
+
+ #region Constructor
+
+ public OperationLightBleedCompensation() { }
+
+ public OperationLightBleedCompensation(FileFormat slicerFile) : base(slicerFile) { }
+
+ #endregion
+
+ #region Properties
+
+ public LightBleedCompensationLookupMode LookupMode
+ {
+ get => _lookupMode;
+ set => RaiseAndSetIfChanged(ref _lookupMode, value);
+ }
+
+ public string DimBy
+ {
+ get => _dimBy;
+ set
+ {
+ if(!RaiseAndSetIfChanged(ref _dimBy, value)) return;
+ RaisePropertyChanged(nameof(MinimumBrightness));
+ RaisePropertyChanged(nameof(MaximumSubtraction));
+ }
+ }
+
+ public int MinimumBrightness => 255 - MaximumSubtraction;
+ public int MaximumSubtraction => DimByArray.Aggregate(0, (current, dim) => current + dim);
+
+ public byte[] DimByArray
+ {
+ get
+ {
+ List<byte> levels = new();
+ var split = _dimBy.Split(',', StringSplitOptions.TrimEntries);
+ foreach (var str in split)
+ {
+ if (!byte.TryParse(str, out var brightness)) continue;
+ if (brightness is byte.MinValue or byte.MaxValue) continue;
+ levels.Add(brightness);
+ }
+
+ return levels.ToArray();
+ }
+ }
+
+ public MCvScalar[] DimByMCvScalar
+ {
+ get
+ {
+ List<MCvScalar> levels = new();
+ var split = _dimBy.Split(',', StringSplitOptions.TrimEntries);
+ foreach (var str in split)
+ {
+ if (!byte.TryParse(str, out var brightness)) continue;
+ if (brightness is byte.MinValue or byte.MaxValue) continue;
+ levels.Add(new MCvScalar(brightness));
+ }
+
+ return levels.ToArray();
+ }
+ }
+
+ #endregion
+
+ #region Equality
+
+ protected bool Equals(OperationLightBleedCompensation other)
+ {
+ return _lookupMode == other._lookupMode && _dimBy == other._dimBy;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != this.GetType()) return false;
+ return Equals((OperationLightBleedCompensation) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine((int) _lookupMode, _dimBy);
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Get the cached dim mat's
+ /// </summary>
+ /// <returns></returns>
+ public Mat[] GetDimMats()
+ {
+ var dimLevels = DimByMCvScalar;
+ if (dimLevels.Length == 0) return Array.Empty<Mat>();
+ var mats = new Mat[dimLevels.Length];
+ var matSize = GetRoiSizeOrDefault();
+ for (var i = 0; i < mats.Length; i++)
+ {
+ mats[i] = EmguExtensions.InitMat(matSize, dimLevels[i]);
+ }
+
+ return mats;
+ }
+
+ protected override bool ExecuteInternally(OperationProgress progress)
+ {
+ var dimMats = GetDimMats();
+ if (dimMats.Length == 0) return false;
+ Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
+ {
+ if (progress.Token.IsCancellationRequested) return; // Abort operation, user requested cancellation
+
+ var layer = SlicerFile[layerIndex];
+ using var mat = layer.LayerMat;
+ using var original = mat.Clone();
+ var target = GetRoiOrDefault(mat);
+
+ for (byte i = 0; i < dimMats.Length; i++)
+ {
+ Mat mask = null;
+ Mat previousMat = null;
+ Mat previousMatRoi = null;
+ Mat nextMat = null;
+ Mat nextMatRoi = null;
+
+
+ if (_lookupMode is LightBleedCompensationLookupMode.Previous or LightBleedCompensationLookupMode.Both)
+ {
+ int layerPreviousIndex = (int)layerIndex - i - 1;
+ if (layerPreviousIndex >= LayerIndexStart)
+ {
+ previousMat = SlicerFile[layerPreviousIndex].LayerMat;
+ mask = previousMatRoi = GetRoiOrDefault(previousMat);
+ }
+ }
+ if (_lookupMode is LightBleedCompensationLookupMode.Next or LightBleedCompensationLookupMode.Both)
+ {
+ uint layerIndexNext = (uint) (layerIndex + i + 1);
+ if (layerIndexNext <= LayerIndexEnd)
+ {
+ nextMat = SlicerFile[layerIndexNext].LayerMat;
+ mask = nextMatRoi = GetRoiOrDefault(nextMat);
+ }
+ }
+
+ if (previousMat is null && nextMat is null) break; // Nothing more to do
+ if (previousMat is not null && nextMat is not null) // both, need to merge previous with next layer
+ {
+ CvInvoke.Add(previousMatRoi, nextMatRoi, previousMatRoi);
+ mask = previousMatRoi;
+ }
+
+ CvInvoke.Subtract(target, dimMats[i], target, mask);
+
+ previousMat?.Dispose();
+ nextMat?.Dispose();
+ }
+
+ // Apply the results only to the selected masked area, if user selected one
+ ApplyMask(original, target);
+
+ // Set current layer image with the modified mat we just manipulated
+ layer.LayerMat = mat;
+
+ // Increment progress bar by 1
+ progress.LockAndIncrement();
+ });
+
+ foreach (var dimMat in dimMats)
+ {
+ dimMat.Dispose();
+ }
+
+ // return true if not cancelled by user
+ return !progress.Token.IsCancellationRequested;
+ }
+
+ #endregion
+ }
+}
diff --git a/UVtools.Core/Operations/OperationPixelArithmetic.cs b/UVtools.Core/Operations/OperationPixelArithmetic.cs
index 0ce74e8..427d7be 100644
--- a/UVtools.Core/Operations/OperationPixelArithmetic.cs
+++ b/UVtools.Core/Operations/OperationPixelArithmetic.cs
@@ -72,7 +72,7 @@ namespace UVtools.Core.Operations
public override string Title => "Pixel arithmetic";
public override string Description =>
- "Perform arithmetic operations over the pixels";
+ "Perform arithmetic operations over the pixels.";
public override string ConfirmationText =>
$"arithmetic {_operator}" +
diff --git a/UVtools.Core/Operations/OperationScripting.cs b/UVtools.Core/Operations/OperationScripting.cs
index 661daad..a54326c 100644
--- a/UVtools.Core/Operations/OperationScripting.cs
+++ b/UVtools.Core/Operations/OperationScripting.cs
@@ -12,7 +12,6 @@ using System.Xml.Serialization;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using UVtools.Core.FileFormats;
-using UVtools.Core.Objects;
using UVtools.Core.Scripting;
namespace UVtools.Core.Operations
@@ -36,7 +35,7 @@ namespace UVtools.Core.Operations
public override string Title => "Scripting";
public override string Description =>
- $"Run external scripts to manipulate the loaded file\n" +
+ $"Run external scripts to manipulate the loaded file.\n" +
$"The scripts have wide access to your system and able to do modifications, read/write files, etc. " +
$"Make sure to run only the scripts you trust! Or run UVtools in a sandbox while executing this.";
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index 5a6763a..4a97b3d 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.12.2</Version>
+ <Version>2.13.0</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
diff --git a/UVtools.Platforms/AppImage/AppDir/AppRun b/UVtools.Platforms/AppImage/AppDir/AppRun
new file mode 100644
index 0000000..f954dda
--- /dev/null
+++ b/UVtools.Platforms/AppImage/AppDir/AppRun
@@ -0,0 +1,5 @@
+#!/bin/sh
+HERE="$(dirname "$(readlink -f "${0}")")"
+export PATH="${HERE}"/usr/bin/:"${PATH}"
+EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1)
+exec "${EXEC}" $@ \ No newline at end of file
diff --git a/UVtools.Platforms/AppImage/AppDir/UVtools.desktop b/UVtools.Platforms/AppImage/AppDir/UVtools.desktop
new file mode 100644
index 0000000..70cd65c
--- /dev/null
+++ b/UVtools.Platforms/AppImage/AppDir/UVtools.desktop
@@ -0,0 +1,12 @@
+# Desktop Entry Specification: https://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
+# https://github.com/AppImage/AppImageKit/wiki/Bundling-.NET-Core-apps
+[Desktop Entry]
+Type=Application
+Name=UVtools
+Comment=MSLA/DLP, file analysis, calibration, repair, conversion and manipulation
+URL=https://github.com/sn4k3/UVtools
+Icon=UVtools
+Exec=UVtools
+Path=~
+Terminal=true
+Categories=Development; \ No newline at end of file
diff --git a/UVtools.Platforms/AppImage/AppDir/UVtools.png b/UVtools.Platforms/AppImage/AppDir/UVtools.png
new file mode 100644
index 0000000..a5b52c7
--- /dev/null
+++ b/UVtools.Platforms/AppImage/AppDir/UVtools.png
Binary files differ
diff --git a/UVtools.Platforms/AppImage/appimagetool-x86_64.AppImage b/UVtools.Platforms/AppImage/appimagetool-x86_64.AppImage
new file mode 100644
index 0000000..25365df
--- /dev/null
+++ b/UVtools.Platforms/AppImage/appimagetool-x86_64.AppImage
Binary files differ
diff --git a/UVtools.ScriptSample/ScriptLightBleedCompensationSample.cs b/UVtools.ScriptSample/ScriptLightBleedCompensationSample.cs
new file mode 100644
index 0000000..b7fc518
--- /dev/null
+++ b/UVtools.ScriptSample/ScriptLightBleedCompensationSample.cs
@@ -0,0 +1,125 @@
+/*
+ * 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.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using UVtools.Core.Scripting;
+using Emgu.CV;
+using Emgu.CV.Structure;
+using UVtools.Core.Extensions;
+
+namespace UVtools.ScriptSample
+{
+ /// <summary>
+ /// Performs a black inset around objects
+ /// </summary>
+ public class ScriptLightBleedCompensationSample : ScriptGlobals
+ {
+ ScriptTextBoxInput BrightnessesInput = new()
+ {
+ Label = "Brightnesses",
+ ToolTip = "Brightness to reduce each subsequent repeated pixels",
+ Unit = "1-255",
+ Value = "25,20,15,10,5"
+ };
+
+
+ public byte[] Levels
+ {
+ get
+ {
+ List<byte> levels = new();
+ var split = BrightnessesInput.Value.Split(',', StringSplitOptions.TrimEntries);
+ foreach (var str in split)
+ {
+ if(!byte.TryParse(str, out var brightness)) continue;
+ if(brightness is byte.MinValue or byte.MaxValue) continue;
+ levels.Add(brightness);
+ }
+
+ return levels.ToArray();
+ }
+ }
+
+ /// <summary>
+ /// Set configurations here, this function trigger just after load a script
+ /// </summary>
+ public void ScriptInit()
+ {
+ Script.Name = "Light bleed compensation";
+ Script.Description = "Dim sequential pixels";
+ Script.Author = "Tiago Conceição";
+ Script.Version = new Version(0, 1);
+ Script.UserInputs.Add(BrightnessesInput);
+ }
+
+ /// <summary>
+ /// Validate user inputs here, this function trigger when user click on execute
+ /// </summary>
+ /// <returns>A error message, empty or null if validation passes.</returns>
+ public string ScriptValidate()
+ {
+ StringBuilder sb = new();
+
+ if (Levels.Length == 0)
+ {
+ sb.AppendLine($"No brightness levels are set");
+ }
+
+ return sb.ToString();
+ }
+
+ /// <summary>
+ /// Execute the script, this function trigger when when user click on execute and validation passes
+ /// </summary>
+ /// <returns>True if executes successfully to the end, otherwise false.</returns>
+ public bool ScriptExecute()
+ {
+ Progress.Reset("Bleed compensation", Operation.LayerRangeCount); // Sets the progress name and number of items to process
+ var brightnesses = Levels;
+
+ // Loop user selected layers in parallel, this will put each core of CPU working here on parallel
+ Parallel.For(Operation.LayerIndexStart, Operation.LayerIndexEnd+1, layerIndex =>
+ {
+ if (Progress.Token.IsCancellationRequested) return; // Abort operation, user requested cancellation
+
+ var layer = SlicerFile[layerIndex]; // Unpack and expose layer variable for easier use
+ using var mat = layer.LayerMat; // Gets this layer mat/image
+ var original = mat.Clone(); // Keep a original mat copy
+
+ var target = Operation.GetRoiOrDefault(mat); // Get ROI from mat if user selected an region
+
+ for (byte i = 0; i < brightnesses.Length; i++)
+ {
+ uint layerIndexNext = (uint) (layerIndex + i + 1);
+ if (layerIndexNext > Operation.LayerIndexEnd) break;
+ using var subtractMat = EmguExtensions.InitMat(target.Size, new MCvScalar(brightnesses[i]));
+
+ using var nextMat = SlicerFile[layerIndexNext].LayerMat;
+ var nextMatRoi = Operation.GetRoiOrDefault(nextMat);
+
+ CvInvoke.Subtract(target, subtractMat, target, nextMatRoi);
+ }
+
+ // Apply the results only to the selected masked area, if user selected one
+ Operation.ApplyMask(original, target);
+
+ // Set current layer image with the modified mat we just manipulated
+ layer.LayerMat = mat;
+
+ // Increment progress bar by 1
+ Progress.LockAndIncrement();
+ });
+
+ // return true if not cancelled by user
+ return !Progress.Token.IsCancellationRequested;
+ }
+ }
+}
diff --git a/UVtools.WPF/Assets/Icons/lightbulb-solid-16x16.png b/UVtools.WPF/Assets/Icons/lightbulb-solid-16x16.png
new file mode 100644
index 0000000..f182d01
--- /dev/null
+++ b/UVtools.WPF/Assets/Icons/lightbulb-solid-16x16.png
Binary files differ
diff --git a/UVtools.WPF/Controls/Tools/ToolLightBleedCompensationControl.axaml b/UVtools.WPF/Controls/Tools/ToolLightBleedCompensationControl.axaml
new file mode 100644
index 0000000..294927e
--- /dev/null
+++ b/UVtools.WPF/Controls/Tools/ToolLightBleedCompensationControl.axaml
@@ -0,0 +1,42 @@
+<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.ToolLightBleedCompensationControl">
+ <Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto" ColumnDefinitions="Auto,10,500">
+ <TextBlock Grid.Row="0" Grid.Column="0"
+ VerticalAlignment="Center"
+ Text="Pixel lookup mode:"/>
+
+ <ComboBox Grid.Row="0" Grid.Column="2"
+ HorizontalAlignment="Stretch"
+ Items="{Binding Operation.LookupMode, Converter={StaticResource EnumToCollectionConverter}, Mode=OneTime}"
+ SelectedItem="{Binding Operation.LookupMode, Converter={StaticResource FromValueDescriptionToEnumConverter}}"/>
+
+ <TextBlock Grid.Row="2" Grid.Column="0"
+ VerticalAlignment="Center"
+ ToolTip.Tip="List of brightnesses to subtract for each subsequent pixel, format: 1-254, 1-254, 1-254, ..."
+ Text="Dim subsequent pixels by:"/>
+
+ <TextBox Grid.Row="2" Grid.Column="2"
+ VerticalAlignment="Center"
+ Text="{Binding Operation.DimBy}"/>
+
+ <TextBlock Grid.Row="4" Grid.Column="0"
+ VerticalAlignment="Center"
+ Text="Minimum pixel brightness:"/>
+
+ <TextBlock Grid.Row="4" Grid.Column="2"
+ VerticalAlignment="Center"
+ Text="{Binding Operation.MinimumBrightness, StringFormat={}{0} of 255}"/>
+
+ <TextBlock Grid.Row="6" Grid.Column="0"
+ VerticalAlignment="Center"
+ Text="Maximum subtraction:"/>
+
+ <TextBlock Grid.Row="6" Grid.Column="2"
+ VerticalAlignment="Center"
+ Text="{Binding Operation.MaximumSubtraction, StringFormat={}{0} of 255}"/>
+ </Grid>
+</UserControl>
diff --git a/UVtools.WPF/Controls/Tools/ToolLightBleedCompensationControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolLightBleedCompensationControl.axaml.cs
new file mode 100644
index 0000000..1cb0f32
--- /dev/null
+++ b/UVtools.WPF/Controls/Tools/ToolLightBleedCompensationControl.axaml.cs
@@ -0,0 +1,20 @@
+using Avalonia.Markup.Xaml;
+using UVtools.Core.Operations;
+
+namespace UVtools.WPF.Controls.Tools
+{
+ public partial class ToolLightBleedCompensationControl : ToolControl
+ {
+ public OperationLightBleedCompensation Operation => BaseOperation as OperationLightBleedCompensation;
+ public ToolLightBleedCompensationControl()
+ {
+ InitializeComponent();
+ BaseOperation = new OperationLightBleedCompensation(SlicerFile);
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+ }
+}
diff --git a/UVtools.WPF/Extensions/WindowExtensions.cs b/UVtools.WPF/Extensions/WindowExtensions.cs
index e1bf8ad..247f71a 100644
--- a/UVtools.WPF/Extensions/WindowExtensions.cs
+++ b/UVtools.WPF/Extensions/WindowExtensions.cs
@@ -34,6 +34,8 @@ namespace UVtools.WPF.Extensions
WindowStartupLocation = location,
CanResize = false,
MaxWidth = window.GetScreenWorkingArea().Width - UserSettings.Instance.General.WindowsHorizontalMargin,
+ MaxHeight = window.GetScreenWorkingArea().Height - UserSettings.Instance.General.WindowsVerticalMargin,
+ SizeToContent = SizeToContent.WidthAndHeight,
ShowInCenter = true
});
return await messageBoxStandardWindow.ShowDialog(window);
diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs
index 14750fc..d146014 100644
--- a/UVtools.WPF/MainWindow.axaml.cs
+++ b/UVtools.WPF/MainWindow.axaml.cs
@@ -175,6 +175,14 @@ namespace UVtools.WPF
},
new()
{
+ Tag = new OperationLightBleedCompensation(),
+ Icon = new Avalonia.Controls.Image
+ {
+ Source = new Bitmap(App.GetAsset("/Assets/Icons/lightbulb-solid-16x16.png"))
+ }
+ },
+ new()
+ {
Tag = new OperationInfill(),
Icon = new Avalonia.Controls.Image
{
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index e54e0d5..16f4847 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.12.2</Version>
+ <Version>2.13.0</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -30,7 +30,7 @@
<PackageReference Include="Avalonia.Desktop" Version="0.10.5" />
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.5" />
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.1.4349" />
- <PackageReference Include="MessageBox.Avalonia" Version="1.2.0" />
+ <PackageReference Include="MessageBox.Avalonia" Version="1.3.1" />
<PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.4" />
</ItemGroup>
<ItemGroup>
diff --git a/build/CreateRelease.WPF.ps1 b/build/CreateRelease.WPF.ps1
index f15382f..9521bea 100644
--- a/build/CreateRelease.WPF.ps1
+++ b/build/CreateRelease.WPF.ps1
@@ -33,8 +33,8 @@ Set-Location $PSScriptRoot\..
### Configuration ###
####################################
$enableMSI = $true
-#$buildOnly = $null
-#$buildOnly = "win-x64"
+#$buildOnly = 'linux-x64'
+#$buildOnly = 'win-x64'
# Profilling
$stopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
$deployStopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
@@ -51,6 +51,11 @@ $objFolder = "$project\obj\$buildWith\$netFolder"
$publishFolder = "publish"
$platformsFolder = "UVtools.Platforms"
+# Not supported yet! No fuse on WSL
+$appImageFile = 'appimagetool-x86_64.AppImage'
+$appImageFilePath = "$platformsFolder/AppImage/$appImageFile"
+$appImageUrl = "https://github.com/AppImage/AppImageKit/releases/download/continuous/$appImageFile"
+
$macIcns = "UVtools.CAD/UVtools.icns"
#$version = (Get-Command "$releaseFolder\UVtools.dll").FileVersionInfo.ProductVersion
@@ -120,6 +125,11 @@ $runtimes =
}
}
+
+# https://github.com/AppImage/AppImageKit/wiki/Bundling-.NET-Core-apps
+#Invoke-WebRequest -Uri $appImageUrl -OutFile $appImageFilePath
+#wsl chmod a+x $appImageFilePath
+
foreach ($obj in $runtimes.GetEnumerator()) {
if(![string]::IsNullOrWhiteSpace($buildOnly) -and !$buildOnly.Equals($obj.Name)) {continue}
# Configuration
@@ -154,9 +164,13 @@ Building: $runtime"
Copy-Item "$platformsFolder\$runtime\$includeObj" -Destination "$publishFolder\$runtime" -Recurse -ErrorAction Ignore
}
- Write-Output "Compressing $runtime to: $targetZip"
- Write-Output $targetZip "$publishFolder/$runtime"
-
+ #if($runtime.Equals('linux-x64')){
+ # $appDirDest = "$publishFolder/AppImage.$runtime/AppDir"
+ # Copy-Item "$platformsFolder/AppImage/AppDir" $appDirDest -Force -Recurse
+ # wsl chmod 755 "$appDirDest/AppRun"
+ # wsl cp -a "$publishFolder/$runtime/." "$appDirDest/usr/bin"
+ # wsl $appImageFilePath $appDirDest
+ #}
if($runtime.Equals('osx-x64')){
$macAppFolder = "${software}.app"
$macPublishFolder = "$publishFolder/${macAppFolder}"
@@ -179,6 +193,8 @@ Building: $runtime"
}
else {
+ Write-Output "Compressing $runtime to: $targetZip"
+ Write-Output $targetZip "$publishFolder/$runtime"
wsl cd "$publishFolder/$runtime" `&`& pwd `&`& zip -r "../../$targetZip" .
}