diff options
Diffstat (limited to 'UVtools.Core/FileFormats/FDGFile.cs')
-rw-r--r-- | UVtools.Core/FileFormats/FDGFile.cs | 341 |
1 files changed, 160 insertions, 181 deletions
diff --git a/UVtools.Core/FileFormats/FDGFile.cs b/UVtools.Core/FileFormats/FDGFile.cs index b67cc0e..2f02dc4 100644 --- a/UVtools.Core/FileFormats/FDGFile.cs +++ b/UVtools.Core/FileFormats/FDGFile.cs @@ -405,7 +405,7 @@ namespace UVtools.Core.FileFormats #endregion #region Layer - public class LayerData + public class LayerDef { /// <summary> /// Gets the build platform Z position for this layer, measured in millimeters. @@ -440,21 +440,28 @@ namespace UVtools.Core.FileFormats [Ignore] public FDGFile Parent { get; set; } - public LayerData() + public LayerDef() { } - public LayerData(FDGFile parent, uint layerIndex) + public LayerDef(FDGFile parent, Layer layer) { Parent = parent; - RefreshLayerData(layerIndex); + SetFrom(layer); } - public void RefreshLayerData(uint layerIndex) + public void SetFrom(Layer layer) { - LayerPositionZ = Parent[layerIndex].PositionZ; - LayerExposure = Parent[layerIndex].ExposureTime; - LightOffDelay = Parent[layerIndex].LightOffDelay; + LayerPositionZ = layer.PositionZ; + LayerExposure = layer.ExposureTime; + LightOffDelay = layer.LightOffDelay; + } + + public void CopyTo(Layer layer) + { + layer.PositionZ = LayerPositionZ; + layer.ExposureTime = LayerExposure; + layer.LightOffDelay = LightOffDelay; } public unsafe Mat Decode(uint layerIndex, bool consumeData = true) @@ -522,7 +529,7 @@ namespace UVtools.Core.FileFormats return image; } - public void Encode(Mat image, uint layerIndex) + public void Encode(Mat mat, uint layerIndex) { List<byte> rawData = new(); @@ -550,12 +557,12 @@ namespace UVtools.Core.FileFormats } } - int halfWidth = image.Width / 2; + int halfWidth = mat.Width / 2; //int pixel = 0; - for (int y = 0; y < image.Height; y++) + for (int y = 0; y < mat.Height; y++) { - var span = image.GetRowSpan<byte>(y); + var span = mat.GetRowSpan<byte>(y); for (int x = 0; x < span.Length; x++) { @@ -589,7 +596,7 @@ namespace UVtools.Core.FileFormats if (Parent.HeaderSettings.EncryptionKey > 0) { - KeyRing kr = new(Parent.HeaderSettings.EncryptionKey, layerIndex); + var kr = new KeyRing(Parent.HeaderSettings.EncryptionKey, layerIndex); EncodedRle = kr.Read(rawData).ToArray(); } else @@ -664,9 +671,7 @@ namespace UVtools.Core.FileFormats public Preview[] Previews { get; protected internal set; } - public LayerData[] LayersDefinitions { get; private set; } - - public Dictionary<string, LayerData> LayersHash { get; } = new(); + public LayerDef[] LayersDefinitions { get; private set; } public override FileFormatType FileType => FileFormatType.Binary; @@ -764,11 +769,7 @@ namespace UVtools.Core.FileFormats public override byte AntiAliasing { get => (byte) HeaderSettings.AntiAliasLevelInfo; - set - { - HeaderSettings.AntiAliasLevelInfo = value.Clamp(1, 16); - RaisePropertyChanged(); - } + set => base.AntiAliasing = (byte)(HeaderSettings.AntiAliasLevelInfo = value.Clamp(1, 16)); } public override float LayerHeight @@ -955,221 +956,201 @@ namespace UVtools.Core.FileFormats protected override void EncodeInternally(string fileFullPath, OperationProgress progress) { - LayersHash.Clear(); - /*if (HeaderSettings.EncryptionKey == 0) { Random rnd = new Random(); HeaderSettings.EncryptionKey = (uint)rnd.Next(short.MaxValue, int.MaxValue); }*/ - uint currentOffset = (uint)Helpers.Serializer.SizeOf(HeaderSettings); - LayersDefinitions = new LayerData[HeaderSettings.LayerCount]; - using (var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write)) - { - outputFile.Seek((int) currentOffset, SeekOrigin.Begin); + 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++) - { - var image = Thumbnails[i]; + for (byte i = 0; i < ThumbnailsCount; i++) + { + var image = Thumbnails[i]; - var bytes = Preview.Encode(image); + var bytes = Preview.Encode(image); - if (bytes.Length == 0) continue; + if (bytes.Length == 0) continue; - if (i == (byte) FileThumbnailSize.Small) - { - HeaderSettings.PreviewSmallOffsetAddress = currentOffset; - } - else - { - HeaderSettings.PreviewLargeOffsetAddress = currentOffset; - } + if (i == (byte) FileThumbnailSize.Small) + { + HeaderSettings.PreviewSmallOffsetAddress = (uint)outputFile.Position; + } + else + { + HeaderSettings.PreviewLargeOffsetAddress = (uint)outputFile.Position; + } - Preview preview = new() - { - ResolutionX = (uint) image.Width, - ResolutionY = (uint) image.Height, - ImageLength = (uint)bytes.Length, - }; + Preview preview = new() + { + ResolutionX = (uint) image.Width, + ResolutionY = (uint) image.Height, + ImageLength = (uint)bytes.Length, + }; - currentOffset += (uint) Helpers.Serializer.SizeOf(preview); - preview.ImageOffset = currentOffset; + preview.ImageOffset = (uint)(outputFile.Position + Helpers.Serializer.SizeOf(preview)); - Helpers.SerializeWriteFileStream(outputFile, preview); + Helpers.SerializeWriteFileStream(outputFile, preview); - currentOffset += (uint)bytes.Length; - outputFile.WriteBytes(bytes); - } + outputFile.WriteBytes(bytes); + } - if (HeaderSettings.MachineNameSize > 0) - { - HeaderSettings.MachineNameAddress = currentOffset; - var machineBytes = Encoding.ASCII.GetBytes(HeaderSettings.MachineName); - outputFile.Write(machineBytes, 0, machineBytes.Length); - currentOffset += (uint)machineBytes.Length; - } + if (HeaderSettings.MachineNameSize > 0) + { + HeaderSettings.MachineNameAddress = (uint)outputFile.Position; + var machineBytes = Encoding.ASCII.GetBytes(HeaderSettings.MachineName); + outputFile.Write(machineBytes, 0, machineBytes.Length); + } + + progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount); + var layersHash = new Dictionary<string, LayerDef>(); + LayersDefinitions = new LayerDef[HeaderSettings.LayerCount]; + HeaderSettings.LayersDefinitionOffsetAddress = (uint)outputFile.Position; + uint layerDefCurrentOffset = HeaderSettings.LayersDefinitionOffsetAddress; + uint layerDataCurrentOffset = HeaderSettings.LayersDefinitionOffsetAddress + (uint)Helpers.Serializer.SizeOf(new LayerDef()) * LayerCount; - Parallel.For(0, LayerCount, /*new ParallelOptions{MaxDegreeOfParallelism = 1},*/ layerIndex => + foreach (var batch in BatchLayersIndexes()) + { + Parallel.ForEach(batch, layerIndex => { - if(progress.Token.IsCancellationRequested) return; - LayerData layer = new(this, (uint) layerIndex); - using (var image = this[layerIndex].LayerMat) + if (progress.Token.IsCancellationRequested) return; + using (var mat = this[layerIndex].LayerMat) { - layer.Encode(image, (uint) layerIndex); - LayersDefinitions[layerIndex] = layer; + LayersDefinitions[layerIndex] = new LayerDef(this, this[layerIndex]); + LayersDefinitions[layerIndex].Encode(mat, (uint)layerIndex); } - progress.LockAndIncrement(); }); - progress.Reset(OperationProgress.StatusWritingFile, LayerCount); - - HeaderSettings.LayersDefinitionOffsetAddress = currentOffset; - uint layerDataCurrentOffset = currentOffset + (uint) Helpers.Serializer.SizeOf(LayersDefinitions[0]) * LayerCount; - for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) + foreach (var layerIndex in batch) { progress.Token.ThrowIfCancellationRequested(); - LayerData layerData = LayersDefinitions[layerIndex]; - LayerData layerDataHash = null; + + var layerDef = LayersDefinitions[layerIndex]; + LayerDef layerDefHash = null; if (HeaderSettings.EncryptionKey == 0) { - string hash = Helpers.ComputeSHA1Hash(layerData.EncodedRle); - if (LayersHash.TryGetValue(hash, out layerDataHash)) + string hash = Helpers.ComputeSHA1Hash(layerDef.EncodedRle); + if (layersHash.TryGetValue(hash, out layerDefHash)) { - layerData.DataAddress = layerDataHash.DataAddress; - layerData.DataSize = layerDataHash.DataSize; + layerDef.DataAddress = layerDefHash.DataAddress; + layerDef.DataSize = layerDefHash.DataSize; } else { - LayersHash.Add(hash, layerData); + layersHash.Add(hash, layerDef); } } - if (ReferenceEquals(layerDataHash, null)) + if (layerDefHash is null) { - layerData.DataAddress = layerDataCurrentOffset; + layerDef.DataAddress = layerDataCurrentOffset; outputFile.Seek(layerDataCurrentOffset, SeekOrigin.Begin); - layerDataCurrentOffset += outputFile.WriteBytes(layerData.EncodedRle); + layerDataCurrentOffset += outputFile.WriteBytes(layerDef.EncodedRle); } - LayersDefinitions[layerIndex] = layerData; + outputFile.Seek(layerDefCurrentOffset, SeekOrigin.Begin); + layerDefCurrentOffset += Helpers.SerializeWriteFileStream(outputFile, layerDef); - outputFile.Seek(currentOffset, SeekOrigin.Begin); - currentOffset += Helpers.SerializeWriteFileStream(outputFile, layerData); - progress++; + layerDef.EncodedRle = null; // Free } + } - outputFile.Seek(0, SeekOrigin.Begin); - Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); - Debug.WriteLine("Encode Results:"); - Debug.WriteLine(HeaderSettings); - Debug.WriteLine(Previews[0]); - Debug.WriteLine(Previews[1]); - Debug.WriteLine("-End-"); - } + outputFile.Seek(0, SeekOrigin.Begin); + Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); + + Debug.WriteLine("Encode Results:"); + Debug.WriteLine(HeaderSettings); + Debug.WriteLine(Previews[0]); + Debug.WriteLine(Previews[1]); + Debug.WriteLine("-End-"); } protected override void DecodeInternally(string fileFullPath, 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); + } - //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); - } - - HeaderSettings.AntiAliasLevel = 1; - - FileFullPath = fileFullPath; - - - progress.Reset(OperationProgress.StatusDecodePreviews, ThumbnailsCount); - Debug.Write("Header -> "); - Debug.WriteLine(HeaderSettings); - - for (byte i = 0; i < ThumbnailsCount; i++) - { - uint offsetAddress = i == 0 - ? HeaderSettings.PreviewSmallOffsetAddress - : HeaderSettings.PreviewLargeOffsetAddress; - if (offsetAddress == 0) continue; + HeaderSettings.AntiAliasLevel = 1; - inputFile.Seek(offsetAddress, SeekOrigin.Begin); - Previews[i] = Helpers.Deserialize<Preview>(inputFile); + FileFullPath = fileFullPath; - Debug.Write($"Preview {i} -> "); - Debug.WriteLine(Previews[i]); - inputFile.Seek(Previews[i].ImageOffset, SeekOrigin.Begin); - byte[] rawImageData = new byte[Previews[i].ImageLength]; - inputFile.Read(rawImageData, 0, (int) Previews[i].ImageLength); + progress.Reset(OperationProgress.StatusDecodePreviews, ThumbnailsCount); + Debug.Write("Header -> "); + Debug.WriteLine(HeaderSettings); - Thumbnails[i] = Previews[i].Decode(rawImageData); - progress++; - } + for (byte i = 0; i < ThumbnailsCount; i++) + { + uint offsetAddress = i == 0 + ? HeaderSettings.PreviewSmallOffsetAddress + : HeaderSettings.PreviewLargeOffsetAddress; + if (offsetAddress == 0) continue; - if (HeaderSettings.MachineNameAddress > 0 && HeaderSettings.MachineNameSize > 0) - { - inputFile.Seek(HeaderSettings.MachineNameAddress, SeekOrigin.Begin); - byte[] buffer = new byte[HeaderSettings.MachineNameSize]; - inputFile.Read(buffer, 0, (int) HeaderSettings.MachineNameSize); - HeaderSettings.MachineName = Encoding.ASCII.GetString(buffer); - } + inputFile.Seek(offsetAddress, SeekOrigin.Begin); + Previews[i] = Helpers.Deserialize<Preview>(inputFile); + Debug.Write($"Preview {i} -> "); + Debug.WriteLine(Previews[i]); - LayersDefinitions = new LayerData[HeaderSettings.LayerCount]; + inputFile.Seek(Previews[i].ImageOffset, SeekOrigin.Begin); + byte[] rawImageData = new byte[Previews[i].ImageLength]; + inputFile.Read(rawImageData, 0, (int) Previews[i].ImageLength); - uint layerOffset = HeaderSettings.LayersDefinitionOffsetAddress; + Thumbnails[i] = Previews[i].Decode(rawImageData); + progress++; + } - progress.Reset(OperationProgress.StatusGatherLayers, HeaderSettings.LayerCount); + if (HeaderSettings.MachineNameAddress > 0 && HeaderSettings.MachineNameSize > 0) + { + inputFile.Seek(HeaderSettings.MachineNameAddress, SeekOrigin.Begin); + var buffer = new byte[HeaderSettings.MachineNameSize]; + inputFile.Read(buffer, 0, (int) HeaderSettings.MachineNameSize); + HeaderSettings.MachineName = Encoding.ASCII.GetString(buffer); + } - for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) + LayerManager.Init(HeaderSettings.LayerCount); + LayersDefinitions = new LayerDef[HeaderSettings.LayerCount]; + + progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount); + foreach (var batch in BatchLayersIndexes()) + { + foreach (var layerIndex in batch) { - inputFile.Seek(layerOffset, SeekOrigin.Begin); - LayerData layerData = Helpers.Deserialize<LayerData>(inputFile); - layerData.Parent = this; - LayersDefinitions[layerIndex] = layerData; + progress.Token.ThrowIfCancellationRequested(); - layerOffset += (uint) Helpers.Serializer.SizeOf(layerData); + var layerDef = Helpers.Deserialize<LayerDef>(inputFile); + layerDef.Parent = this; + LayersDefinitions[layerIndex] = layerDef; + Debug.Write($"LAYER {layerIndex} -> "); - Debug.WriteLine(layerData); + Debug.WriteLine(layerDef); - layerData.EncodedRle = new byte[layerData.DataSize]; - inputFile.Seek(layerData.DataAddress, SeekOrigin.Begin); - inputFile.Read(layerData.EncodedRle, 0, (int) layerData.DataSize); - - progress++; - progress.Token.ThrowIfCancellationRequested(); + inputFile.SeekDoWorkAndRewind(layerDef.DataAddress, () => + { + layerDef.EncodedRle = inputFile.ReadBytes(layerDef.DataSize); + }); } - LayerManager.Init(HeaderSettings.LayerCount); - - progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount); - - Parallel.For(0, LayerCount, layerIndex => + Parallel.ForEach(batch, layerIndex => { - if (progress.Token.IsCancellationRequested) + if (progress.Token.IsCancellationRequested) return; + using (var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex)) { - return; - } - - using (var image = LayersDefinitions[layerIndex].Decode((uint) layerIndex, true)) - { - this[layerIndex] = new Layer((uint) layerIndex, image, LayerManager) - { - PositionZ = LayersDefinitions[layerIndex].LayerPositionZ, - ExposureTime = LayersDefinitions[layerIndex].LayerExposure, - LightOffDelay = LayersDefinitions[layerIndex].LightOffDelay, - }; + var layer = new Layer((uint)layerIndex, mat, this); + LayersDefinitions[layerIndex].CopyTo(layer); + this[layerIndex] = layer; } progress.LockAndIncrement(); @@ -1195,26 +1176,24 @@ namespace UVtools.Core.FileFormats FileFullPath = filePath; } - using (var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write)) - { - outputFile.Seek(0, SeekOrigin.Begin); - Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); + using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write); + outputFile.Seek(0, SeekOrigin.Begin); + Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); - /*if (HeaderSettings.MachineNameAddress > 0 && HeaderSettings.MachineNameSize > 0) + /*if (HeaderSettings.MachineNameAddress > 0 && HeaderSettings.MachineNameSize > 0) { outputFile.Seek(HeaderSettings.MachineNameAddress, SeekOrigin.Begin); byte[] buffer = new byte[HeaderSettings.MachineNameSize]; outputFile.Write(Encoding.ASCII.GetBytes(HeaderSettings.MachineName), 0, (int)HeaderSettings.MachineNameSize); }*/ - uint layerOffset = HeaderSettings.LayersDefinitionOffsetAddress; - for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) - { - LayersDefinitions[layerIndex].RefreshLayerData(layerIndex); - outputFile.Seek(layerOffset, SeekOrigin.Begin); - Helpers.SerializeWriteFileStream(outputFile, LayersDefinitions[layerIndex]); - layerOffset += (uint)Helpers.Serializer.SizeOf(LayersDefinitions[layerIndex]); - } + uint layerOffset = HeaderSettings.LayersDefinitionOffsetAddress; + for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) + { + LayersDefinitions[layerIndex].SetFrom(this[layerIndex]); + outputFile.Seek(layerOffset, SeekOrigin.Begin); + Helpers.SerializeWriteFileStream(outputFile, LayersDefinitions[layerIndex]); + layerOffset += (uint)Helpers.Serializer.SizeOf(LayersDefinitions[layerIndex]); } } |