- **File formats:**
   - (Add) Allow to partial open the files for read and/or change properties, the layer images won't be read nor cached (Fast)
   - (Add) More abstraction on partial save
- **Scripting:**
   - (Add) ScriptOpenFolderDialogInput - Selects a folder path
   - (Add) ScriptOpenFileDialogInput - Selectes a file to open
   - (Add) ScriptSaveFileDialogInput - Selects a file to save
- (Add) [UNSAVED] tag to the title bar when there are unsaved changes on the current session
- (Improvement) Better handling of empty images on the UI
This commit is contained in:
Tiago Conceição
2021-11-18 03:29:08 +00:00
parent 0e099ae50b
commit c968eaedf9
51 changed files with 1890 additions and 1347 deletions
+12
View File
@@ -1,5 +1,17 @@
# Changelog
## 18/11/2021 - v2.25.0
- **File formats:**
- (Add) Allow to partial open the files for read and/or change properties, the layer images won't be read nor cached (Fast)
- (Add) More abstraction on partial save
- **Scripting:**
- (Add) ScriptOpenFolderDialogInput - Selects a folder path
- (Add) ScriptOpenFileDialogInput - Selectes a file to open
- (Add) ScriptSaveFileDialogInput - Selects a file to save
- (Add) [UNSAVED] tag to the title bar when there are unsaved changes on the current session
- (Improvement) Better handling of empty images on the UI
## 14/11/2021 - v2.24.4
- **File - Send to - Device**
@@ -2117,7 +2117,7 @@ namespace UVtools.AvaloniaControls
/// <returns></returns>
public Rect GetImageViewPort()
{
if (ViewPortSize.Width == 0 && ViewPortSize.Height == 0) return Rect.Empty;
if (!IsImageLoaded || (ViewPortSize.Width == 0 && ViewPortSize.Height == 0)) return Rect.Empty;
double xOffset = 0;
double yOffset = 0;
@@ -13,7 +13,7 @@
<PackageTags>Advanced image box</PackageTags>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Description>AvaloniaUI Controls</Description>
<Version>1.0.0</Version>
<Version>1.0.1</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+47 -54
View File
@@ -1097,15 +1097,15 @@ namespace UVtools.Core.FileFormats
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
Header = Helpers.Deserialize<FileHeader>(inputFile);
Debug.WriteLine($"Header: {Header}");
if (Header.Magic is not MAGIC_CBT_ENCRYPTED)
{
throw new FileLoadException($"Not a valid CTB encrypted file! Magic Value: {Header.Magic}", fileFullPath);
throw new FileLoadException($"Not a valid CTB encrypted file! Magic Value: {Header.Magic}", FileFullPath);
}
inputFile.Seek(Header.SettingsOffset, SeekOrigin.Begin);
@@ -1127,7 +1127,7 @@ namespace UVtools.Core.FileFormats
var hash = inputFile.ReadBytes(HASH_LENGTH);
if (!hash.SequenceEqual(encryptedHash))
{
throw new FileLoadException("The file checksum does not match, malformed file.", fileFullPath);
throw new FileLoadException("The file checksum does not match, malformed file.", FileFullPath);
}
progress.Reset(OperationProgress.StatusDecodePreviews, ThumbnailsCount);
@@ -1174,7 +1174,7 @@ namespace UVtools.Core.FileFormats
}
progress.Reset(OperationProgress.StatusDecodeLayers, Settings.LayerCount);
LayerManager.Init(Settings.LayerCount);
LayerManager.Init(Settings.LayerCount, DecodeType == FileDecodeType.Partial);
LayersDefinition = new LayerDef[LayerCount];
var buggyLayers = new ConcurrentBag<uint>();
@@ -1187,43 +1187,48 @@ namespace UVtools.Core.FileFormats
inputFile.Seek(LayersPointer[layerIndex].LayerOffset, SeekOrigin.Begin);
LayersDefinition[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
LayersDefinition[layerIndex].Parent = this;
LayersDefinition[layerIndex].RLEData = inputFile.ReadBytes(LayersDefinition[layerIndex].DataLength);
if (DecodeType == FileDecodeType.Full) LayersDefinition[layerIndex].RLEData = inputFile.ReadBytes(LayersDefinition[layerIndex].DataLength);
Debug.WriteLine($"layer[{layerIndex}]: {LayersDefinition[layerIndex]}");
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
if (DecodeType == FileDecodeType.Full)
{
if (progress.Token.IsCancellationRequested) return;
var layerDef = LayersDefinition[layerIndex];
if (layerDef.EncryptedDataLength > 0)
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
/* Decrypt RLE data here */
if (progress.Token.IsCancellationRequested) return;
var byteBuffer = new byte[layerDef.EncryptedDataLength];
Array.Copy(layerDef.RLEData, (int)layerDef.EncryptedDataOffset, byteBuffer, 0, (int)layerDef.EncryptedDataLength);
var layerDef = LayersDefinition[layerIndex];
byteBuffer = CryptExtensions.AesCryptBytes(byteBuffer, Bigfoot, CipherMode.CBC, PaddingMode.None, false, CookieMonster);
Array.Copy(byteBuffer, 0, layerDef.RLEData, layerDef.EncryptedDataOffset, layerDef.EncryptedDataLength);
}
bool isBugged = false;
/* bug fix for Chitubox when a small layer RLE data is encrypted */
if (layerDef.EncryptedDataLength > 0 && layerDef.RLEData.Length < RLEEncryptedMinimumLength && layerDef.RLEData.Length % 16 != 0)
{
buggyLayers.Add((uint)layerIndex);
isBugged = true;
layerDef.RLEData = null; /* clean up RLE data */
}
if (layerDef.EncryptedDataLength > 0)
{
/* Decrypt RLE data here */
var layer = new Layer((uint)layerIndex, isBugged ? null : layerDef.DecodeImage((uint)layerIndex), this);
layerDef.CopyTo(layer);
this[layerIndex] = layer;
progress.LockAndIncrement();
});
var byteBuffer = new byte[layerDef.EncryptedDataLength];
Array.Copy(layerDef.RLEData, (int)layerDef.EncryptedDataOffset, byteBuffer, 0,
(int)layerDef.EncryptedDataLength);
byteBuffer = CryptExtensions.AesCryptBytes(byteBuffer, Bigfoot, CipherMode.CBC,
PaddingMode.None, false, CookieMonster);
Array.Copy(byteBuffer, 0, layerDef.RLEData, layerDef.EncryptedDataOffset,
layerDef.EncryptedDataLength);
}
bool isBugged = false;
/* bug fix for Chitubox when a small layer RLE data is encrypted */
if (layerDef.EncryptedDataLength > 0 && layerDef.RLEData.Length < RLEEncryptedMinimumLength &&
layerDef.RLEData.Length % 16 != 0)
{
buggyLayers.Add((uint)layerIndex);
isBugged = true;
layerDef.RLEData = null; /* clean up RLE data */
}
this[layerIndex] = new Layer((uint)layerIndex, isBugged ? null : layerDef.DecodeImage((uint)layerIndex), this);
progress.LockAndIncrement();
});
}
}
if (buggyLayers.Count == LayerCount)
@@ -1231,7 +1236,12 @@ namespace UVtools.Core.FileFormats
throw new FileLoadException("Unable to load this file due to Chitubox bug affecting every layer." +
"Please increase the portion of the plate in use and reslice the file.");
}
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
LayersDefinition[layerIndex].CopyTo(this[layerIndex]);
}
if (!buggyLayers.IsEmpty)
{
var sortedLayerIndexes = buggyLayers.ToArray();
@@ -1267,13 +1277,13 @@ namespace UVtools.Core.FileFormats
//inputFile.ReadBytes(HashLength);
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
#if !DEBUG
throw new NotSupportedException(Preamble);
#endif
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
//uint currentOffset = 0;
/* Create the file header and fill out what we can. SignatureOffset will have to be populated later
@@ -1401,25 +1411,8 @@ namespace UVtools.Core.FileFormats
Helpers.SerializeWriteFileStream(outputFile, Header);
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
SanitizeProperties();
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
+51 -66
View File
@@ -575,7 +575,7 @@ namespace UVtools.Core.FileFormats
#region Methods
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
//var filename = fileFullPath.EndsWith(TemporaryFileAppend) ? Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(fileFullPath)) : Path.GetFileNameWithoutExtension(fileFullPath);
@@ -610,7 +610,7 @@ namespace UVtools.Core.FileFormats
throw new InvalidOperationException($"Filename for this format should not end with a digit: {filename}");
}
using ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
if (Printer == PrinterType.Wanhao)
{
var manifest = new CWSManifest
@@ -703,9 +703,9 @@ namespace UVtools.Core.FileFormats
outputFile.PutFileContent($"{filename}.gcode", GCodeStr, ZipArchiveMode.Create);
}
protected override void DecodeInternally(string fileFullPath, 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("manifest.xml");
if (entry is not null) // Wanhao
{
@@ -722,7 +722,7 @@ namespace UVtools.Core.FileFormats
catch (Exception e)
{
Clear();
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
}
@@ -741,7 +741,7 @@ namespace UVtools.Core.FileFormats
catch (Exception e)
{
Clear();
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
}
}
}
@@ -751,7 +751,7 @@ namespace UVtools.Core.FileFormats
if (entry is null)
{
Clear();
throw new FileLoadException("slice.conf not found", fileFullPath);
throw new FileLoadException("slice.conf not found", FileFullPath);
}
using TextReader tr = new StreamReader(entry.Open());
@@ -780,8 +780,7 @@ namespace UVtools.Core.FileFormats
if (entry is null)
{
Clear();
throw new FileLoadException("Unable to find .gcode file",
fileFullPath);
throw new FileLoadException("Unable to find .gcode file", FileFullPath);
}
using (TextReader tr = new StreamReader(entry.Open()))
@@ -821,32 +820,36 @@ namespace UVtools.Core.FileFormats
tr.Close();
}
LayerManager.Init(OutputSettings.LayersNum);
LayerManager.Init(OutputSettings.LayersNum, DecodeType == FileDecodeType.Partial);
progress.ItemCount = OutputSettings.LayersNum;
if(LayerCount > 0)
{
var inputFilename = Path.GetFileNameWithoutExtension(fileFullPath);
foreach (var pngEntry in inputFile.Entries)
if (DecodeType == FileDecodeType.Full)
{
if (!pngEntry.Name.EndsWith(".png")) 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--)
var inputFilename = Path.GetFileNameWithoutExtension(FileFullPath);
foreach (var pngEntry in inputFile.Entries)
{
if (layerStr[i] < '0' || layerStr[i] > '9') break;
layerIndexStr = $"{layerStr[i]}{layerIndexStr}";
if (!pngEntry.Name.EndsWith(".png")) 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, LayerManager);
}
if (string.IsNullOrEmpty(layerIndexStr)) continue;
if (!uint.TryParse(layerIndexStr, out var layerIndex)) continue;
using var stream = pngEntry.Open();
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
}
GCode.ParseLayersFromGCode(this);
var firstLayer = FirstLayer;
@@ -993,61 +996,43 @@ namespace UVtools.Core.FileFormats
RaisePropertyChanged(nameof(GCodeStr));
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
var arch = Environment.Is64BitOperatingSystem ? "64-bits" : "32-bits";
var entry = outputFile.GetPutFile("slice.conf");
var stream = entry.Open();
stream.SetLength(0);
using (TextWriter tw = new StreamWriter(stream))
{
if (!string.IsNullOrEmpty(filePath))
tw.WriteLine($"# {About.Website} {About.Software} {Assembly.GetExecutingAssembly().GetName().Version} {arch} {DateTime.UtcNow}");
tw.WriteLine("# conf version 1.0");
tw.WriteLine("");
foreach (var propertyInfo in SliceSettings.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
FileFullPath = filePath;
var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
if (displayNameAttribute is null) continue;
tw.WriteLine($"{displayNameAttribute.DisplayName.PadRight(24)}= {propertyInfo.GetValue(SliceSettings)}");
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
var entriesToRemove = outputFile.Entries.Where(zipEntry => zipEntry.Name.EndsWith(".gcode")).ToArray();
foreach (var zipEntry in entriesToRemove)
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
zipEntry.Delete();
}
using (var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update))
{
string arch = Environment.Is64BitOperatingSystem ? "64-bits" : "32-bits";
var entry = outputFile.GetPutFile("slice.conf");
var stream = entry.Open();
stream.SetLength(0);
outputFile.PutFileContent($"{About.Software}.gcode", GCodeStr, ZipArchiveMode.Update);
using (TextWriter tw = new StreamWriter(stream))
{
tw.WriteLine($"# {About.Website} {About.Software} {Assembly.GetExecutingAssembly().GetName().Version} {arch} {DateTime.UtcNow}");
tw.WriteLine("# conf version 1.0");
tw.WriteLine("");
foreach (var propertyInfo in SliceSettings.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
if (displayNameAttribute is null) continue;
tw.WriteLine($"{displayNameAttribute.DisplayName.PadRight(24)}= {propertyInfo.GetValue(SliceSettings)}");
}
}
var entriesToRemove = outputFile.Entries.Where(zipEntry => zipEntry.Name.EndsWith(".gcode")).ToArray();
foreach (var zipEntry in entriesToRemove)
{
zipEntry.Delete();
}
outputFile.PutFileContent($"{About.Software}.gcode", GCodeStr, ZipArchiveMode.Update);
/*foreach (var layer in this)
/*foreach (var layer in this)
{
if (!layer.IsModified) continue;
outputFile.PutFileContent(layer.Filename, layer.CompressedBytes, ZipArchiveMode.Update);
layer.IsModified = false;
}*/
}
//Decode(FileFullPath, progress);
}
+58 -95
View File
@@ -17,7 +17,6 @@ using System.Text;
using System.Threading.Tasks;
using BinarySerialization;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using MoreLinq;
using UVtools.Core.Extensions;
@@ -571,9 +570,9 @@ namespace UVtools.Core.FileFormats
SlicerInfoSettings.WaitTimeBeforeCure = (ushort)Math.Max(1, WaitTimeBeforeCure);
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.ReadWrite);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.ReadWrite);
if (ResolutionX == 1620 && ResolutionY == 2560)
{
@@ -790,9 +789,9 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine("-End-");
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
inputFile.Seek(0, SeekOrigin.Begin);
@@ -812,10 +811,10 @@ namespace UVtools.Core.FileFormats
if (expectedCheckSum != checkSum)
{
throw new FileLoadException($"Checksum fails, expecting: {expectedCheckSum} but got: {checkSum}.\n" +
$"Try to reslice the file.", fileFullPath);
$"Try to reslice the file.", FileFullPath);
}
byte[][] previews = new byte[ThumbnailsOriginalSize.Length][];
var previews = new byte[ThumbnailsOriginalSize.Length][];
for (int i = 0; i < ThumbnailsOriginalSize.Length; i++)
{
previews[i] = new byte[ThumbnailsOriginalSize[i].Area() * 2];
@@ -833,116 +832,80 @@ namespace UVtools.Core.FileFormats
SlicerInfoSettings = Helpers.Deserialize<SlicerInfo>(inputFile);
Debug.WriteLine(SlicerInfoSettings);
LayerManager.Init(HeaderSettings.LayerCount);
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
inputFile.Seek(LayerCount * 4 + 2, SeekOrigin.Current); // Skip pre layers
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
/*var preLayers = new PreLayer[LayerCount];
for (int layerIndex = 0; layerIndex < LayerCount; layerIndex++)
if (DecodeType == FileDecodeType.Full)
{
progress.Token.ThrowIfCancellationRequested();
preLayers[layerIndex] = Helpers.Deserialize<PreLayer>(inputFile);
progress++;
}*/
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
//inputFile.Seek(2, SeekOrigin.Current);
var linesBytes = new byte[LayerCount][];
foreach (var batch in BatchLayersIndexes())
{
progress.Token.ThrowIfCancellationRequested();
foreach (var layerIndex in batch)
var linesBytes = new byte[LayerCount][];
foreach (var batch in BatchLayersIndexes())
{
inputFile.Seek(4, SeekOrigin.Current);
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
linesBytes[layerIndex] = new byte[lineCount * 6];
inputFile.ReadBytes(linesBytes[layerIndex]);
inputFile.Seek(2, SeekOrigin.Current);
progress.Token.ThrowIfCancellationRequested();
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = EmguExtensions.InitMat(Resolution))
foreach (var layerIndex in batch)
{
inputFile.Seek(4, SeekOrigin.Current);
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
{
LayerLine line = new()
{
Coordinates =
{
[0] = linesBytes[layerIndex][i++],
[1] = linesBytes[layerIndex][i++],
[2] = linesBytes[layerIndex][i++],
[3] = linesBytes[layerIndex][i++],
[4] = linesBytes[layerIndex][i++]
},
Gray = linesBytes[layerIndex][i]
};
linesBytes[layerIndex] = new byte[lineCount * 6];
inputFile.ReadBytes(linesBytes[layerIndex]);
inputFile.Seek(2, SeekOrigin.Current);
CvInvoke.Line(mat, new Point(line.StartX, line.StartY), new Point(line.StartX, line.EndY),
new MCvScalar(line.Gray));
}
linesBytes[layerIndex] = null;
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.Token.ThrowIfCancellationRequested();
}
progress.LockAndIncrement();
});
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = EmguExtensions.InitMat(Resolution))
{
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
{
LayerLine line = new()
{
Coordinates =
{
[0] = linesBytes[layerIndex][i++],
[1] = linesBytes[layerIndex][i++],
[2] = linesBytes[layerIndex][i++],
[3] = linesBytes[layerIndex][i++],
[4] = linesBytes[layerIndex][i++]
},
Gray = linesBytes[layerIndex][i]
};
CvInvoke.Line(mat, new Point(line.StartX, line.StartY),
new Point(line.StartX, line.EndY),
new MCvScalar(line.Gray));
}
linesBytes[layerIndex] = null;
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
}
progress.LockAndIncrement();
});
}
}
else // Partial read
{
inputFile.Seek(-Helpers.Serializer.SizeOf(FooterSettings), SeekOrigin.End);
}
progress.Token.ThrowIfCancellationRequested();
/*var layerDefs = new LayerDef[LayerCount];
for (int layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
progress.Token.ThrowIfCancellationRequested();
layerDefs[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
progress++;
}
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using var mat = EmguExtensions.InitMat(Resolution);
foreach (var line in layerDefs[layerIndex].Lines)
{
CvInvoke.Line(mat, new Point(line.StartX, line.StartY), new Point(line.StartX, line.EndY), new MCvScalar(line.Gray));
}
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.LockAndIncrement();
});*/
FooterSettings = Helpers.Deserialize<Footer>(inputFile);
FooterSettings.Validate();
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
var offset = Helpers.Serializer.SizeOf(HeaderSettings);
foreach (var size in ThumbnailsOriginalSize)
{
+54 -65
View File
@@ -499,9 +499,9 @@ namespace UVtools.Core.FileFormats
#region Methods
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
if (ResolutionX == 2560 && ResolutionY == 1620)
{
@@ -628,9 +628,9 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine("-End-");
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
HeaderSettings.Validate();
@@ -654,62 +654,67 @@ namespace UVtools.Core.FileFormats
SlicerInfoSettings = Helpers.Deserialize<SlicerInfo>(inputFile);
Debug.WriteLine(SlicerInfoSettings);
LayerManager.Init(HeaderSettings.LayerCount);
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
inputFile.Seek(LayerCount * 4 + 2, SeekOrigin.Current); // Skip pre layers
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
var range = Enumerable.Range(0, (int)LayerCount);
var linesBytes = new byte[LayerCount][];
foreach (var batch in BatchLayersIndexes())
if (DecodeType == FileDecodeType.Full)
{
progress.Token.ThrowIfCancellationRequested();
foreach (var layerIndex in batch)
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
var linesBytes = new byte[LayerCount][];
foreach (var batch in BatchLayersIndexes())
{
inputFile.Seek(4, SeekOrigin.Current);
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
linesBytes[layerIndex] = new byte[lineCount * 6];
inputFile.ReadBytes(linesBytes[layerIndex]);
inputFile.Seek(2, SeekOrigin.Current);
progress.Token.ThrowIfCancellationRequested();
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = EmguExtensions.InitMat(Resolution))
foreach (var layerIndex in batch)
{
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
{
LayerLine line = new()
{
Coordinates =
{
[0] = linesBytes[layerIndex][i++],
[1] = linesBytes[layerIndex][i++],
[2] = linesBytes[layerIndex][i++],
[3] = linesBytes[layerIndex][i++],
[4] = linesBytes[layerIndex][i++]
},
Gray = linesBytes[layerIndex][i]
};
inputFile.Seek(4, SeekOrigin.Current);
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
CvInvoke.Line(mat, new Point(line.StartX, line.StartY), new Point(line.StartX, line.EndY),
new MCvScalar(line.Gray));
}
linesBytes[layerIndex] = new byte[lineCount * 6];
inputFile.ReadBytes(linesBytes[layerIndex]);
inputFile.Seek(2, SeekOrigin.Current);
linesBytes[layerIndex] = null;
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.Token.ThrowIfCancellationRequested();
}
progress.LockAndIncrement();
});
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = EmguExtensions.InitMat(Resolution))
{
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
{
LayerLine line = new()
{
Coordinates =
{
[0] = linesBytes[layerIndex][i++],
[1] = linesBytes[layerIndex][i++],
[2] = linesBytes[layerIndex][i++],
[3] = linesBytes[layerIndex][i++],
[4] = linesBytes[layerIndex][i++]
},
Gray = linesBytes[layerIndex][i]
};
CvInvoke.Line(mat, new Point(line.StartX, line.StartY),
new Point(line.StartX, line.EndY),
new MCvScalar(line.Gray));
}
linesBytes[layerIndex] = null;
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
}
progress.LockAndIncrement();
});
}
}
else // Partial read
{
inputFile.Seek(-Helpers.Serializer.SizeOf(FooterSettings), SeekOrigin.End);
}
progress.Token.ThrowIfCancellationRequested();
@@ -718,24 +723,8 @@ namespace UVtools.Core.FileFormats
FooterSettings.Validate();
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
var offset = Helpers.Serializer.SizeOf(HeaderSettings);
foreach (var size in ThumbnailsOriginalSize)
{
+45 -61
View File
@@ -1775,7 +1775,7 @@ namespace UVtools.Core.FileFormats
return true;
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
SanitizeMagicVersion();
SanitizeProperties();
@@ -1799,7 +1799,7 @@ namespace UVtools.Core.FileFormats
//uint currentOffset = (uint)Helpers.Serializer.SizeOf(HeaderSettings);
LayerDefinitions = new LayerDef[HeaderSettings.AntiAliasLevel, HeaderSettings.LayerCount];
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
outputFile.Seek(Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.Begin);
Mat[] thumbnails = {GetThumbnail(true), GetThumbnail(false)};
@@ -1956,16 +1956,16 @@ namespace UVtools.Core.FileFormats
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
//HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header))));
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
if (HeaderSettings.Magic is not MAGIC_CBDDLP and not MAGIC_CTB and not MAGIC_CTBv4)
{
throw new FileLoadException($"Not a valid PHOTON nor CBDDLP nor CTB file! Magic Value: {HeaderSettings.Magic}", fileFullPath);
throw new FileLoadException($"Not a valid PHOTON nor CBDDLP nor CTB file! Magic Value: {HeaderSettings.Magic}", FileFullPath);
}
if (HeaderSettings.Version == 1 || HeaderSettings.AntiAliasLevel == 0)
@@ -1973,8 +1973,6 @@ namespace UVtools.Core.FileFormats
HeaderSettings.AntiAliasLevel = 1;
}
FileFullPath = fileFullPath;
progress.Reset(OperationProgress.StatusDecodePreviews, ThumbnailsCount);
Debug.Write("Header -> ");
@@ -2031,7 +2029,7 @@ namespace UVtools.Core.FileFormats
{
throw new FileLoadException(
$"Malformed file, PrintParametersV4Address is missing",
fileFullPath);
FileFullPath);
}
inputFile.Seek(SlicerInfoSettings.PrintParametersV4Address, SeekOrigin.Begin);
@@ -2044,7 +2042,7 @@ namespace UVtools.Core.FileFormats
throw new FileLoadException(
$"Malformed file, PrintParametersV4 found invalid validation values, expected (4, 4) " +
$"but got ({PrintParametersV4Settings.Four1}, {PrintParametersV4Settings.Four2})",
fileFullPath);
FileFullPath);
}
}
@@ -2053,8 +2051,7 @@ namespace UVtools.Core.FileFormats
uint layerOffset = HeaderSettings.LayersDefinitionOffsetAddress;
progress.Reset(OperationProgress.StatusGatherLayers,
HeaderSettings.AntiAliasLevel * HeaderSettings.LayerCount);
progress.Reset(OperationProgress.StatusGatherLayers, HeaderSettings.AntiAliasLevel * HeaderSettings.LayerCount);
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
{
@@ -2089,65 +2086,52 @@ namespace UVtools.Core.FileFormats
}
}
LayerManager.Init(HeaderSettings.LayerCount);
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
foreach (var batch in BatchLayersIndexes())
if (DecodeType == FileDecodeType.Full)
{
foreach (var layerIndex in batch)
{
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
{
progress.Token.ThrowIfCancellationRequested();
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
inputFile.Seek(LayerDefinitions[aaIndex, layerIndex].DataAddress, SeekOrigin.Begin);
LayerDefinitions[aaIndex, layerIndex].EncodedRle = inputFile.ReadBytes(LayerDefinitions[aaIndex, layerIndex].DataSize);
foreach (var batch in BatchLayersIndexes())
{
foreach (var layerIndex in batch)
{
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
{
progress.Token.ThrowIfCancellationRequested();
inputFile.Seek(LayerDefinitions[aaIndex, layerIndex].DataAddress, SeekOrigin.Begin);
LayerDefinitions[aaIndex, layerIndex].EncodedRle = inputFile.ReadBytes(LayerDefinitions[aaIndex, layerIndex].DataSize);
}
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using var mat = LayerDefinitions[0, layerIndex].Decode((uint)layerIndex);
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.LockAndIncrement();
});
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = LayerDefinitions[0, layerIndex].Decode((uint)layerIndex))
{
var layer = new Layer((uint)layerIndex, mat, this);
if (layerDefinitionsEx is not null) // CTBv4
{
layerDefinitionsEx[layerIndex].CopyTo(layer);
}
else // others
{
LayerDefinitions[0, layerIndex].CopyTo(layer);
}
this[layerIndex] = layer;
}
progress.LockAndIncrement();
});
}
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
if (layerDefinitionsEx is not null) // CTBv4
{
layerDefinitionsEx[layerIndex].CopyTo(this[layerIndex]);
}
else // others
{
LayerDefinitions[0, layerIndex].CopyTo(this[layerIndex]);
}
}
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
SanitizeProperties();
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(0, SeekOrigin.Begin);
+23 -40
View File
@@ -401,9 +401,9 @@ namespace UVtools.Core.FileFormats
return false;
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create))
using (ZipArchive outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create))
{
if (Thumbnails.Length > 0 && Thumbnails[0] is not null)
{
@@ -416,14 +416,10 @@ namespace UVtools.Core.FileFormats
if (Thumbnails.Length > 1 && Thumbnails[1] is not null)
{
using (Stream stream = outputFile.CreateEntry("preview_cropping.png").Open())
{
using (var vec = new VectorOfByte())
{
stream.WriteBytes(Thumbnails[1].GetPngByes());
stream.Close();
}
}
using Stream stream = outputFile.CreateEntry("preview_cropping.png").Open();
using var vec = new VectorOfByte();
stream.WriteBytes(Thumbnails[1].GetPngByes());
stream.Close();
}
if (!IsPHZZip)
@@ -443,7 +439,7 @@ namespace UVtools.Core.FileFormats
}
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
{
@@ -497,24 +493,27 @@ namespace UVtools.Core.FileFormats
}
}
LayerManager.Init(HeaderSettings.LayerCount);
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
progress.ItemCount = LayerCount;
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
if (DecodeType == FileDecodeType.Full)
{
if (progress.Token.IsCancellationRequested) break;
entry = inputFile.GetEntry($"{layerIndex+1}.png");
if (entry is null)
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
Clear();
throw new FileLoadException($"Layer {layerIndex+1} not found", fileFullPath);
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);
}
using var stream = entry.Open();
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
progress++;
}
using var stream = entry.Open();
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
progress++;
}
if (IsPHZZip) // PHZ file
@@ -561,24 +560,8 @@ namespace UVtools.Core.FileFormats
RaisePropertyChanged(nameof(GCodeStr));
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
var entriesToRemove = outputFile.Entries.Where(zipEntry => zipEntry.Name.EndsWith(".gcode")).ToArray();
foreach (var zipEntry in entriesToRemove)
+27 -38
View File
@@ -904,7 +904,7 @@ namespace UVtools.Core.FileFormats
LayersDefinitions = null;
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
/*if (HeaderSettings.EncryptionKey == 0)
{
@@ -912,7 +912,7 @@ namespace UVtools.Core.FileFormats
HeaderSettings.EncryptionKey = (uint)rnd.Next(short.MaxValue, int.MaxValue);
}*/
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
outputFile.Seek(Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.Begin);
for (byte i = 0; i < ThumbnailsCount; i++)
@@ -1021,22 +1021,19 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine("-End-");
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
//HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header))));
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
if (HeaderSettings.Magic != MAGIC)
{
throw new FileLoadException("Not a valid FDG file!", fileFullPath);
throw new FileLoadException("Not a valid FDG file!", FileFullPath);
}
HeaderSettings.AntiAliasLevel = 1;
FileFullPath = fileFullPath;
progress.Reset(OperationProgress.StatusDecodePreviews, ThumbnailsCount);
Debug.Write("Header -> ");
Debug.WriteLine(HeaderSettings);
@@ -1070,7 +1067,7 @@ namespace UVtools.Core.FileFormats
HeaderSettings.MachineName = Encoding.ASCII.GetString(buffer);
}
LayerManager.Init(HeaderSettings.LayerCount);
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
LayersDefinitions = new LayerDef[HeaderSettings.LayerCount];
progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount);
@@ -1087,45 +1084,37 @@ namespace UVtools.Core.FileFormats
Debug.Write($"LAYER {layerIndex} -> ");
Debug.WriteLine(layerDef);
inputFile.SeekDoWorkAndRewind(layerDef.DataAddress, () =>
if (DecodeType == FileDecodeType.Full)
{
layerDef.EncodedRle = inputFile.ReadBytes(layerDef.DataSize);
});
inputFile.SeekDoWorkAndRewind(layerDef.DataAddress,
() => { layerDef.EncodedRle = inputFile.ReadBytes(layerDef.DataSize); });
}
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
if (DecodeType == FileDecodeType.Full)
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex))
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
var layer = new Layer((uint)layerIndex, mat, this);
LayersDefinitions[layerIndex].CopyTo(layer);
this[layerIndex] = layer;
}
if (progress.Token.IsCancellationRequested) return;
if (DecodeType == FileDecodeType.Full)
{
using var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex);
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
}
progress.LockAndIncrement();
});
progress.LockAndIncrement();
});
}
}
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
LayersDefinitions[layerIndex].CopyTo(this[layerIndex]);
}
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(0, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
+79 -21
View File
@@ -121,6 +121,19 @@ namespace UVtools.Core.FileFormats
Small = 0,
Large
}
public enum FileDecodeType : byte
{
/// <summary>
/// Decodes all the file information and caches layer images
/// </summary>
Full,
/// <summary>
/// Decodes only the information in the file and thumbnails, no layer image is read nor cached, fast
/// </summary>
Partial,
}
#endregion
#region Sub Classes
@@ -441,6 +454,17 @@ namespace UVtools.Core.FileFormats
return PathExtensions.GetFileNameStripExtensions(filepath, AllFileExtensionsString.OrderByDescending(s => s.Length).ToList(), out strippedExtension);
}
public static FileFormat Open(string fileFullPath, FileDecodeType decodeType, OperationProgress progress = null)
{
var slicerFile = FindByExtensionOrFilePath(fileFullPath, true);
if (slicerFile is null) return null;
slicerFile.Decode(fileFullPath, decodeType, progress);
return slicerFile;
}
public static FileFormat Open(string fileFullPath, OperationProgress progress = null) =>
Open(fileFullPath, FileDecodeType.Full, progress);
public static byte[] EncodeImage(string dataType, Mat mat)
{
@@ -762,6 +786,8 @@ namespace UVtools.Core.FileFormats
/// </summary>
public abstract FileExtension[] FileExtensions { get; }
public FileDecodeType DecodeType { get; private set; } = FileDecodeType.Full;
/// <summary>
/// Gets the available <see cref="PrintParameterModifier"/>
/// </summary>
@@ -847,6 +873,7 @@ namespace UVtools.Core.FileFormats
/// </summary>
public string FileFullPath { get; set; }
public string FileDirectoryPath => Path.GetDirectoryName(FileFullPath);
public string Filename => Path.GetFileName(FileFullPath);
public string FileExtension => Path.GetExtension(FileFullPath);
public string FilenameNoExt => GetFileNameStripExtensions(FileFullPath);
@@ -2520,9 +2547,8 @@ namespace UVtools.Core.FileFormats
/// <summary>
/// Encode to an output file
/// </summary>
/// <param name="fileFullPath">Output file</param>
/// <param name="progress"></param>
protected abstract void EncodeInternally(string fileFullPath, OperationProgress progress);
protected abstract void EncodeInternally(OperationProgress progress);
/// <summary>
/// Encode to an output file
@@ -2531,6 +2557,11 @@ namespace UVtools.Core.FileFormats
/// <param name="progress"></param>
public void Encode(string fileFullPath, OperationProgress progress = null)
{
if (DecodeType == FileDecodeType.Partial)
{
throw new InvalidOperationException("File was partial decoded, a full encode is not possible.");
}
progress ??= new OperationProgress();
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
@@ -2543,12 +2574,9 @@ namespace UVtools.Core.FileFormats
LayerManager.Sanitize();
FileFullPath = fileFullPath;
if (File.Exists(fileFullPath)) File.Delete(fileFullPath);
if (File.Exists(fileFullPath))
{
File.Delete(fileFullPath);
}
FileFullPath = fileFullPath;
for (var i = 0; i < Thumbnails.Length; i++)
{
@@ -2557,7 +2585,7 @@ namespace UVtools.Core.FileFormats
CvInvoke.Resize(Thumbnails[i], Thumbnails[i], new Size(ThumbnailsOriginalSize[i].Width, ThumbnailsOriginalSize[i].Height));
}
EncodeInternally(fileFullPath, progress);
EncodeInternally(progress);
LayerManager.SetAllIsModified(false);
RequireFullEncode = false;
@@ -2566,24 +2594,32 @@ namespace UVtools.Core.FileFormats
/// <summary>
/// Decode a slicer file
/// </summary>
/// <param name="fileFullPath"></param>
/// <param name="progress"></param>
protected abstract void DecodeInternally(string fileFullPath, OperationProgress progress);
protected abstract void DecodeInternally(OperationProgress progress);
/// <summary>
/// Decode a slicer file
/// </summary>
/// <param name="fileFullPath"></param>
/// <param name="progress"></param>
public void Decode(string fileFullPath, OperationProgress progress = null)
public void Decode(string fileFullPath, OperationProgress progress = null) => Decode(fileFullPath, FileDecodeType.Full, progress);
/// <summary>
/// Decode a slicer file
/// </summary>
/// <param name="fileFullPath"></param>
/// <param name="fileDecodeType"></param>
/// <param name="progress"></param>
public void Decode(string fileFullPath, FileDecodeType fileDecodeType, OperationProgress progress = null)
{
Clear();
FileValidation(fileFullPath);
FileFullPath = fileFullPath;
DecodeType = fileDecodeType;
progress ??= new OperationProgress();
progress.Reset(OperationProgress.StatusGatherLayers, LayerCount);
DecodeInternally(fileFullPath, progress);
DecodeInternally(progress);
progress.Token.ThrowIfCancellationRequested();
@@ -2745,20 +2781,15 @@ namespace UVtools.Core.FileFormats
}
}
if (LayerCount > 0)
if (LayerCount > 0 && DecodeType == FileDecodeType.Full)
{
Parallel.ForEach(this, CoreSettings.ParallelOptions, layer =>
{
if (progress.Token.IsCancellationRequested) return;
var byteArr = layer.CompressedBytes;
using var stream = File.Create(Path.Combine(path, layer.Filename),
byteArr.Length);
if (byteArr is null) return;
using var stream = new FileStream(Path.Combine(path, layer.Filename), FileMode.Create, FileAccess.Write);
stream.Write(byteArr, 0, byteArr.Length);
stream.Close();
//using var mat = layer.LayerMat;
//mat.Save(Path.Combine(path, $"{layer.Filename}.jpg"));
progress.LockAndIncrement();
});
}
@@ -3343,7 +3374,34 @@ namespace UVtools.Core.FileFormats
/// </summary>
/// <param name="filePath">File path to save copy as, use null to overwrite active file (Same as <see cref="Save"/>)</param>
/// <param name="progress"></param>
public abstract void SaveAs(string filePath = null, OperationProgress progress = null);
public void SaveAs(string filePath = null, OperationProgress progress = null)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
PartialSaveInternally(progress);
}
/// <summary>
/// Partial save of the file, this is the file information only.
/// When this function is called it's already ready to save to file
/// </summary>
/// <param name="progress"></param>
protected abstract void PartialSaveInternally(OperationProgress progress);
/// <summary>
/// Triggers when a conversion is valid and before start converting values
+21 -30
View File
@@ -446,17 +446,17 @@ namespace UVtools.Core.FileFormats
#endregion
#region Methods
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
if (SVGDocument.PrintParameters.ResolutionX == 0 || SVGDocument.PrintParameters.ResolutionY == 0 ||
SVGDocument.PrintParameters.DisplayWidth == 0 || SVGDocument.PrintParameters.DisplayHeight == 0)
{
throw new FileLoadException("This file does not contain a resolution and/or display size information needed to generate the layer images.\n" +
"Note that FlashDLPrint slicer is unable to output files with the required information to load in here.\n" +
"Please use other compatible slicer capable of output the correct information to load the file in here.", fileFullPath);
"Please use other compatible slicer capable of output the correct information to load the file in here.", FileFullPath);
}
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
outputFile.Seek(Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.Begin);
HeaderSettings.Preview1Address = 0;
@@ -594,13 +594,13 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine("-End-");
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
if (HeaderSettings.Identifier != Header.IdentifierText)
{
throw new FileLoadException("Not a valid Flashforge SVGX file!", fileFullPath);
throw new FileLoadException("Not a valid Flashforge SVGX file!", FileFullPath);
}
progress.Reset(OperationProgress.StatusDecodePreviews, ThumbnailsCount);
@@ -644,15 +644,16 @@ namespace UVtools.Core.FileFormats
{
throw new FileLoadException("This file does not contain a resolution and/or display size information needed to generate the layer images.\n" +
"Note that FlashDLPrint slicer is unable to output files with the required information to load in here.\n" +
"Please use other compatible slicer capable of output the correct information to load the file in here.", fileFullPath);
"Please use other compatible slicer capable of output the correct information to load the file in here.", FileFullPath);
}
var halfDisplay = Display.Half();
var ppmm = Ppmm;
LayerManager.Init(SVGDocument.PrintParameters.LayerCount);
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
LayerManager.Init(SVGDocument.PrintParameters.LayerCount, DecodeType == FileDecodeType.Partial);
if (DecodeType != FileDecodeType.Full) return;
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
@@ -661,14 +662,15 @@ namespace UVtools.Core.FileFormats
var group = SVGDocument.Groups.FirstOrDefault(g => g.Id == $"layer-{layerIndex}");
if (group is not null)
if (@group is not null)
{
var pointsOfPoints = 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;
var spaceSplit = path.Value.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
var spaceSplit = path.Value.Split(' ',
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < spaceSplit.Length; i++)
{
@@ -679,8 +681,10 @@ namespace UVtools.Core.FileFormats
pointsOfPoints.Add(points.ToArray());
points.Clear();
}
continue;
}
if (spaceSplit[i] == "Z")
{
if (points.Count > 0)
@@ -688,9 +692,12 @@ namespace UVtools.Core.FileFormats
pointsOfPoints.Add(points.ToArray());
points.Clear();
}
continue;
}
if (spaceSplit[i].Length == 1 && !char.IsDigit(spaceSplit[i][0])) continue; // Ignore any other not processed 1 char that's not a digit (L)
if (spaceSplit[i].Length == 1 && !char.IsDigit(spaceSplit[i][0]))
continue; // Ignore any other not processed 1 char that's not a digit (L)
if (i + 1 >= spaceSplit.Length) break; // No more to see
@@ -730,24 +737,8 @@ namespace UVtools.Core.FileFormats
});
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(HeaderSettings.SVGDocumentAddress, SeekOrigin.Begin);
outputFile.SetLength(outputFile.Position);
+43 -55
View File
@@ -354,9 +354,9 @@ namespace UVtools.Core.FileFormats
#endregion
#region Methods
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
var pageBreak = PageBreak.Bytes;
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
@@ -465,13 +465,13 @@ namespace UVtools.Core.FileFormats
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
if (HeaderSettings.HeaderValue != Header.HEADER_VALUE)
{
throw new FileLoadException("Not a valid Makerbase file!", fileFullPath);
throw new FileLoadException("Not a valid Makerbase file!", FileFullPath);
}
byte[][] previews = new byte[ThumbnailsOriginalSize.Length][];
@@ -491,77 +491,65 @@ namespace UVtools.Core.FileFormats
SlicerInfoSettings = Helpers.Deserialize<SlicerInfo>(inputFile);
LayerManager.Init(SlicerInfoSettings.LayerCount);
LayerManager.Init(SlicerInfoSettings.LayerCount, DecodeType == FileDecodeType.Partial);
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
var range = Enumerable.Range(0, (int)LayerCount);
var linesBytes = new byte[LayerCount][];
foreach (var batch in BatchLayersIndexes())
if (DecodeType == FileDecodeType.Full)
{
progress.Token.ThrowIfCancellationRequested();
foreach (var layerIndex in batch)
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
var linesBytes = new byte[LayerCount][];
foreach (var batch in BatchLayersIndexes())
{
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
linesBytes[layerIndex] = new byte[lineCount * 6];
inputFile.ReadBytes(linesBytes[layerIndex]);
inputFile.Seek(2, SeekOrigin.Current);
progress.Token.ThrowIfCancellationRequested();
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using var mat = EmguExtensions.InitMat(Resolution);
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
foreach (var layerIndex in batch)
{
var startY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
var endY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
var startX = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i]);
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
CvInvoke.Line(mat, new Point(startX, startY), new Point(startX, endY), EmguExtensions.WhiteColor);
linesBytes[layerIndex] = new byte[lineCount * 6];
inputFile.ReadBytes(linesBytes[layerIndex]);
inputFile.Seek(2, SeekOrigin.Current);
progress.Token.ThrowIfCancellationRequested();
}
linesBytes[layerIndex] = null;
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using var mat = EmguExtensions.InitMat(Resolution);
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
{
var startY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
var endY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
var startX = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i]);
progress.LockAndIncrement();
});
CvInvoke.Line(mat, new Point(startX, startY), new Point(startX, endY),
EmguExtensions.WhiteColor);
}
linesBytes[layerIndex] = null;
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.LockAndIncrement();
});
}
}
else // Partial read
{
inputFile.Seek(-Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.End);
}
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
if (HeaderSettings.HeaderValue != Header.HEADER_VALUE)
{
throw new FileLoadException("Not a valid Makerbase file!", fileFullPath);
throw new FileLoadException("Not a valid Makerbase file!", FileFullPath);
}
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(SlicerInfoAddress, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, SlicerInfoSettings);
+6 -6
View File
@@ -77,14 +77,14 @@ namespace UVtools.Core.FileFormats
private Mat ImageMat { get; set; }
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
throw new NotSupportedException();
this[0].LayerMat.Save(FileFullPath);
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
ImageMat = CvInvoke.Imread(fileFullPath, ImreadModes.Grayscale);
ImageMat = CvInvoke.Imread(FileFullPath, ImreadModes.Grayscale);
const byte startDivisor = 2;
for (int i = 0; i < ThumbnailsCount; i++)
{
@@ -102,9 +102,9 @@ namespace UVtools.Core.FileFormats
this[0] = new Layer(0, ImageMat, LayerManager);
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
this[0].LayerMat.Save(filePath ?? FileFullPath);
this[0].LayerMat.Save(FileFullPath);
}
public override FileFormat Convert(Type to, string fileFullPath, OperationProgress progress = null)
+24 -40
View File
@@ -487,7 +487,7 @@ namespace UVtools.Core.FileFormats
#region Methods
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
if (FileEndsWith(".lgs")) // Longer Orange 10
{
@@ -511,7 +511,7 @@ namespace UVtools.Core.FileFormats
}
//uint currentOffset = (uint)Helpers.Serializer.SizeOf(HeaderSettings);
using (var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write))
using (var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write))
{
outputFile.WriteSerialize(HeaderSettings);
outputFile.WriteBytes(EncodeImage(DATATYPE_RGB565_BE, Thumbnails[0]));
@@ -566,13 +566,13 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine("-End-");
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
if (HeaderSettings.Name != Header.NameValue)
{
throw new FileLoadException("Not a valid LGS file!", fileFullPath);
throw new FileLoadException("Not a valid LGS file!", FileFullPath);
}
//if (HeaderSettings.PrinterModel is 10 or 30 or 120)
@@ -594,54 +594,38 @@ namespace UVtools.Core.FileFormats
}
LayerManager.Init(HeaderSettings.LayerCount);
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
var layerData = new LayerDef[LayerCount];
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
foreach (var batch in BatchLayersIndexes())
if (DecodeType == FileDecodeType.Full)
{
foreach (var layerIndex in batch)
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
foreach (var batch in BatchLayersIndexes())
{
progress.Token.ThrowIfCancellationRequested();
layerData[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
layerData[layerIndex].Parent = this;
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = layerData[layerIndex].Decode())
foreach (var layerIndex in batch)
{
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.Token.ThrowIfCancellationRequested();
layerData[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
layerData[layerIndex].Parent = this;
}
progress.LockAndIncrement();
});
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using var mat = layerData[layerIndex].Decode();
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.LockAndIncrement();
});
}
}
LayerManager.RebuildLayersProperties();
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(0, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
+43 -57
View File
@@ -315,9 +315,9 @@ namespace UVtools.Core.FileFormats
#endregion
#region Methods
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
var pageBreak = PageBreak.Bytes;
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
@@ -425,9 +425,9 @@ namespace UVtools.Core.FileFormats
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
//HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header))));
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
@@ -450,76 +450,62 @@ namespace UVtools.Core.FileFormats
SlicerInfoSettings = Helpers.Deserialize<SlicerInfo>(inputFile);
LayerManager.Init(SlicerInfoSettings.LayerCount);
LayerManager.Init(SlicerInfoSettings.LayerCount, DecodeType == FileDecodeType.Partial);
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
var range = Enumerable.Range(0, (int)LayerCount);
var linesBytes = new byte[LayerCount][];
foreach (var batch in BatchLayersIndexes())
if (DecodeType == FileDecodeType.Full)
{
progress.Token.ThrowIfCancellationRequested();
foreach (var layerIndex in batch)
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
var linesBytes = new byte[LayerCount][];
foreach (var batch in BatchLayersIndexes())
{
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
linesBytes[layerIndex] = new byte[lineCount * 6];
inputFile.ReadBytes(linesBytes[layerIndex]);
inputFile.Seek(2, SeekOrigin.Current);
progress.Token.ThrowIfCancellationRequested();
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = EmguExtensions.InitMat(Resolution))
foreach (var layerIndex in batch)
{
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
{
var startY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
var endY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
var startX = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i]);
linesBytes[layerIndex] = new byte[lineCount * 6];
inputFile.ReadBytes(linesBytes[layerIndex]);
inputFile.Seek(2, SeekOrigin.Current);
CvInvoke.Line(mat, new Point(startX, startY), new Point(startX, endY), EmguExtensions.WhiteColor);
}
linesBytes[layerIndex] = null;
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.Token.ThrowIfCancellationRequested();
}
progress.LockAndIncrement();
});
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = EmguExtensions.InitMat(Resolution))
{
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
{
var startY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
var endY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
var startX = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i]);
CvInvoke.Line(mat, new Point(startX, startY), new Point(startX, endY), EmguExtensions.WhiteColor);
}
linesBytes[layerIndex] = null;
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
}
progress.LockAndIncrement();
});
}
}
else // Partial read
{
inputFile.Seek(-Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.End);
}
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
HeaderSettings.Validate();
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(SlicerInfoAddress, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, SlicerInfoSettings);
+30 -43
View File
@@ -465,9 +465,9 @@ namespace UVtools.Core.FileFormats
Previews = null;
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
FileSettings.Update();
var fileDefSize = Helpers.SerializeWriteFileStream(outputFile, FileSettings);
HeaderSettings.TableSize = (uint)Helpers.Serializer.SizeOf(HeaderSettings);
@@ -598,9 +598,9 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine("-End-");
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
FileSettings = Helpers.Deserialize<FileDef>(inputFile);
Debug.Write("File -> ");
Debug.WriteLine(FileSettings);
@@ -646,7 +646,7 @@ namespace UVtools.Core.FileFormats
inputFile.Seek(HeaderSettings.LayerDefinitionsAddress, SeekOrigin.Begin);
LayerManager.Init(HeaderSettings.LayerCount);
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
var layerDef = new LayerDef[LayerCount];
@@ -672,34 +672,37 @@ namespace UVtools.Core.FileFormats
}
progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount);
foreach (var batch in BatchLayersIndexes())
if (DecodeType == FileDecodeType.Full)
{
var layerBytes = new byte[LayerCount][];
foreach (var layerIndex in batch)
progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount);
foreach (var batch in BatchLayersIndexes())
{
progress.Token.ThrowIfCancellationRequested();
var layerBytes = new byte[LayerCount][];
inputFile.Seek(layerDataAddresses[layerIndex], SeekOrigin.Begin);
layerBytes[layerIndex] = inputFile.ReadBytes(inputFile.ReadUIntLittleEndian());
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = DecodeImage(HeaderSettings.LayerDataType, layerBytes[layerIndex], Resolution))
foreach (var layerIndex in batch)
{
layerBytes[layerIndex] = null; // Clean
progress.Token.ThrowIfCancellationRequested();
var layer = new Layer((uint)layerIndex, mat, this);
layerDef[layerIndex].CopyTo(layer);
this[layerIndex] = layer;
inputFile.Seek(layerDataAddresses[layerIndex], SeekOrigin.Begin);
layerBytes[layerIndex] = inputFile.ReadBytes(inputFile.ReadUIntLittleEndian());
}
progress.LockAndIncrement();
});
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using var mat = DecodeImage(HeaderSettings.LayerDataType, layerBytes[layerIndex], Resolution);
layerBytes[layerIndex] = null; // Clean
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.LockAndIncrement();
});
}
}
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
layerDef[layerIndex].CopyTo(this[layerIndex]);
}
progress.Reset(OperationProgress.StatusDecodeGcode);
@@ -711,24 +714,8 @@ namespace UVtools.Core.FileFormats
UpdateGlobalPropertiesFromLayers();
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(0, SeekOrigin.Begin);
FileSettings.Update();
+24 -35
View File
@@ -927,7 +927,7 @@ namespace UVtools.Core.FileFormats
LayersDefinitions = null;
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
/*if (HeaderSettings.EncryptionKey == 0)
{
@@ -936,7 +936,7 @@ namespace UVtools.Core.FileFormats
}*/
LayersDefinitions = new LayerDef[HeaderSettings.LayerCount];
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
outputFile.Seek(Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.Begin);
for (byte i = 0; i < ThumbnailsCount; i++)
@@ -1046,15 +1046,15 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine("-End-");
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
//HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header))));
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
if (HeaderSettings.Magic != MAGIC_PHZ)
{
throw new FileLoadException("Not a valid PHZ file!", fileFullPath);
throw new FileLoadException("Not a valid PHZ file!", FileFullPath);
}
HeaderSettings.AntiAliasLevel = 1;
@@ -1093,7 +1093,7 @@ namespace UVtools.Core.FileFormats
}
LayerManager.Init(HeaderSettings.LayerCount);
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
LayersDefinitions = new LayerDef[HeaderSettings.LayerCount];
progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount);
@@ -1110,45 +1110,34 @@ namespace UVtools.Core.FileFormats
Debug.Write($"LAYER {layerIndex} -> ");
Debug.WriteLine(layerDef);
inputFile.SeekDoWorkAndRewind(layerDef.DataAddress, () =>
if (DecodeType == FileDecodeType.Full)
{
layerDef.EncodedRle = inputFile.ReadBytes(layerDef.DataSize);
});
inputFile.SeekDoWorkAndRewind(layerDef.DataAddress,
() => { layerDef.EncodedRle = inputFile.ReadBytes(layerDef.DataSize); });
}
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
if (DecodeType == FileDecodeType.Full)
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex))
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
var layer = new Layer((uint)layerIndex, mat, this);
LayersDefinitions[layerIndex].CopyTo(layer);
this[layerIndex] = layer;
}
if (progress.Token.IsCancellationRequested) return;
progress.LockAndIncrement();
});
using var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex);
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.LockAndIncrement();
});
}
}
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
LayersDefinitions[layerIndex].CopyTo(this[layerIndex]);
}
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(0, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
+16 -32
View File
@@ -434,10 +434,10 @@ namespace UVtools.Core.FileFormats
#region Methods
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
//throw new NotSupportedException("PhotonS is read-only format, please use pws instead!");
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
outputFile.WriteSerialize(HeaderSettings);
outputFile.WriteBytes(EncodeImage(DATATYPE_BGR565, Thumbnails[0]));
outputFile.WriteSerialize(LayerSettings);
@@ -474,13 +474,13 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine("-End-");
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
if (HeaderSettings.Tag1 != Header.TAG1 || HeaderSettings.Tag2 != Header.TAG2)
{
throw new FileLoadException("Not a valid PHOTONS file! TAGs doesn't match", fileFullPath);
throw new FileLoadException("Not a valid PHOTONS file! TAGs doesn't match", FileFullPath);
}
int previewSize = (int) (HeaderSettings.PreviewResolutionX * HeaderSettings.PreviewResolutionY * 2);
@@ -495,7 +495,7 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine(LayerSettings);
LayerManager.Init(LayerSettings.LayerCount);
LayerManager.Init(LayerSettings.LayerCount, DecodeType == FileDecodeType.Partial);
var layersDefinitions = new LayerDef[LayerSettings.LayerCount];
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
@@ -508,7 +508,8 @@ namespace UVtools.Core.FileFormats
var layerDef = Helpers.Deserialize<LayerDef>(inputFile);
layersDefinitions[layerIndex] = layerDef;
layerDef.EncodedRle = inputFile.ReadBytes(layerDef.RleDataSize);
if (DecodeType == FileDecodeType.Full) layerDef.EncodedRle = inputFile.ReadBytes(layerDef.RleDataSize);
else inputFile.Seek(layerDef.RleDataSize, SeekOrigin.Current);
Debug.Write($"LAYER {layerIndex} -> ");
Debug.WriteLine(layerDef);
@@ -521,40 +522,23 @@ namespace UVtools.Core.FileFormats
}
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
if (DecodeType == FileDecodeType.Full)
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = layersDefinitions[layerIndex].Decode())
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using var mat = layersDefinitions[layerIndex].Decode();
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
}
progress.LockAndIncrement();
});
progress.LockAndIncrement();
});
}
}
LayerManager.RebuildLayersProperties();
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(0, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
+29 -41
View File
@@ -1256,7 +1256,7 @@ namespace UVtools.Core.FileFormats
LayersDefinition = null;
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
HeaderSettings.PixelSizeUm = PixelSizeMicronsMax;
@@ -1277,7 +1277,7 @@ namespace UVtools.Core.FileFormats
FileMarkSettings.HeaderAddress = (uint) Helpers.Serializer.SizeOf(FileMarkSettings);
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
outputFile.Seek((int)FileMarkSettings.HeaderAddress, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
@@ -1348,9 +1348,9 @@ namespace UVtools.Core.FileFormats
Helpers.SerializeWriteFileStream(outputFile, FileMarkSettings);
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
FileMarkSettings = Helpers.Deserialize<FileMark>(inputFile);
Debug.Write("FileMark -> ");
@@ -1359,17 +1359,14 @@ namespace UVtools.Core.FileFormats
if (!FileMarkSettings.Mark.Equals(FileMark.SectionMarkFile))
{
throw new FileLoadException(
$"Invalid Filemark {FileMarkSettings.Mark}, expected {FileMark.SectionMarkFile}", fileFullPath);
$"Invalid Filemark {FileMarkSettings.Mark}, expected {FileMark.SectionMarkFile}", FileFullPath);
}
if (FileMarkSettings.Version is not VERSION_1 and not VERSION_515)
{
throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expected {VERSION_1} or {VERSION_515}",
fileFullPath);
throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expected {VERSION_1} or {VERSION_515}", FileFullPath);
}
FileFullPath = fileFullPath;
inputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin);
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
@@ -1402,7 +1399,7 @@ namespace UVtools.Core.FileFormats
Debug.Write("LayersDefinition -> ");
Debug.WriteLine(LayersDefinition);
LayerManager.Init(LayersDefinition.LayerCount);
LayerManager.Init(LayersDefinition.LayerCount, DecodeType == FileDecodeType.Partial);
LayersDefinition.Layers = new LayerDef[LayerCount];
LayersDefinition.Validate();
@@ -1418,52 +1415,43 @@ namespace UVtools.Core.FileFormats
LayersDefinition[layerIndex].Parent = this;
Debug.WriteLine($"Layer {layerIndex}: {LayersDefinition[layerIndex]}");
inputFile.SeekDoWorkAndRewind(LayersDefinition[layerIndex].DataAddress, () =>
if (DecodeType == FileDecodeType.Full)
{
LayersDefinition[layerIndex].EncodedRle = inputFile.ReadBytes(LayersDefinition[layerIndex].DataLength);
});
inputFile.SeekDoWorkAndRewind(LayersDefinition[layerIndex].DataAddress,
() =>
{
LayersDefinition[layerIndex].EncodedRle = inputFile.ReadBytes(LayersDefinition[layerIndex].DataLength);
});
}
}
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
if (DecodeType == FileDecodeType.Full)
{
if (progress.Token.IsCancellationRequested) return;
using (var mat = LayersDefinition[layerIndex].Decode())
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
{
var layer = new Layer((uint)layerIndex, mat, this)
if (progress.Token.IsCancellationRequested) return;
using var mat = LayersDefinition[layerIndex].Decode();
this[layerIndex] = new Layer((uint)layerIndex, mat, this)
{
PositionZ = LayersDefinition.Layers
.Where((_, i) => i <= layerIndex)
.Sum(def => def.LayerHeight),
};
LayersDefinition[layerIndex].CopyTo(layer);
this[layerIndex] = layer;
}
progress.LockAndIncrement();
});
progress.LockAndIncrement();
});
}
}
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
LayersDefinition[layerIndex].CopyTo(this[layerIndex]);
}
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
HeaderSettings.PerLayerOverride = LayerManager.AllLayersAreUsingGlobalParameters ? 0 : 1u;
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
+18 -32
View File
@@ -533,13 +533,13 @@ namespace UVtools.Core.FileFormats
Statistics.Clear();
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
var filename = fileFullPath;
var filename = FileFullPath;
if (filename.EndsWith(TemporaryFileAppend)) filename = Path.GetFileNameWithoutExtension(filename); // tmp
filename = Path.GetFileNameWithoutExtension(filename); // sl1
OutputConfigSettings.JobDir = filename;
using ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
using ZipArchive outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
var entry = outputFile.CreateEntry("config.ini");
using (TextWriter tw = new StreamWriter(entry.Open()))
{
@@ -596,7 +596,7 @@ namespace UVtools.Core.FileFormats
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
PrinterSettings = new Printer();
MaterialSettings = new Material();
@@ -605,7 +605,7 @@ namespace UVtools.Core.FileFormats
Statistics.ExecutionTime.Restart();
using (var inputFile = ZipFile.OpenRead(fileFullPath))
using (var inputFile = ZipFile.OpenRead(FileFullPath))
{
List<string> iniFiles = new();
foreach (ZipArchiveEntry entity in inputFile.Entries)
@@ -689,7 +689,7 @@ namespace UVtools.Core.FileFormats
LightPWM = LookupCustomValue(Keyword_LightPWM, DefaultBottomLightPWM);
});
LayerManager.Init(OutputConfigSettings.NumSlow + OutputConfigSettings.NumFast);
LayerManager.Init(OutputConfigSettings.NumSlow + OutputConfigSettings.NumFast, DecodeType == FileDecodeType.Partial);
progress.ItemCount = LayerCount;
@@ -698,7 +698,7 @@ namespace UVtools.Core.FileFormats
if (!entity.Name.EndsWith(".png")) continue;
if (entity.Name.StartsWith("thumbnail"))
{
using Stream stream = entity.Open();
using var stream = entity.Open();
Mat image = new();
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
byte thumbnailIndex =
@@ -707,17 +707,21 @@ namespace UVtools.Core.FileFormats
? FileThumbnailSize.Small
: FileThumbnailSize.Large);
Thumbnails[thumbnailIndex] = image;
stream.Close();
//thumbnailIndex++;
continue;
}
// - .png - 5 numbers
string layerStr = entity.Name.Substring(entity.Name.Length - 4 - 5, 5);
uint iLayer = uint.Parse(layerStr);
this[iLayer] = new Layer(iLayer, entity.Open(), LayerManager);
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, LayerManager);
}
progress.ProcessedItems++;
}
}
@@ -729,26 +733,8 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine(Statistics);
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
//InputFile.CreateEntry("Modified");
using (TextWriter tw = new StreamWriter(outputFile.PutFileContent("config.ini", string.Empty, ZipArchiveMode.Update).Open()))
+13 -29
View File
@@ -467,7 +467,7 @@ namespace UVtools.Core.FileFormats
JsonSettings.Layers = new List<LayerDef>();
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
// Redo layer data
if (JsonSettings.Layers is null)
@@ -484,7 +484,7 @@ namespace UVtools.Core.FileFormats
JsonSettings.Layers.Add(new LayerDef(this[layerIndex]));
}
using var outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
outputFile.PutFileContent(FileConfigName, JsonConvert.SerializeObject(JsonSettings, Formatting.Indented), ZipArchiveMode.Create);
if (CreatedThumbnailsCount > 0)
@@ -514,20 +514,20 @@ namespace UVtools.Core.FileFormats
}
}
protected override void DecodeInternally(string fileFullPath, 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)
{
Clear();
throw new FileLoadException($"{FileConfigName} not found", fileFullPath);
throw new FileLoadException($"{FileConfigName} not found", FileFullPath);
}
JsonSettings = Helpers.JsonDeserializeObject<Settings>(entry.Open());
LayerManager.Init(JsonSettings.Properties.Size.Layers);
LayerManager.Init(JsonSettings.Properties.Size.Layers, DecodeType == FileDecodeType.Partial);
entry = inputFile.GetEntry(FilePreviewTinyName);
if (entry is not null)
@@ -554,15 +554,16 @@ namespace UVtools.Core.FileFormats
entry = inputFile.GetEntry($"{FolderImageName}/{layerIndex:D8}.png");
if (entry is null) continue;
using var stream = entry.Open();
var layer = new Layer(layerIndex, stream, LayerManager);
if (DecodeType == FileDecodeType.Full)
{
using var stream = entry.Open();
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
}
if (JsonSettings.Layers?.Count > layerIndex)
{
JsonSettings.Layers[(int)layerIndex].CopyTo(layer);
JsonSettings.Layers[(int)layerIndex].CopyTo(this[layerIndex]);
}
this[layerIndex] = layer;
}
progress.ProcessedItems++;
@@ -571,25 +572,8 @@ namespace UVtools.Core.FileFormats
LayerManager.GetBoundingRectangle(progress);
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
if (JsonSettings.Layers is null)
{
JsonSettings.Layers = new List<LayerDef>();
+14 -27
View File
@@ -302,10 +302,10 @@ namespace UVtools.Core.FileFormats
return false;
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
using var outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
var manifestFilename = Path.GetFileName(fileFullPath).
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
var manifestFilename = Filename.
Replace($".{FileExtensions[0].Extension}{TemporaryFileAppend}", ".xml").
Replace($".{FileExtensions[0].Extension}", ".xml");
@@ -328,7 +328,7 @@ namespace UVtools.Core.FileFormats
serializer.Serialize(stream, ManifestFile, ns);
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
{
@@ -336,7 +336,7 @@ namespace UVtools.Core.FileFormats
if (entry is null)
{
Clear();
throw new FileLoadException($".xml manifest not found", fileFullPath);
throw new FileLoadException($".xml manifest not found", FileFullPath);
}
try
@@ -348,11 +348,11 @@ namespace UVtools.Core.FileFormats
catch (Exception e)
{
Clear();
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
}
LayerManager.Init(ManifestFile.Slices.LayerCount);
LayerManager.Init(ManifestFile.Slices.LayerCount, DecodeType == FileDecodeType.Partial);
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
@@ -364,11 +364,14 @@ namespace UVtools.Core.FileFormats
if (entry is null)
{
Clear();
throw new FileLoadException($"Layer {filename} not found", fileFullPath);
throw new FileLoadException($"Layer {filename} not found", FileFullPath);
}
using var stream = entry.Open();
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
if (DecodeType == FileDecodeType.Full)
{
using var stream = entry.Open();
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
}
progress++;
}
@@ -377,24 +380,8 @@ namespace UVtools.Core.FileFormats
LayerManager.GetBoundingRectangle(progress);
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
bool deleted;
+50 -41
View File
@@ -149,6 +149,42 @@ namespace UVtools.Core.FileFormats
[JsonProperty("retract_distance2")] public float RetractHeight2 { get; set; } = DefaultRetractHeight2;
[JsonProperty("retract_speed2")] public float RetractSpeed2 { get; set; } = DefaultRetractSpeed2;
[JsonProperty("light_pwm")] public byte LightPWM { get; set; } = DefaultLightPWM;
public void SetFrom(Layer layer)
{
PositionZ = layer.PositionZ;
LightOffDelay = layer.LightOffDelay;
WaitTimeBeforeCure = layer.WaitTimeBeforeCure;
ExposureTime = layer.ExposureTime;
WaitTimeAfterCure = layer.WaitTimeAfterCure;
LiftHeight = layer.LiftHeight;
LiftSpeed = layer.LiftSpeed;
LiftHeight2 = layer.LiftHeight2;
LiftSpeed2 = layer.LiftSpeed2;
WaitTimeAfterLift = layer.WaitTimeAfterLift;
RetractSpeed = layer.RetractSpeed;
RetractHeight2 = layer.RetractHeight2;
RetractSpeed2 = layer.RetractSpeed2;
LightPWM = layer.LightPWM;
}
public void CopyTo(Layer layer)
{
layer.PositionZ = PositionZ;
layer.LightOffDelay = LightOffDelay;
layer.WaitTimeBeforeCure = WaitTimeBeforeCure;
layer.ExposureTime = ExposureTime;
layer.WaitTimeAfterCure = WaitTimeAfterCure;
layer.LiftHeight = LiftHeight;
layer.LiftSpeed = LiftSpeed;
layer.LiftHeight2 = LiftHeight2;
layer.LiftSpeed2 = LiftSpeed2;
layer.WaitTimeAfterLift = WaitTimeAfterLift;
layer.RetractSpeed = RetractSpeed;
layer.RetractHeight2 = RetractHeight2;
layer.RetractSpeed2 = RetractSpeed2;
layer.LightPWM = LightPWM;
}
}
#endregion
@@ -566,12 +602,12 @@ namespace UVtools.Core.FileFormats
}
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
// Redo layer data
RebuildVDTLayers();
using var outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
outputFile.PutFileContent(FileManifestName, JsonConvert.SerializeObject(ManifestFile, Formatting.Indented), ZipArchiveMode.Create);
if (CreatedThumbnailsCount > 0)
@@ -598,20 +634,20 @@ namespace UVtools.Core.FileFormats
}
}
protected override void DecodeInternally(string fileFullPath, 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)
{
Clear();
throw new FileLoadException($"{FileManifestName} not found", fileFullPath);
throw new FileLoadException($"{FileManifestName} not found", FileFullPath);
}
ManifestFile = Helpers.JsonDeserializeObject<VDTManifest>(entry.Open());
LayerManager.Init((uint) ManifestFile.Layers.Length);
LayerManager.Init((uint) ManifestFile.Layers.Length, DecodeType == FileDecodeType.Partial);
for (int i = 0; i < FilePreviewNames.Length; i++)
{
@@ -631,24 +667,14 @@ namespace UVtools.Core.FileFormats
var manifestLayer = ManifestFile.Layers[layerIndex];
entry = inputFile.GetEntry($"{layerIndex}.png");
if (entry is null) continue;
using var stream = entry.Open();
this[layerIndex] = new Layer(layerIndex, stream, LayerManager)
if (DecodeType == FileDecodeType.Full)
{
PositionZ = manifestLayer.PositionZ,
LightOffDelay = manifestLayer.LightOffDelay,
WaitTimeBeforeCure = manifestLayer.WaitTimeBeforeCure,
ExposureTime = manifestLayer.ExposureTime,
WaitTimeAfterCure = manifestLayer.WaitTimeAfterCure,
LiftHeight = manifestLayer.LiftHeight,
LiftSpeed = manifestLayer.LiftSpeed,
LiftHeight2 = manifestLayer.LiftHeight2,
LiftSpeed2 = manifestLayer.LiftSpeed2,
WaitTimeAfterLift = manifestLayer.WaitTimeAfterLift,
RetractSpeed = manifestLayer.RetractSpeed,
RetractHeight2 = manifestLayer.RetractHeight2,
RetractSpeed2 = manifestLayer.RetractSpeed2,
LightPWM = manifestLayer.LightPWM,
};
using var stream = entry.Open();
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
}
manifestLayer.CopyTo(this[layerIndex]);
}
progress.ProcessedItems++;
@@ -657,25 +683,8 @@ namespace UVtools.Core.FileFormats
LayerManager.GetBoundingRectangle(progress);
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
RebuildVDTLayers();
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
outputFile.PutFileContent(FileManifestName, JsonConvert.SerializeObject(ManifestFile, Formatting.Indented), ZipArchiveMode.Update);
+15 -28
View File
@@ -467,9 +467,9 @@ namespace UVtools.Core.FileFormats
#region Methods
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
using ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
if (Thumbnails.Length > 0 && Thumbnails[0] is not null)
{
using var thumbnailsStream = outputFile.CreateEntry(PreviewFilename).Open();
@@ -497,14 +497,14 @@ namespace UVtools.Core.FileFormats
outputFile.PutFileContent(GCodeFilename, EncryptGCode(progress), ZipArchiveMode.Create);
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read);
var entry = inputFile.GetEntry(ManifestFilename);
if (entry is null)
{
Clear();
throw new FileLoadException($"{ManifestFilename} not found", fileFullPath);
throw new FileLoadException($"{ManifestFilename} not found", FileFullPath);
}
try
@@ -516,14 +516,14 @@ namespace UVtools.Core.FileFormats
catch (Exception e)
{
Clear();
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
}
entry = inputFile.GetEntry(GCodeFilename);
if (entry is null)
{
Clear();
throw new FileLoadException($"{GCodeFilename} not found", fileFullPath);
throw new FileLoadException($"{GCodeFilename} not found", FileFullPath);
}
var encryptEngine = new RsaEngine();
@@ -551,7 +551,7 @@ namespace UVtools.Core.FileFormats
tr.Close();
}
LayerManager.Init(ManifestFile.Job.LayerCount);
LayerManager.Init(ManifestFile.Job.LayerCount, DecodeType == FileDecodeType.Partial);
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
//var gcode = GCode.ToString();
@@ -564,12 +564,15 @@ namespace UVtools.Core.FileFormats
if (entry is null)
{
Clear();
throw new FileLoadException($"Layer {layerIndex+1} not found", fileFullPath);
throw new FileLoadException($"Layer {layerIndex+1} not found", FileFullPath);
}
using var stream = entry.Open();
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
if (DecodeType == FileDecodeType.Full)
{
using var stream = entry.Open();
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
}
progress++;
}
@@ -585,24 +588,8 @@ namespace UVtools.Core.FileFormats
LayerManager.GetBoundingRectangle(progress);
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
var entriesToRemove = outputFile.Entries.Where(zipEntry => zipEntry.Name.EndsWith(".gcode") || zipEntry.Name.EndsWith(".xml")).ToArray();
+78 -99
View File
@@ -374,7 +374,7 @@ namespace UVtools.Core.FileFormats
LayersSettings.Clear();
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
protected override void EncodeInternally(OperationProgress progress)
{
float usedMaterial = MaterialMilliliters / LayerCount;
ResinMetadataSettings.Layers.Clear();
@@ -387,87 +387,83 @@ namespace UVtools.Core.FileFormats
});
}
using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create))
{
outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings, Formatting.Indented), ZipArchiveMode.Create);
outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings, Formatting.Indented), ZipArchiveMode.Create);
outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings, Formatting.Indented), ZipArchiveMode.Create);
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings, Formatting.Indented), ZipArchiveMode.Create);
outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings, Formatting.Indented), ZipArchiveMode.Create);
outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings, Formatting.Indented), ZipArchiveMode.Create);
if (CreatedThumbnailsCount > 0)
if (CreatedThumbnailsCount > 0)
{
using var stream = outputFile.CreateEntry("Preview.png").Open();
stream.WriteBytes(Thumbnails[0].GetPngByes());
stream.Close();
}
GCode.Clear();
float lastZPosition = 0;
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
progress.Token.ThrowIfCancellationRequested();
var layer = this[layerIndex];
GCode.AppendLine($"{GCodeKeywordSlice} {layerIndex}");
if (lastZPosition != layer.PositionZ)
{
using (var stream = outputFile.CreateEntry("Preview.png").Open())
if (layer.LiftHeight > 0)
{
stream.WriteBytes(Thumbnails[0].GetPngByes());
stream.Close();
GCode.AppendLine($"G1 Z{layer.LiftHeight} F{layer.LiftSpeed}");
GCode.AppendLine($"G1 Z-{Layer.RoundHeight(layer.LiftHeight - layer.PositionZ + lastZPosition)} F{layer.RetractSpeed}");
}
else
{
GCode.AppendLine($"G1 Z{Layer.RoundHeight(layer.PositionZ- lastZPosition)} F{layer.LiftSpeed}");
}
}
GCode.Clear();
float lastZPosition = 0;
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
progress.Token.ThrowIfCancellationRequested();
Layer layer = this[layerIndex];
GCode.AppendLine($"{GCodeKeywordSlice} {layerIndex}");
if (lastZPosition != layer.PositionZ)
{
if (layer.LiftHeight > 0)
{
GCode.AppendLine($"G1 Z{layer.LiftHeight} F{layer.LiftSpeed}");
GCode.AppendLine($"G1 Z-{Layer.RoundHeight(layer.LiftHeight - layer.PositionZ + lastZPosition)} F{layer.RetractSpeed}");
}
else
{
GCode.AppendLine($"G1 Z{Layer.RoundHeight(layer.PositionZ- lastZPosition)} F{layer.LiftSpeed}");
}
}
/*else
/*else
{
//GCode.AppendLine($";G1 Z{LiftHeight} F{LiftSpeed}; Already here");
//GCode.AppendLine($";G1 Z-{LiftHeight - layer.PositionZ + lastZPosition} F{RetractSpeed}; Already here");
}*/
//GCode.AppendLine($"G1 Z{LiftHeight} F{LiftSpeed}");
//GCode.AppendLine($"G1 Z-{LiftHeight - LayerHeight} F{RetractSpeed}");
GCode.AppendLine(GCodeKeywordDelayBlank);
GCode.AppendLine("M106 S255");
GCode.AppendLine(GCodeKeywordDelayModel);
GCode.AppendLine("M106 S0");
//GCode.AppendLine($"G1 Z{LiftHeight} F{LiftSpeed}");
//GCode.AppendLine($"G1 Z-{LiftHeight - LayerHeight} F{RetractSpeed}");
GCode.AppendLine(GCodeKeywordDelayBlank);
GCode.AppendLine("M106 S255");
GCode.AppendLine(GCodeKeywordDelayModel);
GCode.AppendLine("M106 S0");
var layerimagePath = $"{FolderImages}/{FolderImageName}{layerIndex:D5}.png";
using (Stream 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;
progress++;
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();
}
GCode.AppendLine($"G1 Z40.0 F{UserSettings.ZLiftFeedRate}");
GCode.AppendLine("M18");
lastZPosition = layer.PositionZ;
outputFile.PutFileContent("ResinGCodeData", GCode.ToString(), ZipArchiveMode.Create);
progress++;
}
GCode.AppendLine($"G1 Z40.0 F{UserSettings.ZLiftFeedRate}");
GCode.AppendLine("M18");
outputFile.PutFileContent("ResinGCodeData", GCode.ToString(), ZipArchiveMode.Create);
}
protected override void DecodeInternally(string fileFullPath, 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("ResinMetadata");
if (entry is null)
{
Clear();
throw new FileLoadException("ResinMetadata not found", fileFullPath);
throw new FileLoadException("ResinMetadata not found", FileFullPath);
}
ResinMetadataSettings = Helpers.JsonDeserializeObject<ResinMetadata>(entry.Open());
@@ -476,7 +472,7 @@ namespace UVtools.Core.FileFormats
if (entry is null)
{
Clear();
throw new FileLoadException("UserSettingsData not found", fileFullPath);
throw new FileLoadException("UserSettingsData not found", FileFullPath);
}
UserSettings = Helpers.JsonDeserializeObject<UserSettingsdata>(entry.Open());
@@ -485,7 +481,7 @@ namespace UVtools.Core.FileFormats
if (entry is null)
{
Clear();
throw new FileLoadException("ZCodeMetadata not found", fileFullPath);
throw new FileLoadException("ZCodeMetadata not found", FileFullPath);
}
ZCodeMetadataSettings = Helpers.JsonDeserializeObject<ZCodeMetadata>(entry.Open());
@@ -494,10 +490,10 @@ namespace UVtools.Core.FileFormats
if (entry is null)
{
Clear();
throw new FileLoadException("ResinGCodeData not found", fileFullPath);
throw new FileLoadException("ResinGCodeData not found", FileFullPath);
}
LayerManager.Init(ResinMetadataSettings.TotalLayersCount);
LayerManager.Init(ResinMetadataSettings.TotalLayersCount, DecodeType == FileDecodeType.Partial);
GCode.Clear();
using (TextReader tr = new StreamReader(entry.Open()))
{
@@ -577,14 +573,18 @@ M106 S0
LayersSettings[layerIndex].LayerFileIndex = layerFileIndex;
LayersSettings[layerIndex].LayerEntry = inputFile.GetEntry(layerimagePath);
this[layerIndex] = new Layer((uint) layerIndex, LayersSettings[layerIndex].LayerEntry.Open(), LayerManager)
if (DecodeType == FileDecodeType.Full)
{
PositionZ = currentHeight,
LiftHeight = liftHeight,
LiftSpeed = liftSpeed,
RetractSpeed = retractSpeed,
LightPWM = pwm
};
using var stream = LayersSettings[layerIndex].LayerEntry.Open();
this[layerIndex] = new Layer((uint)layerIndex, stream, LayerManager);
}
this[layerIndex].PositionZ = currentHeight;
this[layerIndex].LiftHeight = liftHeight;
this[layerIndex].LiftSpeed = liftSpeed;
this[layerIndex].RetractSpeed = retractSpeed;
this[layerIndex].LightPWM = pwm;
layerIndex++;
progress++;
@@ -595,9 +595,9 @@ M106 S0
}
entry = inputFile.GetEntry("Preview.png");
if (!ReferenceEquals(entry, null))
if (entry is not null)
{
using Stream stream = entry.Open();
using var stream = entry.Open();
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
stream.Close();
}
@@ -622,36 +622,15 @@ M106 S0
RaisePropertyChanged(nameof(GCodeStr));
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
protected override void PartialSaveInternally(OperationProgress progress)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using (var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update))
{
outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings, Formatting.Indented), ZipArchiveMode.Update);
outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings, Formatting.Indented), ZipArchiveMode.Update);
outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings, Formatting.Indented), ZipArchiveMode.Update);
outputFile.PutFileContent("ResinGCodeData", GCodeStr, ZipArchiveMode.Update);
}
//Decode(FileFullPath, progress);
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings, Formatting.Indented), ZipArchiveMode.Update);
outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings, Formatting.Indented), ZipArchiveMode.Update);
outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings, Formatting.Indented), ZipArchiveMode.Update);
outputFile.PutFileContent("ResinGCodeData", GCodeStr, ZipArchiveMode.Update);
}
#endregion
#endregion
}
}
+7 -4
View File
@@ -479,6 +479,7 @@ namespace UVtools.Core.Layers
{
get
{
if (!HaveImage) return null;
Mat mat = new();
CvInvoke.Imdecode(_compressedBytes, ImreadModes.Grayscale, mat);
return mat;
@@ -604,6 +605,8 @@ namespace UVtools.Core.Layers
_lightPWM = SlicerFile.GetBottomOrNormalValue(this, SlicerFile.BottomLightPWM, SlicerFile.LightPWM);
}
public Layer(uint index, FileFormat slicerFile) : this(index, slicerFile.LayerManager) {}
public Layer(uint index, byte[] compressedBytes, LayerManager parentLayerManager) : this(index, parentLayerManager)
{
CompressedBytes = compressedBytes;
@@ -625,8 +628,8 @@ namespace UVtools.Core.Layers
public Layer(uint index, Mat layerMat, FileFormat slicerFile) : this(index, layerMat, slicerFile.LayerManager) { }
public Layer(uint index, Stream stream, LayerManager parentLayerManager) : this(index, stream.ToArray(), parentLayerManager) { }
public Layer(uint index, Stream stream, FileFormat slicerFile) : this(index, stream.ToArray(), slicerFile.LayerManager) { }
public Layer(uint index, Stream stream, LayerManager parentLayerManager) : this(index, stream?.ToArray(), parentLayerManager) { }
public Layer(uint index, Stream stream, FileFormat slicerFile) : this(index, stream?.ToArray(), slicerFile.LayerManager) { }
#endregion
#region Equatables
@@ -671,7 +674,7 @@ namespace UVtools.Core.Layers
if (other is null) return false;
if (ReferenceEquals(this, other)) return true;
if (_index != other._index) return false;
if (_compressedBytes.Length != other._compressedBytes.Length) return false;
if (_compressedBytes?.Length != other._compressedBytes?.Length) return false;
return _compressedBytes.AsSpan().SequenceEqual(other._compressedBytes.AsSpan());
//return Equals(_compressedBytes, other._compressedBytes);
}
@@ -1112,7 +1115,7 @@ namespace UVtools.Core.Layers
//layer.CompressedBytes = _compressedBytes.ToArray();
//Debug.WriteLine(ReferenceEquals(_compressedBytes, layer.CompressedBytes));
//return layer;
return new (_index, CompressedBytes.ToArray(), ParentLayerManager)
return new (_index, CompressedBytes?.ToArray(), ParentLayerManager)
{
_positionZ = _positionZ,
_lightOffDelay = _lightOffDelay,
+11 -5
View File
@@ -176,9 +176,14 @@ namespace UVtools.Core
}
}
public void Init(uint layerCount)
public void Init(uint layerCount, bool initializeLayers = false)
{
_layers = new Layer[layerCount];
if (!initializeLayers) return;
for (uint layerIndex = 0; layerIndex < layerCount; layerIndex++)
{
this[layerIndex] = new Layer(layerIndex, this);
}
}
public void Init(Layer[] layers)
@@ -672,9 +677,10 @@ namespace UVtools.Core
public Rectangle GetBoundingRectangle(OperationProgress progress = null)
{
if (!_boundingRectangle.IsEmpty || LayerCount == 0 || this[0] is null) return _boundingRectangle;
var firstLayer = FirstLayer;
if (!_boundingRectangle.IsEmpty || LayerCount == 0 || firstLayer is null || !firstLayer.HaveImage) return _boundingRectangle;
progress ??= new OperationProgress(OperationProgress.StatusOptimizingBounds, LayerCount - 1);
_boundingRectangle = this[0].BoundingRectangle;
_boundingRectangle = firstLayer.BoundingRectangle;
if (_boundingRectangle.IsEmpty) // Safe checking
{
progress.Reset(OperationProgress.StatusOptimizingBounds, LayerCount-1);
@@ -687,9 +693,9 @@ namespace UVtools.Core
if (progress is null) return;
progress.LockAndIncrement();
});
_boundingRectangle = this[0].BoundingRectangle;
_boundingRectangle = firstLayer.BoundingRectangle;
if (progress is not null && progress.Token.IsCancellationRequested)
if (progress.Token.IsCancellationRequested)
{
_boundingRectangle = Rectangle.Empty;
progress.Token.ThrowIfCancellationRequested();
+3 -3
View File
@@ -275,11 +275,11 @@ namespace UVtools.Core.Managers
/// <param name="slicerFile"></param>
public void Init(FileFormat slicerFile)
{
Clear();
SlicerFile = slicerFile;
if (slicerFile is null || slicerFile.DecodeType == FileFormat.FileDecodeType.Partial) return;
SuppressRestoreWork(() =>
{
Clear();
SlicerFile = slicerFile;
if (slicerFile is null) return;
var clip = new ClipboardItem(SlicerFile, "Original layers", true);
clip.AddRange(SlicerFile.LayerManager.CloneLayers());
Add(clip);
+2
View File
@@ -124,6 +124,8 @@ namespace UVtools.Core.Managers
bool emptyLayersConfig = true,
OperationProgress progress = null)
{
if (SlicerFile.DecodeType == FileFormat.FileDecodeType.Partial) return null;
islandConfig ??= new IslandDetectionConfiguration();
overhangConfig ??= new OverhangDetectionConfiguration();
resinTrapConfig ??= new ResinTrapDetectionConfiguration();
+6 -3
View File
@@ -7,15 +7,12 @@
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Emgu.CV;
using Emgu.CV.Cuda;
using Emgu.CV.Util;
using UVtools.Core.Extensions;
using UVtools.Core.FileFormats;
using UVtools.Core.Layers;
@@ -120,6 +117,11 @@ namespace UVtools.Core.Operations
/// </summary>
public virtual bool PassActualLayerIndex => false;
/// <summary>
/// Gets if this operation can run in a file open as partial mode
/// </summary>
public virtual bool CanRunInPartialMode => false;
/// <summary>
/// Gets if this operation can make use of ROI
/// </summary>
@@ -502,6 +504,7 @@ namespace UVtools.Core.Operations
public bool Execute(OperationProgress progress = null)
{
if (_slicerFile is null) throw new InvalidOperationException($"{Title} can't execute due the lacking of a file parent.");
if (_slicerFile.DecodeType == FileFormat.FileDecodeType.Partial && !CanRunInPartialMode) throw new InvalidOperationException($"The file was open in partial mode and the tool \"{Title}\" is unable to run in this mode.\nPlease reload the file in full mode in order to use this tool.");
if (!IsValidated)
{
var msg = Validate();
@@ -18,6 +18,9 @@ namespace UVtools.Core.Operations
public class OperationCalculator : Operation
{
#region Overrides
public override bool CanRunInPartialMode => true;
public override string Title => "Calculator";
public override string Description => null;
@@ -65,6 +65,8 @@ namespace UVtools.Core.Operations
#region Overrides
public override bool CanRunInPartialMode => true;
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.Normal;
public override string Title => "Dynamic lifts";
@@ -9,10 +9,8 @@
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using UVtools.Core.FileFormats;
using UVtools.Core.Objects;
namespace UVtools.Core.Operations
{
@@ -29,6 +27,8 @@ namespace UVtools.Core.Operations
#endregion
#region Overrides
public override bool CanRunInPartialMode => true;
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.None;
public override bool CanROI => false;
@@ -25,6 +25,7 @@ namespace UVtools.Core.Operations
#endregion
#region Overrides
public override bool CanRunInPartialMode => true;
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.Normal;
public override bool LayerIndexEndEnabled => false;
public override string Title => "Fade exposure time";
@@ -27,6 +27,8 @@ namespace UVtools.Core.Operations
#region Overrides
public override bool CanRunInPartialMode => true;
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.None;
public override bool CanROI => false;
@@ -29,6 +29,9 @@ namespace UVtools.Core.Operations
#endregion
#region Overrides
public override bool CanRunInPartialMode => true;
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.None;
public override string Title => "Raise platform on print finish";
@@ -30,6 +30,8 @@ namespace UVtools.Core.Operations
#region Overrides
public override bool CanRunInPartialMode => true;
public override bool CanHaveProfiles => false;
public override string Title => "Scripting";
@@ -0,0 +1,41 @@
/*
* GNU AFFERO GENERAL PUBLIC LICENSE
* Version 3, 19 November 2007
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
using System.Collections.Generic;
namespace UVtools.Core.Scripting
{
public abstract class ScriptFileDialogInput : ScriptBaseInput<string>
{
public class ScriptFileDialogFilter
{
public string Name { get; set; }
public List<string> Extensions { get; set; } = new();
}
/// <summary>
/// Gets or sets the title for the dialog
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets the default directory to open the dialog in
/// </summary>
public string Directory { get; set; }
/// <summary>
/// Gets or sets the initial filename to be on the dialog
/// </summary>
public string InitialFilename { get; set; }
/// <summary>
/// Gets or sets the file filters on the dropdown list
/// </summary>
public List<ScriptFileDialogFilter> Filters { get; set; }
}
}
@@ -0,0 +1,23 @@
/*
* GNU AFFERO GENERAL PUBLIC LICENSE
* Version 3, 19 November 2007
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
namespace UVtools.Core.Scripting
{
public class ScriptOpenFileDialogInput : ScriptFileDialogInput
{
/// <summary>
/// Gets or sets if allow multiple file selection
/// </summary>
public bool AllowMultiple { get; set; }
/// <summary>
/// Gets or sets the selected files
/// </summary>
public string[] Files {get; set; }
}
}
@@ -0,0 +1,18 @@
/*
* GNU AFFERO GENERAL PUBLIC LICENSE
* Version 3, 19 November 2007
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
namespace UVtools.Core.Scripting
{
public class ScriptOpenFolderDialogInput : ScriptBaseInput<string>
{
/// <summary>
/// Gets the title for the dialog
/// </summary>
public string Title { get; set; }
}
}
@@ -0,0 +1,18 @@
/*
* GNU AFFERO GENERAL PUBLIC LICENSE
* Version 3, 19 November 2007
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
namespace UVtools.Core.Scripting
{
public class ScriptSaveFileDialogInput : ScriptFileDialogInput
{
/// <summary>
/// Gets or sets the default extension for the dialog
/// </summary>
public string DefaultExtension { get; set; }
}
}
+1 -1
View File
@@ -10,7 +10,7 @@
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
<Version>2.24.4</Version>
<Version>2.25.0</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
+427
View File
@@ -0,0 +1,427 @@
/*
* GNU AFFERO GENERAL PUBLIC LICENSE
* Version 3, 19 November 2007
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
using System;
using UVtools.Core.Scripting;
using System.IO;
using System.Collections.Generic;
using UVtools.Core.FileFormats;
using System.Threading.Tasks;
using UVtools.Core;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
namespace UVtools.ScriptSample
{
/// <summary>
/// Performs a black inset around objects
/// </summary>
public class ScriptCloneSettings : ScriptGlobals
{
ScriptCheckBoxInput Recursive = new()
{
Label = "Recursive",
ToolTip = "If unchecked, only files in the same folder are modified; if checked, files in all sub-folders are modified too",
Value = true
};
ScriptCheckBoxInput Report = new()
{
Label = "Generate report file",
ToolTip = "Optionally generate a report file in the same directory as the open file",
Value = true
};
ScriptCheckBoxInput OpenReport = new()
{
Label = "Open report file",
ToolTip = "Optionally open the result file when completed",
Value = true
};
ScriptOpenFolderDialogInput FolderPath = new()
{
Label = "Folder path",
ToolTip = "The folder path to process",
};
private enum ResultStatus
{
Exception,
UnknownFileType,
DifferentMachineTypes,
Success,
Unchanged,
}
/// <summary>
/// Set configurations here, this function trigger just after load a script
/// </summary>
public void ScriptInit()
{
Script.Name = "Clone Settings";
Script.Description = "Copies the print settings from the current file to all files in the same directory and, optionally, recursively below it";
Script.Author = "Gina Venolia";
Script.Version = new Version(0, 2);
Script.UserInputs.Add(Recursive);
Script.UserInputs.Add(Report);
Script.UserInputs.Add(OpenReport);
Script.UserInputs.Add(FolderPath);
FolderPath.Value = SlicerFile.FileDirectoryPath;
}
/// <summary>
/// Validate user inputs here, this function trigger when user click on execute
/// </summary>
/// <returns>A error message, empty or null if validation passes.</returns>
public string ScriptValidate()
{
return null;
}
/// <summary>
/// Execute the script, this function trigger when when user click on execute and validation passes
/// </summary>
/// <returns>True if executes successfully to the end, otherwise false.</returns>
public bool ScriptExecute()
{
Progress.CanCancel = true;
// Gather the list of directories to operate on
Progress.Reset("Processing files...");
var directoryPaths = new List<string>();
directoryPaths.Add(Path.GetDirectoryName(SlicerFile.FileFullPath));
if (Recursive.Value)
{
for (var i = 0; i < directoryPaths.Count; i++)
{
directoryPaths.AddRange(Directory.EnumerateDirectories(directoryPaths[i]));
}
}
// Gather the list of files to operate on
var filePaths = new List<string>();
foreach (var directoryPath in directoryPaths)
{
filePaths.AddRange(Directory.EnumerateFiles(directoryPath));
}
// Except for the file we started with
var normalizedFilePath = Path.GetFullPath(SlicerFile.FileFullPath);
filePaths.RemoveAll(x => Path.GetFullPath(x) == normalizedFilePath);
// Process the files
Progress.Reset("Processing files...", (uint)filePaths.Count, 0);
var results = new List<Tuple<ResultStatus, string, List<string>>>();
foreach (var filePath in filePaths)
{
if (Progress.Token.IsCancellationRequested) return false;
Tuple<ResultStatus, string, List<string>> result;
try
{
result = ProcessFile(filePath);
}
catch (Exception ex)
{
var deets = new List<string>();
deets.Add(ex.GetType().Name);
deets.Add(ex.Message);
result = new Tuple<ResultStatus, string, List<string>>(ResultStatus.Exception, filePath, deets);
}
results.Add(result);
Progress++;
}
// Generate the report
if (Report.Value)
{
var reportDirectory = Path.GetDirectoryName(SlicerFile.FileFullPath);
var reportFilePath = Path.Combine(reportDirectory, "CloneSettingsReport.txt");
using (var writer = new StreamWriter(reportFilePath))
{
writer.WriteLine(Script.Name + " " + Script.Version.ToString() + " by " + Script.Author);
writer.WriteLine("Source file: " + SlicerFile.FileFullPath);
writer.WriteLine(DateTime.Now.ToLongDateString() + ", " + DateTime.Now.ToLongTimeString());
writer.WriteLine("Recursive: " + Recursive.Value.ToString());
writer.WriteLine("Directories: " + directoryPaths.Count);
writer.WriteLine("Files: " + filePaths.Count);
writer.WriteLine();
foreach (var statusGroup in results.GroupBy(x => x.Item1))
{
writer.WriteLine(statusGroup.Key.ToString());
foreach (var result in statusGroup.OrderBy(x => x.Item2))
{
writer.WriteLine("\t" + result.Item2);
if (result.Item3 is not null)
{
foreach (var detail in result.Item3)
{
writer.WriteLine("\t\t" + detail);
}
}
}
}
}
if (OpenReport.Value)
{
var startInfo = new ProcessStartInfo(reportFilePath)
{
UseShellExecute = true
};
Process.Start(startInfo);
}
}
// return true if not cancelled by user
return true;
}
private Tuple<ResultStatus, string, List<string>> ProcessFile(string filePath)
{
// Determine the type of file
var file = FileFormat.FindByExtensionOrFilePath(filePath, true);
if (file is null)
{
return new Tuple<ResultStatus, string, List<string>>(ResultStatus.UnknownFileType, filePath, null);
}
// Load the file
file.Decode(filePath);
if (string.Compare(file.MachineName, SlicerFile.MachineName, true) != 0)
{
var deets = new List<string>();
deets.Add("Source machine type: " + SlicerFile.MachineName);
deets.Add("Destination machine type: " + file.MachineName);
return new Tuple<ResultStatus, string, List<string>>(ResultStatus.DifferentMachineTypes, filePath, deets);
}
// TODO: Validate that some parameters are the same in both files?
// Change the parameters
var changed = false;
var details = new List<string>();
if (file.CanUseBottomLayerCount && file.BottomLayerCount != SlicerFile.BottomLayerCount)
{
details.Add($"Bottom Layer Count: {file.BottomLayerCount} to {SlicerFile.BottomLayerCount}");
file.BottomLayerCount = SlicerFile.BottomLayerCount;
changed = true;
}
if (file.CanUseBottomLightOffDelay && file.BottomLightOffDelay != SlicerFile.BottomLightOffDelay)
{
details.Add($"Bottom Light Off Delay: {file.BottomLightOffDelay} to {SlicerFile.BottomLightOffDelay}");
file.BottomLightOffDelay = SlicerFile.BottomLightOffDelay;
changed = true;
}
if (file.CanUseLightOffDelay && file.LightOffDelay != SlicerFile.LightOffDelay)
{
details.Add($"Light Off Delay: {file.LightOffDelay} to {SlicerFile.LightOffDelay}");
file.LightOffDelay = SlicerFile.LightOffDelay;
changed = true;
}
if (file.CanUseBottomWaitTimeBeforeCure && file.BottomWaitTimeBeforeCure != SlicerFile.BottomWaitTimeBeforeCure)
{
details.Add($"Bottom Wait Time Before Cure: {file.BottomWaitTimeBeforeCure} to {SlicerFile.BottomWaitTimeBeforeCure}");
file.BottomWaitTimeBeforeCure = SlicerFile.BottomWaitTimeBeforeCure;
changed = true;
}
if (file.CanUseWaitTimeBeforeCure && file.WaitTimeBeforeCure != SlicerFile.WaitTimeBeforeCure)
{
details.Add($"Wait Time Before Cure: {file.WaitTimeBeforeCure} to {SlicerFile.WaitTimeBeforeCure}");
file.WaitTimeBeforeCure = SlicerFile.WaitTimeBeforeCure;
changed = true;
}
if (file.CanUseBottomExposureTime && file.BottomExposureTime != SlicerFile.BottomExposureTime)
{
details.Add($"Bottom Exposure Time: {file.BottomExposureTime} to {SlicerFile.BottomExposureTime}");
file.BottomExposureTime = SlicerFile.BottomExposureTime;
changed = true;
}
if (file.CanUseExposureTime && file.ExposureTime != SlicerFile.ExposureTime)
{
details.Add($"Exposure Time: {file.ExposureTime} to {SlicerFile.ExposureTime}");
file.ExposureTime = SlicerFile.ExposureTime;
changed = true;
}
if (file.CanUseBottomWaitTimeAfterCure && file.BottomWaitTimeAfterCure != SlicerFile.BottomWaitTimeAfterCure)
{
details.Add($"Bottom Wait Time After Cure: {file.BottomWaitTimeAfterCure} to {SlicerFile.BottomWaitTimeAfterCure}");
file.BottomWaitTimeAfterCure = SlicerFile.BottomWaitTimeAfterCure;
changed = true;
}
if (file.CanUseWaitTimeAfterCure && file.WaitTimeAfterCure != SlicerFile.WaitTimeAfterCure)
{
details.Add($"Wait Time After Cure: {file.WaitTimeAfterCure} to {SlicerFile.WaitTimeAfterCure}");
file.WaitTimeAfterCure = SlicerFile.WaitTimeAfterCure;
changed = true;
}
if (file.CanUseBottomLiftHeight && file.BottomLiftHeight != SlicerFile.BottomLiftHeight)
{
details.Add($"Bottom Lift Height: {file.BottomLiftHeight} to {SlicerFile.BottomLiftHeight}");
file.BottomLiftHeight = SlicerFile.BottomLiftHeight;
changed = true;
}
if (file.CanUseBottomLiftSpeed && file.BottomLiftSpeed != SlicerFile.BottomLiftSpeed)
{
details.Add($"Bottom Lift Speed: {file.BottomLiftSpeed} to {SlicerFile.BottomLiftSpeed}");
file.BottomLiftSpeed = SlicerFile.BottomLiftSpeed;
changed = true;
}
if (file.CanUseLiftHeight && file.LiftHeight != SlicerFile.LiftHeight)
{
details.Add($"Lift Height: {file.LiftHeight} to {SlicerFile.LiftHeight}");
file.LiftHeight = SlicerFile.LiftHeight;
changed = true;
}
if (file.CanUseLiftSpeed && file.LiftSpeed != SlicerFile.LiftSpeed)
{
details.Add($"Lift Speed: {file.LiftSpeed} to {SlicerFile.LiftSpeed}");
file.LiftSpeed = SlicerFile.LiftSpeed;
changed = true;
}
if (file.CanUseBottomLiftHeight2 && file.BottomLiftHeight2 != SlicerFile.BottomLiftHeight2)
{
details.Add($"Bottom Lift Height 2: {file.BottomLiftHeight2} to {SlicerFile.BottomLiftHeight2}");
file.BottomLiftHeight2 = SlicerFile.BottomLiftHeight2;
changed = true;
}
if (file.CanUseBottomLiftSpeed2 && file.BottomLiftSpeed2 != SlicerFile.BottomLiftSpeed2)
{
details.Add($"Bottom Lift Speed2: {file.BottomLiftSpeed2} to {SlicerFile.BottomLiftSpeed2}");
file.BottomLiftSpeed2 = SlicerFile.BottomLiftSpeed2;
changed = true;
}
if (file.CanUseLiftHeight2 && file.LiftHeight2 != SlicerFile.LiftHeight2)
{
details.Add($"Lift Height 2: {file.LiftHeight2} to {SlicerFile.LiftHeight2}");
file.LiftHeight2 = SlicerFile.LiftHeight2;
changed = true;
}
if (file.CanUseLiftSpeed2 && file.LiftSpeed2 != SlicerFile.LiftSpeed2)
{
details.Add($"Lift Speed 2: {file.LiftSpeed2} to {SlicerFile.LiftSpeed2}");
file.LiftSpeed2 = SlicerFile.LiftSpeed2;
changed = true;
}
if (file.CanUseBottomWaitTimeAfterLift && file.BottomWaitTimeAfterLift != SlicerFile.BottomWaitTimeAfterLift)
{
details.Add($"Bottom Wait Time After Lift: {file.BottomWaitTimeAfterLift} to {SlicerFile.BottomWaitTimeAfterLift}");
file.BottomWaitTimeAfterLift = SlicerFile.BottomWaitTimeAfterLift;
changed = true;
}
if (file.CanUseWaitTimeAfterLift && file.WaitTimeAfterLift != SlicerFile.WaitTimeAfterLift)
{
details.Add($"Wait Time After Lift: {file.WaitTimeAfterLift} to {SlicerFile.WaitTimeAfterLift}");
file.WaitTimeAfterLift = SlicerFile.WaitTimeAfterLift;
changed = true;
}
if (file.CanUseBottomRetractSpeed && file.BottomRetractSpeed != SlicerFile.BottomRetractSpeed)
{
details.Add($"Bottom Retract Speed: {file.BottomRetractSpeed} to {SlicerFile.BottomRetractSpeed}");
file.BottomRetractSpeed = SlicerFile.BottomRetractSpeed;
changed = true;
}
if (file.CanUseRetractSpeed && file.RetractSpeed != SlicerFile.RetractSpeed)
{
details.Add($"Retract Speed: {file.RetractSpeed} to {SlicerFile.RetractSpeed}");
file.RetractSpeed = SlicerFile.RetractSpeed;
changed = true;
}
if (file.CanUseBottomRetractHeight2 && file.BottomRetractHeight2 != SlicerFile.BottomRetractHeight2)
{
details.Add($"Bottom Retract Height 2: {file.BottomRetractHeight2} to {SlicerFile.BottomRetractHeight2}");
file.BottomRetractHeight2 = SlicerFile.BottomRetractHeight2;
changed = true;
}
if (file.CanUseBottomRetractSpeed2 && file.BottomRetractSpeed2 != SlicerFile.BottomRetractSpeed2)
{
details.Add($"Bottom Retract Speed2: {file.BottomRetractSpeed2} to {SlicerFile.BottomRetractSpeed2}");
file.BottomRetractSpeed2 = SlicerFile.BottomRetractSpeed2;
changed = true;
}
if (file.CanUseRetractHeight2 && file.RetractHeight2 != SlicerFile.RetractHeight2)
{
details.Add($"Retract Height 2: {file.RetractHeight2} to {SlicerFile.RetractHeight2}");
file.RetractHeight2 = SlicerFile.RetractHeight2;
changed = true;
}
if (file.CanUseRetractSpeed2 && file.RetractSpeed2 != SlicerFile.RetractSpeed2)
{
details.Add($"Retract Speed 2: {file.RetractSpeed2} to {SlicerFile.RetractSpeed2}");
file.RetractSpeed2 = SlicerFile.RetractSpeed2;
changed = true;
}
if (file.CanUseBottomLightPWM && file.BottomLightPWM != SlicerFile.BottomLightPWM)
{
details.Add($"Bottom Light PWM: {file.BottomLightPWM} to {SlicerFile.BottomLightPWM}");
file.BottomLightPWM = SlicerFile.BottomLightPWM;
changed = true;
}
if (file.CanUseLightPWM && file.LightPWM != SlicerFile.LightPWM)
{
details.Add($"Light PWM: {file.LightPWM} to {SlicerFile.LightPWM}");
file.LightPWM = SlicerFile.LightPWM;
changed = true;
}
// if (file.CanUseXXX && file.XXX != SlicerFile.XXX)
// {
// details.Add($"XXX: {file.XXX} to {SlicerFile.XXX}");
// file.XXX = SlicerFile.XXX;
// changed = true;
// }
// Bail out if not changed
if (!changed)
{
return new Tuple<ResultStatus, string, List<string>>(ResultStatus.Unchanged, filePath, null);
}
// Save the changed file
file.Save();
return new Tuple<ResultStatus, string, List<string>>(ResultStatus.Success, filePath, details);
}
}
}
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using Avalonia;
using Avalonia.Controls;
@@ -39,7 +40,7 @@ namespace UVtools.WPF.Controls.Tools
{
case ToolWindow.Callbacks.Init:
case ToolWindow.Callbacks.Loaded:
ParentWindow.ButtonOkEnabled = Operation.CanExecute;
if(ParentWindow is not null) ParentWindow.ButtonOkEnabled = Operation.CanExecute;
ReloadGUI();
Operation.PropertyChanged += (sender, e) =>
{
@@ -183,309 +184,309 @@ namespace UVtools.WPF.Controls.Tools
switch (variable)
{
case ScriptNumericalInput<sbyte> numSBYTE:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = numSBYTE.Minimum,
Maximum = numSBYTE.Maximum,
Value = numSBYTE.Value,
Increment = numSBYTE.Increment,
MinWidth = 150
};
Minimum = numSBYTE.Minimum,
Maximum = numSBYTE.Maximum,
Value = numSBYTE.Value,
Increment = numSBYTE.Increment,
MinWidth = 150
};
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numSBYTE.Value = (sbyte)value;
control.Value = numSBYTE.Value;
});
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numSBYTE.Value = (sbyte)value;
control.Value = numSBYTE.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
continue;
}
case ScriptNumericalInput<byte> numBYTE:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = numBYTE.Minimum,
Maximum = numBYTE.Maximum,
Value = numBYTE.Value,
Increment = numBYTE.Increment,
MinWidth = 150
};
Minimum = numBYTE.Minimum,
Maximum = numBYTE.Maximum,
Value = numBYTE.Value,
Increment = numBYTE.Increment,
MinWidth = 150
};
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numBYTE.Value = (byte)value;
control.Value = numBYTE.Value;
});
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numBYTE.Value = (byte)value;
control.Value = numBYTE.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
continue;
}
case ScriptNumericalInput<short> numSHORT:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = numSHORT.Minimum,
Maximum = numSHORT.Maximum,
Value = numSHORT.Value,
Increment = numSHORT.Increment,
MinWidth = 150
};
Minimum = numSHORT.Minimum,
Maximum = numSHORT.Maximum,
Value = numSHORT.Value,
Increment = numSHORT.Increment,
MinWidth = 150
};
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numSHORT.Value = (short)value;
control.Value = numSHORT.Value;
});
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numSHORT.Value = (short)value;
control.Value = numSHORT.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
continue;
}
case ScriptNumericalInput<ushort> numUSHORT:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = numUSHORT.Minimum,
Maximum = numUSHORT.Maximum,
Value = numUSHORT.Value,
Increment = numUSHORT.Increment,
MinWidth = 150
};
Minimum = numUSHORT.Minimum,
Maximum = numUSHORT.Maximum,
Value = numUSHORT.Value,
Increment = numUSHORT.Increment,
MinWidth = 150
};
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numUSHORT.Value = (ushort)value;
control.Value = numUSHORT.Value;
});
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numUSHORT.Value = (ushort)value;
control.Value = numUSHORT.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
continue;
}
case ScriptNumericalInput<int> numINT:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = numINT.Minimum,
Maximum = numINT.Maximum,
Value = numINT.Value,
Increment = numINT.Increment,
MinWidth = 150
};
Minimum = numINT.Minimum,
Maximum = numINT.Maximum,
Value = numINT.Value,
Increment = numINT.Increment,
MinWidth = 150
};
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numINT.Value = (int)value;
control.Value = numINT.Value;
});
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numINT.Value = (int)value;
control.Value = numINT.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
continue;
}
case ScriptNumericalInput<uint> numUINT:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = numUINT.Minimum,
Maximum = numUINT.Maximum,
Value = numUINT.Value,
Increment = numUINT.Increment,
MinWidth = 150
};
Minimum = numUINT.Minimum,
Maximum = numUINT.Maximum,
Value = numUINT.Value,
Increment = numUINT.Increment,
MinWidth = 150
};
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numUINT.Value = (uint)value;
control.Value = numUINT.Value;
});
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numUINT.Value = (uint)value;
control.Value = numUINT.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
continue;
}
case ScriptNumericalInput<long> numLONG:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = numLONG.Minimum,
Maximum = numLONG.Maximum,
Value = numLONG.Value,
Increment = numLONG.Increment,
MinWidth = 150
};
Minimum = numLONG.Minimum,
Maximum = numLONG.Maximum,
Value = numLONG.Value,
Increment = numLONG.Increment,
MinWidth = 150
};
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numLONG.Value = (long)value;
control.Value = numLONG.Value;
});
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numLONG.Value = (long)value;
control.Value = numLONG.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
continue;
}
case ScriptNumericalInput<ulong> numULONG:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = numULONG.Minimum,
Maximum = numULONG.Maximum,
Value = numULONG.Value,
Increment = numULONG.Increment,
MinWidth = 150
};
Minimum = numULONG.Minimum,
Maximum = numULONG.Maximum,
Value = numULONG.Value,
Increment = numULONG.Increment,
MinWidth = 150
};
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numULONG.Value = (ulong)value;
control.Value = numULONG.Value;
});
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numULONG.Value = (ulong)value;
control.Value = numULONG.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
continue;
}
case ScriptNumericalInput<float> numFLOAT:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = numFLOAT.Minimum,
Maximum = numFLOAT.Maximum,
Value = numFLOAT.Value,
Increment = numFLOAT.Increment,
MinWidth = 150
};
Minimum = numFLOAT.Minimum,
Maximum = numFLOAT.Maximum,
Value = numFLOAT.Value,
Increment = numFLOAT.Increment,
MinWidth = 150
};
if (numFLOAT.DecimalPlates > 0)
{
control.FormatString = $"F{numFLOAT.DecimalPlates}";
}
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numFLOAT.Value = (float) Math.Round(value, numFLOAT.DecimalPlates);
control.Value = numFLOAT.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
if (numFLOAT.DecimalPlates > 0)
{
control.FormatString = $"F{numFLOAT.DecimalPlates}";
}
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numFLOAT.Value = (float) Math.Round(value, numFLOAT.DecimalPlates);
control.Value = numFLOAT.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
case ScriptNumericalInput<double> numDOUBLE:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = numDOUBLE.Minimum,
Maximum = numDOUBLE.Maximum,
Value = numDOUBLE.Value,
Increment = numDOUBLE.Increment,
MinWidth = 150
};
Minimum = numDOUBLE.Minimum,
Maximum = numDOUBLE.Maximum,
Value = numDOUBLE.Value,
Increment = numDOUBLE.Increment,
MinWidth = 150
};
if (numDOUBLE.DecimalPlates > 0)
{
control.FormatString = $"F{numDOUBLE.DecimalPlates}";
}
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numDOUBLE.Value = Math.Round(value, numDOUBLE.DecimalPlates);
control.Value = numDOUBLE.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
if (numDOUBLE.DecimalPlates > 0)
{
control.FormatString = $"F{numDOUBLE.DecimalPlates}";
}
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numDOUBLE.Value = Math.Round(value, numDOUBLE.DecimalPlates);
control.Value = numDOUBLE.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
case ScriptNumericalInput<decimal> numDECIMAL:
{
NumericUpDown control = new()
{
NumericUpDown control = new()
{
Minimum = (double)numDECIMAL.Minimum,
Maximum = (double)numDECIMAL.Maximum,
Value = (double)numDECIMAL.Value,
Increment = (double)numDECIMAL.Increment,
MinWidth = 150
};
Minimum = (double)numDECIMAL.Minimum,
Maximum = (double)numDECIMAL.Maximum,
Value = (double)numDECIMAL.Value,
Increment = (double)numDECIMAL.Increment,
MinWidth = 150
};
if (numDECIMAL.DecimalPlates > 0)
{
control.FormatString = $"F{numDECIMAL.DecimalPlates}";
}
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numDECIMAL.Value = (decimal)Math.Round(value, numDECIMAL.DecimalPlates);
control.Value = (double)numDECIMAL.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
if (numDECIMAL.DecimalPlates > 0)
{
control.FormatString = $"F{numDECIMAL.DecimalPlates}";
}
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
valueProperty.Subscribe(value =>
{
numDECIMAL.Value = (decimal)Math.Round(value, numDECIMAL.DecimalPlates);
control.Value = (double)numDECIMAL.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
continue;
}
case ScriptCheckBoxInput inputCheckBox:
{
var control = new CheckBox
{
CheckBox control = new()
{
Content = variable.Label,
IsChecked = inputCheckBox.Value
};
Content = variable.Label,
IsChecked = inputCheckBox.Value
};
var valueProperty = control.GetObservable(CheckBox.IsCheckedProperty);
valueProperty.Subscribe(value =>
{
if (value != null) inputCheckBox.Value = value.Value;
});
var valueProperty = control.GetObservable(CheckBox.IsCheckedProperty);
valueProperty.Subscribe(value =>
{
if (value != null) inputCheckBox.Value = value.Value;
});
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
_scriptVariablesGrid.Children.Add(control);
Grid.SetRow(control, i * 2);
Grid.SetColumn(control, 2);
if (!string.IsNullOrWhiteSpace(variable.ToolTip))
{
ToolTip.SetTip(control, variable.ToolTip);
}
continue;
if (!string.IsNullOrWhiteSpace(variable.ToolTip))
{
ToolTip.SetTip(control, variable.ToolTip);
}
continue;
}
case ScriptTextBoxInput inputTextBox:
{
TextBox control = new()
@@ -506,10 +507,169 @@ namespace UVtools.WPF.Controls.Tools
continue;
}
case ScriptOpenFolderDialogInput inputOpenFolder:
{
var panel = new StackPanel
{
Orientation = Orientation.Horizontal,
Spacing = 5
};
var control = new TextBox
{
IsReadOnly = true,
Text = inputOpenFolder.Value,
};
var button = new Button
{
Content = "Select",
};
button.Click += async (sender, args) =>
{
var dialog = new OpenFolderDialog
{
Directory = inputOpenFolder.Value,
Title = inputOpenFolder.Title
};
var result = await dialog.ShowAsync(ParentWindow);
if (!string.IsNullOrWhiteSpace(result))
{
inputOpenFolder.Value = result;
control.Text = result;
}
};
panel.Children.Add(control);
panel.Children.Add(button);
_scriptVariablesGrid.Children.Add(panel);
Grid.SetRow(panel, i * 2);
Grid.SetColumn(panel, 2);
continue;
}
case ScriptSaveFileDialogInput inputSaveFile:
{
var panel = new StackPanel
{
Orientation = Orientation.Horizontal,
Spacing = 5
};
var control = new TextBox
{
IsReadOnly = true,
Text = inputSaveFile.Value,
};
var button = new Button
{
Content = "Select",
};
button.Click += async (sender, args) =>
{
var dialog = new SaveFileDialog
{
Directory = inputSaveFile.Value,
Title = inputSaveFile.Title,
DefaultExtension = inputSaveFile.DefaultExtension,
InitialFileName = inputSaveFile.InitialFilename
};
if (inputSaveFile.Filters is not null)
{
foreach (var filter in inputSaveFile.Filters)
{
dialog.Filters.Add(new FileDialogFilter
{
Extensions = filter.Extensions,
Name = filter.Name
});
}
}
var result = await dialog.ShowAsync(ParentWindow);
if (!string.IsNullOrWhiteSpace(result))
{
inputSaveFile.Value = result;
control.Text = result;
}
};
panel.Children.Add(control);
panel.Children.Add(button);
_scriptVariablesGrid.Children.Add(panel);
Grid.SetRow(panel, i * 2);
Grid.SetColumn(panel, 2);
continue;
}
case ScriptOpenFileDialogInput inputOpenFile:
{
var panel = new StackPanel
{
Orientation = Orientation.Horizontal,
Spacing = 5
};
var control = new TextBox
{
IsReadOnly = true,
Text = inputOpenFile.Value,
AcceptsReturn = true,
};
var button = new Button
{
Content = "Select",
};
button.Click += async (sender, args) =>
{
var dialog = new OpenFileDialog
{
Directory = inputOpenFile.Value,
Title = inputOpenFile.Title,
AllowMultiple = inputOpenFile.AllowMultiple,
InitialFileName = inputOpenFile.InitialFilename
};
if (inputOpenFile.Filters is not null)
{
foreach (var filter in inputOpenFile.Filters)
{
dialog.Filters.Add(new FileDialogFilter
{
Extensions = filter.Extensions,
Name = filter.Name
});
}
}
var result = await dialog.ShowAsync(ParentWindow);
if (result is null || result.Length == 0) return;
inputOpenFile.Value = result[0];
inputOpenFile.Files = result;
control.Text = string.Join('\n', result);
};
panel.Children.Add(control);
panel.Children.Add(button);
_scriptVariablesGrid.Children.Add(panel);
Grid.SetRow(panel, i * 2);
Grid.SetColumn(panel, 2);
continue;
}
}
}
ParentWindow.FitToSize();
ParentWindow?.FitToSize();
}
}
}
+1
View File
@@ -36,6 +36,7 @@ namespace UVtools.WPF
Clear();
_layer = value;
Image = _layer.LayerMat;
if (Image is null) return;
ImageBgr = new Mat();
CvInvoke.CvtColor(Image, ImageBgr, ColorConversion.Gray2Bgr);
+8
View File
@@ -24,6 +24,7 @@ using MoreLinq;
using UVtools.Core;
using UVtools.Core.EmguCV;
using UVtools.Core.Extensions;
using UVtools.Core.FileFormats;
using UVtools.Core.Layers;
using UVtools.Core.Operations;
using UVtools.WPF.Extensions;
@@ -467,6 +468,13 @@ namespace UVtools.WPF
public async Task OnClickDetectIssues()
{
if (!IsFileLoaded) return;
if (SlicerFile.DecodeType == FileFormat.FileDecodeType.Partial)
{
await this.MessageBoxError("The file was open in partial mode and the detect issues is unable to run in this mode.\n" +
"Please reload the file in full mode in order to use detect issues.", "Unable to run in partial mode");
return;
}
await ComputeIssues(
GetIslandDetectionConfiguration(),
GetOverhangDetectionConfiguration(),
+5 -4
View File
@@ -799,7 +799,11 @@ namespace UVtools.WPF
var watch = Stopwatch.StartNew();
LayerCache.Layer = SlicerFile[_actualLayer];
if (LayerCache.Image is null)
{
RefreshCurrentLayerData();
return;
}
try
{
//var imageSpan = LayerCache.Image.GetPixelSpan<byte>();
@@ -1304,9 +1308,6 @@ namespace UVtools.WPF
CvInvoke.Rotate(LayerCache.ImageBgr, LayerCache.ImageBgr, _showLayerImageRotateCcwDirection ? RotateFlags.Rotate90CounterClockwise : RotateFlags.Rotate90Clockwise);
}
LayerImageBox.Image = LayerCache.Bitmap = LayerCache.ImageBgr.ToBitmap();
RefreshCurrentLayerData();
+7
View File
@@ -43,6 +43,13 @@
<Image Source="\Assets\Icons\file-import-16x16.png"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Name="MainMenu.File.OpenInPartialMode" Header="Open in partial mode" Command="{Binding MenuFileOpenInPartialModeClicked}"
ToolTip.Tip="Open a file only to see and/or edit properties.
&#x0a;Layer images won't be loaded and most tools won't run in this mode.">
<MenuItem.Icon>
<Image Source="\Assets\Icons\file-import-16x16.png"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem
Name="MainMenu.File.Reload"
Header="_Reload"
+66 -39
View File
@@ -584,8 +584,7 @@ namespace UVtools.WPF
menuTool.Click += async (sender, args) => await ShowRunOperation(operation.GetType());
}
}
/*LayerSlider.PropertyChanged += (sender, args) =>
{
Debug.WriteLine(args.Property.Name);
@@ -1146,6 +1145,7 @@ namespace UVtools.WPF
public void MenuFileOpenClicked() => OpenFile();
public void MenuFileOpenNewWindowClicked() => OpenFile(true);
public void MenuFileOpenInPartialModeClicked() => OpenFile(false, FileFormat.FileDecodeType.Partial);
public void MenuFileOpenCurrentFileFolderClicked()
{
@@ -1196,7 +1196,7 @@ namespace UVtools.WPF
await SaveFile(file);
}
public async void OpenFile(bool newWindow = false)
public async void OpenFile(bool newWindow = false, FileFormat.FileDecodeType fileDecodeType = FileFormat.FileDecodeType.Full)
{
var filters = Helpers.ToAvaloniaFileFilter(FileFormat.AllFileFiltersAvalonia);
var orderedFilters = new List<FileDialogFilter> {filters[Settings.General.DefaultOpenFileExtensionIndex]};
@@ -1213,7 +1213,7 @@ namespace UVtools.WPF
Directory = Settings.General.DefaultDirectoryOpenFile
};
var files = await dialog.ShowAsync(this);
ProcessFiles(files, newWindow);
ProcessFiles(files, newWindow, fileDecodeType);
}
public async void OnMenuFileCloseFile()
@@ -1386,19 +1386,36 @@ namespace UVtools.WPF
private void UpdateTitle()
{
Title = SlicerFile is null
? $"{About.Software} Version: {App.VersionStr}"
: $"{About.Software} File: {Path.GetFileName(SlicerFile.FileFullPath)} ({Math.Round(LastStopWatch.ElapsedMilliseconds / 1000m, 2)}s) Version: {App.VersionStr}"
;
var title = $"{About.Software} ";
Title += $" RAM: {SizeExtensions.SizeSuffix(Environment.WorkingSet)}";
if (IsFileLoaded)
{
title += $"File: {Path.GetFileName(SlicerFile.FileFullPath)} ({Math.Round(LastStopWatch.ElapsedMilliseconds / 1000m, 2)}s) ";
}
title += $"Version: {App.VersionStr} RAM: {SizeExtensions.SizeSuffix(Environment.WorkingSet)}";
if (IsFileLoaded)
{
if (CanSave)
{
title += " [UNSAVED]";
}
if (SlicerFile.DecodeType == FileFormat.FileDecodeType.Partial)
{
title += " [PARTIAL MODE]";
}
}
#if DEBUG
Title += " [DEBUG]";
title += " [DEBUG]";
#endif
Title = title;
}
public async void ProcessFiles(string[] files, bool openNewWindow = false)
public async void ProcessFiles(string[] files, bool openNewWindow = false, FileFormat.FileDecodeType fileDecodeType = FileFormat.FileDecodeType.Full)
{
if (files is null || files.Length == 0) return;
@@ -1436,7 +1453,7 @@ namespace UVtools.WPF
if (i == 0 && !openNewWindow && (_globalModifiers & KeyModifiers.Shift) == 0)
{
ProcessFile(files[i]);
ProcessFile(files[i], fileDecodeType);
continue;
}
@@ -1450,10 +1467,11 @@ namespace UVtools.WPF
void ReloadFile(uint actualLayer)
{
if (App.SlicerFile is null) return;
ProcessFile(SlicerFile.FileFullPath, _actualLayer);
ProcessFile(SlicerFile.FileFullPath, SlicerFile.DecodeType, _actualLayer);
}
async void ProcessFile(string fileName, uint actualLayer = 0)
void ProcessFile(string fileName, uint actualLayer = 0) => ProcessFile(fileName, FileFormat.FileDecodeType.Full, actualLayer);
async void ProcessFile(string fileName, FileFormat.FileDecodeType fileDecodeType, uint actualLayer = 0)
{
if (!File.Exists(fileName)) return;
CloseFile();
@@ -1468,7 +1486,7 @@ namespace UVtools.WPF
{
try
{
SlicerFile.Decode(fileName, Progress);
SlicerFile.Decode(fileName, fileDecodeType, Progress);
return true;
}
catch (OperationCanceledException)
@@ -1507,7 +1525,7 @@ namespace UVtools.WPF
return;
}
if (Settings.Automations.AutoConvertFiles)
if (Settings.Automations.AutoConvertFiles && SlicerFile.DecodeType == FileFormat.FileDecodeType.Full)
{
string convertFileExtension = SlicerFile switch
{
@@ -1626,7 +1644,7 @@ namespace UVtools.WPF
Clipboard.Init(SlicerFile);
if (SlicerFile is not ImageFile)
if (SlicerFile is not ImageFile && SlicerFile.DecodeType == FileFormat.FileDecodeType.Full)
{
List<MenuItem> menuItems = new();
foreach (var fileFormat in FileFormat.AvailableFormats)
@@ -1664,7 +1682,7 @@ namespace UVtools.WPF
MenuFileConvertItems = menuItems.ToArray();
}
using var mat = SlicerFile[0].LayerMat;
using var mat = SlicerFile.FirstLayer?.LayerMat;
VisibleThumbnailIndex = 1;
@@ -1672,7 +1690,6 @@ namespace UVtools.WPF
UpdateTitle();
if (mat is not null)
{
if (Settings.LayerPreview.AutoRotateLayerBestView)
@@ -1726,7 +1743,7 @@ namespace UVtools.WPF
"Incorrect image ratio detected");
}
if (mat.Size != SlicerFile.Resolution)
if (mat is not null && mat.Size != SlicerFile.Resolution)
{
var result = await this.MessageBoxWaring($"Layer image resolution of {mat.Size} mismatch with printer resolution of {SlicerFile.Resolution}.\n" +
"1) Printing this file can lead to problems or malformed model, please verify your slicer printer settings;\n" +
@@ -1747,29 +1764,32 @@ namespace UVtools.WPF
UpdateLayerTrackerHighlightIssues();
};
if (Settings.Issues.ComputeIssuesOnLoad)
if (SlicerFile.DecodeType == FileFormat.FileDecodeType.Full)
{
_firstTimeOnIssues = false;
await OnClickDetectIssues();
if (SlicerFile.IssueManager.Count > 0)
if (Settings.Issues.ComputeIssuesOnLoad)
{
SelectedTabItem = TabIssues;
if(Settings.Issues.AutoRepairIssuesOnLoad)
await RunOperation(ToolRepairLayersControl.GetOperationRepairLayers());
_firstTimeOnIssues = false;
await OnClickDetectIssues();
if (SlicerFile.IssueManager.Count > 0)
{
SelectedTabItem = TabIssues;
if (Settings.Issues.AutoRepairIssuesOnLoad)
await RunOperation(ToolRepairLayersControl.GetOperationRepairLayers());
}
}
}
else
{
await ComputeIssues(
GetIslandDetectionConfiguration(false),
GetOverhangDetectionConfiguration(false),
GetResinTrapDetectionConfiguration(false),
GetTouchingBoundsDetectionConfiguration(false),
GetPrintHeightDetectionConfiguration(true),
true);
if (SlicerFile.IssueManager.Count > 0)
else
{
SelectedTabItem = TabIssues;
await ComputeIssues(
GetIslandDetectionConfiguration(false),
GetOverhangDetectionConfiguration(false),
GetResinTrapDetectionConfiguration(false),
GetTouchingBoundsDetectionConfiguration(false),
GetPrintHeightDetectionConfiguration(true),
true);
if (SlicerFile.IssueManager.Count > 0)
{
SelectedTabItem = TabIssues;
}
}
}
@@ -2066,6 +2086,13 @@ namespace UVtools.WPF
return null;
}
if (SlicerFile.DecodeType == FileFormat.FileDecodeType.Partial && !control.BaseOperation.CanRunInPartialMode)
{
await this.MessageBoxError($"The file was open in partial mode and the tool \"{control.BaseOperation.Title}\" is unable to run in this mode.\n" +
"Please reload the file in full mode in order to use this tool.", "Unable to run in partial mode");
return null;
}
if (removeContent)
{
control.IsVisible = false;
+1 -1
View File
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<Version>2.24.4</Version>
<Version>2.25.0</Version>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>