mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-08 17:42:31 +02:00
v3.1.0
- **Benchmark:**
- (Add) PNG, GZip, Deflate and LZ4 compress tests
- (Change) Test against a known image instead of random noise
- (Change) Single-thread tests from 100 to 200 and multi-thread tests from 1000 to 5000
- (Improvement) Same image instance is shared between tests instead of create new per test
- (Fix) Encode typo
- **Core:**
- (Add) Layer compression method: Allow to choose the compression method for layer image
- **PNG:** Compression=High Speed=Slow (Use with low RAM)
- **GZip:** Compression=Medium Speed=Medium (Optimal)
- **Deflate:** Compression=Medium Speed=Medium (Optimal)
- **LZ4:** Compression=Low Speed=Fast (Use with high RAM)
- (Improvement) Better handling on cancel operations and more immediate response
- (Fix) Extract: Zip Slip Vulnerability (CWE-22)
- **File formats:**
- (Improvement) Better handling of encode/decoding layers from zip files
- (Fix) ZCode: Canceling the file load can trigger an error
- (Fix) VDA: Unable to open vda zip files
- **Tools:**
- (Improvement) Allow operations to be aware of ROI and Masks before execution (#436)
- (Improvement) Scripting: Allow save and load profiles (#436)
- (Fix) Adjust layer height: When using the Offset type the last layer in the range was not taken in account (#435)
- **UI:**
- (Improvement) Allow layer zoom levels of 0.1x and 64x but constrain minimum zoom to the level of image fit
- (Improvement) Update change log now shows with markdown style and more readable
- (Fix) Windows MSI upgrade to this version (#432)
- (Fix) Auto-updater for Mac ARM, was downloading x64 instead
This commit is contained in:
@@ -1,5 +1,35 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 17/03/2022 - v3.1.0
|
||||||
|
|
||||||
|
- **Benchmark:**
|
||||||
|
- (Add) PNG, GZip, Deflate and LZ4 compress tests
|
||||||
|
- (Change) Test against a known image instead of random noise
|
||||||
|
- (Change) Single-thread tests from 100 to 200 and multi-thread tests from 1000 to 5000
|
||||||
|
- (Improvement) Same image instance is shared between tests instead of create new per test
|
||||||
|
- (Fix) Encode typo
|
||||||
|
- **Core:**
|
||||||
|
- (Add) Layer compression method: Allow to choose the compression method for layer image
|
||||||
|
- **PNG:** Compression=High Speed=Slow (Use with low RAM)
|
||||||
|
- **GZip:** Compression=Medium Speed=Medium (Optimal)
|
||||||
|
- **Deflate:** Compression=Medium Speed=Medium (Optimal)
|
||||||
|
- **LZ4:** Compression=Low Speed=Fast (Use with high RAM)
|
||||||
|
- (Improvement) Better handling on cancel operations and more immediate response
|
||||||
|
- (Fix) Extract: Zip Slip Vulnerability (CWE-22)
|
||||||
|
- **File formats:**
|
||||||
|
- (Improvement) Better handling of encode/decoding layers from zip files
|
||||||
|
- (Fix) ZCode: Canceling the file load can trigger an error
|
||||||
|
- (Fix) VDA: Unable to open vda zip files
|
||||||
|
- **Tools:**
|
||||||
|
- (Improvement) Allow operations to be aware of ROI and Masks before execution (#436)
|
||||||
|
- (Improvement) Scripting: Allow save and load profiles (#436)
|
||||||
|
- (Fix) Adjust layer height: When using the Offset type the last layer in the range was not taken in account (#435)
|
||||||
|
- **UI:**
|
||||||
|
- (Improvement) Allow layer zoom levels of 0.1x and 64x but constrain minimum zoom to the level of image fit
|
||||||
|
- (Improvement) Update change log now shows with markdown style and more readable
|
||||||
|
- (Fix) Windows MSI upgrade to this version (#432)
|
||||||
|
- (Fix) Auto-updater for Mac ARM, was downloading x64 instead
|
||||||
|
|
||||||
## 12/03/2022 - v3.0.0
|
## 12/03/2022 - v3.0.0
|
||||||
|
|
||||||
- **(Add) Suggestions:**
|
- **(Add) Suggestions:**
|
||||||
|
|||||||
+3
-1
@@ -70,4 +70,6 @@
|
|||||||
- Tim Anderson
|
- Tim Anderson
|
||||||
- Sakari Toivonen
|
- Sakari Toivonen
|
||||||
- Ed Wagaman
|
- Ed Wagaman
|
||||||
- Marcin Chomiczuk
|
- Marcin Chomiczuk
|
||||||
|
- Patrick Hofmann
|
||||||
|
- Ajilus
|
||||||
@@ -113,7 +113,7 @@ public class AdvancedImageBox : UserControl
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static ZoomLevelCollection Default =>
|
public static ZoomLevelCollection Default =>
|
||||||
new(new[] {
|
new(new[] {
|
||||||
7, 10, 15, 20, 25, 30, 50, 70, 100, 150, 200, 300, 400, 500, 600, 700, 800, 1200, 1600, 3200
|
7, 10, 15, 20, 25, 30, 50, 70, 100, 150, 200, 300, 400, 500, 600, 700, 800, 1200, 1600, 3200, 6400
|
||||||
});
|
});
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -276,32 +276,28 @@ public class AdvancedImageBox : UserControl
|
|||||||
/// Returns the next increased zoom level for the given current zoom.
|
/// Returns the next increased zoom level for the given current zoom.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="zoomLevel">The current zoom level.</param>
|
/// <param name="zoomLevel">The current zoom level.</param>
|
||||||
|
/// <param name="constrainZoomLevel">When positive, constrain maximum zoom to this value</param>
|
||||||
/// <returns>The next matching increased zoom level for the given current zoom if applicable, otherwise the nearest zoom.</returns>
|
/// <returns>The next matching increased zoom level for the given current zoom if applicable, otherwise the nearest zoom.</returns>
|
||||||
public int NextZoom(int zoomLevel)
|
public int NextZoom(int zoomLevel, int constrainZoomLevel = 0)
|
||||||
{
|
{
|
||||||
var index = IndexOf(FindNearest(zoomLevel));
|
var index = IndexOf(FindNearest(zoomLevel));
|
||||||
if (index < Count - 1)
|
if (index < Count - 1) index++;
|
||||||
{
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this[index];
|
return constrainZoomLevel > 0 && this[index] >= constrainZoomLevel ? constrainZoomLevel : this[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the next decreased zoom level for the given current zoom.
|
/// Returns the next decreased zoom level for the given current zoom.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="zoomLevel">The current zoom level.</param>
|
/// <param name="zoomLevel">The current zoom level.</param>
|
||||||
|
/// <param name="constrainZoomLevel">When positive, constrain minimum zoom to this value</param>
|
||||||
/// <returns>The next matching decreased zoom level for the given current zoom if applicable, otherwise the nearest zoom.</returns>
|
/// <returns>The next matching decreased zoom level for the given current zoom if applicable, otherwise the nearest zoom.</returns>
|
||||||
public int PreviousZoom(int zoomLevel)
|
public int PreviousZoom(int zoomLevel, int constrainZoomLevel = 0)
|
||||||
{
|
{
|
||||||
var index = IndexOf(FindNearest(zoomLevel));
|
var index = IndexOf(FindNearest(zoomLevel));
|
||||||
if (index > 0)
|
if (index > 0) index--;
|
||||||
{
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this[index];
|
return constrainZoomLevel > 0 && this[index] <= constrainZoomLevel ? constrainZoomLevel : this[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -842,7 +838,7 @@ public class AdvancedImageBox : UserControl
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<int> MaxZoomProperty =
|
public static readonly StyledProperty<int> MaxZoomProperty =
|
||||||
AvaloniaProperty.Register<AdvancedImageBox, int>(nameof(MaxZoom), 3500);
|
AvaloniaProperty.Register<AdvancedImageBox, int>(nameof(MaxZoom), 6400);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the maximum possible zoom.
|
/// Gets or sets the maximum possible zoom.
|
||||||
@@ -854,6 +850,18 @@ public class AdvancedImageBox : UserControl
|
|||||||
set => SetValue(MaxZoomProperty, value);
|
set => SetValue(MaxZoomProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> ConstrainZoomOutToFitLevelProperty =
|
||||||
|
AvaloniaProperty.Register<AdvancedImageBox, bool>(nameof(ConstrainZoomOutToFitLevel), true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets if the zoom out should constrain to fit image as the lowest zoom level.
|
||||||
|
/// </summary>
|
||||||
|
public bool ConstrainZoomOutToFitLevel
|
||||||
|
{
|
||||||
|
get => GetValue(ConstrainZoomOutToFitLevelProperty);
|
||||||
|
set => SetValue(ConstrainZoomOutToFitLevelProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static readonly DirectProperty<AdvancedImageBox, int> OldZoomProperty =
|
public static readonly DirectProperty<AdvancedImageBox, int> OldZoomProperty =
|
||||||
AvaloniaProperty.RegisterDirect<AdvancedImageBox, int>(
|
AvaloniaProperty.RegisterDirect<AdvancedImageBox, int>(
|
||||||
@@ -884,12 +892,14 @@ public class AdvancedImageBox : UserControl
|
|||||||
get => GetValue(ZoomProperty);
|
get => GetValue(ZoomProperty);
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
var newZoom = Math.Clamp(value, MinZoom, MaxZoom);
|
var minZoom = MinZoom;
|
||||||
|
if (ConstrainZoomOutToFitLevel) minZoom = Math.Max(ZoomLevelToFit, minZoom);
|
||||||
|
var newZoom = Math.Clamp(value, minZoom, MaxZoom);
|
||||||
|
|
||||||
var previousZoom = Zoom;
|
var previousZoom = Zoom;
|
||||||
if (previousZoom == newZoom) return;
|
if (previousZoom == newZoom) return;
|
||||||
OldZoom = previousZoom;
|
OldZoom = previousZoom;
|
||||||
SetValue(ZoomProperty, value);
|
SetValue(ZoomProperty, newZoom);
|
||||||
|
|
||||||
UpdateViewPort();
|
UpdateViewPort();
|
||||||
TriggerRender();
|
TriggerRender();
|
||||||
@@ -899,13 +909,58 @@ public class AdvancedImageBox : UserControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Gets if the image have zoom.</para>
|
||||||
|
/// <para>True if zoomed in or out</para>
|
||||||
|
/// <para>False if no zoom applied</para>
|
||||||
|
/// </summary>
|
||||||
public bool IsActualSize => Zoom == 100;
|
public bool IsActualSize => Zoom == 100;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the zoom factor, the zoom / 100
|
/// Gets the zoom factor, the zoom / 100.0
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double ZoomFactor => Zoom / 100.0;
|
public double ZoomFactor => Zoom / 100.0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the zoom to fit level which shows all the image
|
||||||
|
/// </summary>
|
||||||
|
public int ZoomLevelToFit
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!IsImageLoaded) return 100;
|
||||||
|
var image = Image!;
|
||||||
|
|
||||||
|
double zoom;
|
||||||
|
double aspectRatio;
|
||||||
|
|
||||||
|
if (image.Size.Width > image.Size.Height)
|
||||||
|
{
|
||||||
|
aspectRatio = ViewPortSize.Width / image.Size.Width;
|
||||||
|
zoom = aspectRatio * 100.0;
|
||||||
|
|
||||||
|
if (ViewPortSize.Height < image.Size.Height * zoom / 100.0)
|
||||||
|
{
|
||||||
|
aspectRatio = ViewPortSize.Height / image.Size.Height;
|
||||||
|
zoom = aspectRatio * 100.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aspectRatio = ViewPortSize.Height / image.Size.Height;
|
||||||
|
zoom = aspectRatio * 100.0;
|
||||||
|
|
||||||
|
if (ViewPortSize.Width < image.Size.Width * zoom / 100.0)
|
||||||
|
{
|
||||||
|
aspectRatio = ViewPortSize.Width / image.Size.Width;
|
||||||
|
zoom = aspectRatio * 100.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) zoom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the width of the scaled image.
|
/// Gets the width of the scaled image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1442,36 +1497,8 @@ public class AdvancedImageBox : UserControl
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void ZoomToFit()
|
public void ZoomToFit()
|
||||||
{
|
{
|
||||||
var image = Image;
|
if (!IsImageLoaded) return;
|
||||||
if (image is null) return;
|
Zoom = ZoomLevelToFit;
|
||||||
|
|
||||||
double zoom;
|
|
||||||
double aspectRatio;
|
|
||||||
|
|
||||||
if (image.Size.Width > image.Size.Height)
|
|
||||||
{
|
|
||||||
aspectRatio = ViewPortSize.Width / image.Size.Width;
|
|
||||||
zoom = aspectRatio * 100.0;
|
|
||||||
|
|
||||||
if (ViewPortSize.Height < image.Size.Height * zoom / 100.0)
|
|
||||||
{
|
|
||||||
aspectRatio = ViewPortSize.Height / image.Size.Height;
|
|
||||||
zoom = aspectRatio * 100.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
aspectRatio = ViewPortSize.Height / image.Size.Height;
|
|
||||||
zoom = aspectRatio * 100.0;
|
|
||||||
|
|
||||||
if (ViewPortSize.Width < image.Size.Width * zoom / 100.0)
|
|
||||||
{
|
|
||||||
aspectRatio = ViewPortSize.Width / image.Size.Width;
|
|
||||||
zoom = aspectRatio * 100.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Zoom = (int)zoom;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -10,11 +10,14 @@
|
|||||||
<PackageIconUrl />
|
<PackageIconUrl />
|
||||||
<RepositoryUrl>https://github.com/sn4k3/UVtools/tree/master/UVtools.AvaloniaControls</RepositoryUrl>
|
<RepositoryUrl>https://github.com/sn4k3/UVtools/tree/master/UVtools.AvaloniaControls</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<PackageTags>Advanced image box</PackageTags>
|
<PackageTags>Advanced image box; Avalonia</PackageTags>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
<Description>AvaloniaUI Controls</Description>
|
<Description>AvaloniaUI Controls
|
||||||
<Version>1.0.1</Version>
|
- AdvancedImageBox: Pan, zoom, cursor, pixel grid and selections image box</Description>
|
||||||
|
<Version>2.0.0</Version>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
@@ -49,4 +52,11 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="README.md">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath>\</PackagePath>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ using Emgu.CV.Cuda;
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using UVtools.Core.Layers;
|
||||||
|
using UVtools.Core.Operations;
|
||||||
|
|
||||||
namespace UVtools.Core;
|
namespace UVtools.Core;
|
||||||
|
|
||||||
@@ -40,6 +43,21 @@ public static class CoreSettings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static ParallelOptions ParallelOptions => new() {MaxDegreeOfParallelism = _maxDegreeOfParallelism};
|
public static ParallelOptions ParallelOptions => new() {MaxDegreeOfParallelism = _maxDegreeOfParallelism};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the ParallelOptions with <see cref="MaxDegreeOfParallelism"/> and the <see cref="CancellationToken"/> set
|
||||||
|
/// </summary>
|
||||||
|
public static ParallelOptions GetParallelOptions(CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var options = ParallelOptions;
|
||||||
|
options.CancellationToken = token;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the ParallelOptions with <see cref="MaxDegreeOfParallelism"/> and the <see cref="CancellationToken"/> set
|
||||||
|
/// </summary>
|
||||||
|
public static ParallelOptions GetParallelOptions(OperationProgress progress) => GetParallelOptions(progress.Token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets if operations run via CUDA when possible
|
/// Gets or sets if operations run via CUDA when possible
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -50,6 +68,11 @@ public static class CoreSettings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool CanUseCuda => EnableCuda && CudaInvoke.HasCuda;
|
public static bool CanUseCuda => EnableCuda && CudaInvoke.HasCuda;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default compression type for layers
|
||||||
|
/// </summary>
|
||||||
|
public static Layer.LayerCompressionMethod DefaultLayerCompressionMethod { get; set; } = Layer.LayerCompressionMethod.Png;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the default folder to save the settings
|
/// Gets the default folder to save the settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -14,6 +14,15 @@ namespace UVtools.Core;
|
|||||||
|
|
||||||
public class Enumerations
|
public class Enumerations
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets index start number
|
||||||
|
/// </summary>
|
||||||
|
public enum IndexStartNumber : byte
|
||||||
|
{
|
||||||
|
Zero,
|
||||||
|
One
|
||||||
|
}
|
||||||
|
|
||||||
public enum LayerRangeSelection : byte
|
public enum LayerRangeSelection : byte
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -60,4 +60,9 @@ public static class StreamExtensions
|
|||||||
{
|
{
|
||||||
await CopyToAsync(source, destination, DefaultCopyBufferSize, progress, cancellationToken);
|
await CopyToAsync(source, destination, DefaultCopyBufferSize, progress, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MemoryStream ToStream(this byte[] arr)
|
||||||
|
{
|
||||||
|
return new MemoryStream(arr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -103,16 +103,12 @@ public static class ZipArchiveExtensions
|
|||||||
{
|
{
|
||||||
//Gets the complete path for the destination file, including any
|
//Gets the complete path for the destination file, including any
|
||||||
//relative paths that were in the zip file
|
//relative paths that were in the zip file
|
||||||
string destinationFileName = Path.Combine(destinationPath, file.FullName);
|
var destFileName = Path.Combine(destinationPath, file.FullName);
|
||||||
|
var fullDestDirPath = Path.GetFullPath(destinationPath + Path.DirectorySeparatorChar);
|
||||||
//Gets just the new path, minus the file name so we can create the
|
if (!destFileName.StartsWith(fullDestDirPath)) return; // Entry is outside the target dir
|
||||||
//directory if it does not exist
|
|
||||||
string? destinationFilePath = Path.GetDirectoryName(destinationFileName);
|
|
||||||
|
|
||||||
destinationFilePath ??= string.Empty;
|
|
||||||
|
|
||||||
//Creates the directory (if it doesn't exist) for the new path
|
//Creates the directory (if it doesn't exist) for the new path
|
||||||
Directory.CreateDirectory(destinationFilePath);
|
Directory.CreateDirectory(fullDestDirPath);
|
||||||
|
|
||||||
//Determines what to do with the file based upon the
|
//Determines what to do with the file based upon the
|
||||||
//method of overwriting chosen
|
//method of overwriting chosen
|
||||||
@@ -120,26 +116,28 @@ public static class ZipArchiveExtensions
|
|||||||
{
|
{
|
||||||
case Overwrite.Always:
|
case Overwrite.Always:
|
||||||
//Just put the file in and overwrite anything that is found
|
//Just put the file in and overwrite anything that is found
|
||||||
file.ExtractToFile(destinationFileName, true);
|
file.ExtractToFile(destFileName, true);
|
||||||
break;
|
break;
|
||||||
case Overwrite.IfNewer:
|
case Overwrite.IfNewer:
|
||||||
//Checks to see if the file exists, and if so, if it should
|
//Checks to see if the file exists, and if so, if it should
|
||||||
//be overwritten
|
//be overwritten
|
||||||
if (!File.Exists(destinationFileName) || File.GetLastWriteTime(destinationFileName) < file.LastWriteTime)
|
if (!File.Exists(destFileName) || File.GetLastWriteTime(destFileName) < file.LastWriteTime)
|
||||||
{
|
{
|
||||||
//Either the file didn't exist or this file is newer, so
|
//Either the file didn't exist or this file is newer, so
|
||||||
//we will extract it and overwrite any existing file
|
//we will extract it and overwrite any existing file
|
||||||
file.ExtractToFile(destinationFileName, true);
|
file.ExtractToFile(destFileName, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Overwrite.Never:
|
case Overwrite.Never:
|
||||||
//Put the file in if it is new but ignores the
|
//Put the file in if it is new but ignores the
|
||||||
//file if it already exists
|
//file if it already exists
|
||||||
if (!File.Exists(destinationFileName))
|
if (!File.Exists(destFileName))
|
||||||
{
|
{
|
||||||
file.ExtractToFile(destinationFileName);
|
file.ExtractToFile(destFileName);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(overwriteMethod), overwriteMethod, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +192,7 @@ public static class ZipArchiveExtensions
|
|||||||
//Throws an error if the file exists
|
//Throws an error if the file exists
|
||||||
if (archiveExists)
|
if (archiveExists)
|
||||||
{
|
{
|
||||||
throw new IOException(String.Format("The zip file {0} already exists.", archiveFullName));
|
throw new IOException(string.Format("The zip file {0} already exists.", archiveFullName));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ArchiveAction.Ignore:
|
case ArchiveAction.Ignore:
|
||||||
|
|||||||
@@ -1169,7 +1169,7 @@ public class CTBEncryptedFile : FileFormat
|
|||||||
LayersPointer = new LayerPointer[Settings.LayerCount];
|
LayersPointer = new LayerPointer[Settings.LayerCount];
|
||||||
for (uint layerIndex = 0; layerIndex < Settings.LayerCount; layerIndex++)
|
for (uint layerIndex = 0; layerIndex < Settings.LayerCount; layerIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
LayersPointer[layerIndex] = Helpers.Deserialize<LayerPointer>(inputFile);
|
LayersPointer[layerIndex] = Helpers.Deserialize<LayerPointer>(inputFile);
|
||||||
Debug.WriteLine($"pointer[{layerIndex}]: {LayersPointer[layerIndex]}");
|
Debug.WriteLine($"pointer[{layerIndex}]: {LayersPointer[layerIndex]}");
|
||||||
progress++;
|
progress++;
|
||||||
@@ -1184,7 +1184,7 @@ public class CTBEncryptedFile : FileFormat
|
|||||||
{
|
{
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
inputFile.Seek(LayersPointer[layerIndex].LayerOffset, SeekOrigin.Begin);
|
inputFile.Seek(LayersPointer[layerIndex].LayerOffset, SeekOrigin.Begin);
|
||||||
LayersDefinition[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
LayersDefinition[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
||||||
@@ -1195,10 +1195,8 @@ public class CTBEncryptedFile : FileFormat
|
|||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
if (DecodeType == FileDecodeType.Full)
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
var layerDef = LayersDefinition[layerIndex];
|
var layerDef = LayersDefinition[layerIndex];
|
||||||
|
|
||||||
|
|
||||||
@@ -1359,9 +1357,8 @@ public class CTBEncryptedFile : FileFormat
|
|||||||
outputFile.Seek(outputFile.Position + layerTableSize, SeekOrigin.Begin);
|
outputFile.Seek(outputFile.Position + layerTableSize, SeekOrigin.Begin);
|
||||||
|
|
||||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||||
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(0, LayerCount, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var layerDef = new LayerDef(this, this[layerIndex]);
|
var layerDef = new LayerDef(this, this[layerIndex]);
|
||||||
using (var mat = this[layerIndex].LayerMat)
|
using (var mat = this[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
@@ -1375,6 +1372,7 @@ public class CTBEncryptedFile : FileFormat
|
|||||||
progress.Reset(OperationProgress.StatusWritingFile, LayerCount);
|
progress.Reset(OperationProgress.StatusWritingFile, LayerCount);
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||||
{
|
{
|
||||||
|
progress.ThrowIfCancellationRequested();
|
||||||
var layerDef = LayersDefinition[layerIndex];
|
var layerDef = LayersDefinition[layerIndex];
|
||||||
LayersPointer[layerIndex] = new LayerPointer((uint)outputFile.Position);
|
LayersPointer[layerIndex] = new LayerPointer((uint)outputFile.Position);
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ using System.IO.Compression;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using UVtools.Core.Extensions;
|
using UVtools.Core.Extensions;
|
||||||
@@ -624,7 +625,7 @@ public class CWSFile : FileFormat
|
|||||||
|
|
||||||
for (int layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
for (int layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||||
{
|
{
|
||||||
manifest.Slices[layerIndex] = new CWSManifest.Slice(this[layerIndex].FormatFileName(filename));
|
manifest.Slices[layerIndex] = new CWSManifest.Slice(this[layerIndex].FormatFileNameWithLayerDigits(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
var entry = outputFile.CreateEntry(CWSManifest.FileName);
|
var entry = outputFile.CreateEntry(CWSManifest.FileName);
|
||||||
@@ -659,16 +660,27 @@ public class CWSFile : FileFormat
|
|||||||
|
|
||||||
if (Printer == PrinterType.BeneMono)
|
if (Printer == PrinterType.BeneMono)
|
||||||
{
|
{
|
||||||
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions,
|
EncodeLayersInZip(outputFile, filename, LayerDigits, Enumerations.IndexStartNumber.Zero, progress, matGenFunc:
|
||||||
|
(_, mat) =>
|
||||||
|
{
|
||||||
|
var matEncode = new Mat(mat.Height, mat.GetRealStep() / 3, DepthType.Cv8U, 3);
|
||||||
|
var span = mat.GetDataByteSpan();
|
||||||
|
var spanEncode = matEncode.GetDataByteSpan();
|
||||||
|
for (int i = 0; i < span.Length; i++)
|
||||||
|
{
|
||||||
|
spanEncode[i] = span[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return matEncode;
|
||||||
|
});
|
||||||
|
/*Parallel.For(0, LayerCount, CoreSettings.GetParallelOptions(progress),
|
||||||
//new ParallelOptions { MaxDegreeOfParallelism = Printer == PrinterType.BeneMono ? 1 : 1 },
|
//new ParallelOptions { MaxDegreeOfParallelism = Printer == PrinterType.BeneMono ? 1 : 1 },
|
||||||
layerIndex =>
|
layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
var layer = this[layerIndex];
|
var layer = this[layerIndex];
|
||||||
var layerImagePath = layer.FormatFileName(filename);
|
var layerImagePath = layer.FormatFileNameWithLayerDigits(filename);
|
||||||
|
|
||||||
using var mat = layer.LayerMat!;
|
using var mat = layer.LayerMat;
|
||||||
using var matEncode = new Mat(mat.Height, mat.GetRealStep() / 3, DepthType.Cv8U, 3);
|
using var matEncode = new Mat(mat.Height, mat.GetRealStep() / 3, DepthType.Cv8U, 3);
|
||||||
var span = mat.GetDataByteSpan();
|
var span = mat.GetDataByteSpan();
|
||||||
var spanEncode = matEncode.GetDataByteSpan();
|
var spanEncode = matEncode.GetDataByteSpan();
|
||||||
@@ -683,18 +695,11 @@ public class CWSFile : FileFormat
|
|||||||
outputFile.PutFileContent(layerImagePath, bytes, ZipArchiveMode.Create);
|
outputFile.PutFileContent(layerImagePath, bytes, ZipArchiveMode.Create);
|
||||||
progress++;
|
progress++;
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
EncodeLayersInZip(outputFile, filename, LayerDigits, Enumerations.IndexStartNumber.Zero, progress);
|
||||||
{
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
var layer = this[layerIndex];
|
|
||||||
var layerImagePath = layer.FormatFileName(filename);
|
|
||||||
outputFile.PutFileContent(layerImagePath, layer.CompressedBytes, ZipArchiveMode.Create);
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RebuildGCode();
|
RebuildGCode();
|
||||||
@@ -822,70 +827,65 @@ public class CWSFile : FileFormat
|
|||||||
|
|
||||||
Init(OutputSettings.LayersNum, DecodeType == FileDecodeType.Partial);
|
Init(OutputSettings.LayersNum, DecodeType == FileDecodeType.Partial);
|
||||||
|
|
||||||
progress.ItemCount = OutputSettings.LayersNum;
|
if (LayerCount <= 0) return;
|
||||||
|
|
||||||
if(LayerCount > 0)
|
// Must discover png depth grayscale or color
|
||||||
|
if (DecodeType == FileDecodeType.Full && Printer == PrinterType.Unknown)
|
||||||
{
|
{
|
||||||
if (DecodeType == FileDecodeType.Full)
|
var inputFilename = Path.GetFileNameWithoutExtension(FileFullPath)!;
|
||||||
|
foreach (var pngEntry in inputFile.Entries)
|
||||||
{
|
{
|
||||||
var inputFilename = Path.GetFileNameWithoutExtension(FileFullPath)!;
|
if (!pngEntry.Name.EndsWith(".png")) continue;
|
||||||
foreach (var pngEntry in inputFile.Entries)
|
var match = Regex.Match(pngEntry.Name, @"(\d+).png");
|
||||||
{
|
if (!match.Success || match.Groups.Count < 2) continue;
|
||||||
if (!pngEntry.Name.EndsWith(".png")) continue;
|
if (!uint.TryParse(match.Groups[1].Value, out var layerIndex)) continue;
|
||||||
var filename = Path.GetFileNameWithoutExtension(pngEntry.Name).Replace(inputFilename, string.Empty, StringComparison.Ordinal);
|
|
||||||
|
|
||||||
var layerIndexStr = string.Empty;
|
|
||||||
var layerStr = filename;
|
|
||||||
for (int i = layerStr.Length - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (layerStr[i] < '0' || layerStr[i] > '9') break;
|
|
||||||
layerIndexStr = $"{layerStr[i]}{layerIndexStr}";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(layerIndexStr)) continue;
|
|
||||||
if (!uint.TryParse(layerIndexStr, out var layerIndex)) continue;
|
|
||||||
using var stream = pngEntry.Open();
|
|
||||||
this[layerIndex] = new Layer(layerIndex, stream, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GCode.ParseLayersFromGCode(this);
|
/*var filename = Path.GetFileNameWithoutExtension(pngEntry.Name).Replace(inputFilename, string.Empty, StringComparison.Ordinal);
|
||||||
|
|
||||||
var firstLayer = FirstLayer;
|
var layerIndexStr = string.Empty;
|
||||||
if (firstLayer is not null && DecodeType == FileDecodeType.Full)
|
var layerStr = filename;
|
||||||
{
|
for (int i = layerStr.Length - 1; i >= 0; i--)
|
||||||
if (Printer == PrinterType.Unknown)
|
|
||||||
{
|
{
|
||||||
using Mat mat = new ();
|
if (layerStr[i] < '0' || layerStr[i] > '9') break;
|
||||||
CvInvoke.Imdecode(firstLayer.CompressedBytes, ImreadModes.AnyColor, mat);
|
layerIndexStr = $"{layerStr[i]}{layerIndexStr}";
|
||||||
Printer = mat.NumberOfChannels == 1 ? PrinterType.Elfin : PrinterType.BeneMono;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Printer == PrinterType.BeneMono)
|
if (string.IsNullOrEmpty(layerIndexStr)) continue;
|
||||||
{
|
if (!uint.TryParse(layerIndexStr, out var layerIndex)) continue;*/
|
||||||
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
|
||||||
{
|
using var stream = pngEntry.Open();
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
using var mat = new Mat();
|
||||||
var layer = this[layerIndex];
|
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, mat);
|
||||||
using Mat mat = new();
|
Printer = mat.NumberOfChannels == 1 ? PrinterType.Elfin : PrinterType.BeneMono;
|
||||||
CvInvoke.Imdecode(layer.CompressedBytes, ImreadModes.Color, mat);
|
break;
|
||||||
using Mat matDecode = new(mat.Height, mat.GetRealStep(), DepthType.Cv8U, 1);
|
|
||||||
var span = mat.GetDataByteSpan();
|
|
||||||
var spanDecode = matDecode.GetDataByteSpan();
|
|
||||||
for (int i = 0; i < span.Length; i++)
|
|
||||||
{
|
|
||||||
spanDecode[i] = span[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
layer.LayerMat = matDecode;
|
|
||||||
layer.IsModified = false;
|
|
||||||
progress.LockAndIncrement();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBoundingRectangle(progress);
|
if (Printer == PrinterType.BeneMono)
|
||||||
|
{
|
||||||
|
DecodeLayersFromZipRegex(inputFile, @"(\d+).png", Enumerations.IndexStartNumber.Zero, progress,
|
||||||
|
(layerIndex, pngBytes) =>
|
||||||
|
{
|
||||||
|
using Mat mat = new();
|
||||||
|
CvInvoke.Imdecode(pngBytes, ImreadModes.AnyColor, mat);
|
||||||
|
var matDecode = new Mat(mat.Height, mat.GetRealStep(), DepthType.Cv8U, 1);
|
||||||
|
var span = mat.GetDataByteSpan();
|
||||||
|
var spanDecode = matDecode.GetDataByteSpan();
|
||||||
|
for (int i = 0; i < span.Length; i++)
|
||||||
|
{
|
||||||
|
spanDecode[i] = span[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return matDecode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DecodeLayersFromZipRegex(inputFile, @"(\d+).png", Enumerations.IndexStartNumber.Zero, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
GCode.ParseLayersFromGCode(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RebuildGCode()
|
public override void RebuildGCode()
|
||||||
|
|||||||
@@ -657,9 +657,8 @@ public class CXDLPFile : FileFormat
|
|||||||
var previews = new byte[ThumbnailsOriginalSize!.Length][];
|
var previews = new byte[ThumbnailsOriginalSize!.Length][];
|
||||||
|
|
||||||
// Previews
|
// Previews
|
||||||
Parallel.For(0, previews.Length, CoreSettings.ParallelOptions, previewIndex =>
|
Parallel.For(0, previews.Length, CoreSettings.GetParallelOptions(progress), previewIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var encodeLength = ThumbnailsOriginalSize[previewIndex].Area() * 2;
|
var encodeLength = ThumbnailsOriginalSize[previewIndex].Area() * 2;
|
||||||
if (Thumbnails[previewIndex] is null)
|
if (Thumbnails[previewIndex] is null)
|
||||||
{
|
{
|
||||||
@@ -707,11 +706,8 @@ public class CXDLPFile : FileFormat
|
|||||||
var layerBytes = new List<byte>[LayerCount];
|
var layerBytes = new List<byte>[LayerCount];
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var layer = this[layerIndex];
|
var layer = this[layerIndex];
|
||||||
using (var mat = layer.LayerMat)
|
using (var mat = layer.LayerMat)
|
||||||
{
|
{
|
||||||
@@ -762,8 +758,6 @@ public class CXDLPFile : FileFormat
|
|||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
});
|
});
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
outputFile.WriteBytes(layerBytes[layerIndex].ToArray());
|
outputFile.WriteBytes(layerBytes[layerIndex].ToArray());
|
||||||
@@ -892,7 +886,7 @@ public class CXDLPFile : FileFormat
|
|||||||
inputFile.Seek(2, SeekOrigin.Current);
|
inputFile.Seek(2, SeekOrigin.Current);
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.For(0, previews.Length, CoreSettings.ParallelOptions, previewIndex =>
|
Parallel.For(0, previews.Length, CoreSettings.GetParallelOptions(progress), previewIndex =>
|
||||||
{
|
{
|
||||||
Thumbnails[previewIndex] = DecodeImage(DATATYPE_RGB565_BE, previews[previewIndex], ThumbnailsOriginalSize[previewIndex]);
|
Thumbnails[previewIndex] = DecodeImage(DATATYPE_RGB565_BE, previews[previewIndex], ThumbnailsOriginalSize[previewIndex]);
|
||||||
previews[previewIndex] = null!;
|
previews[previewIndex] = null!;
|
||||||
@@ -919,23 +913,20 @@ public class CXDLPFile : FileFormat
|
|||||||
var linesBytes = new byte[LayerCount][];
|
var linesBytes = new byte[LayerCount][];
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
inputFile.Seek(4, SeekOrigin.Current);
|
inputFile.Seek(4, SeekOrigin.Current);
|
||||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||||
|
|
||||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||||
inputFile.Seek(2, SeekOrigin.Current);
|
inputFile.Seek(2, SeekOrigin.Current);
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = EmguExtensions.InitMat(Resolution))
|
using (var mat = EmguExtensions.InitMat(Resolution))
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -973,10 +964,6 @@ public class CXDLPFile : FileFormat
|
|||||||
inputFile.Seek(-Helpers.Serializer.SizeOf(FooterSettings), SeekOrigin.End);
|
inputFile.Seek(-Helpers.Serializer.SizeOf(FooterSettings), SeekOrigin.End);
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FooterSettings = Helpers.Deserialize<Footer>(inputFile);
|
FooterSettings = Helpers.Deserialize<Footer>(inputFile);
|
||||||
FooterSettings.Validate();
|
FooterSettings.Validate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -519,9 +519,8 @@ public class CXDLPv1File : FileFormat
|
|||||||
var previews = new byte[ThumbnailsOriginalSize!.Length][];
|
var previews = new byte[ThumbnailsOriginalSize!.Length][];
|
||||||
|
|
||||||
// Previews
|
// Previews
|
||||||
Parallel.For(0, previews.Length, CoreSettings.ParallelOptions, previewIndex =>
|
Parallel.For(0, previews.Length, CoreSettings.GetParallelOptions(progress), previewIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var encodeLength = ThumbnailsOriginalSize[previewIndex].Area() * 2;
|
var encodeLength = ThumbnailsOriginalSize[previewIndex].Area() * 2;
|
||||||
if (Thumbnails[previewIndex] is null)
|
if (Thumbnails[previewIndex] is null)
|
||||||
{
|
{
|
||||||
@@ -557,11 +556,8 @@ public class CXDLPv1File : FileFormat
|
|||||||
var layerBytes = new List<byte>[LayerCount];
|
var layerBytes = new List<byte>[LayerCount];
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var layer = this[layerIndex];
|
var layer = this[layerIndex];
|
||||||
using (var mat = layer.LayerMat)
|
using (var mat = layer.LayerMat)
|
||||||
{
|
{
|
||||||
@@ -610,8 +606,6 @@ public class CXDLPv1File : FileFormat
|
|||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
});
|
});
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
outputFile.WriteBytes(layerBytes[layerIndex].ToArray());
|
outputFile.WriteBytes(layerBytes[layerIndex].ToArray());
|
||||||
@@ -644,7 +638,7 @@ public class CXDLPv1File : FileFormat
|
|||||||
inputFile.Seek(2, SeekOrigin.Current);
|
inputFile.Seek(2, SeekOrigin.Current);
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.For(0, previews.Length, CoreSettings.ParallelOptions, previewIndex =>
|
Parallel.For(0, previews.Length, CoreSettings.GetParallelOptions(progress), previewIndex =>
|
||||||
{
|
{
|
||||||
Thumbnails[previewIndex] = DecodeImage(DATATYPE_RGB565_BE, previews[previewIndex], ThumbnailsOriginalSize[previewIndex]);
|
Thumbnails[previewIndex] = DecodeImage(DATATYPE_RGB565_BE, previews[previewIndex], ThumbnailsOriginalSize[previewIndex]);
|
||||||
previews[previewIndex] = null!;
|
previews[previewIndex] = null!;
|
||||||
@@ -664,10 +658,10 @@ public class CXDLPv1File : FileFormat
|
|||||||
var linesBytes = new byte[LayerCount][];
|
var linesBytes = new byte[LayerCount][];
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
inputFile.Seek(4, SeekOrigin.Current);
|
inputFile.Seek(4, SeekOrigin.Current);
|
||||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||||
|
|
||||||
@@ -675,12 +669,10 @@ public class CXDLPv1File : FileFormat
|
|||||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||||
inputFile.Seek(2, SeekOrigin.Current);
|
inputFile.Seek(2, SeekOrigin.Current);
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = EmguExtensions.InitMat(Resolution))
|
using (var mat = EmguExtensions.InitMat(Resolution))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
||||||
@@ -717,8 +709,6 @@ public class CXDLPv1File : FileFormat
|
|||||||
inputFile.Seek(-Helpers.Serializer.SizeOf(FooterSettings), SeekOrigin.End);
|
inputFile.Seek(-Helpers.Serializer.SizeOf(FooterSettings), SeekOrigin.End);
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
FooterSettings = Helpers.Deserialize<Footer>(inputFile);
|
FooterSettings = Helpers.Deserialize<Footer>(inputFile);
|
||||||
FooterSettings.Validate();
|
FooterSettings.Validate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1914,9 +1914,8 @@ public class ChituboxFile : FileFormat
|
|||||||
|
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = this[layerIndex].LayerMat)
|
using (var mat = this[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
|
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
|
||||||
@@ -1934,7 +1933,7 @@ public class ChituboxFile : FileFormat
|
|||||||
if (layerIndex == 0) layerDefSize = (uint)Helpers.Serializer.SizeOf(LayerDefinitions[0, layerIndex]);
|
if (layerIndex == 0) layerDefSize = (uint)Helpers.Serializer.SizeOf(LayerDefinitions[0, layerIndex]);
|
||||||
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
|
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var layerDef = LayerDefinitions[aaIndex, layerIndex];
|
var layerDef = LayerDefinitions[aaIndex, layerIndex];
|
||||||
LayerDef? layerDefHash = null;
|
LayerDef? layerDefHash = null;
|
||||||
@@ -2098,7 +2097,7 @@ public class ChituboxFile : FileFormat
|
|||||||
Debug.WriteLine($"-Image GROUP {aaIndex}-");
|
Debug.WriteLine($"-Image GROUP {aaIndex}-");
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
inputFile.Seek(layerOffset, SeekOrigin.Begin);
|
inputFile.Seek(layerOffset, SeekOrigin.Begin);
|
||||||
var layerDef = Helpers.Deserialize<LayerDef>(inputFile);
|
var layerDef = Helpers.Deserialize<LayerDef>(inputFile);
|
||||||
layerDef.Parent = this;
|
layerDef.Parent = this;
|
||||||
@@ -2136,16 +2135,15 @@ public class ChituboxFile : FileFormat
|
|||||||
{
|
{
|
||||||
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
|
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
inputFile.Seek(LayerDefinitions[aaIndex, layerIndex].DataAddress, SeekOrigin.Begin);
|
inputFile.Seek(LayerDefinitions[aaIndex, layerIndex].DataAddress, SeekOrigin.Begin);
|
||||||
LayerDefinitions[aaIndex, layerIndex].EncodedRle = inputFile.ReadBytes(LayerDefinitions[aaIndex, layerIndex].DataSize);
|
LayerDefinitions[aaIndex, layerIndex].EncodedRle = inputFile.ReadBytes(LayerDefinitions[aaIndex, layerIndex].DataSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = LayerDefinitions[0, layerIndex].Decode((uint)layerIndex);
|
using var mat = LayerDefinitions[0, layerIndex].Decode((uint)layerIndex);
|
||||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||||
|
|
||||||
|
|||||||
@@ -426,116 +426,87 @@ public class ChituboxZipFile : FileFormat
|
|||||||
outputFile.PutFileContent(GCodeFilename, GCodeStr, ZipArchiveMode.Create);
|
outputFile.PutFileContent(GCodeFilename, GCodeStr, ZipArchiveMode.Create);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
EncodeLayersInZip(outputFile, Enumerations.IndexStartNumber.One, progress);
|
||||||
{
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
var layer = this[layerIndex];
|
|
||||||
outputFile.PutFileContent($"{layerIndex + 1}.png", layer.CompressedBytes, ZipArchiveMode.Create);
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void DecodeInternally(OperationProgress progress)
|
protected override void DecodeInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
using (var inputFile = ZipFile.Open(FileFullPath!, ZipArchiveMode.Read))
|
using var inputFile = ZipFile.Open(FileFullPath!, ZipArchiveMode.Read);
|
||||||
|
var entry = inputFile.GetEntry(GCodeFilename);
|
||||||
|
if (entry is not null)
|
||||||
{
|
{
|
||||||
var entry = inputFile.GetEntry(GCodeFilename);
|
//Clear();
|
||||||
if (entry is not null)
|
//throw new FileLoadException("run.gcode not found", fileFullPath);
|
||||||
|
using TextReader tr = new StreamReader(entry.Open());
|
||||||
|
string? line;
|
||||||
|
GCode!.Clear();
|
||||||
|
while ((line = tr.ReadLine()) != null)
|
||||||
{
|
{
|
||||||
//Clear();
|
GCode.AppendLine(line);
|
||||||
//throw new FileLoadException("run.gcode not found", fileFullPath);
|
if (string.IsNullOrEmpty(line)) continue;
|
||||||
using TextReader tr = new StreamReader(entry.Open());
|
|
||||||
string? line;
|
if (line[0] != ';')
|
||||||
GCode!.Clear();
|
|
||||||
while ((line = tr.ReadLine()) != null)
|
|
||||||
{
|
{
|
||||||
GCode.AppendLine(line);
|
continue;
|
||||||
if (string.IsNullOrEmpty(line)) continue;
|
|
||||||
|
|
||||||
if (line[0] != ';')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var splitLine = line.Split(':');
|
|
||||||
if (splitLine.Length < 2) continue;
|
|
||||||
|
|
||||||
foreach (var propertyInfo in HeaderSettings.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
|
||||||
{
|
|
||||||
var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
|
|
||||||
if (displayNameAttribute is null) continue;
|
|
||||||
if (!splitLine[0].Trim(' ', ';').Equals(displayNameAttribute.DisplayName)) continue;
|
|
||||||
Helpers.SetPropertyValue(propertyInfo, HeaderSettings, splitLine[1].Trim());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tr.Close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IsPHZZip = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HeaderSettings.LayerCount == 0)
|
var splitLine = line.Split(':');
|
||||||
{
|
if (splitLine.Length < 2) continue;
|
||||||
foreach (var zipEntry in inputFile.Entries)
|
|
||||||
|
foreach (var propertyInfo in HeaderSettings.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
||||||
{
|
{
|
||||||
if(!zipEntry.Name.EndsWith(".png")) continue;
|
var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
|
||||||
var filename = Path.GetFileNameWithoutExtension(zipEntry.Name);
|
if (displayNameAttribute is null) continue;
|
||||||
if (!filename.All(char.IsDigit)) continue;
|
if (!splitLine[0].Trim(' ', ';').Equals(displayNameAttribute.DisplayName)) continue;
|
||||||
if (!uint.TryParse(filename, out var layerIndex)) continue;
|
Helpers.SetPropertyValue(propertyInfo, HeaderSettings, splitLine[1].Trim());
|
||||||
HeaderSettings.LayerCount = Math.Max(HeaderSettings.LayerCount, layerIndex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tr.Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IsPHZZip = true;
|
||||||
|
}
|
||||||
|
|
||||||
Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
if (HeaderSettings.LayerCount == 0)
|
||||||
|
{
|
||||||
progress.ItemCount = LayerCount;
|
foreach (var zipEntry in inputFile.Entries)
|
||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
|
||||||
{
|
{
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
if(!zipEntry.Name.EndsWith(".png")) continue;
|
||||||
{
|
var filename = Path.GetFileNameWithoutExtension(zipEntry.Name);
|
||||||
if (progress.Token.IsCancellationRequested) break;
|
if (!filename.All(char.IsDigit)) continue;
|
||||||
entry = inputFile.GetEntry($"{layerIndex + 1}.png");
|
if (!uint.TryParse(filename, out var layerIndex)) continue;
|
||||||
if (entry is null)
|
HeaderSettings.LayerCount = Math.Max(HeaderSettings.LayerCount, layerIndex);
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
throw new FileLoadException($"Layer {layerIndex + 1} not found", FileFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
using var stream = entry.Open();
|
|
||||||
this[layerIndex] = new Layer(layerIndex, stream, this);
|
|
||||||
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsPHZZip) // PHZ file
|
|
||||||
{
|
|
||||||
RebuildLayersProperties();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GCode?.ParseLayersFromGCode(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = inputFile.GetEntry("preview.png");
|
|
||||||
if (entry is not null)
|
|
||||||
{
|
|
||||||
Thumbnails![0] = new Mat();
|
|
||||||
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = inputFile.GetEntry("preview_cropping.png");
|
|
||||||
if (entry is not null)
|
|
||||||
{
|
|
||||||
var count = CreatedThumbnailsCount;
|
|
||||||
Thumbnails![count] = new Mat();
|
|
||||||
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[count]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBoundingRectangle(progress);
|
Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||||
|
|
||||||
|
DecodeLayersFromZip(inputFile, Enumerations.IndexStartNumber.One, progress);
|
||||||
|
|
||||||
|
if (IsPHZZip) // PHZ file
|
||||||
|
{
|
||||||
|
RebuildLayersProperties();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GCode?.ParseLayersFromGCode(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = inputFile.GetEntry("preview.png");
|
||||||
|
if (entry is not null)
|
||||||
|
{
|
||||||
|
Thumbnails![0] = new Mat();
|
||||||
|
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = inputFile.GetEntry("preview_cropping.png");
|
||||||
|
if (entry is not null)
|
||||||
|
{
|
||||||
|
var count = CreatedThumbnailsCount;
|
||||||
|
Thumbnails![count] = new Mat();
|
||||||
|
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[count]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RebuildGCode()
|
public override void RebuildGCode()
|
||||||
|
|||||||
@@ -976,9 +976,8 @@ public class FDGFile : FileFormat
|
|||||||
|
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = this[layerIndex].LayerMat)
|
using (var mat = this[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
LayersDefinitions[layerIndex] = new LayerDef(this, this[layerIndex]);
|
LayersDefinitions[layerIndex] = new LayerDef(this, this[layerIndex]);
|
||||||
@@ -989,7 +988,7 @@ public class FDGFile : FileFormat
|
|||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var layerDef = LayersDefinitions[layerIndex];
|
var layerDef = LayersDefinitions[layerIndex];
|
||||||
LayerDef? layerDefHash = null;
|
LayerDef? layerDefHash = null;
|
||||||
@@ -1089,7 +1088,7 @@ public class FDGFile : FileFormat
|
|||||||
{
|
{
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var layerDef = Helpers.Deserialize<LayerDef>(inputFile);
|
var layerDef = Helpers.Deserialize<LayerDef>(inputFile);
|
||||||
layerDef.Parent = this;
|
layerDef.Parent = this;
|
||||||
@@ -1107,9 +1106,8 @@ public class FDGFile : FileFormat
|
|||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
if (DecodeType == FileDecodeType.Full)
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
if (DecodeType == FileDecodeType.Full)
|
||||||
{
|
{
|
||||||
using var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex);
|
using var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex);
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ using System.Diagnostics;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
using UVtools.Core.EmguCV;
|
using UVtools.Core.EmguCV;
|
||||||
@@ -3229,7 +3231,7 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
|
|||||||
|
|
||||||
DecodeInternally(progress);
|
DecodeInternally(progress);
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var layerHeightDigits = LayerHeight.DecimalDigits();
|
var layerHeightDigits = LayerHeight.DecimalDigits();
|
||||||
if (layerHeightDigits > Layer.HeightPrecision)
|
if (layerHeightDigits > Layer.HeightPrecision)
|
||||||
@@ -3243,8 +3245,128 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
|
|||||||
{
|
{
|
||||||
Save(progress);
|
Save(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetBoundingRectangle(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EncodeLayersInZip(ZipArchive zipArchive, string prepend, byte padDigits, Enumerations.IndexStartNumber layerIndexStartNumber = default,
|
||||||
|
OperationProgress? progress = null, string path = "", Func<uint, Mat, Mat>? matGenFunc = null)
|
||||||
|
{
|
||||||
|
if (DecodeType != FileDecodeType.Full || LayerCount == 0) return;
|
||||||
|
progress ??= new OperationProgress();
|
||||||
|
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||||
|
var batches = BatchLayersIndexes();
|
||||||
|
var pngLayerBytes = new byte[LayerCount][];
|
||||||
|
foreach (var batch in batches)
|
||||||
|
{
|
||||||
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
|
{
|
||||||
|
if (matGenFunc is null)
|
||||||
|
{
|
||||||
|
pngLayerBytes[layerIndex] = this[layerIndex].CompressedPngBytes!;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using var mat = this[layerIndex].LayerMat;
|
||||||
|
using var newMat = matGenFunc.Invoke((uint) layerIndex, mat);
|
||||||
|
pngLayerBytes[layerIndex] = newMat.GetPngByes();
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.LockAndIncrement();
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var layerIndex in batch)
|
||||||
|
{
|
||||||
|
zipArchive.PutFileContent(Path.Combine(path, this[layerIndex].FormatFileName(prepend, padDigits, layerIndexStartNumber)), pngLayerBytes[layerIndex], ZipArchiveMode.Create);
|
||||||
|
pngLayerBytes[layerIndex] = null!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EncodeLayersInZip(ZipArchive zipArchive, byte padDigits, Enumerations.IndexStartNumber layerIndexStartNumber = default, OperationProgress? progress = null, string path = "", Func<uint, Mat, Mat>? matGenFunc = null)
|
||||||
|
=> EncodeLayersInZip(zipArchive, string.Empty, padDigits, layerIndexStartNumber, progress, path, matGenFunc);
|
||||||
|
|
||||||
|
public void EncodeLayersInZip(ZipArchive zipArchive, string prepend, Enumerations.IndexStartNumber layerIndexStartNumber = default, OperationProgress? progress = null, string path = "", Func<uint, Mat, Mat>? matGenFunc = null)
|
||||||
|
=> EncodeLayersInZip(zipArchive, prepend, 0, layerIndexStartNumber, progress, path, matGenFunc);
|
||||||
|
|
||||||
|
public void EncodeLayersInZip(ZipArchive zipArchive, Enumerations.IndexStartNumber layerIndexStartNumber, OperationProgress? progress = null, string path = "", Func<uint, Mat, Mat>? matGenFunc = null)
|
||||||
|
=> EncodeLayersInZip(zipArchive, string.Empty, 0, layerIndexStartNumber, progress, path, matGenFunc);
|
||||||
|
|
||||||
|
public void EncodeLayersInZip(ZipArchive zipArchive, OperationProgress progress, string path = "", Func<uint, Mat, Mat>? matGenFunc = null)
|
||||||
|
=> EncodeLayersInZip(zipArchive, string.Empty, 0, Enumerations.IndexStartNumber.Zero, progress, path, matGenFunc);
|
||||||
|
|
||||||
|
|
||||||
|
public void DecodeLayersFromZip(ZipArchiveEntry[] layerEntries, OperationProgress? progress = null, Func<uint, byte[], Mat>? matGenFunc = null)
|
||||||
|
{
|
||||||
|
if (DecodeType != FileDecodeType.Full || LayerCount == 0) return;
|
||||||
|
progress ??= new OperationProgress();
|
||||||
|
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||||
|
|
||||||
|
Parallel.For(0, LayerCount, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
|
{
|
||||||
|
byte[] pngBytes;
|
||||||
|
lock (Mutex)
|
||||||
|
{
|
||||||
|
using var stream = layerEntries[layerIndex].Open();
|
||||||
|
pngBytes = stream.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matGenFunc is null)
|
||||||
|
{
|
||||||
|
this[layerIndex] = new Layer((uint)layerIndex, pngBytes, this);
|
||||||
|
}
|
||||||
|
if (matGenFunc is not null)
|
||||||
|
{
|
||||||
|
using var mat = matGenFunc.Invoke((uint) layerIndex, pngBytes);
|
||||||
|
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.LockAndIncrement();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecodeLayersFromZipRegex(ZipArchive zipArchive, string regex, Enumerations.IndexStartNumber layerIndexStartNumber = Enumerations.IndexStartNumber.Zero, OperationProgress? progress = null, Func<uint, byte[], Mat>? matGenFunc = null)
|
||||||
|
{
|
||||||
|
var layerEntries = new ZipArchiveEntry?[LayerCount];
|
||||||
|
|
||||||
|
foreach (var entry in zipArchive.Entries)
|
||||||
|
{
|
||||||
|
var match = Regex.Match(entry.Name, regex);
|
||||||
|
if (!match.Success || match.Groups.Count < 2) continue;
|
||||||
|
if (!uint.TryParse(match.Groups[1].Value, out var layerIndex)) continue;
|
||||||
|
|
||||||
|
if (layerIndexStartNumber == Enumerations.IndexStartNumber.One && layerIndex > 0) layerIndex--;
|
||||||
|
if (layerIndex >= LayerCount)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
layerEntries[layerIndex] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||||
|
{
|
||||||
|
if (layerEntries[layerIndex] is not null) continue;
|
||||||
|
Clear();
|
||||||
|
throw new FileLoadException($"Layer {layerIndex} not found", FileFullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DecodeLayersFromZip(layerEntries!, progress, matGenFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecodeLayersFromZip(ZipArchive zipArchive, byte padDigits, Enumerations.IndexStartNumber layerIndexStartNumber = Enumerations.IndexStartNumber.Zero, OperationProgress? progress = null, Func<uint, byte[], Mat>? matGenFunc = null)
|
||||||
|
=> DecodeLayersFromZipRegex(zipArchive, $@"(\d{{{padDigits}}}).png", layerIndexStartNumber, progress, matGenFunc);
|
||||||
|
|
||||||
|
public void DecodeLayersFromZip(ZipArchive zipArchive, Enumerations.IndexStartNumber layerIndexStartNumber = Enumerations.IndexStartNumber.Zero, OperationProgress? progress = null, Func<uint, byte[], Mat>? matGenFunc = null)
|
||||||
|
=> DecodeLayersFromZipRegex(zipArchive, @"^(\d+).png", layerIndexStartNumber, progress, matGenFunc);
|
||||||
|
|
||||||
|
public void DecodeLayersFromZip(ZipArchive zipArchive, string prepend, Enumerations.IndexStartNumber layerIndexStartNumber = Enumerations.IndexStartNumber.Zero, OperationProgress? progress = null, Func<uint, byte[], Mat>? matGenFunc = null)
|
||||||
|
=> DecodeLayersFromZipRegex(zipArchive, $@"^{Regex.Escape(prepend)}(\d+).png", layerIndexStartNumber, progress, matGenFunc);
|
||||||
|
|
||||||
|
public void DecodeLayersFromZip(ZipArchive zipArchive, OperationProgress progress, Func<uint, byte[], Mat>? matGenFunc = null)
|
||||||
|
=> DecodeLayersFromZipRegex(zipArchive, @"^(\d+).png", Enumerations.IndexStartNumber.Zero, progress, matGenFunc);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extract contents to a folder
|
/// Extract contents to a folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3389,10 +3511,9 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
|
|||||||
|
|
||||||
if (LayerCount > 0 && DecodeType == FileDecodeType.Full)
|
if (LayerCount > 0 && DecodeType == FileDecodeType.Full)
|
||||||
{
|
{
|
||||||
Parallel.ForEach(this, CoreSettings.ParallelOptions, layer =>
|
Parallel.ForEach(this, CoreSettings.GetParallelOptions(progress), layer =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
var byteArr = layer.CompressedPngBytes;
|
||||||
var byteArr = layer.CompressedBytes;
|
|
||||||
if (byteArr is null) return;
|
if (byteArr is null) return;
|
||||||
using var stream = new FileStream(Path.Combine(path, layer.Filename), FileMode.Create, FileAccess.Write);
|
using var stream = new FileStream(Path.Combine(path, layer.Filename), FileMode.Create, FileAccess.Write);
|
||||||
stream.Write(byteArr, 0, byteArr.Length);
|
stream.Write(byteArr, 0, byteArr.Length);
|
||||||
@@ -4366,6 +4487,23 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
|
|||||||
public FileFormat? Convert(FileFormat to, string fileFullPath, uint version = 0, OperationProgress? progress = null)
|
public FileFormat? Convert(FileFormat to, string fileFullPath, uint version = 0, OperationProgress? progress = null)
|
||||||
=> Convert(to.GetType(), fileFullPath, version, progress);
|
=> Convert(to.GetType(), fileFullPath, version, progress);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the compression method of all layers to a new method
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="to">The new method to change to</param>
|
||||||
|
/// <param name="progress"></param>
|
||||||
|
public void ChangeLayersCompressionMethod(Layer.LayerCompressionMethod to, OperationProgress? progress = null)
|
||||||
|
{
|
||||||
|
progress ??= new OperationProgress($"Changing layers compress method to {to}");
|
||||||
|
progress.Reset("Layers", LayerCount);
|
||||||
|
|
||||||
|
Parallel.ForEach(this, CoreSettings.GetParallelOptions(progress), layer =>
|
||||||
|
{
|
||||||
|
layer.CompressionMethod = to;
|
||||||
|
progress.LockAndIncrement();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Validate AntiAlias Level
|
/// Validate AntiAlias Level
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -4598,21 +4736,12 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
|
|||||||
if (_boundingRectangle.IsEmpty) // Safe checking, all layers haven't a bounding rectangle
|
if (_boundingRectangle.IsEmpty) // Safe checking, all layers haven't a bounding rectangle
|
||||||
{
|
{
|
||||||
progress.Reset(OperationProgress.StatusOptimizingBounds, LayerCount - 1);
|
progress.Reset(OperationProgress.StatusOptimizingBounds, LayerCount - 1);
|
||||||
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(0, LayerCount, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
this[layerIndex].GetBoundingRectangle();
|
this[layerIndex].GetBoundingRectangle();
|
||||||
|
|
||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (progress.Token.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
_boundingRectangle = Rectangle.Empty;
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
}
|
|
||||||
|
|
||||||
FindFirstBoundingRectangle();
|
FindFirstBoundingRectangle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4960,10 +5089,11 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mats"></param>
|
/// <param name="mats"></param>
|
||||||
/// <returns>The new Layer array</returns>
|
/// <returns>The new Layer array</returns>
|
||||||
public Layer[] AllocateFromMat(Mat[] mats)
|
public Layer[] AllocateFromMat(Mat[] mats, OperationProgress? progress = null)
|
||||||
{
|
{
|
||||||
|
progress ??= new OperationProgress();
|
||||||
var layers = new Layer[mats.Length];
|
var layers = new Layer[mats.Length];
|
||||||
Parallel.For(0, mats.Length, CoreSettings.ParallelOptions, i =>
|
Parallel.For(0, mats.Length, CoreSettings.GetParallelOptions(progress), i =>
|
||||||
{
|
{
|
||||||
layers[i] = new Layer((uint)i, mats[i], this);
|
layers[i] = new Layer((uint)i, mats[i], this);
|
||||||
});
|
});
|
||||||
@@ -4976,9 +5106,9 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mats"></param>
|
/// <param name="mats"></param>
|
||||||
/// /// <returns>The new Layer array</returns>
|
/// /// <returns>The new Layer array</returns>
|
||||||
public Layer[] AllocateAndSetFromMat(Mat[] mats)
|
public Layer[] AllocateAndSetFromMat(Mat[] mats, OperationProgress? progress = null)
|
||||||
{
|
{
|
||||||
var layers = AllocateFromMat(mats);
|
var layers = AllocateFromMat(mats, progress);
|
||||||
Layers = layers;
|
Layers = layers;
|
||||||
return layers;
|
return layers;
|
||||||
}
|
}
|
||||||
@@ -5349,7 +5479,7 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
|
|||||||
}
|
}
|
||||||
|
|
||||||
progress.Reset("Saving", (uint)modifiedLayers.Count);
|
progress.Reset("Saving", (uint)modifiedLayers.Count);
|
||||||
Parallel.ForEach(modifiedLayers, CoreSettings.ParallelOptions, modifiedLayer =>
|
Parallel.ForEach(modifiedLayers, CoreSettings.GetParallelOptions(progress), modifiedLayer =>
|
||||||
{
|
{
|
||||||
this[modifiedLayer.Key].LayerMat = modifiedLayer.Value;
|
this[modifiedLayer.Key].LayerMat = modifiedLayer.Value;
|
||||||
modifiedLayer.Value.Dispose();
|
modifiedLayer.Value.Dispose();
|
||||||
|
|||||||
@@ -503,10 +503,8 @@ public class FlashForgeSVGXFile : FileFormat
|
|||||||
SVGDocument.Groups = new List<FlashForgeSVGXSvgGroup> { new("background") };
|
SVGDocument.Groups = new List<FlashForgeSVGXSvgGroup> { new("background") };
|
||||||
var groups = new FlashForgeSVGXSvgGroup[LayerCount];
|
var groups = new FlashForgeSVGXSvgGroup[LayerCount];
|
||||||
|
|
||||||
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(0, LayerCount, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
groups[layerIndex] = new FlashForgeSVGXSvgGroup($"layer-{layerIndex}");
|
groups[layerIndex] = new FlashForgeSVGXSvgGroup($"layer-{layerIndex}");
|
||||||
|
|
||||||
using var mat = this[layerIndex].LayerMat;
|
using var mat = this[layerIndex].LayerMat;
|
||||||
@@ -651,10 +649,8 @@ public class FlashForgeSVGXFile : FileFormat
|
|||||||
|
|
||||||
if (DecodeType != FileDecodeType.Full) return;
|
if (DecodeType != FileDecodeType.Full) return;
|
||||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||||
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(0, LayerCount, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
var mat = EmguExtensions.InitMat(Resolution);
|
var mat = EmguExtensions.InitMat(Resolution);
|
||||||
|
|
||||||
var group = SVGDocument.Groups.FirstOrDefault(g => g.Id == $"layer-{layerIndex}");
|
var group = SVGDocument.Groups.FirstOrDefault(g => g.Id == $"layer-{layerIndex}");
|
||||||
@@ -665,7 +661,7 @@ public class FlashForgeSVGXFile : FileFormat
|
|||||||
var points = new List<Point>();
|
var points = new List<Point>();
|
||||||
foreach (var path in @group.Paths)
|
foreach (var path in @group.Paths)
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) break;
|
progress.ThrowIfCancellationRequested();
|
||||||
var spaceSplit = path.Value.Split(' ',
|
var spaceSplit = path.Value.Split(' ',
|
||||||
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
@@ -727,8 +723,6 @@ public class FlashForgeSVGXFile : FileFormat
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -364,9 +364,8 @@ public class GR1File : FileFormat
|
|||||||
var previews = new byte[ThumbnailsOriginalSize!.Length][];
|
var previews = new byte[ThumbnailsOriginalSize!.Length][];
|
||||||
|
|
||||||
// Previews
|
// Previews
|
||||||
Parallel.For(0, previews.Length, CoreSettings.ParallelOptions, previewIndex =>
|
Parallel.For(0, previews.Length, CoreSettings.GetParallelOptions(progress), previewIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var encodeLength = ThumbnailsOriginalSize[previewIndex].Area() * 2;
|
var encodeLength = ThumbnailsOriginalSize[previewIndex].Area() * 2;
|
||||||
if (Thumbnails[previewIndex] is null)
|
if (Thumbnails[previewIndex] is null)
|
||||||
{
|
{
|
||||||
@@ -396,11 +395,8 @@ public class GR1File : FileFormat
|
|||||||
var layerBytes = new List<byte>[LayerCount];
|
var layerBytes = new List<byte>[LayerCount];
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var layer = this[layerIndex];
|
var layer = this[layerIndex];
|
||||||
using (var mat = layer.LayerMat)
|
using (var mat = layer.LayerMat)
|
||||||
{
|
{
|
||||||
@@ -446,8 +442,6 @@ public class GR1File : FileFormat
|
|||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
});
|
});
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
outputFile.WriteBytes(layerBytes[layerIndex].ToArray());
|
outputFile.WriteBytes(layerBytes[layerIndex].ToArray());
|
||||||
@@ -482,7 +476,7 @@ public class GR1File : FileFormat
|
|||||||
inputFile.Seek(2, SeekOrigin.Current);
|
inputFile.Seek(2, SeekOrigin.Current);
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.For(0, previews.Length, CoreSettings.ParallelOptions, previewIndex =>
|
Parallel.For(0, previews.Length, CoreSettings.GetParallelOptions(progress), previewIndex =>
|
||||||
{
|
{
|
||||||
Thumbnails[previewIndex] = DecodeImage(DATATYPE_RGB565_BE, previews[previewIndex], ThumbnailsOriginalSize[previewIndex]);
|
Thumbnails[previewIndex] = DecodeImage(DATATYPE_RGB565_BE, previews[previewIndex], ThumbnailsOriginalSize[previewIndex]);
|
||||||
previews[previewIndex] = null!;
|
previews[previewIndex] = null!;
|
||||||
@@ -500,22 +494,18 @@ public class GR1File : FileFormat
|
|||||||
var linesBytes = new byte[LayerCount][];
|
var linesBytes = new byte[LayerCount][];
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
|
progress.ThrowIfCancellationRequested();
|
||||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||||
|
|
||||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||||
inputFile.Seek(2, SeekOrigin.Current);
|
inputFile.Seek(2, SeekOrigin.Current);
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = EmguExtensions.InitMat(Resolution);
|
using var mat = EmguExtensions.InitMat(Resolution);
|
||||||
|
|
||||||
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
||||||
|
|||||||
@@ -167,6 +167,7 @@ public class GenericZIPFile : FileFormat
|
|||||||
{
|
{
|
||||||
if (entry.Name == ManifestFileName) return true;
|
if (entry.Name == ManifestFileName) return true;
|
||||||
if (entry.Name.EndsWith(".gcode")) return false;
|
if (entry.Name.EndsWith(".gcode")) return false;
|
||||||
|
if (entry.Name.EndsWith(".xml")) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -201,14 +202,7 @@ public class GenericZIPFile : FileFormat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
EncodeLayersInZip(outputFile, Enumerations.IndexStartNumber.One, progress);
|
||||||
{
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
var layer = this[layerIndex];
|
|
||||||
var filename = $"{layerIndex + 1}.png";
|
|
||||||
outputFile.PutFileContent(filename, layer.CompressedBytes, ZipArchiveMode.Create);
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ManifestFile.Update();
|
ManifestFile.Update();
|
||||||
|
|
||||||
@@ -219,81 +213,56 @@ public class GenericZIPFile : FileFormat
|
|||||||
|
|
||||||
protected override void DecodeInternally(OperationProgress progress)
|
protected override void DecodeInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
using (var inputFile = ZipFile.Open(FileFullPath!, ZipArchiveMode.Read))
|
using var inputFile = ZipFile.Open(FileFullPath!, ZipArchiveMode.Read);
|
||||||
|
var entry = inputFile.Entries.FirstOrDefault(zipEntry => zipEntry.Name == ManifestFileName);
|
||||||
|
if (entry is not null)
|
||||||
{
|
{
|
||||||
var entry = inputFile.Entries.FirstOrDefault(zipEntry => zipEntry.Name == ManifestFileName);
|
try
|
||||||
if (entry is not null)
|
|
||||||
{
|
{
|
||||||
try
|
using var stream = entry.Open();
|
||||||
{
|
ManifestFile = XmlExtensions.DeserializeFromStream<GenericZipManifest>(stream);
|
||||||
using var stream = entry.Open();
|
|
||||||
ManifestFile = XmlExtensions.DeserializeFromStream<GenericZipManifest>(stream);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// Not required
|
|
||||||
//Clear();
|
|
||||||
//throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
uint layerCount = 0;
|
|
||||||
foreach (var zipEntry in inputFile.Entries)
|
|
||||||
{
|
{
|
||||||
if (!zipEntry.Name.EndsWith(".png")) continue;
|
// Not required
|
||||||
var filename = Path.GetFileNameWithoutExtension(zipEntry.Name);
|
//Clear();
|
||||||
if (!filename.All(char.IsDigit)) continue;
|
//throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
|
||||||
if (!uint.TryParse(filename, out var layerIndex)) continue;
|
|
||||||
layerCount = Math.Max(layerCount, layerIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layerCount == 0)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
throw new FileLoadException("Unable to detect layer images in the file", FileFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
Init(layerCount, DecodeType == FileDecodeType.Partial);
|
|
||||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
|
||||||
|
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
|
||||||
{
|
|
||||||
if (progress.Token.IsCancellationRequested) break;
|
|
||||||
var filename = $"{layerIndex + 1}.png";
|
|
||||||
entry = inputFile.GetEntry(filename);
|
|
||||||
if (entry is null)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
throw new FileLoadException($"Layer {filename} not found", FileFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
|
||||||
{
|
|
||||||
using var stream = entry.Open();
|
|
||||||
this[layerIndex] = new Layer(layerIndex, stream, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = inputFile.GetEntry("preview.png");
|
|
||||||
if (entry is not null)
|
|
||||||
{
|
|
||||||
Thumbnails[0] = new Mat();
|
|
||||||
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = inputFile.GetEntry("preview_cropping.png");
|
|
||||||
if (entry is not null)
|
|
||||||
{
|
|
||||||
var count = CreatedThumbnailsCount;
|
|
||||||
Thumbnails[count] = new Mat();
|
|
||||||
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[count]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBoundingRectangle(progress);
|
uint layerCount = 0;
|
||||||
|
foreach (var zipEntry in inputFile.Entries)
|
||||||
|
{
|
||||||
|
if (!zipEntry.Name.EndsWith(".png")) continue;
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(zipEntry.Name);
|
||||||
|
if (!filename.All(char.IsDigit)) continue;
|
||||||
|
if (!uint.TryParse(filename, out var layerIndex)) continue;
|
||||||
|
layerCount = Math.Max(layerCount, layerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layerCount == 0)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
throw new FileLoadException("Unable to detect layer images in the file", FileFullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Init(layerCount, DecodeType == FileDecodeType.Partial);
|
||||||
|
DecodeLayersFromZip(inputFile, Enumerations.IndexStartNumber.One, progress);
|
||||||
|
|
||||||
|
entry = inputFile.GetEntry("preview.png");
|
||||||
|
if (entry is not null)
|
||||||
|
{
|
||||||
|
Thumbnails[0] = new Mat();
|
||||||
|
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = inputFile.GetEntry("preview_cropping.png");
|
||||||
|
if (entry is not null)
|
||||||
|
{
|
||||||
|
var count = CreatedThumbnailsCount;
|
||||||
|
Thumbnails[count] = new Mat();
|
||||||
|
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[count]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PartialSaveInternally(OperationProgress progress)
|
protected override void PartialSaveInternally(OperationProgress progress)
|
||||||
|
|||||||
@@ -530,9 +530,8 @@ public class LGSFile : FileFormat
|
|||||||
|
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = this[layerIndex].LayerMat)
|
using (var mat = this[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
layerData[layerIndex] = new LayerDef(this);
|
layerData[layerIndex] = new LayerDef(this);
|
||||||
@@ -543,7 +542,7 @@ public class LGSFile : FileFormat
|
|||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
outputFile.WriteSerialize(layerData[layerIndex]);
|
outputFile.WriteSerialize(layerData[layerIndex]);
|
||||||
layerData[layerIndex].EncodedRle = null!; // Free this
|
layerData[layerIndex].EncodedRle = null!; // Free this
|
||||||
}
|
}
|
||||||
@@ -555,7 +554,7 @@ public class LGSFile : FileFormat
|
|||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
outputFile.WriteSerialize(layerData[layerIndex]);
|
outputFile.WriteSerialize(layerData[layerIndex]);
|
||||||
progress++;
|
progress++;
|
||||||
}
|
}
|
||||||
@@ -604,15 +603,14 @@ public class LGSFile : FileFormat
|
|||||||
{
|
{
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
layerData[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
layerData[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
||||||
layerData[layerIndex].Parent = this;
|
layerData[layerIndex].Parent = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = layerData[layerIndex].Decode();
|
using var mat = layerData[layerIndex].Decode();
|
||||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||||
|
|
||||||
|
|||||||
@@ -323,9 +323,8 @@ public class MDLPFile : FileFormat
|
|||||||
var previews = new byte[ThumbnailsOriginalSize!.Length][];
|
var previews = new byte[ThumbnailsOriginalSize!.Length][];
|
||||||
|
|
||||||
// Previews
|
// Previews
|
||||||
Parallel.For(0, previews.Length, CoreSettings.ParallelOptions, previewIndex =>
|
Parallel.For(0, previews.Length, CoreSettings.GetParallelOptions(progress), previewIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var encodeLength = ThumbnailsOriginalSize[previewIndex].Area() * 2;
|
var encodeLength = ThumbnailsOriginalSize[previewIndex].Area() * 2;
|
||||||
if (Thumbnails[previewIndex] is null)
|
if (Thumbnails[previewIndex] is null)
|
||||||
{
|
{
|
||||||
@@ -355,11 +354,8 @@ public class MDLPFile : FileFormat
|
|||||||
var layerBytes = new List<byte>[LayerCount];
|
var layerBytes = new List<byte>[LayerCount];
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var layer = this[layerIndex];
|
var layer = this[layerIndex];
|
||||||
using (var mat = layer.LayerMat)
|
using (var mat = layer.LayerMat)
|
||||||
{
|
{
|
||||||
@@ -405,8 +401,6 @@ public class MDLPFile : FileFormat
|
|||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
});
|
});
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
outputFile.WriteBytes(layerBytes[layerIndex].ToArray());
|
outputFile.WriteBytes(layerBytes[layerIndex].ToArray());
|
||||||
@@ -439,7 +433,7 @@ public class MDLPFile : FileFormat
|
|||||||
inputFile.Seek(2, SeekOrigin.Current);
|
inputFile.Seek(2, SeekOrigin.Current);
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.For(0, previews.Length, CoreSettings.ParallelOptions, previewIndex =>
|
Parallel.For(0, previews.Length, CoreSettings.GetParallelOptions(progress), previewIndex =>
|
||||||
{
|
{
|
||||||
Thumbnails[previewIndex] = DecodeImage(DATATYPE_RGB565_BE, previews[previewIndex], ThumbnailsOriginalSize[previewIndex]);
|
Thumbnails[previewIndex] = DecodeImage(DATATYPE_RGB565_BE, previews[previewIndex], ThumbnailsOriginalSize[previewIndex]);
|
||||||
previews[previewIndex] = null!;
|
previews[previewIndex] = null!;
|
||||||
@@ -456,22 +450,19 @@ public class MDLPFile : FileFormat
|
|||||||
var linesBytes = new byte[LayerCount][];
|
var linesBytes = new byte[LayerCount][];
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||||
|
|
||||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||||
inputFile.Seek(2, SeekOrigin.Current);
|
inputFile.Seek(2, SeekOrigin.Current);
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = EmguExtensions.InitMat(Resolution))
|
using (var mat = EmguExtensions.InitMat(Resolution))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ public class OSLAFile : FileFormat
|
|||||||
var image = Thumbnails[i];
|
var image = Thumbnails[i];
|
||||||
if(image is null) continue;
|
if(image is null) continue;
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var bytes = EncodeImage(HeaderSettings.PreviewDataType, image);
|
var bytes = EncodeImage(HeaderSettings.PreviewDataType, image);
|
||||||
if (bytes.Length == 0) continue;
|
if (bytes.Length == 0) continue;
|
||||||
@@ -517,9 +517,8 @@ public class OSLAFile : FileFormat
|
|||||||
{
|
{
|
||||||
var layerBytes = new byte[LayerCount][];
|
var layerBytes = new byte[LayerCount][];
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = this[layerIndex].LayerMat)
|
using (var mat = this[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
layerBytes[layerIndex] = EncodeImage(HeaderSettings.LayerDataType, mat);
|
layerBytes[layerIndex] = EncodeImage(HeaderSettings.LayerDataType, mat);
|
||||||
@@ -530,7 +529,7 @@ public class OSLAFile : FileFormat
|
|||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
// Try to reuse layers
|
// Try to reuse layers
|
||||||
var hash = CryptExtensions.ComputeSHA1Hash(layerBytes[layerIndex]);
|
var hash = CryptExtensions.ComputeSHA1Hash(layerBytes[layerIndex]);
|
||||||
@@ -556,7 +555,7 @@ public class OSLAFile : FileFormat
|
|||||||
outputFile.Seek(HeaderSettings.LayerDefinitionsAddress, SeekOrigin.Begin);
|
outputFile.Seek(HeaderSettings.LayerDefinitionsAddress, SeekOrigin.Begin);
|
||||||
for (int layerIndex = 0; layerIndex < layerDataAddresses.Length; layerIndex++)
|
for (int layerIndex = 0; layerIndex < layerDataAddresses.Length; layerIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var layer = this[layerIndex];
|
var layer = this[layerIndex];
|
||||||
var layerdef = new LayerDef(layer);
|
var layerdef = new LayerDef(layer);
|
||||||
@@ -615,7 +614,7 @@ public class OSLAFile : FileFormat
|
|||||||
|
|
||||||
for (byte i = 0; i < HeaderSettings.PreviewCount; i++)
|
for (byte i = 0; i < HeaderSettings.PreviewCount; i++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
var preview = Helpers.Deserialize<Preview>(inputFile);
|
var preview = Helpers.Deserialize<Preview>(inputFile);
|
||||||
|
|
||||||
Debug.Write($"Preview {i} -> ");
|
Debug.Write($"Preview {i} -> ");
|
||||||
@@ -644,7 +643,7 @@ public class OSLAFile : FileFormat
|
|||||||
uint layerTableSize = 0;
|
uint layerTableSize = 0;
|
||||||
for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++)
|
for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
layerDataAddresses[layerIndex] = inputFile.ReadUIntLittleEndian();
|
layerDataAddresses[layerIndex] = inputFile.ReadUIntLittleEndian();
|
||||||
|
|
||||||
layerDef[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
layerDef[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
||||||
@@ -670,15 +669,14 @@ public class OSLAFile : FileFormat
|
|||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
inputFile.Seek(layerDataAddresses[layerIndex], SeekOrigin.Begin);
|
inputFile.Seek(layerDataAddresses[layerIndex], SeekOrigin.Begin);
|
||||||
layerBytes[layerIndex] = inputFile.ReadBytes(inputFile.ReadUIntLittleEndian());
|
layerBytes[layerIndex] = inputFile.ReadBytes(inputFile.ReadUIntLittleEndian());
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = DecodeImage(HeaderSettings.LayerDataType, layerBytes[layerIndex], Resolution);
|
using var mat = DecodeImage(HeaderSettings.LayerDataType, layerBytes[layerIndex], Resolution);
|
||||||
layerBytes[layerIndex] = null!; // Clean
|
layerBytes[layerIndex] = null!; // Clean
|
||||||
|
|
||||||
|
|||||||
@@ -1002,9 +1002,8 @@ public class PHZFile : FileFormat
|
|||||||
|
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = this[layerIndex].LayerMat)
|
using (var mat = this[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
LayersDefinitions[layerIndex] = new LayerDef(this, this[layerIndex]);
|
LayersDefinitions[layerIndex] = new LayerDef(this, this[layerIndex]);
|
||||||
@@ -1015,7 +1014,7 @@ public class PHZFile : FileFormat
|
|||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var layerDef = LayersDefinitions[layerIndex];
|
var layerDef = LayersDefinitions[layerIndex];
|
||||||
LayerDef? layerDefHash = null;
|
LayerDef? layerDefHash = null;
|
||||||
@@ -1116,7 +1115,7 @@ public class PHZFile : FileFormat
|
|||||||
{
|
{
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var layerDef = Helpers.Deserialize<LayerDef>(inputFile);
|
var layerDef = Helpers.Deserialize<LayerDef>(inputFile);
|
||||||
layerDef.Parent = this;
|
layerDef.Parent = this;
|
||||||
@@ -1134,10 +1133,8 @@ public class PHZFile : FileFormat
|
|||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
if (DecodeType == FileDecodeType.Full)
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
using var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex);
|
using var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex);
|
||||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
|
|||||||
@@ -447,9 +447,8 @@ public class PhotonSFile : FileFormat
|
|||||||
|
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = this[layerIndex].LayerMat)
|
using (var mat = this[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
layerData[layerIndex] = new LayerDef(mat);
|
layerData[layerIndex] = new LayerDef(mat);
|
||||||
@@ -460,7 +459,7 @@ public class PhotonSFile : FileFormat
|
|||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
outputFile.WriteSerialize(layerData[layerIndex]);
|
outputFile.WriteSerialize(layerData[layerIndex]);
|
||||||
outputFile.WriteBytes(layerData[layerIndex].EncodedRle);
|
outputFile.WriteBytes(layerData[layerIndex].EncodedRle);
|
||||||
@@ -503,7 +502,7 @@ public class PhotonSFile : FileFormat
|
|||||||
{
|
{
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var layerDef = Helpers.Deserialize<LayerDef>(inputFile);
|
var layerDef = Helpers.Deserialize<LayerDef>(inputFile);
|
||||||
layersDefinitions[layerIndex] = layerDef;
|
layersDefinitions[layerIndex] = layerDef;
|
||||||
@@ -524,9 +523,8 @@ public class PhotonSFile : FileFormat
|
|||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
if (DecodeType == FileDecodeType.Full)
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = layersDefinitions[layerIndex].Decode();
|
using var mat = layersDefinitions[layerIndex].Decode();
|
||||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
|
|||||||
@@ -1695,9 +1695,8 @@ public class PhotonWorkshopFile : FileFormat
|
|||||||
|
|
||||||
foreach (var batch in BatchLayersIndexes())
|
foreach (var batch in BatchLayersIndexes())
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = this[layerIndex].LayerMat)
|
using (var mat = this[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
LayersDefinition.Layers[layerIndex] = new LayerDef(this, this[layerIndex]);
|
LayersDefinition.Layers[layerIndex] = new LayerDef(this, this[layerIndex]);
|
||||||
@@ -1708,7 +1707,7 @@ public class PhotonWorkshopFile : FileFormat
|
|||||||
|
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var layerDef = LayersDefinition.Layers[layerIndex];
|
var layerDef = LayersDefinition.Layers[layerIndex];
|
||||||
|
|
||||||
@@ -1822,7 +1821,7 @@ public class PhotonWorkshopFile : FileFormat
|
|||||||
{
|
{
|
||||||
foreach (var layerIndex in batch)
|
foreach (var layerIndex in batch)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
LayersDefinition[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
LayersDefinition[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
||||||
LayersDefinition[layerIndex].Parent = this;
|
LayersDefinition[layerIndex].Parent = this;
|
||||||
@@ -1840,10 +1839,8 @@ public class PhotonWorkshopFile : FileFormat
|
|||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
if (DecodeType == FileDecodeType.Full)
|
||||||
{
|
{
|
||||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
using var mat = LayersDefinition[layerIndex].Decode();
|
using var mat = LayersDefinition[layerIndex].Decode();
|
||||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this)
|
this[layerIndex] = new Layer((uint)layerIndex, mat, this)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -614,15 +614,7 @@ public class SL1File : FileFormat
|
|||||||
stream.Close();
|
stream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
EncodeLayersInZip(outputFile, filename, 5, Enumerations.IndexStartNumber.Zero, progress);
|
||||||
{
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
Layer layer = this[layerIndex];
|
|
||||||
var layerImagePath = $"{filename}{layerIndex:D5}.png";
|
|
||||||
//layer.Filename = layerImagePath;
|
|
||||||
outputFile.PutFileContent(layerImagePath, layer.CompressedBytes, ZipArchiveMode.Create);
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -635,135 +627,118 @@ public class SL1File : FileFormat
|
|||||||
|
|
||||||
Statistics.ExecutionTime.Restart();
|
Statistics.ExecutionTime.Restart();
|
||||||
|
|
||||||
using (var inputFile = ZipFile.OpenRead(FileFullPath!))
|
using var inputFile = ZipFile.OpenRead(FileFullPath!);
|
||||||
|
List<string> iniFiles = new();
|
||||||
|
foreach (var entity in inputFile.Entries)
|
||||||
{
|
{
|
||||||
List<string> iniFiles = new();
|
if (!entity.Name.EndsWith(".ini")) continue;
|
||||||
foreach (ZipArchiveEntry entity in inputFile.Entries)
|
iniFiles.Add(entity.Name);
|
||||||
|
using StreamReader streamReader = new(entity.Open());
|
||||||
|
string? line;
|
||||||
|
while ((line = streamReader.ReadLine()) != null)
|
||||||
{
|
{
|
||||||
if (!entity.Name.EndsWith(".ini")) continue;
|
string[] keyValue = line.Split(new[] {'='}, 2);
|
||||||
iniFiles.Add(entity.Name);
|
if (keyValue.Length < 2) continue;
|
||||||
using StreamReader streamReader = new(entity.Open());
|
keyValue[0] = keyValue[0].Trim();
|
||||||
string? line;
|
keyValue[1] = keyValue[1].Trim();
|
||||||
while ((line = streamReader.ReadLine()) != null)
|
|
||||||
{
|
|
||||||
string[] keyValue = line.Split(new[] {'='}, 2);
|
|
||||||
if (keyValue.Length < 2) continue;
|
|
||||||
keyValue[0] = keyValue[0].Trim();
|
|
||||||
keyValue[1] = keyValue[1].Trim();
|
|
||||||
|
|
||||||
var fieldName = IniKeyToMemberName(keyValue[0]);
|
var fieldName = IniKeyToMemberName(keyValue[0]);
|
||||||
bool foundMember = false;
|
bool foundMember = false;
|
||||||
|
|
||||||
|
|
||||||
foreach (var obj in Configs)
|
foreach (var obj in Configs)
|
||||||
{
|
{
|
||||||
var attribute = obj.GetType().GetProperty(fieldName);
|
var attribute = obj.GetType().GetProperty(fieldName);
|
||||||
if (attribute is null || !attribute.CanWrite) continue;
|
if (attribute is null || !attribute.CanWrite) continue;
|
||||||
//Debug.WriteLine(attribute.Name);
|
//Debug.WriteLine(attribute.Name);
|
||||||
Helpers.SetPropertyValue(attribute, obj, keyValue[1]);
|
Helpers.SetPropertyValue(attribute, obj, keyValue[1]);
|
||||||
|
|
||||||
Statistics.ImplementedKeys.Add(keyValue[0]);
|
Statistics.ImplementedKeys.Add(keyValue[0]);
|
||||||
foundMember = true;
|
foundMember = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundMember)
|
if (!foundMember)
|
||||||
{
|
|
||||||
Statistics.MissingKeys.Add(keyValue[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!iniFiles.Contains(IniConfig))
|
|
||||||
{
|
|
||||||
throw new FileLoadException($"Malformed file: {IniConfig} is missing.");
|
|
||||||
}
|
|
||||||
if (!iniFiles.Contains(IniPrusaslicer))
|
|
||||||
{
|
|
||||||
throw new FileLoadException($"Malformed file: {IniPrusaslicer} is missing.");
|
|
||||||
}
|
|
||||||
|
|
||||||
SuppressRebuildPropertiesWork(() =>
|
|
||||||
{
|
|
||||||
TransitionLayerCount = LookupCustomValue<ushort>(Keyword_TransitionLayerCount, 0);
|
|
||||||
BottomLightOffDelay = LookupCustomValue(Keyword_BottomLightOffDelay, 0f);
|
|
||||||
LightOffDelay = LookupCustomValue(Keyword_LightOffDelay, 0f);
|
|
||||||
|
|
||||||
BottomWaitTimeBeforeCure = LookupCustomValue(Keyword_BottomWaitTimeBeforeCure, 0f);
|
|
||||||
WaitTimeBeforeCure = LookupCustomValue(Keyword_WaitTimeBeforeCure, 0f);
|
|
||||||
|
|
||||||
BottomWaitTimeAfterCure = LookupCustomValue(Keyword_BottomWaitTimeAfterCure, 0f);
|
|
||||||
WaitTimeAfterCure = LookupCustomValue(Keyword_WaitTimeAfterCure, 0f);
|
|
||||||
|
|
||||||
BottomLiftHeight = LookupCustomValue(Keyword_BottomLiftHeight, DefaultBottomLiftHeight);
|
|
||||||
BottomLiftSpeed = LookupCustomValue(Keyword_BottomLiftSpeed, DefaultBottomLiftSpeed);
|
|
||||||
|
|
||||||
LiftHeight = LookupCustomValue(Keyword_LiftHeight, DefaultLiftHeight);
|
|
||||||
LiftSpeed = LookupCustomValue(Keyword_LiftSpeed, DefaultLiftSpeed);
|
|
||||||
|
|
||||||
BottomLiftHeight2 = LookupCustomValue(Keyword_BottomLiftHeight2, DefaultBottomLiftHeight2);
|
|
||||||
BottomLiftSpeed2 = LookupCustomValue(Keyword_BottomLiftSpeed2, DefaultBottomLiftSpeed2);
|
|
||||||
|
|
||||||
LiftHeight2 = LookupCustomValue(Keyword_LiftHeight2, DefaultLiftHeight2);
|
|
||||||
LiftSpeed2 = LookupCustomValue(Keyword_LiftSpeed2, DefaultLiftSpeed2);
|
|
||||||
|
|
||||||
BottomWaitTimeAfterLift = LookupCustomValue(Keyword_BottomWaitTimeAfterLift, 0f);
|
|
||||||
WaitTimeAfterLift = LookupCustomValue(Keyword_WaitTimeAfterLift, 0f);
|
|
||||||
|
|
||||||
BottomRetractSpeed = LookupCustomValue(Keyword_BottomRetractSpeed, DefaultBottomRetractSpeed);
|
|
||||||
RetractSpeed = LookupCustomValue(Keyword_RetractSpeed, DefaultRetractSpeed);
|
|
||||||
|
|
||||||
BottomRetractHeight2 = LookupCustomValue(Keyword_BottomRetractHeight2, DefaultBottomRetractHeight2);
|
|
||||||
RetractHeight2 = LookupCustomValue(Keyword_RetractHeight2, DefaultRetractHeight2);
|
|
||||||
BottomRetractSpeed2 = LookupCustomValue(Keyword_BottomRetractSpeed2, DefaultBottomRetractSpeed2);
|
|
||||||
RetractSpeed2 = LookupCustomValue(Keyword_RetractSpeed2, DefaultRetractSpeed2);
|
|
||||||
BottomLightPWM = LookupCustomValue(Keyword_BottomLightPWM, DefaultLightPWM);
|
|
||||||
LightPWM = LookupCustomValue(Keyword_LightPWM, DefaultBottomLightPWM);
|
|
||||||
});
|
|
||||||
|
|
||||||
Init(OutputConfigSettings.NumSlow + OutputConfigSettings.NumFast, DecodeType == FileDecodeType.Partial);
|
|
||||||
|
|
||||||
progress.ItemCount = LayerCount;
|
|
||||||
|
|
||||||
foreach (var entity in inputFile.Entries)
|
|
||||||
{
|
|
||||||
if (!entity.Name.EndsWith(".png")) continue;
|
|
||||||
if (entity.Name.StartsWith("thumbnail"))
|
|
||||||
{
|
{
|
||||||
using var stream = entity.Open();
|
Statistics.MissingKeys.Add(keyValue[0]);
|
||||||
Mat image = new();
|
|
||||||
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
|
|
||||||
byte thumbnailIndex =
|
|
||||||
(byte) (image.Width == ThumbnailsOriginalSize![(int) FileThumbnailSize.Small].Width &&
|
|
||||||
image.Height == ThumbnailsOriginalSize[(int) FileThumbnailSize.Small].Height
|
|
||||||
? FileThumbnailSize.Small
|
|
||||||
: FileThumbnailSize.Large);
|
|
||||||
Thumbnails[thumbnailIndex] = image;
|
|
||||||
|
|
||||||
//thumbnailIndex++;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
|
||||||
{
|
|
||||||
// - .png - 5 numbers
|
|
||||||
string layerStr = entity.Name.Substring(entity.Name.Length - 4 - 5, 5);
|
|
||||||
uint iLayer = uint.Parse(layerStr);
|
|
||||||
using var stream = entity.Open();
|
|
||||||
this[iLayer] = new Layer(iLayer, stream, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.ProcessedItems++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!iniFiles.Contains(IniConfig))
|
||||||
|
{
|
||||||
|
throw new FileLoadException($"Malformed file: {IniConfig} is missing.");
|
||||||
|
}
|
||||||
|
if (!iniFiles.Contains(IniPrusaslicer))
|
||||||
|
{
|
||||||
|
throw new FileLoadException($"Malformed file: {IniPrusaslicer} is missing.");
|
||||||
|
}
|
||||||
|
|
||||||
|
SuppressRebuildPropertiesWork(() =>
|
||||||
|
{
|
||||||
|
TransitionLayerCount = LookupCustomValue<ushort>(Keyword_TransitionLayerCount, 0);
|
||||||
|
BottomLightOffDelay = LookupCustomValue(Keyword_BottomLightOffDelay, 0f);
|
||||||
|
LightOffDelay = LookupCustomValue(Keyword_LightOffDelay, 0f);
|
||||||
|
|
||||||
|
BottomWaitTimeBeforeCure = LookupCustomValue(Keyword_BottomWaitTimeBeforeCure, 0f);
|
||||||
|
WaitTimeBeforeCure = LookupCustomValue(Keyword_WaitTimeBeforeCure, 0f);
|
||||||
|
|
||||||
|
BottomWaitTimeAfterCure = LookupCustomValue(Keyword_BottomWaitTimeAfterCure, 0f);
|
||||||
|
WaitTimeAfterCure = LookupCustomValue(Keyword_WaitTimeAfterCure, 0f);
|
||||||
|
|
||||||
|
BottomLiftHeight = LookupCustomValue(Keyword_BottomLiftHeight, DefaultBottomLiftHeight);
|
||||||
|
BottomLiftSpeed = LookupCustomValue(Keyword_BottomLiftSpeed, DefaultBottomLiftSpeed);
|
||||||
|
|
||||||
|
LiftHeight = LookupCustomValue(Keyword_LiftHeight, DefaultLiftHeight);
|
||||||
|
LiftSpeed = LookupCustomValue(Keyword_LiftSpeed, DefaultLiftSpeed);
|
||||||
|
|
||||||
|
BottomLiftHeight2 = LookupCustomValue(Keyword_BottomLiftHeight2, DefaultBottomLiftHeight2);
|
||||||
|
BottomLiftSpeed2 = LookupCustomValue(Keyword_BottomLiftSpeed2, DefaultBottomLiftSpeed2);
|
||||||
|
|
||||||
|
LiftHeight2 = LookupCustomValue(Keyword_LiftHeight2, DefaultLiftHeight2);
|
||||||
|
LiftSpeed2 = LookupCustomValue(Keyword_LiftSpeed2, DefaultLiftSpeed2);
|
||||||
|
|
||||||
|
BottomWaitTimeAfterLift = LookupCustomValue(Keyword_BottomWaitTimeAfterLift, 0f);
|
||||||
|
WaitTimeAfterLift = LookupCustomValue(Keyword_WaitTimeAfterLift, 0f);
|
||||||
|
|
||||||
|
BottomRetractSpeed = LookupCustomValue(Keyword_BottomRetractSpeed, DefaultBottomRetractSpeed);
|
||||||
|
RetractSpeed = LookupCustomValue(Keyword_RetractSpeed, DefaultRetractSpeed);
|
||||||
|
|
||||||
|
BottomRetractHeight2 = LookupCustomValue(Keyword_BottomRetractHeight2, DefaultBottomRetractHeight2);
|
||||||
|
RetractHeight2 = LookupCustomValue(Keyword_RetractHeight2, DefaultRetractHeight2);
|
||||||
|
BottomRetractSpeed2 = LookupCustomValue(Keyword_BottomRetractSpeed2, DefaultBottomRetractSpeed2);
|
||||||
|
RetractSpeed2 = LookupCustomValue(Keyword_RetractSpeed2, DefaultRetractSpeed2);
|
||||||
|
BottomLightPWM = LookupCustomValue(Keyword_BottomLightPWM, DefaultLightPWM);
|
||||||
|
LightPWM = LookupCustomValue(Keyword_LightPWM, DefaultBottomLightPWM);
|
||||||
|
});
|
||||||
|
|
||||||
|
Init(OutputConfigSettings.NumSlow + OutputConfigSettings.NumFast, DecodeType == FileDecodeType.Partial);
|
||||||
|
|
||||||
|
progress.ItemCount = LayerCount;
|
||||||
|
|
||||||
|
foreach (var entity in inputFile.Entries)
|
||||||
|
{
|
||||||
|
if (!entity.Name.EndsWith(".png")) continue;
|
||||||
|
if (!entity.Name.StartsWith("thumbnail")) continue;
|
||||||
|
using var stream = entity.Open();
|
||||||
|
Mat image = new();
|
||||||
|
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
|
||||||
|
byte thumbnailIndex =
|
||||||
|
(byte) (image.Width == ThumbnailsOriginalSize![(int) FileThumbnailSize.Small].Width &&
|
||||||
|
image.Height == ThumbnailsOriginalSize[(int) FileThumbnailSize.Small].Height
|
||||||
|
? FileThumbnailSize.Small
|
||||||
|
: FileThumbnailSize.Large);
|
||||||
|
Thumbnails[thumbnailIndex] = image;
|
||||||
|
|
||||||
|
//thumbnailIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DecodeLayersFromZip(inputFile, 5, Enumerations.IndexStartNumber.Zero, progress);
|
||||||
|
|
||||||
if (TransitionLayerCount > 0)
|
if (TransitionLayerCount > 0)
|
||||||
{
|
{
|
||||||
SetTransitionLayers(TransitionLayerCount, false);
|
SetTransitionLayers(TransitionLayerCount, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBoundingRectangle(progress);
|
|
||||||
|
|
||||||
Statistics.ExecutionTime.Stop();
|
Statistics.ExecutionTime.Stop();
|
||||||
|
|
||||||
Debug.WriteLine(Statistics);
|
Debug.WriteLine(Statistics);
|
||||||
|
|||||||
@@ -502,75 +502,52 @@ public class UVJFile : FileFormat
|
|||||||
stream.Close();
|
stream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
EncodeLayersInZip(outputFile, 8, Enumerations.IndexStartNumber.Zero, progress, FolderImageName);
|
||||||
{
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
Layer layer = this[layerIndex];
|
|
||||||
|
|
||||||
var layerimagePath = $"{FolderImageName}/{layerIndex:D8}.png";
|
|
||||||
outputFile.PutFileContent(layerimagePath, layer.CompressedBytes, ZipArchiveMode.Create);
|
|
||||||
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void DecodeInternally(OperationProgress progress)
|
protected override void DecodeInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
using (var inputFile = ZipFile.Open(FileFullPath!, ZipArchiveMode.Read))
|
using var inputFile = ZipFile.Open(FileFullPath!, ZipArchiveMode.Read);
|
||||||
|
var entry = inputFile.GetEntry(FileConfigName);
|
||||||
|
if (entry is null)
|
||||||
{
|
{
|
||||||
var entry = inputFile.GetEntry(FileConfigName);
|
Clear();
|
||||||
if (entry is null)
|
throw new FileLoadException($"{FileConfigName} not found", FileFullPath);
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
throw new FileLoadException($"{FileConfigName} not found", FileFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonSettings = JsonSerializer.Deserialize<Settings>(entry.Open())!;
|
|
||||||
|
|
||||||
Init(JsonSettings.Properties.Size.Layers, DecodeType == FileDecodeType.Partial);
|
|
||||||
|
|
||||||
entry = inputFile.GetEntry(FilePreviewTinyName);
|
|
||||||
if (entry is not null)
|
|
||||||
{
|
|
||||||
using var stream = entry.Open();
|
|
||||||
Mat image = new();
|
|
||||||
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
|
|
||||||
Thumbnails[0] = image;
|
|
||||||
stream.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = inputFile.GetEntry(FilePreviewHugeName);
|
|
||||||
if (entry is not null)
|
|
||||||
{
|
|
||||||
using var stream = entry.Open();
|
|
||||||
Mat image = new();
|
|
||||||
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
|
|
||||||
Thumbnails[1] = image;
|
|
||||||
stream.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
|
||||||
{
|
|
||||||
entry = inputFile.GetEntry($"{FolderImageName}/{layerIndex:D8}.png");
|
|
||||||
if (entry is null) continue;
|
|
||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
|
||||||
{
|
|
||||||
using var stream = entry.Open();
|
|
||||||
this[layerIndex] = new Layer(layerIndex, stream, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JsonSettings.Layers?.Count > layerIndex)
|
|
||||||
{
|
|
||||||
JsonSettings.Layers[(int)layerIndex].CopyTo(this[layerIndex]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.ProcessedItems++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBoundingRectangle(progress);
|
JsonSettings = JsonSerializer.Deserialize<Settings>(entry.Open())!;
|
||||||
|
|
||||||
|
Init(JsonSettings.Properties.Size.Layers, DecodeType == FileDecodeType.Partial);
|
||||||
|
|
||||||
|
entry = inputFile.GetEntry(FilePreviewTinyName);
|
||||||
|
if (entry is not null)
|
||||||
|
{
|
||||||
|
using var stream = entry.Open();
|
||||||
|
Mat image = new();
|
||||||
|
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
|
||||||
|
Thumbnails[0] = image;
|
||||||
|
stream.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = inputFile.GetEntry(FilePreviewHugeName);
|
||||||
|
if (entry is not null)
|
||||||
|
{
|
||||||
|
using var stream = entry.Open();
|
||||||
|
Mat image = new();
|
||||||
|
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
|
||||||
|
Thumbnails[1] = image;
|
||||||
|
stream.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
DecodeLayersFromZip(inputFile, progress);
|
||||||
|
|
||||||
|
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||||
|
{
|
||||||
|
if (JsonSettings.Layers?.Count > layerIndex)
|
||||||
|
{
|
||||||
|
JsonSettings.Layers[(int)layerIndex].CopyTo(this[layerIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PartialSaveInternally(OperationProgress progress)
|
protected override void PartialSaveInternally(OperationProgress progress)
|
||||||
|
|||||||
@@ -309,15 +309,8 @@ public class VDAFile : FileFormat
|
|||||||
Replace($".{FileExtensions[0].Extension}{TemporaryFileAppend}", ".xml").
|
Replace($".{FileExtensions[0].Extension}{TemporaryFileAppend}", ".xml").
|
||||||
Replace($".{FileExtensions[0].Extension}", ".xml");
|
Replace($".{FileExtensions[0].Extension}", ".xml");
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
EncodeLayersInZip(outputFile, 4, Enumerations.IndexStartNumber.One, progress);
|
||||||
{
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
var layer = this[layerIndex];
|
|
||||||
var filename = $"{layerIndex + 1}".PadLeft(4, '0') + ".png";
|
|
||||||
outputFile.PutFileContent(filename, layer.CompressedBytes, ZipArchiveMode.Create);
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateManifest();
|
UpdateManifest();
|
||||||
|
|
||||||
var entry = outputFile.CreateEntry(manifestFilename);
|
var entry = outputFile.CreateEntry(manifestFilename);
|
||||||
@@ -327,53 +320,28 @@ public class VDAFile : FileFormat
|
|||||||
|
|
||||||
protected override void DecodeInternally(OperationProgress progress)
|
protected override void DecodeInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
using (var inputFile = ZipFile.Open(FileFullPath!, ZipArchiveMode.Read))
|
using var inputFile = ZipFile.Open(FileFullPath!, ZipArchiveMode.Read);
|
||||||
|
var entry = inputFile.Entries.FirstOrDefault(zipEntry => zipEntry.Name.EndsWith(".xml"));
|
||||||
|
if (entry is null)
|
||||||
{
|
{
|
||||||
var entry = inputFile.Entries.FirstOrDefault(zipEntry => zipEntry.Name.EndsWith(".xml"));
|
Clear();
|
||||||
if (entry is null)
|
throw new FileLoadException($".xml manifest not found", FileFullPath);
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
throw new FileLoadException($".xml manifest not found", FileFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var stream = entry.Open();
|
|
||||||
ManifestFile = XmlExtensions.DeserializeFromStream<VDARoot>(stream);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Init(ManifestFile.Slices.LayerCount, DecodeType == FileDecodeType.Partial);
|
|
||||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
|
||||||
|
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
|
||||||
{
|
|
||||||
if (progress.Token.IsCancellationRequested) break;
|
|
||||||
var filename = $"{layerIndex + 1}".PadLeft(4, '0')+".png";
|
|
||||||
entry = inputFile.GetEntry(filename);
|
|
||||||
if (entry is null)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
throw new FileLoadException($"Layer {filename} not found", FileFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
|
||||||
{
|
|
||||||
using var stream = entry.Open();
|
|
||||||
this[layerIndex] = new Layer(layerIndex, stream, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBoundingRectangle(progress);
|
try
|
||||||
|
{
|
||||||
|
using var stream = entry.Open();
|
||||||
|
ManifestFile = XmlExtensions.DeserializeFromStream<VDARoot>(stream);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Init(ManifestFile.Slices.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||||
|
DecodeLayersFromZip(inputFile, Enumerations.IndexStartNumber.One, progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PartialSaveInternally(OperationProgress progress)
|
protected override void PartialSaveInternally(OperationProgress progress)
|
||||||
@@ -413,7 +381,7 @@ public class VDAFile : FileFormat
|
|||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||||
{
|
{
|
||||||
var layer = this[layerIndex];
|
var layer = this[layerIndex];
|
||||||
ManifestFile.Layers.Add(new VDARoot.VDALayer(layerIndex, layer.PositionZ, layer.FormatFileName(4, false)));
|
ManifestFile.Layers.Add(new VDARoot.VDALayer(layerIndex, layer.PositionZ, layer.FormatFileName(4, Enumerations.IndexStartNumber.One)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -651,64 +651,45 @@ public class VDTFile : FileFormat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
EncodeLayersInZip(outputFile, progress);
|
||||||
{
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var layer = this[layerIndex];
|
|
||||||
var layerImagePath = $"{layerIndex}.png";
|
|
||||||
outputFile.PutFileContent(layerImagePath, layer.CompressedBytes, ZipArchiveMode.Create);
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void DecodeInternally(OperationProgress progress)
|
protected override void DecodeInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
using (var inputFile = ZipFile.Open(FileFullPath!, ZipArchiveMode.Read))
|
using var inputFile = ZipFile.Open(FileFullPath!, ZipArchiveMode.Read);
|
||||||
|
var entry = inputFile.GetEntry(FileManifestName);
|
||||||
|
if (entry is null)
|
||||||
{
|
{
|
||||||
var entry = inputFile.GetEntry(FileManifestName);
|
Clear();
|
||||||
if (entry is null)
|
throw new FileLoadException($"{FileManifestName} not found", FileFullPath);
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
throw new FileLoadException($"{FileManifestName} not found", FileFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
ManifestFile = JsonSerializer.Deserialize<VDTManifest>(entry.Open())!;
|
|
||||||
|
|
||||||
Init((uint) ManifestFile.Layers!.Length, DecodeType == FileDecodeType.Partial);
|
|
||||||
|
|
||||||
for (int i = 0; i < FilePreviewNames.Length; i++)
|
|
||||||
{
|
|
||||||
if (Thumbnails.Length <= i) break;
|
|
||||||
|
|
||||||
entry = inputFile.GetEntry(FilePreviewNames[i]);
|
|
||||||
if (entry is null) continue;
|
|
||||||
using var stream = entry.Open();
|
|
||||||
Mat image = new();
|
|
||||||
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
|
|
||||||
Thumbnails[i] = image;
|
|
||||||
stream.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
|
||||||
{
|
|
||||||
var manifestLayer = ManifestFile.Layers[layerIndex];
|
|
||||||
entry = inputFile.GetEntry($"{layerIndex}.png");
|
|
||||||
if (entry is null) continue;
|
|
||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
|
||||||
{
|
|
||||||
using var stream = entry.Open();
|
|
||||||
this[layerIndex] = new Layer(layerIndex, stream, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
manifestLayer.CopyTo(this[layerIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.ProcessedItems++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBoundingRectangle(progress);
|
ManifestFile = JsonSerializer.Deserialize<VDTManifest>(entry.Open())!;
|
||||||
|
|
||||||
|
Init((uint) ManifestFile.Layers!.Length, DecodeType == FileDecodeType.Partial);
|
||||||
|
|
||||||
|
for (int i = 0; i < FilePreviewNames.Length; i++)
|
||||||
|
{
|
||||||
|
if (Thumbnails.Length <= i) break;
|
||||||
|
|
||||||
|
entry = inputFile.GetEntry(FilePreviewNames[i]);
|
||||||
|
if (entry is null) continue;
|
||||||
|
using var stream = entry.Open();
|
||||||
|
Mat image = new();
|
||||||
|
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
|
||||||
|
Thumbnails[i] = image;
|
||||||
|
stream.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
DecodeLayersFromZip(inputFile, progress);
|
||||||
|
|
||||||
|
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||||
|
{
|
||||||
|
var manifestLayer = ManifestFile.Layers[layerIndex];
|
||||||
|
manifestLayer.CopyTo(this[layerIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.ProcessedItems++;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PartialSaveInternally(OperationProgress progress)
|
protected override void PartialSaveInternally(OperationProgress progress)
|
||||||
|
|||||||
@@ -13,11 +13,13 @@ using Org.BouncyCastle.Crypto.Engines;
|
|||||||
using Org.BouncyCastle.OpenSsl;
|
using Org.BouncyCastle.OpenSsl;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using UVtools.Core.Extensions;
|
using UVtools.Core.Extensions;
|
||||||
using UVtools.Core.GCode;
|
using UVtools.Core.GCode;
|
||||||
@@ -477,13 +479,7 @@ public class ZCodeFile : FileFormat
|
|||||||
thumbnailsStream.Close();
|
thumbnailsStream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
EncodeLayersInZip(outputFile, Enumerations.IndexStartNumber.One, progress);
|
||||||
{
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
var layer = this[layerIndex];
|
|
||||||
outputFile.PutFileContent($"{layerIndex + 1}.png", layer.CompressedBytes, ZipArchiveMode.Create);
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
|
|
||||||
var entry = outputFile.CreateEntry(ManifestFilename);
|
var entry = outputFile.CreateEntry(ManifestFilename);
|
||||||
using (var stream = entry.Open())
|
using (var stream = entry.Open())
|
||||||
@@ -549,29 +545,8 @@ public class ZCodeFile : FileFormat
|
|||||||
}
|
}
|
||||||
|
|
||||||
Init(ManifestFile.Job.LayerCount, DecodeType == FileDecodeType.Partial);
|
Init(ManifestFile.Job.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
|
||||||
|
|
||||||
//var gcode = GCode.ToString();
|
DecodeLayersFromZip(inputFile, Enumerations.IndexStartNumber.One, progress);
|
||||||
//float lastPostZ = LayerHeight;
|
|
||||||
|
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
|
||||||
{
|
|
||||||
if (progress.Token.IsCancellationRequested) break;
|
|
||||||
entry = inputFile.GetEntry($"{layerIndex+1}.png");
|
|
||||||
if (entry is null)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
throw new FileLoadException($"Layer {layerIndex+1} not found", FileFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
|
||||||
{
|
|
||||||
using var stream = entry.Open();
|
|
||||||
this[layerIndex] = new Layer(layerIndex, stream, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
|
|
||||||
GCode!.ParseLayersFromGCode(this);
|
GCode!.ParseLayersFromGCode(this);
|
||||||
|
|
||||||
@@ -581,8 +556,6 @@ public class ZCodeFile : FileFormat
|
|||||||
Thumbnails[0] = new Mat();
|
Thumbnails[0] = new Mat();
|
||||||
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
|
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBoundingRectangle(progress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PartialSaveInternally(OperationProgress progress)
|
protected override void PartialSaveInternally(OperationProgress progress)
|
||||||
|
|||||||
@@ -401,12 +401,14 @@ public class ZCodexFile : FileFormat
|
|||||||
stream.Close();
|
stream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EncodeLayersInZip(outputFile, FolderImageName, 5, Enumerations.IndexStartNumber.Zero, progress, FolderImages);
|
||||||
|
|
||||||
GCode!.Clear();
|
GCode!.Clear();
|
||||||
|
|
||||||
float lastZPosition = 0;
|
float lastZPosition = 0;
|
||||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var layer = this[layerIndex];
|
var layer = this[layerIndex];
|
||||||
GCode.AppendLine($"{GCodeKeywordSlice} {layerIndex}");
|
GCode.AppendLine($"{GCodeKeywordSlice} {layerIndex}");
|
||||||
@@ -436,19 +438,7 @@ public class ZCodexFile : FileFormat
|
|||||||
GCode.AppendLine(GCodeKeywordDelayModel);
|
GCode.AppendLine(GCodeKeywordDelayModel);
|
||||||
GCode.AppendLine("M106 S0");
|
GCode.AppendLine("M106 S0");
|
||||||
|
|
||||||
|
|
||||||
var layerimagePath = $"{FolderImages}/{FolderImageName}{layerIndex:D5}.png";
|
|
||||||
using (var stream = outputFile.CreateEntry(layerimagePath).Open())
|
|
||||||
{
|
|
||||||
//image.Save(stream, Helpers.PngEncoder);
|
|
||||||
var byteArr = this[layerIndex].CompressedBytes;
|
|
||||||
stream.Write(byteArr!, 0, byteArr!.Length);
|
|
||||||
stream.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
lastZPosition = layer.PositionZ;
|
lastZPosition = layer.PositionZ;
|
||||||
|
|
||||||
progress++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GCode.AppendLine($"G1 Z40.0 F{UserSettings.ZLiftFeedRate}");
|
GCode.AppendLine($"G1 Z40.0 F{UserSettings.ZLiftFeedRate}");
|
||||||
@@ -496,6 +486,8 @@ public class ZCodexFile : FileFormat
|
|||||||
}
|
}
|
||||||
|
|
||||||
Init(ResinMetadataSettings.TotalLayersCount, DecodeType == FileDecodeType.Partial);
|
Init(ResinMetadataSettings.TotalLayersCount, DecodeType == FileDecodeType.Partial);
|
||||||
|
DecodeLayersFromZip(inputFile, FolderImageName, Enumerations.IndexStartNumber.Zero, progress);
|
||||||
|
|
||||||
GCode!.Clear();
|
GCode!.Clear();
|
||||||
using (TextReader tr = new StreamReader(entry.Open()))
|
using (TextReader tr = new StreamReader(entry.Open()))
|
||||||
{
|
{
|
||||||
@@ -576,11 +568,11 @@ M106 S0
|
|||||||
LayersSettings[layerIndex].LayerFileIndex = layerFileIndex;
|
LayersSettings[layerIndex].LayerFileIndex = layerFileIndex;
|
||||||
LayersSettings[layerIndex].LayerEntry = inputFile.GetEntry(layerimagePath);
|
LayersSettings[layerIndex].LayerEntry = inputFile.GetEntry(layerimagePath);
|
||||||
|
|
||||||
if (DecodeType == FileDecodeType.Full)
|
/*if (DecodeType == FileDecodeType.Full)
|
||||||
{
|
{
|
||||||
using var stream = LayersSettings[layerIndex].LayerEntry!.Open();
|
using var stream = LayersSettings[layerIndex].LayerEntry!.Open();
|
||||||
this[layerIndex] = new Layer((uint)layerIndex, stream, this);
|
this[layerIndex] = new Layer((uint)layerIndex, stream, this);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
this[layerIndex].PositionZ = currentHeight;
|
this[layerIndex].PositionZ = currentHeight;
|
||||||
this[layerIndex].LiftHeight = liftHeight;
|
this[layerIndex].LiftHeight = liftHeight;
|
||||||
@@ -588,8 +580,6 @@ M106 S0
|
|||||||
this[layerIndex].RetractSpeed = retractSpeed;
|
this[layerIndex].RetractSpeed = retractSpeed;
|
||||||
this[layerIndex].LightPWM = pwm;
|
this[layerIndex].LightPWM = pwm;
|
||||||
layerIndex++;
|
layerIndex++;
|
||||||
|
|
||||||
progress++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,7 +596,6 @@ M106 S0
|
|||||||
}
|
}
|
||||||
|
|
||||||
BottomRetractSpeed = RetractSpeed; // Compability
|
BottomRetractSpeed = RetractSpeed; // Compability
|
||||||
GetBoundingRectangle(progress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RebuildGCode()
|
public override void RebuildGCode()
|
||||||
|
|||||||
+214
-25
@@ -10,9 +10,12 @@ using Emgu.CV;
|
|||||||
using Emgu.CV.CvEnum;
|
using Emgu.CV.CvEnum;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using K4os.Compression.LZ4;
|
||||||
using UVtools.Core.Extensions;
|
using UVtools.Core.Extensions;
|
||||||
using UVtools.Core.FileFormats;
|
using UVtools.Core.FileFormats;
|
||||||
using UVtools.Core.Objects;
|
using UVtools.Core.Objects;
|
||||||
@@ -25,6 +28,24 @@ namespace UVtools.Core.Layers;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
||||||
{
|
{
|
||||||
|
#region Enums
|
||||||
|
|
||||||
|
public enum LayerCompressionMethod : byte
|
||||||
|
{
|
||||||
|
[Description("PNG: Compression=High Speed=Slow (Use with low RAM)")]
|
||||||
|
Png,
|
||||||
|
[Description("GZip: Compression=Medium Speed=Medium (Optimal)")]
|
||||||
|
GZip,
|
||||||
|
[Description("Deflate: Compression=Medium Speed=Medium (Optimal)")]
|
||||||
|
Deflate,
|
||||||
|
[Description("LZ4: Compression=Low Speed=Fast (Use with high RAM)")]
|
||||||
|
Lz4,
|
||||||
|
//[Description("None: Compression=None Speed=Fastest (Your soul belongs to RAM)")]
|
||||||
|
//None
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Constants
|
#region Constants
|
||||||
public const byte HeightPrecision = 3;
|
public const byte HeightPrecision = 3;
|
||||||
public const decimal HeightPrecisionIncrement = 0.001M;
|
public const decimal HeightPrecisionIncrement = 0.001M;
|
||||||
@@ -35,6 +56,7 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
#region Members
|
#region Members
|
||||||
|
|
||||||
public object Mutex = new();
|
public object Mutex = new();
|
||||||
|
private LayerCompressionMethod _compressionMethod;
|
||||||
private byte[]? _compressedBytes;
|
private byte[]? _compressedBytes;
|
||||||
private uint _nonZeroPixelCount;
|
private uint _nonZeroPixelCount;
|
||||||
private Rectangle _boundingRectangle = Rectangle.Empty;
|
private Rectangle _boundingRectangle = Rectangle.Empty;
|
||||||
@@ -55,6 +77,7 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
private float _retractSpeed2 = FileFormat.DefaultRetractSpeed2;
|
private float _retractSpeed2 = FileFormat.DefaultRetractSpeed2;
|
||||||
private byte _lightPWM = FileFormat.DefaultLightPWM;
|
private byte _lightPWM = FileFormat.DefaultLightPWM;
|
||||||
private float _materialMilliliters;
|
private float _materialMilliliters;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
@@ -567,6 +590,29 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float MaterialMillilitersPercent => _materialMilliliters * 100 / SlicerFile.MaterialMilliliters;
|
public float MaterialMillilitersPercent => _materialMilliliters * 100 / SlicerFile.MaterialMilliliters;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the compression method used to cache the image
|
||||||
|
/// </summary>
|
||||||
|
public LayerCompressionMethod CompressionMethod
|
||||||
|
{
|
||||||
|
get => _compressionMethod;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!HaveImage)
|
||||||
|
{
|
||||||
|
RaiseAndSetIfChanged(ref _compressionMethod, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle conversion
|
||||||
|
if (_compressionMethod == value) return;
|
||||||
|
using var mat = LayerMat;
|
||||||
|
_compressionMethod = value;
|
||||||
|
_compressedBytes = CompressMat(mat, value);
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets layer image compressed data
|
/// Gets or sets layer image compressed data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -583,6 +629,18 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[]? CompressedPngBytes
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_compressedBytes is null) return null;
|
||||||
|
if (_compressionMethod == LayerCompressionMethod.Png) return _compressedBytes;
|
||||||
|
|
||||||
|
using var mat = LayerMat;
|
||||||
|
return mat.GetPngByes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if this layer have an valid initialized image, otherwise false
|
/// True if this layer have an valid initialized image, otherwise false
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -596,13 +654,70 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!HaveImage) return null!;
|
if (!HaveImage) return null!;
|
||||||
Mat mat = new();
|
|
||||||
CvInvoke.Imdecode(_compressedBytes, ImreadModes.Grayscale, mat);
|
Mat mat;
|
||||||
return mat;
|
switch (_compressionMethod)
|
||||||
|
{
|
||||||
|
case LayerCompressionMethod.Png:
|
||||||
|
mat = new Mat();
|
||||||
|
CvInvoke.Imdecode(_compressedBytes, ImreadModes.Grayscale, mat);
|
||||||
|
break;
|
||||||
|
case LayerCompressionMethod.Lz4:
|
||||||
|
mat = new Mat(SlicerFile.Resolution, DepthType.Cv8U, 1);
|
||||||
|
LZ4Codec.Decode(_compressedBytes.AsSpan(), mat.GetDataByteSpan());
|
||||||
|
break;
|
||||||
|
case LayerCompressionMethod.GZip:
|
||||||
|
{
|
||||||
|
mat = new(SlicerFile.Resolution, DepthType.Cv8U, 1);
|
||||||
|
var matSpan = mat.GetDataByteSpan();
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (byte* pBuffer = _compressedBytes)
|
||||||
|
{
|
||||||
|
using var compressedStream = new UnmanagedMemoryStream(pBuffer, _compressedBytes!.Length);
|
||||||
|
using var matStream = new UnmanagedMemoryStream(mat.GetBytePointer(), matSpan.Length, matSpan.Length, FileAccess.Write);
|
||||||
|
using var gZipStream = new GZipStream(compressedStream, CompressionMode.Decompress);
|
||||||
|
gZipStream.CopyTo(matStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LayerCompressionMethod.Deflate:
|
||||||
|
{
|
||||||
|
mat = new(SlicerFile.Resolution, DepthType.Cv8U, 1);
|
||||||
|
var matSpan = mat.GetDataByteSpan();
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (byte* pBuffer = _compressedBytes)
|
||||||
|
{
|
||||||
|
using var compressedStream = new UnmanagedMemoryStream(pBuffer, _compressedBytes!.Length);
|
||||||
|
using var matStream = new UnmanagedMemoryStream(mat.GetBytePointer(), matSpan.Length, matSpan.Length, FileAccess.Write);
|
||||||
|
using var deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress);
|
||||||
|
deflateStream.CopyTo(matStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*case LayerCompressionMethod.None:
|
||||||
|
mat = new(SlicerFile.Resolution, DepthType.Cv8U, 1);
|
||||||
|
//mat.SetBytes(_compressedBytes!);
|
||||||
|
_compressedBytes.CopyTo(mat.GetDataByteSpan());
|
||||||
|
break;*/
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(LayerMat));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mat;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
CompressedBytes = value?.GetPngByes();
|
if (value is not null)
|
||||||
|
{
|
||||||
|
CompressedBytes = CompressMat(value, _compressionMethod);
|
||||||
|
}
|
||||||
|
|
||||||
GetBoundingRectangle(value, true);
|
GetBoundingRectangle(value, true);
|
||||||
RaisePropertyChanged();
|
RaisePropertyChanged();
|
||||||
}
|
}
|
||||||
@@ -627,7 +742,7 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a computed layer filename, padding zeros are equal to layer count digits
|
/// Gets a computed layer filename, padding zeros are equal to layer count digits
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Filename => FormatFileName("layer");
|
public string Filename => FormatFileNameWithLayerDigits("layer");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets if layer image has been modified
|
/// Gets if layer image has been modified
|
||||||
@@ -700,29 +815,55 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
|
|
||||||
#region Constructor
|
#region Constructor
|
||||||
|
|
||||||
public Layer(uint index, FileFormat slicerFile)
|
public Layer(uint index, FileFormat slicerFile, LayerCompressionMethod? compressionMethod = null)
|
||||||
{
|
{
|
||||||
|
compressionMethod ??= CoreSettings.DefaultLayerCompressionMethod;
|
||||||
|
_compressionMethod = compressionMethod.Value;
|
||||||
|
|
||||||
SlicerFile = slicerFile;
|
SlicerFile = slicerFile;
|
||||||
_index = index;
|
_index = index;
|
||||||
|
|
||||||
//if (slicerFile is null) return;
|
//if (slicerFile is null) return;
|
||||||
_positionZ = SlicerFile.GetHeightFromLayer(index);
|
_positionZ = SlicerFile.GetHeightFromLayer(index);
|
||||||
ResetParameters();
|
ResetParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Layer(uint index, byte[] compressedBytes, FileFormat slicerFile) : this(index, slicerFile)
|
public Layer(uint index, byte[] pngBytes, FileFormat slicerFile, LayerCompressionMethod? compressionMethod = null) : this(index, slicerFile, compressionMethod)
|
||||||
{
|
{
|
||||||
CompressedBytes = compressedBytes;
|
if (_compressionMethod == LayerCompressionMethod.Png)
|
||||||
|
{
|
||||||
|
CompressedBytes = pngBytes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var mat = new Mat();
|
||||||
|
CvInvoke.Imdecode(pngBytes, ImreadModes.Grayscale, mat);
|
||||||
|
LayerMat = mat;
|
||||||
|
}
|
||||||
|
|
||||||
_isModified = false;
|
_isModified = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Layer(uint index, Mat layerMat, FileFormat slicerFile) : this(index, slicerFile)
|
public Layer(uint index, Mat layerMat, FileFormat slicerFile, LayerCompressionMethod? compressionMethod = null) : this(index, slicerFile, compressionMethod)
|
||||||
{
|
{
|
||||||
LayerMat = layerMat;
|
LayerMat = layerMat;
|
||||||
_isModified = false;
|
_isModified = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Layer(uint index, Stream stream, FileFormat slicerFile) : this(index, stream.ToArray(), slicerFile) { }
|
public Layer(uint index, Stream stream, FileFormat slicerFile, LayerCompressionMethod? compressionMethod = null) : this(index, stream.ToArray(), slicerFile, compressionMethod)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public Layer(FileFormat slicerFile, LayerCompressionMethod? compressionMethod = null) : this(0, slicerFile, compressionMethod)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public Layer(byte[] pngBytes, FileFormat slicerFile, LayerCompressionMethod? compressionMethod = null) : this(0, pngBytes, slicerFile, compressionMethod)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public Layer(Mat layerMat, FileFormat slicerFile, LayerCompressionMethod? compressionMethod = null) : this(0, layerMat, slicerFile, compressionMethod)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public Layer(Stream stream, FileFormat slicerFile, LayerCompressionMethod? compressionMethod = null) : this(0, stream, slicerFile, compressionMethod) { }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Equatables
|
#region Equatables
|
||||||
@@ -946,22 +1087,22 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
WaitTimeAfterLift = 0;
|
WaitTimeAfterLift = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string FormatFileName(string prepend, byte padDigits, bool layerIndexZeroStarted = true, string appendExt = ".png")
|
public string FormatFileName(string prepend = "", byte padDigits = 0, Enumerations.IndexStartNumber layerIndexStartNumber = default, string appendExt = ".png")
|
||||||
{
|
{
|
||||||
var index = Index;
|
var index = Index;
|
||||||
if (!layerIndexZeroStarted)
|
if (layerIndexStartNumber == Enumerations.IndexStartNumber.One)
|
||||||
{
|
{
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
return $"{prepend}{index.ToString().PadLeft(padDigits, '0')}{appendExt}";
|
return $"{prepend}{index.ToString().PadLeft(padDigits, '0')}{appendExt}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public string FormatFileName(string prepend = "", bool layerIndexZeroStarted = true, string appendExt = ".png")
|
public string FormatFileName(byte padDigits, Enumerations.IndexStartNumber layerIndexStartNumber = default, string appendExt = ".png")
|
||||||
=> FormatFileName(prepend, SlicerFile.LayerDigits, layerIndexZeroStarted, appendExt);
|
=> FormatFileName(string.Empty, padDigits, layerIndexStartNumber, appendExt);
|
||||||
|
|
||||||
public string FormatFileName(byte padDigits, bool layerIndexZeroStarted = true, string appendExt = ".png")
|
public string FormatFileNameWithLayerDigits(string prepend = "", Enumerations.IndexStartNumber layerIndexStartNumber = default, string appendExt = ".png")
|
||||||
=> FormatFileName(string.Empty, padDigits, layerIndexZeroStarted, appendExt);
|
=> FormatFileName(prepend, SlicerFile.LayerDigits, layerIndexStartNumber, appendExt);
|
||||||
|
|
||||||
|
|
||||||
public Rectangle GetBoundingRectangle(Mat? mat = null, bool reCalculate = false)
|
public Rectangle GetBoundingRectangle(Mat? mat = null, bool reCalculate = false)
|
||||||
{
|
{
|
||||||
@@ -1314,12 +1455,13 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
|
|
||||||
public Layer Clone()
|
public Layer Clone()
|
||||||
{
|
{
|
||||||
//var layer = (Layer)MemberwiseClone();
|
var layer = (Layer)MemberwiseClone();
|
||||||
//layer.CompressedBytes = _compressedBytes.ToArray();
|
layer._compressedBytes = _compressedBytes?.ToArray();
|
||||||
//Debug.WriteLine(ReferenceEquals(_compressedBytes, layer.CompressedBytes));
|
//Debug.WriteLine(ReferenceEquals(_compressedBytes, layer.CompressedBytes));
|
||||||
//return layer;
|
return layer;
|
||||||
return new (_index, CompressedBytes?.ToArray()!, SlicerFile)
|
/*return new (_index, CompressedBytes?.ToArray()!, SlicerFile)
|
||||||
{
|
{
|
||||||
|
_compressionMethod = _compressionMethod,
|
||||||
_positionZ = _positionZ,
|
_positionZ = _positionZ,
|
||||||
_lightOffDelay = _lightOffDelay,
|
_lightOffDelay = _lightOffDelay,
|
||||||
_waitTimeBeforeCure = _waitTimeBeforeCure,
|
_waitTimeBeforeCure = _waitTimeBeforeCure,
|
||||||
@@ -1337,8 +1479,8 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
_boundingRectangle = _boundingRectangle,
|
_boundingRectangle = _boundingRectangle,
|
||||||
_nonZeroPixelCount = _nonZeroPixelCount,
|
_nonZeroPixelCount = _nonZeroPixelCount,
|
||||||
_isModified = _isModified,
|
_isModified = _isModified,
|
||||||
_materialMilliliters = _materialMilliliters
|
_materialMilliliters = _materialMilliliters,
|
||||||
};
|
};*/
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -1362,5 +1504,52 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
|||||||
return clonedLayers;
|
return clonedLayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] CompressMat(Mat mat, LayerCompressionMethod method)
|
||||||
|
{
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case LayerCompressionMethod.Png:
|
||||||
|
return mat.GetPngByes();
|
||||||
|
case LayerCompressionMethod.Lz4:
|
||||||
|
{
|
||||||
|
var span = mat.GetDataByteSpan();
|
||||||
|
var target = new byte[LZ4Codec.MaximumOutputSize(span.Length)];
|
||||||
|
var encodedLength = LZ4Codec.Encode(span, target.AsSpan());
|
||||||
|
return target[..encodedLength];
|
||||||
|
}
|
||||||
|
case LayerCompressionMethod.GZip:
|
||||||
|
{
|
||||||
|
/*var matSpan = mat.GetDataByteSpan();
|
||||||
|
var compressedBytes = new byte[matSpan.Length];
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (byte* pBuffer = compressedBytes)
|
||||||
|
{
|
||||||
|
using var compressedStream = new UnmanagedMemoryStream(pBuffer, compressedBytes.Length, compressedBytes.Length, FileAccess.Write);
|
||||||
|
using var gZipStream = new GZipStream(compressedStream, CompressionLevel.Fastest);
|
||||||
|
gZipStream.Write(mat.GetDataByteSpan());
|
||||||
|
//return compressedBytes;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
using var compressedStream = new MemoryStream();
|
||||||
|
using var gZipStream = new GZipStream(compressedStream, CompressionLevel.Fastest);
|
||||||
|
gZipStream.Write(mat.GetDataByteSpan());
|
||||||
|
return compressedStream.ToArray();
|
||||||
|
}
|
||||||
|
case LayerCompressionMethod.Deflate:
|
||||||
|
{
|
||||||
|
using var compressedStream = new MemoryStream();
|
||||||
|
using var deflateStream = new DeflateStream(compressedStream, CompressionLevel.Fastest);
|
||||||
|
deflateStream.Write(mat.GetDataByteSpan());
|
||||||
|
return compressedStream.ToArray();
|
||||||
|
}
|
||||||
|
/*case LayerCompressionMethod.None:
|
||||||
|
return mat.GetBytes();*/
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(method));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -553,7 +553,7 @@ public abstract class Operation : BindableBase, IDisposable
|
|||||||
|
|
||||||
var result = ExecuteInternally(progress);
|
var result = ExecuteInternally(progress);
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,9 +130,8 @@ public sealed class OperationBlur : Operation
|
|||||||
|
|
||||||
protected override bool ExecuteInternally(OperationProgress progress)
|
protected override bool ExecuteInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = SlicerFile[layerIndex].LayerMat)
|
using (var mat = SlicerFile[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
Execute(mat);
|
Execute(mat);
|
||||||
|
|||||||
@@ -1892,9 +1892,8 @@ public sealed class OperationCalibrateExposureFinder : Operation
|
|||||||
var tableGrouped = table.GroupBy(pair => new {pair.Key.LayerHeight, pair.Key.BottomExposure, pair.Key.Exposure}).Distinct();
|
var tableGrouped = table.GroupBy(pair => new {pair.Key.LayerHeight, pair.Key.BottomExposure, pair.Key.Exposure}).Distinct();
|
||||||
SlicerFile.BottomLayerCount = _bottomLayers;
|
SlicerFile.BottomLayerCount = _bottomLayers;
|
||||||
progress.ItemCount = (uint) (SlicerFile.LayerCount * table.Count);
|
progress.ItemCount = (uint) (SlicerFile.LayerCount * table.Count);
|
||||||
Parallel.For(0, SlicerFile.LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(0, SlicerFile.LayerCount, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var layer = SlicerFile[layerIndex];
|
var layer = SlicerFile[layerIndex];
|
||||||
using var mat = layer.LayerMat;
|
using var mat = layer.LayerMat;
|
||||||
var matRoi = new Mat(mat, boundingRectangle);
|
var matRoi = new Mat(mat, boundingRectangle);
|
||||||
@@ -1964,7 +1963,6 @@ public sealed class OperationCalibrateExposureFinder : Operation
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
if (parallelLayers.IsEmpty) return false;
|
if (parallelLayers.IsEmpty) return false;
|
||||||
var layers = parallelLayers.OrderBy(layer => layer.PositionZ).ThenBy(layer => layer.ExposureTime).ToList();
|
var layers = parallelLayers.OrderBy(layer => layer.PositionZ).ThenBy(layer => layer.ExposureTime).ToList();
|
||||||
|
|
||||||
@@ -1973,7 +1971,7 @@ public sealed class OperationCalibrateExposureFinder : Operation
|
|||||||
Layer currentLayer = layers[0];
|
Layer currentLayer = layers[0];
|
||||||
for (var layerIndex = 1; layerIndex < layers.Count; layerIndex++)
|
for (var layerIndex = 1; layerIndex < layers.Count; layerIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
progress++;
|
progress++;
|
||||||
var layer = layers[layerIndex];
|
var layer = layers[layerIndex];
|
||||||
if (currentLayer.PositionZ != layer.PositionZ ||
|
if (currentLayer.PositionZ != layer.PositionZ ||
|
||||||
@@ -2206,7 +2204,7 @@ public sealed class OperationCalibrateExposureFinder : Operation
|
|||||||
currentHeight = Layer.RoundHeight(currentHeight);
|
currentHeight = Layer.RoundHeight(currentHeight);
|
||||||
for (decimal layerHeight = _layerHeight; layerHeight <= endLayerHeight; layerHeight += _multipleLayerHeightStep)
|
for (decimal layerHeight = _layerHeight; layerHeight <= endLayerHeight; layerHeight += _multipleLayerHeightStep)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
layerHeight = Layer.RoundHeight(layerHeight);
|
layerHeight = Layer.RoundHeight(layerHeight);
|
||||||
|
|
||||||
if (_multipleExposures)
|
if (_multipleExposures)
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ public sealed class OperationCalibrateStressTower : Operation
|
|||||||
|
|
||||||
var layers = GetLayers();
|
var layers = GetLayers();
|
||||||
|
|
||||||
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(0, LayerCount, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
newLayers[layerIndex] = new Layer((uint)layerIndex, layers[layerIndex], SlicerFile) {IsModified = true};
|
newLayers[layerIndex] = new Layer((uint)layerIndex, layers[layerIndex], SlicerFile) {IsModified = true};
|
||||||
layers[layerIndex].Dispose();
|
layers[layerIndex].Dispose();
|
||||||
|
|||||||
@@ -729,7 +729,7 @@ public sealed class OperationCalibrateTolerance : Operation
|
|||||||
|
|
||||||
var layers = GetLayers();
|
var layers = GetLayers();
|
||||||
|
|
||||||
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(0, LayerCount, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
newLayers[layerIndex] = new Layer((uint)layerIndex, layers[layerIndex], SlicerFile) {IsModified = true};
|
newLayers[layerIndex] = new Layer((uint)layerIndex, layers[layerIndex], SlicerFile) {IsModified = true};
|
||||||
layers[layerIndex].Dispose();
|
layers[layerIndex].Dispose();
|
||||||
|
|||||||
@@ -205,10 +205,8 @@ public sealed class OperationChangeResolution : Operation
|
|||||||
|
|
||||||
var finalBounds = new Size((int)finalBoundsWidth, (int)finalBoundsHeight);
|
var finalBounds = new Size((int)finalBoundsWidth, (int)finalBoundsHeight);
|
||||||
|
|
||||||
Parallel.For(0, SlicerFile.LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(0, SlicerFile.LayerCount, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
|
|
||||||
if (mat.Size != newSize)
|
if (mat.Size != newSize)
|
||||||
@@ -230,8 +228,6 @@ public sealed class OperationChangeResolution : Operation
|
|||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
});
|
});
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
SlicerFile.ResolutionX = NewResolutionX;
|
SlicerFile.ResolutionX = NewResolutionX;
|
||||||
SlicerFile.ResolutionY = NewResolutionY;
|
SlicerFile.ResolutionY = NewResolutionY;
|
||||||
|
|
||||||
|
|||||||
@@ -283,10 +283,8 @@ public class OperationDoubleExposure : Operation
|
|||||||
layers[i] = SlicerFile[i];
|
layers[i] = SlicerFile[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
var firstLayer = SlicerFile[layerIndex];
|
var firstLayer = SlicerFile[layerIndex];
|
||||||
var secondLayer = firstLayer.Clone();
|
var secondLayer = firstLayer.Clone();
|
||||||
var isBottomLayer = firstLayer.IsBottomLayer;
|
var isBottomLayer = firstLayer.IsBottomLayer;
|
||||||
|
|||||||
@@ -669,7 +669,7 @@ public sealed class OperationDynamicLayerHeight : Operation
|
|||||||
|
|
||||||
while (true) // In a stack
|
while (true) // In a stack
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
progress.ProcessedItems = layerIndex - LayerIndexStart;
|
progress.ProcessedItems = layerIndex - LayerIndexStart;
|
||||||
|
|
||||||
if (currentLayerHeight >= (float)_maximumLayerHeight || layerIndex == LayerIndexEnd)
|
if (currentLayerHeight >= (float)_maximumLayerHeight || layerIndex == LayerIndexEnd)
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ public sealed class OperationDynamicLifts : Operation
|
|||||||
|
|
||||||
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++)
|
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
var layer = SlicerFile[layerIndex];
|
var layer = SlicerFile[layerIndex];
|
||||||
|
|
||||||
// Height
|
// Height
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ public class OperationFadeExposureTime : Operation
|
|||||||
var exposure = _fromExposureTime;
|
var exposure = _fromExposureTime;
|
||||||
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++)
|
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
exposure += increment;
|
exposure += increment;
|
||||||
SlicerFile[layerIndex].ExposureTime = (float)exposure;
|
SlicerFile[layerIndex].ExposureTime = (float)exposure;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,9 +101,8 @@ public class OperationFlip : Operation
|
|||||||
#region Methods
|
#region Methods
|
||||||
protected override bool ExecuteInternally(OperationProgress progress)
|
protected override bool ExecuteInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
Execute(mat);
|
Execute(mat);
|
||||||
SlicerFile[layerIndex].LayerMat = mat;
|
SlicerFile[layerIndex].LayerMat = mat;
|
||||||
|
|||||||
@@ -135,10 +135,8 @@ public sealed class OperationInfill : Operation
|
|||||||
mask = GetHoneycombMask(GetRoiSizeOrDefault());
|
mask = GetHoneycombMask(GetRoiSizeOrDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
Execute(mat, layerIndex, mask!);
|
Execute(mat, layerIndex, mask!);
|
||||||
SlicerFile[layerIndex].LayerMat = mat;
|
SlicerFile[layerIndex].LayerMat = mat;
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ public class OperationLayerArithmetic : Operation
|
|||||||
progress.ItemCount = (uint) Operations.Count;
|
progress.ItemCount = (uint) Operations.Count;
|
||||||
for (int i = 1; i < Operations.Count; i++)
|
for (int i = 1; i < Operations.Count; i++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
using var image = SlicerFile[Operations[i].LayerIndex].LayerMat;
|
using var image = SlicerFile[Operations[i].LayerIndex].LayerMat;
|
||||||
var imageRoi = GetRoiOrDefault(image);
|
var imageRoi = GetRoiOrDefault(image);
|
||||||
|
|
||||||
@@ -289,9 +289,8 @@ public class OperationLayerArithmetic : Operation
|
|||||||
}
|
}
|
||||||
|
|
||||||
progress.Reset("Applied layers", (uint) SetLayers.Count);
|
progress.Reset("Applied layers", (uint) SetLayers.Count);
|
||||||
Parallel.ForEach(SetLayers, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(SetLayers, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
if (Operations.Count == 1 || HaveROIorMask)
|
if (Operations.Count == 1 || HaveROIorMask)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -224,9 +224,8 @@ public sealed class OperationLayerExportGif : Operation
|
|||||||
ROI = SlicerFile.BoundingRectangle;
|
ROI = SlicerFile.BoundingRectangle;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.For(0, TotalLayers, CoreSettings.ParallelOptions, i =>
|
Parallel.For(0, TotalLayers, CoreSettings.GetParallelOptions(progress), i =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
uint layerIndex = (uint) (LayerIndexStart + i * (_skip + 1));
|
uint layerIndex = (uint) (LayerIndexStart + i * (_skip + 1));
|
||||||
var layer = SlicerFile[layerIndex];
|
var layer = SlicerFile[layerIndex];
|
||||||
using var mat = layer.LayerMat;
|
using var mat = layer.LayerMat;
|
||||||
@@ -270,8 +269,8 @@ public sealed class OperationLayerExportGif : Operation
|
|||||||
progress.ResetNameAndProcessed("Packed layers");
|
progress.ResetNameAndProcessed("Packed layers");
|
||||||
foreach (var buffer in layerBuffer)
|
foreach (var buffer in layerBuffer)
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) break;
|
progress.ThrowIfCancellationRequested();
|
||||||
using Stream stream = new MemoryStream(buffer);
|
using var stream = new MemoryStream(buffer);
|
||||||
using var img = Image.FromStream(stream);
|
using var img = Image.FromStream(stream);
|
||||||
gif.AddFrame(img, -1, GifQuality.Bit8);
|
gif.AddFrame(img, -1, GifQuality.Bit8);
|
||||||
progress++;
|
progress++;
|
||||||
|
|||||||
@@ -152,10 +152,8 @@ public sealed class OperationLayerExportHeatMap : Operation
|
|||||||
}
|
}
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
Parallel.ForEach(layerRange, CoreSettings.ParallelOptions, layer =>
|
Parallel.ForEach(layerRange, CoreSettings.GetParallelOptions(progress), layer =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
using var mat = _mergeSamePositionedLayers
|
using var mat = _mergeSamePositionedLayers
|
||||||
? SlicerFile.GetMergedMatForSequentialPositionedLayers(layer.Index)
|
? SlicerFile.GetMergedMatForSequentialPositionedLayers(layer.Index)
|
||||||
: layer.LayerMat;
|
: layer.LayerMat;
|
||||||
@@ -171,32 +169,31 @@ public sealed class OperationLayerExportHeatMap : Operation
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!progress.Token.IsCancellationRequested)
|
|
||||||
|
using var sumMat = EmguExtensions.InitMat(sumMat32.Size);
|
||||||
|
sumMat32.ConvertTo(sumMat, DepthType.Cv8U, 1.0 / layerRange.Length);
|
||||||
|
|
||||||
|
if (_flipDirection != Enumerations.FlipDirection.None)
|
||||||
{
|
{
|
||||||
using var sumMat = EmguExtensions.InitMat(sumMat32.Size);
|
CvInvoke.Flip(sumMat, sumMat, Enumerations.ToOpenCVFlipType(_flipDirection));
|
||||||
sumMat32.ConvertTo(sumMat, DepthType.Cv8U, 1.0 / layerRange.Length);
|
|
||||||
|
|
||||||
if (_flipDirection != Enumerations.FlipDirection.None)
|
|
||||||
{
|
|
||||||
CvInvoke.Flip(sumMat, sumMat, Enumerations.ToOpenCVFlipType(_flipDirection));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_rotateDirection != Enumerations.RotateDirection.None)
|
|
||||||
{
|
|
||||||
CvInvoke.Rotate(sumMat, sumMat, Enumerations.ToOpenCVRotateFlags(_rotateDirection));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_cropByRoi && HaveROI)
|
|
||||||
{
|
|
||||||
var sumMatRoi = GetRoiOrDefault(sumMat);
|
|
||||||
sumMatRoi.Save(_filePath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sumMat.Save(_filePath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_rotateDirection != Enumerations.RotateDirection.None)
|
||||||
|
{
|
||||||
|
CvInvoke.Rotate(sumMat, sumMat, Enumerations.ToOpenCVRotateFlags(_rotateDirection));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cropByRoi && HaveROI)
|
||||||
|
{
|
||||||
|
var sumMatRoi = GetRoiOrDefault(sumMat);
|
||||||
|
sumMatRoi.Save(_filePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sumMat.Save(_filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return !progress.Token.IsCancellationRequested;
|
return !progress.Token.IsCancellationRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -180,10 +180,8 @@ public sealed class OperationLayerExportImage : Operation
|
|||||||
|
|
||||||
var slicedFileNameNoExt = SlicerFile.FilenameNoExt;
|
var slicedFileNameNoExt = SlicerFile.FilenameNoExt;
|
||||||
|
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd+1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd+1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
var matRoi = mat;
|
var matRoi = mat;
|
||||||
if (_cropByRoi && HaveROI)
|
if (_cropByRoi && HaveROI)
|
||||||
@@ -201,7 +199,7 @@ public sealed class OperationLayerExportImage : Operation
|
|||||||
CvInvoke.Rotate(matRoi, matRoi, Enumerations.ToOpenCVRotateFlags(_rotateDirection));
|
CvInvoke.Rotate(matRoi, matRoi, Enumerations.ToOpenCVRotateFlags(_rotateDirection));
|
||||||
}
|
}
|
||||||
|
|
||||||
var filename = SlicerFile[layerIndex].FormatFileName(_filename, _padLayerIndex ? SlicerFile.LayerDigits : byte.MinValue, true, string.Empty);
|
var filename = SlicerFile[layerIndex].FormatFileName(_filename, _padLayerIndex ? SlicerFile.LayerDigits : byte.MinValue, Enumerations.IndexStartNumber.Zero, string.Empty);
|
||||||
var fileFullPath = Path.Combine(_outputFolder, $"{filename}.{_imageType.ToString().ToLower()}");
|
var fileFullPath = Path.Combine(_outputFolder, $"{filename}.{_imageType.ToString().ToLower()}");
|
||||||
|
|
||||||
if (_imageType != LayerExportImageTypes.SVG)
|
if (_imageType != LayerExportImageTypes.SVG)
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ public sealed class OperationLayerExportMesh : Operation
|
|||||||
var voxelSpan = voxelLayer.GetBytePointer();
|
var voxelSpan = voxelLayer.GetBytePointer();
|
||||||
|
|
||||||
/* Seems to be faster to parallel on the Y and not the X */
|
/* Seems to be faster to parallel on the Y and not the X */
|
||||||
Parallel.For(0, curLayer!.Height, CoreSettings.ParallelOptions, y =>
|
Parallel.For(0, curLayer!.Height, CoreSettings.GetParallelOptions(progress), y =>
|
||||||
{
|
{
|
||||||
/* Collects all the faces found for this thread, will be combined into the main dictionary later */
|
/* Collects all the faces found for this thread, will be combined into the main dictionary later */
|
||||||
var threadDict = new Dictionary<Voxelizer.FaceOrientation, List<Point>>();
|
var threadDict = new Dictionary<Voxelizer.FaceOrientation, List<Point>>();
|
||||||
@@ -477,10 +477,8 @@ public sealed class OperationLayerExportMesh : Operation
|
|||||||
progress.ProcessedItems = 0;
|
progress.ProcessedItems = 0;
|
||||||
|
|
||||||
/* We build out a 3 dimensional KD tree for each layer, having 1 big KD tree is prohibitive when you get to millions and millions of faces. */
|
/* We build out a 3 dimensional KD tree for each layer, having 1 big KD tree is prohibitive when you get to millions and millions of faces. */
|
||||||
Parallel.For(0, distinctLayers.Length, layerIndex =>
|
Parallel.For(0, distinctLayers.Length, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
/* Create the KD tree for the layer, in practice there should never be dups, but just in case, set to skip */
|
/* Create the KD tree for the layer, in practice there should never be dups, but just in case, set to skip */
|
||||||
layerTrees[layerIndex] = new KdTree<float, Voxelizer.UVFace>(3, new FloatMath(), AddDuplicateBehavior.Skip);
|
layerTrees[layerIndex] = new KdTree<float, Voxelizer.UVFace>(3, new FloatMath(), AddDuplicateBehavior.Skip);
|
||||||
|
|
||||||
|
|||||||
@@ -91,10 +91,8 @@ public sealed class OperationLayerExportSkeleton : Operation
|
|||||||
using var mask = GetMask(skeletonSum);
|
using var mask = GetMask(skeletonSum);
|
||||||
|
|
||||||
|
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd+1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd+1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
var matRoi = GetRoiOrDefault(mat);
|
var matRoi = GetRoiOrDefault(mat);
|
||||||
using var skeletonRoi = matRoi.Skeletonize();
|
using var skeletonRoi = matRoi.Skeletonize();
|
||||||
@@ -104,17 +102,14 @@ public sealed class OperationLayerExportSkeleton : Operation
|
|||||||
progress++;
|
progress++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!progress.Token.IsCancellationRequested)
|
if (_cropByRoi && HaveROI)
|
||||||
{
|
{
|
||||||
if (_cropByRoi && HaveROI)
|
skeletonSumRoi.Save(_filePath);
|
||||||
{
|
}
|
||||||
skeletonSumRoi.Save(_filePath);
|
else
|
||||||
}
|
{
|
||||||
else
|
skeletonSum.Save(_filePath);
|
||||||
{
|
|
||||||
skeletonSum.Save(_filePath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !progress.Token.IsCancellationRequested;
|
return !progress.Token.IsCancellationRequested;
|
||||||
|
|||||||
@@ -255,9 +255,8 @@ public sealed class OperationLayerImport : Operation
|
|||||||
SL1File format = new();
|
SL1File format = new();
|
||||||
format.Init((uint)keyImage.Count);
|
format.Init((uint)keyImage.Count);
|
||||||
|
|
||||||
Parallel.ForEach(keyImage, CoreSettings.ParallelOptions, pair =>
|
Parallel.ForEach(keyImage, CoreSettings.GetParallelOptions(progress), pair =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = CvInvoke.Imread(pair.Value, ImreadModes.Grayscale);
|
using var mat = CvInvoke.Imread(pair.Value, ImreadModes.Grayscale);
|
||||||
if (pair.Key == 0) format.Resolution = mat.Size;
|
if (pair.Key == 0) format.Resolution = mat.Size;
|
||||||
format[pair.Key] = new Layer(pair.Key, mat, format);
|
format[pair.Key] = new Layer(pair.Key, mat, format);
|
||||||
@@ -265,7 +264,6 @@ public sealed class OperationLayerImport : Operation
|
|||||||
progress.LockAndIncrement();
|
progress.LockAndIncrement();
|
||||||
});
|
});
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
fileFormats.Add(format);
|
fileFormats.Add(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +282,7 @@ public sealed class OperationLayerImport : Operation
|
|||||||
fileFormats.Add(fileFormat);
|
fileFormats.Add(fileFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
if (fileFormats.Count == 0) return false;
|
if (fileFormats.Count == 0) return false;
|
||||||
|
|
||||||
@@ -379,9 +377,8 @@ public sealed class OperationLayerImport : Operation
|
|||||||
}
|
}
|
||||||
|
|
||||||
progress.Reset(ProgressAction, fileFormat.LayerCount);
|
progress.Reset(ProgressAction, fileFormat.LayerCount);
|
||||||
Parallel.For(0, fileFormat.LayerCount, CoreSettings.ParallelOptions, i =>
|
Parallel.For(0, fileFormat.LayerCount, CoreSettings.GetParallelOptions(progress), i =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
uint layerIndex = (uint)(_startLayerIndex + i);
|
uint layerIndex = (uint)(_startLayerIndex + i);
|
||||||
|
|
||||||
switch (_importType)
|
switch (_importType)
|
||||||
@@ -503,7 +500,6 @@ public sealed class OperationLayerImport : Operation
|
|||||||
});
|
});
|
||||||
|
|
||||||
fileFormat.Dispose();
|
fileFormat.Dispose();
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_importType == ImportTypes.Stack)
|
if (_importType == ImportTypes.Stack)
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ public sealed class OperationLayerReHeight : Operation
|
|||||||
uint newLayerIndex = 0;
|
uint newLayerIndex = 0;
|
||||||
for (uint layerIndex = 0; layerIndex < SlicerFile.LayerCount; layerIndex++)
|
for (uint layerIndex = 0; layerIndex < SlicerFile.LayerCount; layerIndex++)
|
||||||
{
|
{
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var oldLayer = SlicerFile[layerIndex];
|
var oldLayer = SlicerFile[layerIndex];
|
||||||
for (byte i = 0; i < _selectedItem.Modifier; i++)
|
for (byte i = 0; i < _selectedItem.Modifier; i++)
|
||||||
@@ -318,9 +318,8 @@ public sealed class OperationLayerReHeight : Operation
|
|||||||
layerIndexes[i] = i * _selectedItem.Modifier;
|
layerIndexes[i] = i * _selectedItem.Modifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.ForEach(layerIndexes, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.ForEach(layerIndexes, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var oldLayer = SlicerFile[layerIndex];
|
var oldLayer = SlicerFile[layerIndex];
|
||||||
using var matSum = oldLayer.LayerMat;
|
using var matSum = oldLayer.LayerMat;
|
||||||
Mat? matXorSum = null;
|
Mat? matXorSum = null;
|
||||||
@@ -395,8 +394,6 @@ public sealed class OperationLayerReHeight : Operation
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
SlicerFile.SuppressRebuildPropertiesWork(() =>
|
SlicerFile.SuppressRebuildPropertiesWork(() =>
|
||||||
{
|
{
|
||||||
SlicerFile.LayerHeight = (float)_selectedItem!.LayerHeight;
|
SlicerFile.LayerHeight = (float)_selectedItem!.LayerHeight;
|
||||||
|
|||||||
@@ -203,10 +203,8 @@ public class OperationLightBleedCompensation : Operation
|
|||||||
{
|
{
|
||||||
var dimMats = GetDimMats();
|
var dimMats = GetDimMats();
|
||||||
if (dimMats.Length == 0) return false;
|
if (dimMats.Length == 0) return false;
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return; // Abort operation, user requested cancellation
|
|
||||||
|
|
||||||
var layer = SlicerFile[layerIndex];
|
var layer = SlicerFile[layerIndex];
|
||||||
using var mat = layer.LayerMat;
|
using var mat = layer.LayerMat;
|
||||||
using var original = mat.Clone();
|
using var original = mat.Clone();
|
||||||
|
|||||||
@@ -74,9 +74,8 @@ public class OperationMask : Operation
|
|||||||
|
|
||||||
protected override bool ExecuteInternally(OperationProgress progress)
|
protected override bool ExecuteInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
Execute(mat);
|
Execute(mat);
|
||||||
SlicerFile[layerIndex].LayerMat = mat;
|
SlicerFile[layerIndex].LayerMat = mat;
|
||||||
|
|||||||
@@ -176,9 +176,8 @@ public sealed class OperationMorph : Operation
|
|||||||
out var maxIteration
|
out var maxIteration
|
||||||
);
|
);
|
||||||
|
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
int iterations = FileFormat.MutateGetIterationVar(isFade, (int)IterationsStart, (int)IterationsEnd, iterationSteps, maxIteration, LayerIndexStart, (uint)layerIndex);
|
int iterations = FileFormat.MutateGetIterationVar(isFade, (int)IterationsStart, (int)IterationsEnd, iterationSteps, maxIteration, LayerIndexStart, (uint)layerIndex);
|
||||||
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
|
|||||||
@@ -264,10 +264,8 @@ public class OperationMove : Operation
|
|||||||
if (ROI.IsEmpty) ROI = SlicerFile.GetBoundingRectangle(progress);
|
if (ROI.IsEmpty) ROI = SlicerFile.GetBoundingRectangle(progress);
|
||||||
CalculateDstRoi();
|
CalculateDstRoi();
|
||||||
|
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
using (var mat = SlicerFile[layerIndex].LayerMat)
|
using (var mat = SlicerFile[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
Execute(mat);
|
Execute(mat);
|
||||||
|
|||||||
@@ -299,10 +299,8 @@ public class OperationPattern : Operation
|
|||||||
|
|
||||||
protected override bool ExecuteInternally(OperationProgress progress)
|
protected override bool ExecuteInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
using var layerRoi = new Mat(mat, ROI);
|
using var layerRoi = new Mat(mat, ROI);
|
||||||
using var dstLayer = mat.NewBlank();
|
using var dstLayer = mat.NewBlank();
|
||||||
@@ -321,8 +319,6 @@ public class OperationPattern : Operation
|
|||||||
|
|
||||||
SlicerFile.BoundingRectangle = Rectangle.Empty;
|
SlicerFile.BoundingRectangle = Rectangle.Empty;
|
||||||
|
|
||||||
progress.Token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
if (Anchor == Enumerations.Anchor.None) return true;
|
if (Anchor == Enumerations.Anchor.None) return true;
|
||||||
var operationMove = new OperationMove(SlicerFile, Anchor)
|
var operationMove = new OperationMove(SlicerFile, Anchor)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -582,9 +582,8 @@ public class OperationPixelArithmetic : Operation
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var layer = SlicerFile[layerIndex];
|
var layer = SlicerFile[layerIndex];
|
||||||
using (var mat = layer.LayerMat)
|
using (var mat = layer.LayerMat)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -650,9 +650,8 @@ public class OperationPixelDimming : Operation
|
|||||||
CvInvoke.BitwiseNot(patternMask, patternMask);
|
CvInvoke.BitwiseNot(patternMask, patternMask);
|
||||||
CvInvoke.BitwiseNot(alternatePatternMask, alternatePatternMask);
|
CvInvoke.BitwiseNot(alternatePatternMask, alternatePatternMask);
|
||||||
|
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
Execute(mat, layerIndex, patternMask, alternatePatternMask);
|
Execute(mat, layerIndex, patternMask, alternatePatternMask);
|
||||||
SlicerFile[layerIndex].LayerMat = mat;
|
SlicerFile[layerIndex].LayerMat = mat;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public sealed class OperationProgress : BindableBase
|
|||||||
|
|
||||||
public CancellationTokenSource TokenSource { get; private set; } = null!;
|
public CancellationTokenSource TokenSource { get; private set; } = null!;
|
||||||
public CancellationToken Token => TokenSource.Token;
|
public CancellationToken Token => TokenSource.Token;
|
||||||
|
public void ThrowIfCancellationRequested() => TokenSource.Token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
private bool _canCancel = true;
|
private bool _canCancel = true;
|
||||||
private string _title = "Operation";
|
private string _title = "Operation";
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ public class OperationRaftRelief : Operation
|
|||||||
progress.Reset("Tracing raft", layerCount, firstSupportLayerIndex);
|
progress.Reset("Tracing raft", layerCount, firstSupportLayerIndex);
|
||||||
for (; firstSupportLayerIndex < layerCount; firstSupportLayerIndex++)
|
for (; firstSupportLayerIndex < layerCount; firstSupportLayerIndex++)
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return false;
|
progress.ThrowIfCancellationRequested();
|
||||||
progress++;
|
progress++;
|
||||||
supportsMat = GetRoiOrDefault(SlicerFile[firstSupportLayerIndex].LayerMat);
|
supportsMat = GetRoiOrDefault(SlicerFile[firstSupportLayerIndex].LayerMat);
|
||||||
var circles = CvInvoke.HoughCircles(supportsMat, HoughModes.Gradient, 1, 5, 80, 35, 5, 200);
|
var circles = CvInvoke.HoughCircles(supportsMat, HoughModes.Gradient, 1, 5, 80, 35, 5, 200);
|
||||||
@@ -240,9 +240,8 @@ public class OperationRaftRelief : Operation
|
|||||||
}
|
}
|
||||||
|
|
||||||
progress.Reset(ProgressAction, firstSupportLayerIndex - _ignoreFirstLayers);
|
progress.Reset(ProgressAction, firstSupportLayerIndex - _ignoreFirstLayers);
|
||||||
Parallel.For(_ignoreFirstLayers, firstSupportLayerIndex, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(_ignoreFirstLayers, firstSupportLayerIndex, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
using var original = mat.Clone();
|
using var original = mat.Clone();
|
||||||
var target = GetRoiOrDefault(mat);
|
var target = GetRoiOrDefault(mat);
|
||||||
|
|||||||
@@ -170,9 +170,8 @@ public class OperationRedrawModel : Operation
|
|||||||
|
|
||||||
int startLayerIndex = (int)(SlicerFile.LayerCount - otherFile.LayerCount);
|
int startLayerIndex = (int)(SlicerFile.LayerCount - otherFile.LayerCount);
|
||||||
if (startLayerIndex < 0) return false;
|
if (startLayerIndex < 0) return false;
|
||||||
Parallel.For(0, otherFile.LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(0, otherFile.LayerCount, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var fullMatLayerIndex = startLayerIndex + layerIndex;
|
var fullMatLayerIndex = startLayerIndex + layerIndex;
|
||||||
using var fullMat = SlicerFile[fullMatLayerIndex].LayerMat;
|
using var fullMat = SlicerFile[fullMatLayerIndex].LayerMat;
|
||||||
using var original = fullMat.Clone();
|
using var original = fullMat.Clone();
|
||||||
|
|||||||
@@ -247,9 +247,8 @@ public class OperationRepairLayers : Operation
|
|||||||
if (!issuesGroup.Any()) break; // Nothing to process
|
if (!issuesGroup.Any()) break; // Nothing to process
|
||||||
|
|
||||||
islandsToRecompute.Clear();
|
islandsToRecompute.Clear();
|
||||||
Parallel.ForEach(issuesGroup, CoreSettings.ParallelOptions, group =>
|
Parallel.ForEach(issuesGroup, CoreSettings.GetParallelOptions(progress), group =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var layer = SlicerFile[group.Key];
|
var layer = SlicerFile[group.Key];
|
||||||
var image = layer.LayerMat;
|
var image = layer.LayerMat;
|
||||||
var bytes = image.GetDataByteSpan();
|
var bytes = image.GetDataByteSpan();
|
||||||
@@ -300,7 +299,7 @@ public class OperationRepairLayers : Operation
|
|||||||
|
|
||||||
progress.Reset("Attempt to attach islands below", (uint) islandsToProcess!.Count);
|
progress.Reset("Attempt to attach islands below", (uint) islandsToProcess!.Count);
|
||||||
var sync = new object();
|
var sync = new object();
|
||||||
Parallel.ForEach(issuesGroup, CoreSettings.ParallelOptions, group =>
|
Parallel.ForEach(issuesGroup, CoreSettings.GetParallelOptions(progress), group =>
|
||||||
{
|
{
|
||||||
using var mat = SlicerFile[group.Key].LayerMat;
|
using var mat = SlicerFile[group.Key].LayerMat;
|
||||||
var matSpan = mat.GetDataByteSpan();
|
var matSpan = mat.GetDataByteSpan();
|
||||||
@@ -390,9 +389,8 @@ public class OperationRepairLayers : Operation
|
|||||||
progress.Reset(ProgressAction, LayerRangeCount);
|
progress.Reset(ProgressAction, LayerRangeCount);
|
||||||
if (_repairIslands || _repairResinTraps)
|
if (_repairIslands || _repairResinTraps)
|
||||||
{
|
{
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var layer = SlicerFile[layerIndex];
|
var layer = SlicerFile[layerIndex];
|
||||||
Mat? image = null;
|
Mat? image = null;
|
||||||
|
|
||||||
|
|||||||
@@ -157,9 +157,8 @@ public class OperationResize : Operation
|
|||||||
decimal xSteps = Math.Abs(100 - _x) / (LayerIndexEnd - LayerIndexStart + 1);
|
decimal xSteps = Math.Abs(100 - _x) / (LayerIndexEnd - LayerIndexStart + 1);
|
||||||
decimal ySteps = Math.Abs(100 - _y) / (LayerIndexEnd - LayerIndexStart + 1);
|
decimal ySteps = Math.Abs(100 - _y) / (LayerIndexEnd - LayerIndexStart + 1);
|
||||||
|
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
var newX = _x;
|
var newX = _x;
|
||||||
var newY = _y;
|
var newY = _y;
|
||||||
if (IsFade)
|
if (IsFade)
|
||||||
|
|||||||
@@ -95,9 +95,8 @@ public class OperationRotate : Operation
|
|||||||
|
|
||||||
protected override bool ExecuteInternally(OperationProgress progress)
|
protected override bool ExecuteInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
Execute(mat);
|
Execute(mat);
|
||||||
SlicerFile[layerIndex].LayerMat = mat;
|
SlicerFile[layerIndex].LayerMat = mat;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public sealed class OperationScripting : Operation
|
|||||||
|
|
||||||
public override bool CanRunInPartialMode => true;
|
public override bool CanRunInPartialMode => true;
|
||||||
|
|
||||||
public override bool CanHaveProfiles => false;
|
//public override bool CanHaveProfiles => false;
|
||||||
public override string IconClass => "fas fa-code";
|
public override string IconClass => "fas fa-code";
|
||||||
public override string Title => "Scripting";
|
public override string Title => "Scripting";
|
||||||
|
|
||||||
@@ -67,6 +67,13 @@ public sealed class OperationScripting : Operation
|
|||||||
return scriptValidation.ReturnValue;
|
return scriptValidation.ReturnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
var result = $"[{Path.GetFileName(_filePath)}]" + LayerRangeString;
|
||||||
|
if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Enums
|
#region Enums
|
||||||
@@ -75,6 +82,7 @@ public sealed class OperationScripting : Operation
|
|||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
|
[XmlIgnore]
|
||||||
public ScriptGlobals? ScriptGlobals { get; private set; }
|
public ScriptGlobals? ScriptGlobals { get; private set; }
|
||||||
|
|
||||||
public string? FilePath
|
public string? FilePath
|
||||||
@@ -104,10 +112,8 @@ public sealed class OperationScripting : Operation
|
|||||||
set => RaiseAndSetIfChanged(ref _scriptText, value);
|
set => RaiseAndSetIfChanged(ref _scriptText, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[XmlIgnore]
|
|
||||||
public bool CanExecute => !string.IsNullOrWhiteSpace(_filePath) && _scriptState is not null && ScriptGlobals is not null && About.Version.CompareTo(ScriptGlobals.Script.MinimumVersionToRun) >= 0;
|
public bool CanExecute => !string.IsNullOrWhiteSpace(_filePath) && _scriptState is not null && ScriptGlobals is not null && About.Version.CompareTo(ScriptGlobals.Script.MinimumVersionToRun) >= 0;
|
||||||
|
|
||||||
[XmlIgnore]
|
|
||||||
public bool HaveFile => !string.IsNullOrWhiteSpace(_filePath);
|
public bool HaveFile => !string.IsNullOrWhiteSpace(_filePath);
|
||||||
|
|
||||||
/*public override string ToString()
|
/*public override string ToString()
|
||||||
@@ -131,7 +137,22 @@ public sealed class OperationScripting : Operation
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Equality
|
#region Equality
|
||||||
|
|
||||||
|
private bool Equals(OperationScripting other)
|
||||||
|
{
|
||||||
|
return _filePath == other._filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
return ReferenceEquals(this, obj) || obj is OperationScripting other && Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (_filePath != null ? _filePath.GetHashCode() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|||||||
@@ -87,9 +87,8 @@ public sealed class OperationSolidify : Operation
|
|||||||
|
|
||||||
protected override bool ExecuteInternally(OperationProgress progress)
|
protected override bool ExecuteInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
Execute(mat);
|
Execute(mat);
|
||||||
SlicerFile[layerIndex].LayerMat = mat;
|
SlicerFile[layerIndex].LayerMat = mat;
|
||||||
|
|||||||
@@ -82,9 +82,8 @@ public class OperationThreshold : Operation
|
|||||||
|
|
||||||
protected override bool ExecuteInternally(OperationProgress progress)
|
protected override bool ExecuteInternally(OperationProgress progress)
|
||||||
{
|
{
|
||||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var mat = SlicerFile[layerIndex].LayerMat)
|
using (var mat = SlicerFile[layerIndex].LayerMat)
|
||||||
{
|
{
|
||||||
Execute(mat);
|
Execute(mat);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||||
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
|
||||||
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
|
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
|
||||||
<Version>3.0.0</Version>
|
<Version>3.1.0</Version>
|
||||||
<Copyright>Copyright © 2020 PTRTECH</Copyright>
|
<Copyright>Copyright © 2020 PTRTECH</Copyright>
|
||||||
<PackageIcon>UVtools.png</PackageIcon>
|
<PackageIcon>UVtools.png</PackageIcon>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
@@ -62,6 +62,7 @@
|
|||||||
<PackageReference Include="AnimatedGif" Version="1.0.5" />
|
<PackageReference Include="AnimatedGif" Version="1.0.5" />
|
||||||
<PackageReference Include="BinarySerializer" Version="8.6.2.2" />
|
<PackageReference Include="BinarySerializer" Version="8.6.2.2" />
|
||||||
<PackageReference Include="Emgu.CV" Version="4.5.5.4823" />
|
<PackageReference Include="Emgu.CV" Version="4.5.5.4823" />
|
||||||
|
<PackageReference Include="K4os.Compression.LZ4" Version="1.2.16" />
|
||||||
<PackageReference Include="KdTree" Version="1.4.1" />
|
<PackageReference Include="KdTree" Version="1.4.1" />
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.1.0" />
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.1.0" />
|
||||||
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
|
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
<Package InstallerVersion="301" Compressed="yes" InstallScope="perMachine" Platform="x64" />
|
<Package InstallerVersion="301" Compressed="yes" InstallScope="perMachine" Platform="x64" />
|
||||||
<MediaTemplate EmbedCab="yes" />
|
<MediaTemplate EmbedCab="yes" />
|
||||||
<!-- Major Upgrade Rule to disallow downgrades -->
|
<!-- Major Upgrade Rule to disallow downgrades -->
|
||||||
<!-- AllowSameVersionUpgrades="yes" -->
|
|
||||||
<MajorUpgrade
|
<MajorUpgrade
|
||||||
AllowDowngrades="no"
|
AllowDowngrades="no"
|
||||||
|
AllowSameVersionUpgrades="yes"
|
||||||
IgnoreRemoveFailure="no"
|
IgnoreRemoveFailure="no"
|
||||||
DowngradeErrorMessage="A newer version of [ProductName] is already installed."
|
DowngradeErrorMessage="A newer version of [ProductName] is already installed."
|
||||||
Schedule="afterInstallInitialize" />
|
Schedule="afterInstallInitialize" />
|
||||||
|
|||||||
@@ -335,9 +335,6 @@
|
|||||||
<Component Id="owc79156F385239CEA4DEA3C87C1DA3E1D8" Guid="68380c80-6708-5eb6-415d-10e278417679" Win64="yes">
|
<Component Id="owc79156F385239CEA4DEA3C87C1DA3E1D8" Guid="68380c80-6708-5eb6-415d-10e278417679" Win64="yes">
|
||||||
<File Id="owf79156F385239CEA4DEA3C87C1DA3E1D8" Source="$(var.SourceDir)\netstandard.dll" KeyPath="yes" />
|
<File Id="owf79156F385239CEA4DEA3C87C1DA3E1D8" Source="$(var.SourceDir)\netstandard.dll" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="owc3FC8434C1A84605AEEBC6A100CA2F3E1" Guid="47d7e276-db6d-424e-d797-1a69e1e24b3b" Win64="yes">
|
|
||||||
<File Id="owf3FC8434C1A84605AEEBC6A100CA2F3E1" Source="$(var.SourceDir)\Newtonsoft.Json.dll" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="owc7BB28EFC52A49429849339DF748B25E7" Guid="ded507d6-fd2b-41f2-bd03-cf489e47df7a" Win64="yes">
|
<Component Id="owc7BB28EFC52A49429849339DF748B25E7" Guid="ded507d6-fd2b-41f2-bd03-cf489e47df7a" Win64="yes">
|
||||||
<File Id="owf7BB28EFC52A49429849339DF748B25E7" Source="$(var.SourceDir)\runtime_package.dat" KeyPath="yes" />
|
<File Id="owf7BB28EFC52A49429849339DF748B25E7" Source="$(var.SourceDir)\runtime_package.dat" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
@@ -1449,6 +1446,21 @@
|
|||||||
<Component Id="owc9C1F0C0351694913958CEBFB4D988C2D" Guid="9C1F0C03-5169-4913-958C-EBFB4D988C2D">
|
<Component Id="owc9C1F0C0351694913958CEBFB4D988C2D" Guid="9C1F0C03-5169-4913-958C-EBFB4D988C2D">
|
||||||
<File Id="owf9C1F0C0351694913958CEBFB4D988C2D" Source="$(var.SourceDir)\System.Net.Quic.dll" KeyPath="yes" />
|
<File Id="owf9C1F0C0351694913958CEBFB4D988C2D" Source="$(var.SourceDir)\System.Net.Quic.dll" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component Id="owcE9728785ABFF46BBBB650949E58582F6" Guid="E9728785-ABFF-46BB-BB65-0949E58582F6">
|
||||||
|
<File Id="owfE9728785ABFF46BBBB650949E58582F6" Source="$(var.SourceDir)\AvaloniaEdit.dll" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="owc457BCA8E75BC42FFAB4C395A1E488E86" Guid="457BCA8E-75BC-42FF-AB4C-395A1E488E86">
|
||||||
|
<File Id="owf457BCA8E75BC42FFAB4C395A1E488E86" Source="$(var.SourceDir)\ColorTextBlock.Avalonia.dll" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="owcBD9F04FC618C4C23A76BC23A5949C99E" Guid="BD9F04FC-618C-4C23-A76B-C23A5949C99E">
|
||||||
|
<File Id="owfBD9F04FC618C4C23A76BC23A5949C99E" Source="$(var.SourceDir)\K4os.Compression.LZ4.dll" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="owc016FC6E6F2AC48FFA8AA1DF1773755ED" Guid="016FC6E6-F2AC-48FF-A8AA-1DF1773755ED">
|
||||||
|
<File Id="owf016FC6E6F2AC48FFA8AA1DF1773755ED" Source="$(var.SourceDir)\Markdown.Avalonia.dll" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="owc1BDB050EB61B44609ECD990453AC8FB5" Guid="1BDB050E-B61B-4460-9ECD-990453AC8FB5">
|
||||||
|
<File Id="owf1BDB050EB61B44609ECD990453AC8FB5" Source="$(var.SourceDir)\Markdown.Avalonia.SyntaxHigh.dll" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
</Directory>
|
</Directory>
|
||||||
<Directory Id="ProgramMenuFolder">
|
<Directory Id="ProgramMenuFolder">
|
||||||
<Directory Id="scd220707349D4C8FA275285514283F3E2A" Name="UVtools" />
|
<Directory Id="scd220707349D4C8FA275285514283F3E2A" Name="UVtools" />
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.cs.allow-jit</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-library-validation</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.cs.allow-jit</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-library-validation</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -100,7 +100,7 @@ public class ScriptAutomateWorkflowSample : ScriptGlobals
|
|||||||
|
|
||||||
foreach (var operation in operations) // Loop all my created operations to execute them
|
foreach (var operation in operations) // Loop all my created operations to execute them
|
||||||
{
|
{
|
||||||
Progress.Token.ThrowIfCancellationRequested(); // Abort operation, user requested cancellation
|
Progress.ThrowIfCancellationRequested(); // Abort operation, user requested cancellation
|
||||||
operation.ROI = Operation.ROI; // Copy user selected ROI to my operation
|
operation.ROI = Operation.ROI; // Copy user selected ROI to my operation
|
||||||
operation.MaskPoints = Operation.MaskPoints; // Copy user selected Masks to my operation
|
operation.MaskPoints = Operation.MaskPoints; // Copy user selected Masks to my operation
|
||||||
if (!operation.CanValidate()) continue; // If cant validate don't execute the operation
|
if (!operation.CanValidate()) continue; // If cant validate don't execute the operation
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class ScriptChangeLayerPropertiesSample : ScriptGlobals
|
|||||||
|
|
||||||
for (uint layerIndex = Operation.LayerIndexStart; layerIndex <= Operation.LayerIndexEnd; layerIndex++)
|
for (uint layerIndex = Operation.LayerIndexStart; layerIndex <= Operation.LayerIndexEnd; layerIndex++)
|
||||||
{
|
{
|
||||||
Progress.Token.ThrowIfCancellationRequested(); // Abort operation, user requested cancellation
|
Progress.ThrowIfCancellationRequested(); // Abort operation, user requested cancellation
|
||||||
var layer = SlicerFile[layerIndex]; // Unpack and expose layer variable for easier use
|
var layer = SlicerFile[layerIndex]; // Unpack and expose layer variable for easier use
|
||||||
|
|
||||||
layer.LiftHeight = random.Next(3, 10); // Random value from 3 to 10
|
layer.LiftHeight = random.Next(3, 10); // Random value from 3 to 10
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ public class ScriptCloneSettings : ScriptGlobals
|
|||||||
var results = new List<Tuple<ResultStatus, string, List<string>?>>();
|
var results = new List<Tuple<ResultStatus, string, List<string>?>>();
|
||||||
foreach (var filePath in filePaths)
|
foreach (var filePath in filePaths)
|
||||||
{
|
{
|
||||||
if (Progress.Token.IsCancellationRequested) return false;
|
Progress.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
Tuple<ResultStatus, string, List<string>?> result;
|
Tuple<ResultStatus, string, List<string>?> result;
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -93,10 +93,8 @@ public class ScriptInsetSample : ScriptGlobals
|
|||||||
|
|
||||||
|
|
||||||
// Loop user selected layers in parallel, this will put each core of CPU working here on parallel
|
// Loop user selected layers in parallel, this will put each core of CPU working here on parallel
|
||||||
Parallel.For(Operation.LayerIndexStart, Operation.LayerIndexEnd+1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(Operation.LayerIndexStart, Operation.LayerIndexEnd+1, CoreSettings.GetParallelOptions(Progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (Progress.Token.IsCancellationRequested) return; // Abort operation, user requested cancellation
|
|
||||||
|
|
||||||
var layer = SlicerFile[layerIndex]; // Unpack and expose layer variable for easier use
|
var layer = SlicerFile[layerIndex]; // Unpack and expose layer variable for easier use
|
||||||
using var mat = layer.LayerMat; // Gets this layer mat/image
|
using var mat = layer.LayerMat; // Gets this layer mat/image
|
||||||
var original = mat.Clone(); // Keep a original mat copy
|
var original = mat.Clone(); // Keep a original mat copy
|
||||||
|
|||||||
@@ -87,10 +87,8 @@ public class ScriptLightBleedCompensationSample : ScriptGlobals
|
|||||||
var brightnesses = Levels;
|
var brightnesses = Levels;
|
||||||
|
|
||||||
// Loop user selected layers in parallel, this will put each core of CPU working here on parallel
|
// Loop user selected layers in parallel, this will put each core of CPU working here on parallel
|
||||||
Parallel.For(Operation.LayerIndexStart, Operation.LayerIndexEnd+1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(Operation.LayerIndexStart, Operation.LayerIndexEnd+1, CoreSettings.GetParallelOptions(Progress), layerIndex =>
|
||||||
{
|
{
|
||||||
if (Progress.Token.IsCancellationRequested) return; // Abort operation, user requested cancellation
|
|
||||||
|
|
||||||
var layer = SlicerFile[layerIndex]; // Unpack and expose layer variable for easier use
|
var layer = SlicerFile[layerIndex]; // Unpack and expose layer variable for easier use
|
||||||
using var mat = layer.LayerMat; // Gets this layer mat/image
|
using var mat = layer.LayerMat; // Gets this layer mat/image
|
||||||
var original = mat.Clone(); // Keep a original mat copy
|
var original = mat.Clone(); // Keep a original mat copy
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public class ScriptTestPerLayerSettingsSample : ScriptGlobals
|
|||||||
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[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);
|
CvInvoke.Ellipse(mats[4], new Point(x, y), new Size(eyeDiameter+faceSpacing+noseThickness/2, mouthHeight), 0, 0, 180, EmguExtensions.WhiteColor, -1, lineType);
|
||||||
|
|
||||||
SlicerFile.AllocateAndSetFromMat(mats); // Replace layers and rebuild properties
|
SlicerFile.AllocateAndSetFromMat(mats, Progress); // Replace layers and rebuild properties
|
||||||
|
|
||||||
SlicerFile.BottomLayerCount = 1; // Set one bottom layer, the whole face
|
SlicerFile.BottomLayerCount = 1; // Set one bottom layer, the whole face
|
||||||
SlicerFile.BottomExposureTime = 5; // Set exposure to be fixed at 5s
|
SlicerFile.BottomExposureTime = 5; // Set exposure to be fixed at 5s
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class ScriptChangeLayesrPropertiesSample : ScriptGlobals
|
|||||||
public bool ScriptExecute()
|
public bool ScriptExecute()
|
||||||
{
|
{
|
||||||
var dict = new Dictionary<uint, List<(Point[] points, Rectangle rect)>>();
|
var dict = new Dictionary<uint, List<(Point[] points, Rectangle rect)>>();
|
||||||
Parallel.For(Operation.LayerIndexStart, Operation.LayerIndexEnd + 1, CoreSettings.ParallelOptions, layerIndex =>
|
Parallel.For(Operation.LayerIndexStart, Operation.LayerIndexEnd + 1, CoreSettings.GetParallelOptions(Progress), layerIndex =>
|
||||||
{
|
{
|
||||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||||
using var contours = mat.FindContours(out var hierarchy, RetrType.Tree);
|
using var contours = mat.FindContours(out var hierarchy, RetrType.Tree);
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ public static class AppSettings
|
|||||||
// These settings eliminate very small zoom factors from the ImageBox default values,
|
// These settings eliminate very small zoom factors from the ImageBox default values,
|
||||||
// while ensuring that 4K/5K build plates can still easily fit on screen.
|
// while ensuring that 4K/5K build plates can still easily fit on screen.
|
||||||
public static readonly int[] ZoomLevels =
|
public static readonly int[] ZoomLevels =
|
||||||
{20, 25, 30, 50, 75, 100, 150, 200, 300, 400, 500, 600, 700, 800, 1200, 1600, 3200};
|
{10, 20, 25, 30, 50, 75, 100, 150, 200, 300, 400, 500, 600, 700, 800, 1200, 1600, 3200, 6400};
|
||||||
|
|
||||||
// Count of the bottom portion of the full zoom range which will be skipped for
|
// Count of the bottom portion of the full zoom range which will be skipped for
|
||||||
// assignable actions such as auto-zoom level, and crosshair fade level. If values
|
// assignable actions such as auto-zoom level, and crosshair fade level. If values
|
||||||
// are added/removed from ZoomLevels above, this value may also need to be adjusted.
|
// are added/removed from ZoomLevels above, this value may also need to be adjusted.
|
||||||
public const byte ZoomLevelSkipCount = 7; // Start at 2x which is index 7.
|
public const byte ZoomLevelSkipCount = 8; // Start at 2x which is index 8.
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the zoom level at which the crosshairs will fade and no longer be displayed
|
/// Returns the zoom level at which the crosshairs will fade and no longer be displayed
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 294 KiB |
@@ -20,7 +20,7 @@
|
|||||||
<StackPanel Grid.Row="0" Grid.Column="4"
|
<StackPanel Grid.Row="0" Grid.Column="4"
|
||||||
Orientation="Horizontal" Spacing="1">
|
Orientation="Horizontal" Spacing="1">
|
||||||
<Button
|
<Button
|
||||||
ToolTip.Tip="Loads an script file"
|
ToolTip.Tip="Load script file"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Command="{Binding LoadScript}"
|
Command="{Binding LoadScript}"
|
||||||
i:Attached.Icon="fas fa-file-import"/>
|
i:Attached.Icon="fas fa-file-import"/>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.Threading;
|
||||||
using UVtools.Core;
|
using UVtools.Core;
|
||||||
using UVtools.Core.Operations;
|
using UVtools.Core.Operations;
|
||||||
using UVtools.Core.Scripting;
|
using UVtools.Core.Scripting;
|
||||||
@@ -43,7 +45,10 @@ public class ToolScriptingControl : ToolControl
|
|||||||
case ToolWindow.Callbacks.Loaded:
|
case ToolWindow.Callbacks.Loaded:
|
||||||
if(ParentWindow is not null) ParentWindow.ButtonOkEnabled = Operation.CanExecute;
|
if(ParentWindow is not null) ParentWindow.ButtonOkEnabled = Operation.CanExecute;
|
||||||
ReloadGUI();
|
ReloadGUI();
|
||||||
ReloadScript();
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
{
|
||||||
|
ReloadScript();
|
||||||
|
}, DispatcherPriority.Loaded);
|
||||||
Operation.PropertyChanged += (sender, e) =>
|
Operation.PropertyChanged += (sender, e) =>
|
||||||
{
|
{
|
||||||
if (e.PropertyName == nameof(Operation.CanExecute))
|
if (e.PropertyName == nameof(Operation.CanExecute))
|
||||||
@@ -93,13 +98,13 @@ public class ToolScriptingControl : ToolControl
|
|||||||
public void OpenScriptFolder()
|
public void OpenScriptFolder()
|
||||||
{
|
{
|
||||||
if (!Operation.HaveFile) return;
|
if (!Operation.HaveFile) return;
|
||||||
SystemAware.StartProcess(Path.GetDirectoryName(Operation.FilePath));
|
SystemAware.SelectFileOnExplorer(Operation.FilePath!);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenScriptFile()
|
public void OpenScriptFile()
|
||||||
{
|
{
|
||||||
if (!Operation.HaveFile) return;
|
if (!Operation.HaveFile) return;
|
||||||
SystemAware.StartProcess(Operation.FilePath);
|
SystemAware.StartProcess(Operation.FilePath!);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReloadGUI()
|
public void ReloadGUI()
|
||||||
|
|||||||
@@ -18,15 +18,17 @@ namespace UVtools.WPF.Extensions;
|
|||||||
|
|
||||||
public static class WindowExtensions
|
public static class WindowExtensions
|
||||||
{
|
{
|
||||||
public static async Task<ButtonResult> MessageBoxGeneric(this Window window, string message, string title = null,
|
public static async Task<ButtonResult> MessageBoxGeneric(this Window window, string message, string title = null, string header = null,
|
||||||
ButtonEnum buttons = ButtonEnum.Ok, Icon icon = Icon.None, bool topMost = false, WindowStartupLocation location = WindowStartupLocation.CenterOwner)
|
ButtonEnum buttons = ButtonEnum.Ok, Icon icon = Icon.None, bool markdown = false, bool topMost = false, WindowStartupLocation location = WindowStartupLocation.CenterOwner)
|
||||||
{
|
{
|
||||||
var messageBoxStandardWindow = MessageBox.Avalonia.MessageBoxManager.GetMessageBoxStandardWindow(
|
var messageBoxStandardWindow = MessageBox.Avalonia.MessageBoxManager.GetMessageBoxStandardWindow(
|
||||||
new MessageBoxStandardParams
|
new MessageBoxStandardParams
|
||||||
{
|
{
|
||||||
ButtonDefinitions = buttons,
|
ButtonDefinitions = buttons,
|
||||||
ContentTitle = title ?? window.Title,
|
ContentTitle = title ?? window.Title,
|
||||||
|
ContentHeader = header,
|
||||||
ContentMessage = message,
|
ContentMessage = message,
|
||||||
|
Markdown = markdown,
|
||||||
Icon = icon,
|
Icon = icon,
|
||||||
WindowIcon = new WindowIcon(App.GetAsset("/Assets/Icons/UVtools.ico")),
|
WindowIcon = new WindowIcon(App.GetAsset("/Assets/Icons/UVtools.ico")),
|
||||||
WindowStartupLocation = location,
|
WindowStartupLocation = location,
|
||||||
@@ -40,17 +42,29 @@ public static class WindowExtensions
|
|||||||
return await messageBoxStandardWindow.ShowDialog(window);
|
return await messageBoxStandardWindow.ShowDialog(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<ButtonResult> MessageBoxInfo(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false)
|
public static async Task<ButtonResult> MessageBoxInfo(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool markdown = false, bool topMost = false)
|
||||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Information", buttons, Icon.Info, topMost, WindowStartupLocation.CenterOwner);
|
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Information", null, buttons, Icon.Info, markdown, topMost, WindowStartupLocation.CenterOwner);
|
||||||
|
|
||||||
public static async Task<ButtonResult> MessageBoxError(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false)
|
public static async Task<ButtonResult> MessageBoxError(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool markdown = false, bool topMost = false)
|
||||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Error", buttons, Icon.Error, topMost, WindowStartupLocation.CenterOwner);
|
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Error", null, buttons, Icon.Error, markdown, topMost, WindowStartupLocation.CenterOwner);
|
||||||
|
|
||||||
public static async Task<ButtonResult> MessageBoxQuestion(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.YesNo, bool topMost = false)
|
public static async Task<ButtonResult> MessageBoxQuestion(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.YesNo, bool markdown = false, bool topMost = false)
|
||||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Setting, topMost, WindowStartupLocation.CenterOwner);
|
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", null, buttons, Icon.Question, markdown, topMost, WindowStartupLocation.CenterOwner);
|
||||||
|
|
||||||
public static async Task<ButtonResult> MessageBoxWaring(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false)
|
public static async Task<ButtonResult> MessageBoxWaring(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool markdown = false, bool topMost = false)
|
||||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Warning, topMost, WindowStartupLocation.CenterOwner);
|
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", null, buttons, Icon.Warning, markdown, topMost, WindowStartupLocation.CenterOwner);
|
||||||
|
|
||||||
|
public static async Task<ButtonResult> MessageBoxWithHeaderInfo(this Window window, string header, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool markdown = false, bool topMost = false)
|
||||||
|
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Information", header, buttons, Icon.Info, markdown, topMost, WindowStartupLocation.CenterOwner);
|
||||||
|
|
||||||
|
public static async Task<ButtonResult> MessageBoxWithHeaderError(this Window window, string header, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool markdown = false, bool topMost = false)
|
||||||
|
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Error", header, buttons, Icon.Error, markdown, topMost, WindowStartupLocation.CenterOwner);
|
||||||
|
|
||||||
|
public static async Task<ButtonResult> MessageBoxWithHeaderQuestion(this Window window, string header, string message, string title = null, ButtonEnum buttons = ButtonEnum.YesNo, bool markdown = false, bool topMost = false)
|
||||||
|
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", header, buttons, Icon.Question, markdown, topMost, WindowStartupLocation.CenterOwner);
|
||||||
|
|
||||||
|
public static async Task<ButtonResult> MessageBoxWithHeaderWaring(this Window window, string header, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool markdown = false, bool topMost = false)
|
||||||
|
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", header, buttons, Icon.Warning, markdown, topMost, WindowStartupLocation.CenterOwner);
|
||||||
|
|
||||||
|
|
||||||
public static void ShowDialogSync(this Window window, Window parent = null)
|
public static void ShowDialogSync(this Window window, Window parent = null)
|
||||||
|
|||||||
@@ -174,9 +174,8 @@ public partial class MainWindow
|
|||||||
Progress.Reset("Removing selected issues", (uint)processParallelIssues.Count);
|
Progress.Reset("Removing selected issues", (uint)processParallelIssues.Count);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Parallel.ForEach(processParallelIssues, CoreSettings.ParallelOptions, layerIssues =>
|
Parallel.ForEach(processParallelIssues, CoreSettings.GetParallelOptions(Progress), layerIssues =>
|
||||||
{
|
{
|
||||||
if (Progress.Token.IsCancellationRequested) return;
|
|
||||||
using (var image = SlicerFile[layerIssues.Key].LayerMat)
|
using (var image = SlicerFile[layerIssues.Key].LayerMat)
|
||||||
{
|
{
|
||||||
var bytes = image.GetDataByteSpan();
|
var bytes = image.GetDataByteSpan();
|
||||||
|
|||||||
@@ -844,6 +844,50 @@ public partial class MainWindow
|
|||||||
//var imageSpan = LayerCache.Image.GetPixelSpan<byte>();
|
//var imageSpan = LayerCache.Image.GetPixelSpan<byte>();
|
||||||
//var imageBgrSpan = LayerCache.ImageBgr.GetPixelSpan<byte>();
|
//var imageBgrSpan = LayerCache.ImageBgr.GetPixelSpan<byte>();
|
||||||
|
|
||||||
|
/*var mat = LayerCache.Layer.LayerMat;
|
||||||
|
var layers = Enum.GetValues<Layer.LayerCompressionMethod>().Select(value => new Layer(mat, SlicerFile, value)).ToList();
|
||||||
|
|
||||||
|
const ushort tests = 100;
|
||||||
|
Debug.WriteLine($"Looping {tests} tests on {SlicerFile.Resolution} resolution");
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
foreach (var layer in layers)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"{layer.CompressionMethod} compressed size: {layer.CompressedBytes.Length} bytes");
|
||||||
|
sw.Restart();
|
||||||
|
for (var i = 0; i < tests; i++)
|
||||||
|
{
|
||||||
|
using (layer.LayerMat) { }
|
||||||
|
}
|
||||||
|
Debug.WriteLine($"Single thread - Decompress: {sw.ElapsedMilliseconds}ms");
|
||||||
|
|
||||||
|
sw.Restart();
|
||||||
|
for (var i = 0; i < tests; i++)
|
||||||
|
{
|
||||||
|
layer.LayerMat = mat;
|
||||||
|
}
|
||||||
|
Debug.WriteLine($"Single thread - Compress: {sw.ElapsedMilliseconds}ms");
|
||||||
|
|
||||||
|
|
||||||
|
sw.Restart();
|
||||||
|
Parallel.For(0, tests, i =>
|
||||||
|
{
|
||||||
|
using (layer.LayerMat) { }
|
||||||
|
});
|
||||||
|
Debug.WriteLine($"Multi thread - Decompress: {sw.ElapsedMilliseconds}ms");
|
||||||
|
|
||||||
|
sw.Restart();
|
||||||
|
Parallel.For(0, tests, i =>
|
||||||
|
{
|
||||||
|
layer.LayerMat = mat;
|
||||||
|
});
|
||||||
|
Debug.WriteLine($"Multi thread - Compress: {sw.ElapsedMilliseconds}ms");
|
||||||
|
|
||||||
|
Debug.WriteLine(string.Empty);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
var imageSpan = LayerCache.ImageSpan;
|
var imageSpan = LayerCache.ImageSpan;
|
||||||
var imageBgrSpan = LayerCache.ImageBgrSpan;
|
var imageBgrSpan = LayerCache.ImageBgrSpan;
|
||||||
|
|
||||||
|
|||||||
@@ -569,6 +569,7 @@
|
|||||||
IsReadOnly="{Binding !SlicerFile.SuppressRebuildGCode}"
|
IsReadOnly="{Binding !SlicerFile.SuppressRebuildGCode}"
|
||||||
AcceptsReturn="True"
|
AcceptsReturn="True"
|
||||||
Text="{Binding SlicerFile.GCodeStr}" />
|
Text="{Binding SlicerFile.GCodeStr}" />
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ using UVtools.WPF.Controls.Tools;
|
|||||||
using UVtools.WPF.Extensions;
|
using UVtools.WPF.Extensions;
|
||||||
using UVtools.WPF.Structures;
|
using UVtools.WPF.Structures;
|
||||||
using UVtools.WPF.Windows;
|
using UVtools.WPF.Windows;
|
||||||
using Bitmap = Avalonia.Media.Imaging.Bitmap;
|
|
||||||
using Helpers = UVtools.WPF.Controls.Helpers;
|
using Helpers = UVtools.WPF.Controls.Helpers;
|
||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
using Point = Avalonia.Point;
|
using Point = Avalonia.Point;
|
||||||
@@ -1164,6 +1163,7 @@ public partial class MainWindow : WindowEx
|
|||||||
public async void MenuFileSettingsClicked()
|
public async void MenuFileSettingsClicked()
|
||||||
{
|
{
|
||||||
var oldTheme = Settings.General.Theme;
|
var oldTheme = Settings.General.Theme;
|
||||||
|
var oldLayerCompressionMethod = Settings.General.LayerCompressionMethod;
|
||||||
var settingsWindow = new SettingsWindow();
|
var settingsWindow = new SettingsWindow();
|
||||||
await settingsWindow.ShowDialog(this);
|
await settingsWindow.ShowDialog(this);
|
||||||
if (settingsWindow.DialogResult == DialogResults.OK)
|
if (settingsWindow.DialogResult == DialogResults.OK)
|
||||||
@@ -1173,6 +1173,33 @@ public partial class MainWindow : WindowEx
|
|||||||
App.ApplyTheme();
|
App.ApplyTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldLayerCompressionMethod != Settings.General.LayerCompressionMethod)
|
||||||
|
{
|
||||||
|
IsGUIEnabled = false;
|
||||||
|
ShowProgressWindow($"Changing layer compression method from {oldLayerCompressionMethod.ToString().ToUpper()} to {Settings.General.LayerCompressionMethod.ToString().ToUpper()}");
|
||||||
|
|
||||||
|
await Task.Factory.StartNew(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SlicerFile.ChangeLayersCompressionMethod(Settings.General.LayerCompressionMethod, Progress);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
|
await this.MessageBoxError(exception.ToString(), "Error while converting layers"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
IsGUIEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
_layerNavigationSliderDebounceTimer.Interval = Settings.LayerPreview.LayerSliderDebounce == 0 ? 1 : Settings.LayerPreview.LayerSliderDebounce;
|
_layerNavigationSliderDebounceTimer.Interval = Settings.LayerPreview.LayerSliderDebounce == 0 ? 1 : Settings.LayerPreview.LayerSliderDebounce;
|
||||||
RaisePropertyChanged(nameof(IssuesGridItems));
|
RaisePropertyChanged(nameof(IssuesGridItems));
|
||||||
}
|
}
|
||||||
@@ -1232,13 +1259,16 @@ public partial class MainWindow : WindowEx
|
|||||||
public async void MenuNewVersionClicked()
|
public async void MenuNewVersionClicked()
|
||||||
{
|
{
|
||||||
var result =
|
var result =
|
||||||
await this.MessageBoxQuestion(
|
await this.MessageBoxWithHeaderQuestion(
|
||||||
$"Do you like to auto-update {About.Software} v{App.VersionStr} to v{VersionChecker.Version}?\n" +
|
$"Do you like to auto-update {About.Software} v{App.VersionStr} to v{VersionChecker.Version}?",
|
||||||
"Yes: Auto update\n" +
|
"Yes: Auto update \n" +
|
||||||
"No: Manual update\n" +
|
"No: Manual update \n" +
|
||||||
"Cancel: No action\n\n" +
|
"Cancel: No action \n\n" +
|
||||||
"Changelog:\n" +
|
"Changelog: \n\n" +
|
||||||
$"{VersionChecker.Changelog}", $"Update UVtools to v{VersionChecker.Version}?", ButtonEnum.YesNoCancel);
|
$"{VersionChecker.Changelog}",
|
||||||
|
$"Update UVtools to v{VersionChecker.Version}?",
|
||||||
|
|
||||||
|
ButtonEnum.YesNoCancel, true);
|
||||||
|
|
||||||
|
|
||||||
if (result == ButtonResult.No)
|
if (result == ButtonResult.No)
|
||||||
|
|||||||
@@ -12,10 +12,9 @@ using System.IO.Compression;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Text.Json.Nodes;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using UVtools.Core;
|
using UVtools.Core;
|
||||||
using UVtools.Core.Extensions;
|
using UVtools.Core.Extensions;
|
||||||
using UVtools.Core.Objects;
|
using UVtools.Core.Objects;
|
||||||
@@ -36,33 +35,35 @@ public class AppVersionChecker : BindableBase
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
var file = Path.Combine(App.ApplicationPath, RuntimePackageFile);
|
||||||
|
if (File.Exists(file))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var package = File.ReadAllText(file);
|
||||||
|
if (!string.IsNullOrWhiteSpace(package) && (package.EndsWith("-x64") || package.EndsWith("-arm64")))
|
||||||
|
{
|
||||||
|
return $"{About.Software}_{package}_v{_version}.zip";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
{
|
{
|
||||||
return $"{About.Software}_win-x64_v{_version}.msi";
|
return $"{About.Software}_win-x64_v{_version}.msi";
|
||||||
}
|
}
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
{
|
{
|
||||||
var file = Path.Combine(App.ApplicationPath, RuntimePackageFile);
|
|
||||||
if (File.Exists(file))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var package = File.ReadAllText(file);
|
|
||||||
if (!string.IsNullOrWhiteSpace(package) && package.EndsWith("-x64"))
|
|
||||||
{
|
|
||||||
return $"{About.Software}_{package}_v{_version}.zip";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.WriteLine(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return $"{About.Software}_linux-x64_v{_version}.zip";
|
return $"{About.Software}_linux-x64_v{_version}.zip";
|
||||||
}
|
}
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||||
{
|
{
|
||||||
|
if (RuntimeInformation.ProcessArchitecture is Architecture.Arm or Architecture.Arm64) return $"{About.Software}_osx-arm64_v{_version}.zip";
|
||||||
|
|
||||||
return $"{About.Software}_osx-x64_v{_version}.zip";
|
return $"{About.Software}_osx-x64_v{_version}.zip";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +132,8 @@ public class AppVersionChecker : BindableBase
|
|||||||
|
|
||||||
var result= NetworkExtensions.HttpClient.Send(request);
|
var result= NetworkExtensions.HttpClient.Send(request);
|
||||||
|
|
||||||
var json = JObject.Parse(result.Content.ReadAsStringAsync().Result);
|
var json = JsonNode.Parse(result.Content.ReadAsStream());
|
||||||
|
|
||||||
string tag_name = json["tag_name"]?.ToString();
|
string tag_name = json["tag_name"]?.ToString();
|
||||||
if (string.IsNullOrEmpty(tag_name)) return false;
|
if (string.IsNullOrEmpty(tag_name)) return false;
|
||||||
tag_name = tag_name.Trim(' ', 'v', 'V');
|
tag_name = tag_name.Trim(' ', 'v', 'V');
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
* Everyone is permitted to copy and distribute verbatim copies
|
* Everyone is permitted to copy and distribute verbatim copies
|
||||||
* of this license document, but changing it is not allowed.
|
* of this license document, but changing it is not allowed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using UVtools.WPF.Windows;
|
||||||
|
|
||||||
namespace UVtools.WPF.Structures;
|
namespace UVtools.WPF.Structures;
|
||||||
|
|
||||||
public sealed class BenchmarkTest
|
public sealed class BenchmarkTest
|
||||||
@@ -12,10 +15,11 @@ public sealed class BenchmarkTest
|
|||||||
public const string DEVCPU = "Intel® Core™ i9-9900K @ 3.60 GHz";
|
public const string DEVCPU = "Intel® Core™ i9-9900K @ 3.60 GHz";
|
||||||
public const string DEVRAM = "G.SKILL Trident Z 32GB DDR4-3200MHz CL14";
|
public const string DEVRAM = "G.SKILL Trident Z 32GB DDR4-3200MHz CL14";
|
||||||
|
|
||||||
public BenchmarkTest(string name, string functionName, float devSingleThreadResult = 0, float devMultiThreadResult = 0)
|
public BenchmarkTest(string name, string functionName, BenchmarkWindow.BenchmarkResolution resolution, float devSingleThreadResult = 0, float devMultiThreadResult = 0)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
FunctionName = functionName;
|
FunctionName = functionName;
|
||||||
|
Resolution = resolution;
|
||||||
DevSingleThreadResult = devSingleThreadResult;
|
DevSingleThreadResult = devSingleThreadResult;
|
||||||
DevMultiThreadResult = devMultiThreadResult;
|
DevMultiThreadResult = devMultiThreadResult;
|
||||||
}
|
}
|
||||||
@@ -23,6 +27,8 @@ public sealed class BenchmarkTest
|
|||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public string FunctionName { get; }
|
public string FunctionName { get; }
|
||||||
|
|
||||||
|
public BenchmarkWindow.BenchmarkResolution Resolution { get; }
|
||||||
|
|
||||||
public float DevSingleThreadResult { get; }
|
public float DevSingleThreadResult { get; }
|
||||||
public float DevMultiThreadResult { get; }
|
public float DevMultiThreadResult { get; }
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class OperationProfiles //: IList<Operation>
|
|||||||
[XmlElement(typeof(OperationRaiseOnPrintFinish))]
|
[XmlElement(typeof(OperationRaiseOnPrintFinish))]
|
||||||
[XmlElement(typeof(OperationChangeResolution))]
|
[XmlElement(typeof(OperationChangeResolution))]
|
||||||
[XmlElement(typeof(OperationTimelapse))]
|
[XmlElement(typeof(OperationTimelapse))]
|
||||||
|
[XmlElement(typeof(OperationScripting))]
|
||||||
|
|
||||||
[XmlElement(typeof(OperationLayerExportGif))]
|
[XmlElement(typeof(OperationLayerExportGif))]
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<Version>3.0.0</Version>
|
<Version>3.1.0</Version>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<PackageIcon>UVtools.png</PackageIcon>
|
<PackageIcon>UVtools.png</PackageIcon>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
@@ -40,14 +40,14 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="0.10.13" />
|
<PackageReference Include="Avalonia" Version="0.10.13" />
|
||||||
<PackageReference Include="Avalonia.Angle.Windows.Natives" Version="2.1.0.2020091801" />
|
|
||||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.13" />
|
<PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.13" />
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="0.10.13" />
|
<PackageReference Include="Avalonia.Desktop" Version="0.10.13" />
|
||||||
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.13" />
|
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.13" />
|
||||||
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.5.4823" />
|
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.5.4823" />
|
||||||
<PackageReference Include="MessageBox.Avalonia" Version="1.8.1-night" />
|
<PackageReference Include="MessageBox.Avalonia" Version="2.0.0" />
|
||||||
<PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="4.1.0" />
|
<PackageReference Include="Projektanker.Icons.Avalonia" Version="4.2.1" />
|
||||||
<PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="4.1.0" />
|
<PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="4.2.1" />
|
||||||
|
<PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="4.2.1" />
|
||||||
<PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.12" />
|
<PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.12" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -95,6 +95,7 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AvaloniaResource>
|
</AvaloniaResource>
|
||||||
<AvaloniaResource Include="Assets\Icons\*" />
|
<AvaloniaResource Include="Assets\Icons\*" />
|
||||||
|
<AvaloniaResource Include="Assets\benchmark.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="Windows\SuggestionSettingsWindow.axaml.cs">
|
<Compile Update="Windows\SuggestionSettingsWindow.axaml.cs">
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ using JetBrains.Annotations;
|
|||||||
using UVtools.Core;
|
using UVtools.Core;
|
||||||
using UVtools.Core.Extensions;
|
using UVtools.Core.Extensions;
|
||||||
using UVtools.Core.FileFormats;
|
using UVtools.Core.FileFormats;
|
||||||
|
using UVtools.Core.Layers;
|
||||||
using UVtools.Core.Network;
|
using UVtools.Core.Network;
|
||||||
using UVtools.Core.Objects;
|
using UVtools.Core.Objects;
|
||||||
using Color=UVtools.WPF.Structures.Color;
|
using Color=UVtools.WPF.Structures.Color;
|
||||||
@@ -42,6 +43,7 @@ public sealed class UserSettings : BindableBase
|
|||||||
private bool _loadDemoFileOnStartup = true;
|
private bool _loadDemoFileOnStartup = true;
|
||||||
private bool _loadLastRecentFileOnStartup;
|
private bool _loadLastRecentFileOnStartup;
|
||||||
private int _maxDegreeOfParallelism = -1;
|
private int _maxDegreeOfParallelism = -1;
|
||||||
|
private Layer.LayerCompressionMethod _layerCompressionMethod = CoreSettings.DefaultLayerCompressionMethod;
|
||||||
|
|
||||||
private bool _windowsCanResize;
|
private bool _windowsCanResize;
|
||||||
private bool _windowsTakeIntoAccountScreenScaling = true;
|
private bool _windowsTakeIntoAccountScreenScaling = true;
|
||||||
@@ -100,6 +102,12 @@ public sealed class UserSettings : BindableBase
|
|||||||
set => RaiseAndSetIfChanged(ref _maxDegreeOfParallelism, Math.Min(value, Environment.ProcessorCount));
|
set => RaiseAndSetIfChanged(ref _maxDegreeOfParallelism, Math.Min(value, Environment.ProcessorCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Layer.LayerCompressionMethod LayerCompressionMethod
|
||||||
|
{
|
||||||
|
get => _layerCompressionMethod;
|
||||||
|
set => RaiseAndSetIfChanged(ref _layerCompressionMethod, value);
|
||||||
|
}
|
||||||
|
|
||||||
public bool WindowsCanResize
|
public bool WindowsCanResize
|
||||||
{
|
{
|
||||||
get => _windowsCanResize;
|
get => _windowsCanResize;
|
||||||
@@ -1633,6 +1641,7 @@ public sealed class UserSettings : BindableBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoreSettings.MaxDegreeOfParallelism = _instance.General.MaxDegreeOfParallelism;
|
CoreSettings.MaxDegreeOfParallelism = _instance.General.MaxDegreeOfParallelism;
|
||||||
|
CoreSettings.DefaultLayerCompressionMethod = _instance.General.LayerCompressionMethod;
|
||||||
|
|
||||||
if (_instance.Network.RemotePrinters.Count == 0)
|
if (_instance.Network.RemotePrinters.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -1855,6 +1864,7 @@ public sealed class UserSettings : BindableBase
|
|||||||
Instance.SavesCount++;
|
Instance.SavesCount++;
|
||||||
_instance.ModifiedDateTime = DateTime.Now;
|
_instance.ModifiedDateTime = DateTime.Now;
|
||||||
CoreSettings.MaxDegreeOfParallelism = _instance.General.MaxDegreeOfParallelism;
|
CoreSettings.MaxDegreeOfParallelism = _instance.General.MaxDegreeOfParallelism;
|
||||||
|
CoreSettings.DefaultLayerCompressionMethod = _instance.General.LayerCompressionMethod;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
XmlExtensions.SerializeToFile(_instance, FilePath, XmlExtensions.SettingsIndent);
|
XmlExtensions.SerializeToFile(_instance, FilePath, XmlExtensions.SettingsIndent);
|
||||||
|
|||||||
@@ -9,33 +9,28 @@
|
|||||||
Icon="/Assets/Icons/UVtools.ico"
|
Icon="/Assets/Icons/UVtools.ico"
|
||||||
SizeToContent="WidthAndHeight"
|
SizeToContent="WidthAndHeight"
|
||||||
WindowStartupLocation="CenterOwner"
|
WindowStartupLocation="CenterOwner"
|
||||||
CanResize="False"
|
CanResize="False">
|
||||||
>
|
|
||||||
|
|
||||||
<Grid
|
<Grid RowDefinitions="Auto,10,
|
||||||
RowDefinitions="Auto,10,
|
|
||||||
Auto,10,
|
Auto,10,
|
||||||
Auto,10,
|
Auto,10,
|
||||||
Auto,20,
|
Auto,20,
|
||||||
Auto,10,
|
Auto,10,
|
||||||
Auto,20,
|
Auto,20,
|
||||||
Auto"
|
Auto">
|
||||||
>
|
|
||||||
<Border
|
<Border
|
||||||
Background="{DynamicResource LightBackground}"
|
Background="{DynamicResource LightBackground}"
|
||||||
Padding="10"
|
Padding="10"
|
||||||
BorderBrush="Black"
|
BorderBrush="Black"
|
||||||
BorderThickness="1"
|
BorderThickness="1">
|
||||||
>
|
<TextBox Classes="TransparentReadOnly" Text="{Binding Description}"/>
|
||||||
<TextBlock Text="{Binding Description}"/>
|
|
||||||
|
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
ColumnDefinitions="Auto,10,*"
|
ColumnDefinitions="Auto,10,*"
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Margin="10"
|
Margin="10">
|
||||||
>
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
@@ -45,27 +40,25 @@
|
|||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
SelectedIndex="{Binding TestSelectedIndex}"
|
SelectedIndex="{Binding TestSelectedIndex}"
|
||||||
Items="{Binding Tests}"
|
Items="{Binding Tests}"
|
||||||
IsEnabled="{Binding !IsRunning}"
|
IsEnabled="{Binding !IsRunning}"/>
|
||||||
/>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="10,0"
|
Margin="10,0"
|
||||||
Grid.Row="4"
|
Grid.Row="4"
|
||||||
FontWeight="Bold" Text="Your results:" />
|
FontWeight="Bold" Text="Your results:"/>
|
||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
Grid.Row="6"
|
Grid.Row="6"
|
||||||
ColumnDefinitions="Auto,5,Auto"
|
ColumnDefinitions="Auto,5,Auto"
|
||||||
RowDefinitions="Auto,5,Auto"
|
RowDefinitions="Auto,5,Auto"
|
||||||
Margin="10,0"
|
Margin="10,0">
|
||||||
>
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Text="Single Thread:" />
|
Text="Single Thread:" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Text="{Binding SingleThreadTDPS}" />
|
Text="{Binding SingleThreadTDPS}"/>
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
@@ -74,13 +67,13 @@
|
|||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Text="{Binding MultiThreadTDPS}" />
|
Text="{Binding MultiThreadTDPS}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="10,0"
|
Margin="10,0"
|
||||||
Grid.Row="8"
|
Grid.Row="8"
|
||||||
FontWeight="Bold" Text="Developer results:" />
|
FontWeight="Bold" Text="Developer results:"/>
|
||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
Grid.Row="10"
|
Grid.Row="10"
|
||||||
@@ -93,7 +86,7 @@
|
|||||||
Text="Single Thread:" />
|
Text="Single Thread:" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Text="{Binding DevSingleThreadTDPS}" />
|
Text="{Binding DevSingleThreadTDPS}"/>
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
@@ -102,7 +95,7 @@
|
|||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Text="{Binding DevMultiThreadTDPS}" />
|
Text="{Binding DevMultiThreadTDPS}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
@@ -112,8 +105,7 @@
|
|||||||
<ProgressBar
|
<ProgressBar
|
||||||
IsIndeterminate="{Binding IsRunning}"
|
IsIndeterminate="{Binding IsRunning}"
|
||||||
IsEnabled="{Binding IsRunning}"
|
IsEnabled="{Binding IsRunning}"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"/>
|
||||||
/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
Name="StartStopButton"
|
Name="StartStopButton"
|
||||||
@@ -121,8 +113,7 @@
|
|||||||
Padding="40,10"
|
Padding="40,10"
|
||||||
IsDefault="True"
|
IsDefault="True"
|
||||||
Content="{Binding StartStopButtonText}"
|
Content="{Binding StartStopButtonText}"
|
||||||
Command="{Binding StartStop}"
|
Command="{Binding StartStop}"/>
|
||||||
/>
|
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Avalonia.Threading;
|
|||||||
using Emgu.CV;
|
using Emgu.CV;
|
||||||
using Emgu.CV.CvEnum;
|
using Emgu.CV.CvEnum;
|
||||||
using UVtools.Core.Extensions;
|
using UVtools.Core.Extensions;
|
||||||
|
using UVtools.Core.Layers;
|
||||||
using UVtools.WPF.Controls;
|
using UVtools.WPF.Controls;
|
||||||
using UVtools.WPF.Extensions;
|
using UVtools.WPF.Extensions;
|
||||||
using UVtools.WPF.Structures;
|
using UVtools.WPF.Structures;
|
||||||
@@ -24,27 +25,56 @@ public class BenchmarkWindow : WindowEx
|
|||||||
private string _devMultiThreadTdps = $"{Tests[0].DevMultiThreadResult} {RunsAbbreviation} ({MultiThreadTests} tests / {Math.Round(MultiThreadTests / Tests[0].DevMultiThreadResult, 2)}s)";
|
private string _devMultiThreadTdps = $"{Tests[0].DevMultiThreadResult} {RunsAbbreviation} ({MultiThreadTests} tests / {Math.Round(MultiThreadTests / Tests[0].DevMultiThreadResult, 2)}s)";
|
||||||
private bool _isRunning;
|
private bool _isRunning;
|
||||||
private string _startStopButtonText = "Start";
|
private string _startStopButtonText = "Start";
|
||||||
private const ushort SingleThreadTests = 100;
|
private const ushort SingleThreadTests = 200;
|
||||||
private const ushort MultiThreadTests = 1000;
|
private const ushort MultiThreadTests = 5000;
|
||||||
|
|
||||||
public const string RunsAbbreviation = "TDPS";
|
public const string RunsAbbreviation = "TDPS";
|
||||||
public const string StressCPUTestName = "Stress CPU (Run until stop)";
|
public const string StressCPUTestName = "Stress CPU (Run until stop)";
|
||||||
|
|
||||||
|
private readonly Dictionary<BenchmarkResolution, Mat> Mats = new();
|
||||||
|
|
||||||
//private readonly RNGCryptoServiceProvider _randomProvider = new();
|
//private readonly RNGCryptoServiceProvider _randomProvider = new();
|
||||||
|
|
||||||
private CancellationTokenSource _tokenSource;
|
private CancellationTokenSource _tokenSource;
|
||||||
private CancellationToken _token => _tokenSource.Token;
|
private CancellationToken _token => _tokenSource.Token;
|
||||||
|
|
||||||
|
public enum BenchmarkResolution
|
||||||
|
{
|
||||||
|
Resolution4K,
|
||||||
|
Resolution8K
|
||||||
|
}
|
||||||
|
|
||||||
public static BenchmarkTest[] Tests =>
|
public static BenchmarkTest[] Tests =>
|
||||||
new[]
|
new[]
|
||||||
{
|
{
|
||||||
new BenchmarkTest("4K Random CBBDLP Enconde", "Test4KRandomCBBDLPEncode", 57.14f, 401.61f),
|
new BenchmarkTest("CBBDLP 4K Encode", "TestCBBDLPEncode", BenchmarkResolution.Resolution4K, 108.70f, 912.41f),
|
||||||
new BenchmarkTest("8K Random CBBDLP Enconde", "Test8KRandomCBBDLPEncode", 12.03f, 99.80f),
|
new BenchmarkTest("CBBDLP 8K Encode", "TestCBBDLPEncode", BenchmarkResolution.Resolution8K, 27.47f, 226.76f),
|
||||||
new BenchmarkTest("4K Random CBT Enconde", "Test4KRandomCBTEncode", 19.05f, 124.38f),
|
new BenchmarkTest("CBT 4K Encode", "TestCBTEncode", BenchmarkResolution.Resolution4K, 86.96f, 782.47f),
|
||||||
new BenchmarkTest("8K Random CBT Enconde", "Test8KRandomCBTEncode", 4.03f, 35.64f),
|
new BenchmarkTest("CBT 8K Encode", "TestCBTEncode", BenchmarkResolution.Resolution8K, 21.86f, 196.15f),
|
||||||
new BenchmarkTest("4K Random PW0 Enconde", "Test4KRandomPW0Encode", 18.85f, 103.00f),
|
new BenchmarkTest("PW0 4K Encode", "TestPW0Encode",BenchmarkResolution.Resolution4K, 84.03f, 886.53f),
|
||||||
new BenchmarkTest("8K Random PW0 Enconde", "Test8KRandomPW0Encode", 4.07f, 26.65f),
|
new BenchmarkTest("PW0 8K Encode", "TestPW0Encode", BenchmarkResolution.Resolution8K, 21.05f, 221.63f),
|
||||||
new BenchmarkTest(StressCPUTestName, "Test4KRandomCBTEncode", 0, 0),
|
|
||||||
|
new BenchmarkTest("PNG 4K Compress", "TestPNGCompress", BenchmarkResolution.Resolution4K, 55.25f, 501.00f),
|
||||||
|
//new BenchmarkTest("PNG 4K Decompress", "TestPNGDecompress", BenchmarkResolution.Resolution4K, 4.07f, 26.65f),
|
||||||
|
new BenchmarkTest("PNG 8K Compress", "TestPNGCompress", BenchmarkResolution.Resolution8K, 14.28f, 124.10f),
|
||||||
|
//new BenchmarkTest("PNG 8K Decompress", "TestPNGDecompress", BenchmarkResolution.Resolution8K, 4.07f, 26.65f),
|
||||||
|
|
||||||
|
new BenchmarkTest("GZip 4K Compress", "TestGZipCompress", BenchmarkResolution.Resolution4K, 169.49f, 1506.02f),
|
||||||
|
//new BenchmarkTest("GZip 4K Decompress", "TestGZipDecompress", BenchmarkResolution.Resolution4K, 4.07f, 26.65f),
|
||||||
|
new BenchmarkTest("GZip 8K Compress", "TestGZipCompress", BenchmarkResolution.Resolution8K, 45.77f, 397.47f),
|
||||||
|
//new BenchmarkTest("GZip 8K Decompress", "TestGZipDecompress", BenchmarkResolution.Resolution8K, 4.07f, 26.65f),
|
||||||
|
|
||||||
|
new BenchmarkTest("Deflate 4K Compress", "TestDeflateCompress", BenchmarkResolution.Resolution4K, 170.94f, 1592.36f),
|
||||||
|
//new BenchmarkTest("Deflate 4K Decompress", "TestDeflateDecompress", BenchmarkResolution.Resolution4K, 4.07f, 26.65f),
|
||||||
|
new BenchmarkTest("Deflate 8K Compress", "TestDeflateCompress", BenchmarkResolution.Resolution8K, 46.30f, 406.50f),
|
||||||
|
//new BenchmarkTest("Deflate 8K Decompress", "TestDeflateDecompress", BenchmarkResolution.Resolution8K, 4.07f, 26.65f),
|
||||||
|
|
||||||
|
new BenchmarkTest("LZ4 4K Compress", "TestLZ4Compress", BenchmarkResolution.Resolution4K, 665.12f, 2762.43f),
|
||||||
|
//new BenchmarkTest("LZ4 4K Decompress", "TestLZ4Decompress", BenchmarkResolution.Resolution4K, 4.07f, 26.65f),
|
||||||
|
new BenchmarkTest("LZ4 8K Compress", "TestLZ4Compress", BenchmarkResolution.Resolution8K, 148.15f, 907.44f),
|
||||||
|
//new BenchmarkTest("LZ4 8K Decompress", "TestLZ4Decompress", BenchmarkResolution.Resolution8K, 4.07f, 26.65f),
|
||||||
|
|
||||||
|
new BenchmarkTest(StressCPUTestName, "TestCBTEncode", BenchmarkResolution.Resolution4K, 0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
public string Description => "Benchmark your machine against pre-defined tests.\n" +
|
public string Description => "Benchmark your machine against pre-defined tests.\n" +
|
||||||
@@ -112,6 +142,12 @@ public class BenchmarkWindow : WindowEx
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
DataContext = this;
|
DataContext = this;
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var resolution in Enum.GetValues<BenchmarkResolution>())
|
||||||
|
{
|
||||||
|
Mats.Add(resolution, GetBenchmarkMat(resolution));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
@@ -146,22 +182,18 @@ public class BenchmarkWindow : WindowEx
|
|||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (_token.IsCancellationRequested) break;
|
Parallel.For(0, MultiThreadTests, new ParallelOptions{CancellationToken = _tokenSource.Token }, i =>
|
||||||
Parallel.For(0, MultiThreadTests, i =>
|
|
||||||
{
|
{
|
||||||
if (_token.IsCancellationRequested) return;
|
theMethod.Invoke(this, new object[]{benchmark.Resolution});
|
||||||
theMethod.Invoke(this, null);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < SingleThreadTests; i++)
|
for (int i = 0; i < SingleThreadTests; i++)
|
||||||
{
|
{
|
||||||
if (_token.IsCancellationRequested) _token.ThrowIfCancellationRequested();
|
if (_token.IsCancellationRequested) _token.ThrowIfCancellationRequested();
|
||||||
theMethod.Invoke(this, null);
|
theMethod.Invoke(this, new object[] { benchmark.Resolution });
|
||||||
}
|
}
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
@@ -171,15 +203,13 @@ public class BenchmarkWindow : WindowEx
|
|||||||
if (_token.IsCancellationRequested) _token.ThrowIfCancellationRequested();
|
if (_token.IsCancellationRequested) _token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
sw.Restart();
|
sw.Restart();
|
||||||
Parallel.For(0, MultiThreadTests, i =>
|
Parallel.For(0, MultiThreadTests, new ParallelOptions { CancellationToken = _tokenSource.Token }, i =>
|
||||||
{
|
{
|
||||||
if (_token.IsCancellationRequested) return;
|
theMethod.Invoke(this, new object[] { benchmark.Resolution });
|
||||||
theMethod.Invoke(this, null);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
|
|
||||||
if (_token.IsCancellationRequested) _token.ThrowIfCancellationRequested();
|
|
||||||
var multiMiliseconds = sw.ElapsedMilliseconds;
|
var multiMiliseconds = sw.ElapsedMilliseconds;
|
||||||
Dispatcher.UIThread.InvokeAsync(() => UpdateResults(false, multiMiliseconds));
|
Dispatcher.UIThread.InvokeAsync(() => UpdateResults(false, multiMiliseconds));
|
||||||
}
|
}
|
||||||
@@ -417,13 +447,32 @@ public class BenchmarkWindow : WindowEx
|
|||||||
return rawData.ToArray();
|
return rawData.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mat RandomMat(int width, int height)
|
public static Mat RandomMat(int width, int height)
|
||||||
{
|
{
|
||||||
Mat mat = new(new Size(width, height), DepthType.Cv8U, 1);
|
Mat mat = new(new Size(width, height), DepthType.Cv8U, 1);
|
||||||
CvInvoke.Randu(mat, EmguExtensions.BlackColor, EmguExtensions.WhiteColor);
|
CvInvoke.Randu(mat, EmguExtensions.BlackColor, EmguExtensions.WhiteColor);
|
||||||
return mat;
|
return mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Mat GetBenchmarkMat(BenchmarkResolution resolution = default)
|
||||||
|
{
|
||||||
|
using var stream = App.GetAsset("/Assets/benchmark.png");
|
||||||
|
var mat4K = new Mat();
|
||||||
|
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.Grayscale, mat4K);
|
||||||
|
switch (resolution)
|
||||||
|
{
|
||||||
|
case BenchmarkResolution.Resolution4K:
|
||||||
|
return mat4K;
|
||||||
|
case BenchmarkResolution.Resolution8K:
|
||||||
|
var mat8K = new Mat();
|
||||||
|
CvInvoke.Repeat(mat4K, 2, 2, mat8K);
|
||||||
|
mat4K.Dispose();
|
||||||
|
return mat8K;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(resolution), resolution, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Test4KRandomCBBDLPEncode()
|
public void Test4KRandomCBBDLPEncode()
|
||||||
{
|
{
|
||||||
using var mat = RandomMat(3840, 2160);
|
using var mat = RandomMat(3840, 2160);
|
||||||
@@ -436,6 +485,11 @@ public class BenchmarkWindow : WindowEx
|
|||||||
EncodeCbddlpImage(mat);
|
EncodeCbddlpImage(mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TestCBBDLPEncode(BenchmarkResolution resolution)
|
||||||
|
{
|
||||||
|
EncodeCbddlpImage(Mats[resolution]);
|
||||||
|
}
|
||||||
|
|
||||||
public void Test4KRandomCBTEncode()
|
public void Test4KRandomCBTEncode()
|
||||||
{
|
{
|
||||||
using var mat = RandomMat(3840, 2160);
|
using var mat = RandomMat(3840, 2160);
|
||||||
@@ -448,6 +502,11 @@ public class BenchmarkWindow : WindowEx
|
|||||||
EncodeCbtImage(mat);
|
EncodeCbtImage(mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TestCBTEncode(BenchmarkResolution resolution)
|
||||||
|
{
|
||||||
|
EncodeCbtImage(Mats[resolution]);
|
||||||
|
}
|
||||||
|
|
||||||
public void Test4KRandomPW0Encode()
|
public void Test4KRandomPW0Encode()
|
||||||
{
|
{
|
||||||
using var mat = RandomMat(3840, 2160);
|
using var mat = RandomMat(3840, 2160);
|
||||||
@@ -460,5 +519,42 @@ public class BenchmarkWindow : WindowEx
|
|||||||
EncodePW0Image(mat);
|
EncodePW0Image(mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TestPW0Encode(BenchmarkResolution resolution)
|
||||||
|
{
|
||||||
|
EncodePW0Image(Mats[resolution]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TestPNGCompress(BenchmarkResolution resolution)
|
||||||
|
{
|
||||||
|
Layer.CompressMat(Mats[resolution], Layer.LayerCompressionMethod.Png);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TestPNGDecompress(BenchmarkResolution resolution)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public void TestGZipCompress(BenchmarkResolution resolution)
|
||||||
|
{
|
||||||
|
Layer.CompressMat(Mats[resolution], Layer.LayerCompressionMethod.GZip);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TestGZipDecompress(BenchmarkResolution resolution)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public void TestDeflateCompress(BenchmarkResolution resolution)
|
||||||
|
{
|
||||||
|
Layer.CompressMat(Mats[resolution], Layer.LayerCompressionMethod.Deflate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TestDeflateDecompress(BenchmarkResolution resolution)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public void TestLZ4Compress(BenchmarkResolution resolution)
|
||||||
|
{
|
||||||
|
Layer.CompressMat(Mats[resolution], Layer.LayerCompressionMethod.Lz4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TestLZ4Decompress(BenchmarkResolution resolution)
|
||||||
|
{ }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<TextBlock Classes="GroupBoxHeader" Text="Tasks"/>
|
<TextBlock Classes="GroupBoxHeader" Text="Tasks"/>
|
||||||
<StackPanel Margin="10" Orientation="Vertical" Spacing="10">
|
<StackPanel Margin="10" Orientation="Vertical" Spacing="10">
|
||||||
<Grid RowDefinitions="Auto"
|
<Grid RowDefinitions="Auto,10,Auto"
|
||||||
ColumnDefinitions="Auto,10,150,5,Auto,20,Auto,2,Auto,2,Auto,2,Auto,2,Auto,2,Auto,2,Auto">
|
ColumnDefinitions="Auto,10,150,5,Auto,20,Auto,2,Auto,2,Auto,2,Auto,2,Auto,2,Auto,2,Auto">
|
||||||
|
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
@@ -123,7 +123,18 @@
|
|||||||
ToolTip.Tip="{Binding MaxProcessorCount, StringFormat=All of the available threads [{0}] (Full performance)}"
|
ToolTip.Tip="{Binding MaxProcessorCount, StringFormat=All of the available threads [{0}] (Full performance)}"
|
||||||
Command="{Binding SetMaxDegreeOfParallelism}"
|
Command="{Binding SetMaxDegreeOfParallelism}"
|
||||||
CommandParameter="{Binding MaxProcessorCount}"/>
|
CommandParameter="{Binding MaxProcessorCount}"/>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
ToolTip.Tip="Sets the compression method used to store layer image cache.
|
||||||
|

The selected method will impact RAM usage and operations speed."
|
||||||
|
Text="Layer compression:"/>
|
||||||
|
|
||||||
|
<ComboBox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="17"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Items="{Binding Settings.General.LayerCompressionMethod, Converter={StaticResource EnumToCollectionConverter}, Mode=OneTime}"
|
||||||
|
SelectedItem="{Binding Settings.General.LayerCompressionMethod, Converter={StaticResource FromValueDescriptionToEnumConverter}}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
@@ -603,6 +603,8 @@ public class ToolWindow : WindowEx
|
|||||||
ToolControl = toolControl;
|
ToolControl = toolControl;
|
||||||
toolControl.ParentWindow = this;
|
toolControl.ParentWindow = this;
|
||||||
toolControl.Margin = new Thickness(15);
|
toolControl.Margin = new Thickness(15);
|
||||||
|
ToolControl.BaseOperation.ROI = ROI;
|
||||||
|
ToolControl.BaseOperation.MaskPoints = Masks;
|
||||||
|
|
||||||
Title = toolControl.BaseOperation.Title;
|
Title = toolControl.BaseOperation.Title;
|
||||||
//LayerRangeVisible = toolControl.BaseOperation.StartLayerRangeSelection != Enumerations.LayerRangeSelection.None;
|
//LayerRangeVisible = toolControl.BaseOperation.StartLayerRangeSelection != Enumerations.LayerRangeSelection.None;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
cd "$(dirname "$0")"
|
||||||
cd ..
|
cd ..
|
||||||
dotnet build
|
dotnet build
|
||||||
@@ -183,7 +183,7 @@ $enableMSI = $true
|
|||||||
#$buildOnly = 'osx-x64'
|
#$buildOnly = 'osx-x64'
|
||||||
#$buildOnly = 'osx-arm64'
|
#$buildOnly = 'osx-arm64'
|
||||||
$zipPackages = $true
|
$zipPackages = $true
|
||||||
#$enableNugetPublish = $true
|
$enableNugetPublish = $true
|
||||||
|
|
||||||
# Profilling
|
# Profilling
|
||||||
$stopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
|
$stopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
|
||||||
@@ -357,17 +357,19 @@ Building: $runtime"
|
|||||||
$macAppFolder = "${software}.app"
|
$macAppFolder = "${software}.app"
|
||||||
$macPublishFolder = "$publishFolder/${macAppFolder}"
|
$macPublishFolder = "$publishFolder/${macAppFolder}"
|
||||||
$macInfoplist = "$platformsFolder/$runtime/Info.plist"
|
$macInfoplist = "$platformsFolder/$runtime/Info.plist"
|
||||||
$macOutputInfoplist = "$macPublishFolder/Contents"
|
$macEntitlements = "$platformsFolder/$runtime/UVtools.entitlements"
|
||||||
|
$macContents = "$macPublishFolder/Contents"
|
||||||
$macTargetZipLegacy = "$publishFolder/${software}_${runtime}-legacy_v$version.zip"
|
$macTargetZipLegacy = "$publishFolder/${software}_${runtime}-legacy_v$version.zip"
|
||||||
|
|
||||||
New-Item -ItemType directory -Path "$macPublishFolder"
|
New-Item -ItemType directory -Path $macPublishFolder
|
||||||
New-Item -ItemType directory -Path "$macPublishFolder/Contents"
|
New-Item -ItemType directory -Path "$macPublishFolder/Contents"
|
||||||
New-Item -ItemType directory -Path "$macPublishFolder/Contents/MacOS"
|
New-Item -ItemType directory -Path "$macPublishFolder/Contents/MacOS"
|
||||||
New-Item -ItemType directory -Path "$macPublishFolder/Contents/Resources"
|
New-Item -ItemType directory -Path "$macPublishFolder/Contents/Resources"
|
||||||
|
|
||||||
|
|
||||||
Copy-Item "$macIcns" -Destination "$macPublishFolder/Contents/Resources"
|
Copy-Item $macIcns -Destination "$macPublishFolder/Contents/Resources"
|
||||||
((Get-Content -Path "$macInfoplist") -replace '#VERSION',"$version") | Set-Content -Path "$macOutputInfoplist/Info.plist"
|
((Get-Content -Path $macInfoplist) -replace '#VERSION',"$version") | Set-Content -Path "$macContents/Info.plist"
|
||||||
|
Copy-Item $macEntitlements -Destination $macContents
|
||||||
wsl cp -a "$publishFolder/$runtime/." "$macPublishFolder/Contents/MacOS"
|
wsl cp -a "$publishFolder/$runtime/." "$macPublishFolder/Contents/MacOS"
|
||||||
wsl chmod +x "$macPublishFolder/Contents/MacOS/UVtools"
|
wsl chmod +x "$macPublishFolder/Contents/MacOS/UVtools"
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user