Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
- (Fix) CTB: Error when open file in partial model with malformed file due invalid checksum
- (Improvement) Improve "extract" command to allow extract specific thumbnails or layers in a range or indexes (#754)
  • Loading branch information
sn4k3 committed Sep 16, 2023
1 parent b842105 commit e171130
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 11 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,19 @@
- (Fix) Accessing `BoundingRectangleMillimeters` was not calculating the `BoundingRectangle` if necessary
- (Fix) SL1: Files with thumbnails size different from original SL1 would not display under the UI
- (Fix) Anycubic: Model information is not set after an auto-conversion from SL1
- (Fix) CTB: Error when open file in partial model with malformed file due invalid checksum
- (Fix) Image files: Could not find a writer for the specified extension (#755)
- **UVtoolsCmd:**
- (Add) "compare" command to compare two files and output the differences
- (Add) "print-formats" command to print the available formats
- (Improvement) Improve "extract" command to allow extract specific thumbnails or layers in a range or indexes (#754)
- **Project:**
- (Change) Rename UVtools.WPF to UVtools.UI
- (Change) Make UVtools.UI nullable enabled
- (Remove) UVtools.GUI
- (Improvement) Use CompiledBinding instead of ReflectionBinding
- (Improvement) Sign the libraries and project with a strong key
- (Upgrade) .NET from 6.0.18 to 6.0.21
- (Upgrade) .NET from 6.0.18 to 6.0.22
- (Upgrade) AvaloniaUI from 0.10.21 to 11.0.4
- (Upgrade) OpenCV from 4.7.0 to 4.8.0
- (Add) PrusaSlicer printer: Elegoo Saturn S
Expand Down
140 changes: 136 additions & 4 deletions UVtools.Cmd/Symbols/ExtractCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,46 @@
* of this license document, but changing it is not allowed.
*/

using Emgu.CV.Flann;
using Emgu.CV;
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using UVtools.Core.FileFormats;

namespace UVtools.Cmd.Symbols;

internal static class ExtractCommand
{

internal enum ExtractContentType
{
File,
Thumbnails,
Layers
}

internal static Command CreateCommand()
{
var noOverwriteOption = new Option<bool>("--no-overwrite", "If the output folder exists do not overwrite");
var contentTypeOption = new Option<ExtractContentType>(new []{ "-c", "--content" }, () => ExtractContentType.File, "Set the type of content to extract");
var indexesOption = new Option<uint[] >(new []{ "-i", "--index" }, "Sets the thumbnail or layer index to extract");
var rangeOption = new Option<string>(new []{ "-r", "--range" }, "Sets the layer range to extract");

var command = new Command("extract", "Extract file contents to a folder")
{
GlobalArguments.InputFileArgument,
GlobalArguments.OutputDirectoryArgument,
noOverwriteOption,
contentTypeOption,
indexesOption,
rangeOption
};

command.SetHandler((inputFile, outputDirectory, noOverwrite) =>
command.SetHandler((inputFile, outputDirectory, noOverwrite, contentType, indexes, range) =>
{
var path = outputDirectory is null
? Path.Combine(inputFile.DirectoryName!, Path.GetFileNameWithoutExtension(inputFile.Name))
Expand All @@ -36,15 +57,126 @@ internal static Command CreateCommand()
return;
}
var slicerFile = Program.OpenInputFile(inputFile);
var slicerFile = Program.OpenInputFile(inputFile, contentType == ExtractContentType.Thumbnails ? FileFormat.FileDecodeType.Partial : FileFormat.FileDecodeType.Full);
Program.ProgressBarWork($"Extracting to {Path.GetFileName(path)}",
() =>
{
slicerFile.Extract(path, progress: Program.Progress);
if (contentType == ExtractContentType.File)
{
slicerFile.Extract(path, progress: Program.Progress);
}
else
{
var indexesList = new List<uint>();
if (contentType == ExtractContentType.Layers)
{
if (slicerFile.LayerCount == 0)
{
Program.WriteLineWarning("File have no valid layers to extract.");
return;
}
if (!string.IsNullOrWhiteSpace(range))
{
if (slicerFile.TryParseLayerIndexRange(range, out var layerIndexStart, out var layerIndexEnd))
{
for (var layerIndex = layerIndexStart; layerIndex <= layerIndexEnd; layerIndex++)
{
indexesList.Add(layerIndex);
}
}
else
{
Program.WriteLineError($"The specified layer range '{range}' is malformed, use startindex:endindex with positive numbers");
}
}
}
else if (contentType == ExtractContentType.Thumbnails)
{
if (slicerFile.ThumbnailsCount == 0)
{
Program.WriteLineWarning("File have no valid thumbnails to extract.");
return;
}
}
if (indexes.Length == 0 && indexesList.Count == 0)
{
if (contentType == ExtractContentType.Layers)
{
for (uint i = 0; i < slicerFile.LayerCount; i++)
{
indexesList.Add(slicerFile.SanitizeLayerIndex(i));
}
}
else if (contentType == ExtractContentType.Thumbnails)
{
for (uint i = 0; i < slicerFile.Thumbnails.Count; i++)
{
indexesList.Add(i);
}
}
}
else
{
if (contentType == ExtractContentType.Layers)
{
foreach (var index in indexes)
{
if (index < slicerFile.LayerCount)
{
indexesList.Add(index);
}
}
}
else if (contentType == ExtractContentType.Thumbnails)
{
foreach (var index in indexes)
{
if (index < slicerFile.ThumbnailsCount)
{
indexesList.Add(index);
}
}
}
}
indexesList = indexesList.Distinct().OrderBy(layerIndex => layerIndex).ToList();
if (indexesList.Count == 0)
{
Program.WriteLineWarning("No valid indexes to extract.");
return;
}
Directory.CreateDirectory(path);
if (contentType == ExtractContentType.Layers)
{
Parallel.ForEach(indexesList, layerIndex =>
{
using var mat = slicerFile[layerIndex].LayerMat;
mat.Save(Path.Combine(path, slicerFile[layerIndex].Filename));
});
}
else if (contentType == ExtractContentType.Thumbnails)
{
foreach (var index in indexesList)
{
var thumbnail = slicerFile.Thumbnails[(int)index];
if (thumbnail.IsEmpty)
{
continue;
}
thumbnail.Save(Path.Combine(path, $"Thumbnail{index}.png"));
}
}
}
});
}, GlobalArguments.InputFileArgument, GlobalArguments.OutputDirectoryArgument, noOverwriteOption);
}, GlobalArguments.InputFileArgument, GlobalArguments.OutputDirectoryArgument, noOverwriteOption, contentTypeOption, indexesOption, rangeOption);

return command;
}
Expand Down
9 changes: 6 additions & 3 deletions UVtools.Core/FileFormats/CTBEncryptedFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1199,10 +1199,13 @@ protected override void DecodeInternally(OperationProgress progress)
"Please increase the portion of the plate in use and re-slice the file.");
}

var hash = inputFile.ReadBytes(HASH_LENGTH);
if (!hash.SequenceEqual(encryptedHash))
if (DecodeType == FileDecodeType.Full)
{
throw new FileLoadException("The file checksum does not match, malformed file.", FileFullPath);
var hash = inputFile.ReadBytes(HASH_LENGTH);
if (!hash.SequenceEqual(encryptedHash))
{
throw new FileLoadException("The file checksum does not match, malformed file.", FileFullPath);
}
}

for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
Expand Down
5 changes: 2 additions & 3 deletions UVtools.Core/FileFormats/FileFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3937,7 +3937,7 @@ public void Encode(string? fileFullPath, OperationProgress? progress = null)
EncodeInternally(progress);

// Move temporary output file in place
File.Move(tempFile, fileFullPath, true);
if (File.Exists(tempFile)) File.Move(tempFile, fileFullPath, true);

IsModified = false;
RequireFullEncode = false;
Expand Down Expand Up @@ -4332,8 +4332,7 @@ public void DecodeLayersFromZipIgnoreFilename(ZipArchive zipArchive, OperationPr
/// <param name="genericConfigExtract"></param>
/// <param name="genericLayersExtract"></param>
/// <param name="progress"></param>
public virtual void Extract(string path, bool genericConfigExtract = true, bool genericLayersExtract = true,
OperationProgress? progress = null)
public virtual void Extract(string path, bool genericConfigExtract = true, bool genericLayersExtract = true, OperationProgress? progress = null)
{
progress ??= new OperationProgress();
progress.ItemName = OperationProgress.StatusExtracting;
Expand Down

0 comments on commit e171130

Please sign in to comment.