diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-04-18 02:18:42 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-04-18 02:18:42 +0300 |
commit | 6cfedea4cc36200caab87301e0dd121e97ddc8f2 (patch) | |
tree | 3325980560fc5bb3fa8befea1b827a2ca945e9ea /UVtools.Core/FileFormats/PhotonSFile.cs | |
parent | 4dae750e83987fde8b34087d26fc75407e88f55a (diff) |
v2.9.1v2.9.1
* **File formats:**
* PhotonS: Implement the write/encode method to allow to use this format and fix the thumbnail
* VDT: Allow to auto convert the .vdt to the target printer format using the Machine - Notes, using a flag: FILEFORMAT_YourPrinterExtension, for example: FILEFORMAT_CTB
* (Fix) Unable to convert files with no thumbnails to other file format that requires thumbnails
* **Tools:**
* (Add) Re-height: Option to Anti-Aliasing layers
* (Fix) Morph and Blur: The combobox was not setting to the selected item when preform a redo operation (Ctrl+Shift+Z)
* **GUI:**
* (Change) Progress window to be a grid element inside MainWindow, this allow to reuse the graphics and its elements without the need of spawning a Window instance everytime a progress is shown, resulting in better performance and more fluid transaction
* (Improvement) Clear issues when generating calibration tests
Diffstat (limited to 'UVtools.Core/FileFormats/PhotonSFile.cs')
-rw-r--r-- | UVtools.Core/FileFormats/PhotonSFile.cs | 294 |
1 files changed, 154 insertions, 140 deletions
diff --git a/UVtools.Core/FileFormats/PhotonSFile.cs b/UVtools.Core/FileFormats/PhotonSFile.cs index e2391a7..6e6fe47 100644 --- a/UVtools.Core/FileFormats/PhotonSFile.cs +++ b/UVtools.Core/FileFormats/PhotonSFile.cs @@ -24,7 +24,7 @@ namespace UVtools.Core.FileFormats { public class PhotonSFile : FileFormat { - public const byte RLEEncodingLimit = 0x7f - 2; // 128; + public const byte RLEEncodingLimit = 128; #region Sub Classes @@ -37,7 +37,7 @@ namespace UVtools.Core.FileFormats public const float DisplayWidth = 68.04f; public const float DisplayHeight = 120.96f; - public const float BuildZ = 150f; + public const float BuildZ = 165f; public const uint TAG1 = 2; public const ushort TAG2 = 49; @@ -55,7 +55,7 @@ namespace UVtools.Core.FileFormats [FieldOrder(9)] [FieldEndianness(Endianness.Big)] public double LiftSpeed { get; set; } // mm/s [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public double RetractSpeed { get; set; } // mm/s [FieldOrder(11)] [FieldEndianness(Endianness.Big)] public double VolumeMl { get; set; } // ml - [FieldOrder(12)] [FieldEndianness(Endianness.Big)] public uint PreviewResolutionX { get; set; } = 225; + [FieldOrder(12)] [FieldEndianness(Endianness.Big)] public uint PreviewResolutionX { get; set; } = 224; [FieldOrder(13)] [FieldEndianness(Endianness.Big)] public uint Unknown2 { get; set; } = 42; [FieldOrder(14)] [FieldEndianness(Endianness.Big)] public uint PreviewResolutionY { get; set; } = 168; [FieldOrder(15)] [FieldEndianness(Endianness.Big)] public uint Unknown4 { get; set; } = 10; @@ -88,7 +88,14 @@ namespace UVtools.Core.FileFormats [FieldOrder(3)] [FieldEndianness(Endianness.Big)] public uint ResolutionX { get; set; } = 1440; [FieldOrder(4)] [FieldEndianness(Endianness.Big)] public uint ResolutionY { get; set; } = 2560; [FieldOrder(5)] [FieldEndianness(Endianness.Big)] public uint DataSize { get; set; } - [Ignore] public uint RleDataSize => (DataSize >> 3) - 4; + [Ignore] public uint RleDataSize + { + get => (DataSize >> 3) - 4; + set => DataSize = (value + 4) << 3; + //get => DataSize / 8 - 4; + //set => DataSize = (value + 4) * 8; + } + [FieldOrder(6)] [FieldEndianness(Endianness.Big)] public uint Unknown5 { get; set; } = 2684702720; [Ignore] public byte[] EncodedRle { get; set; } @@ -100,33 +107,34 @@ namespace UVtools.Core.FileFormats public unsafe byte[] Encode(Mat mat) { - List<byte> rawData = new List<byte>(); + List<byte> rawData = new(); var spanMat = mat.GetBytePointer(); var imageLength = mat.GetLength(); int rep = 0; byte color = 0; + int totalPixels = 0; void AddRep() { if (rep <= 0) return; + + totalPixels += rep; rep--; - byte rle = - (byte) (((rep & 1) > 0 ? 128 : 0) | - ((rep & 2) > 0 ? 64 : 0) | - ((rep & 4) > 0 ? 32 : 0) | - ((rep & 8) > 0 ? 16 : 0) | - ((rep & 16) > 0 ? 8 : 0) | - ((rep & 32) > 0 ? 4 : 0) | - ((rep & 64) > 0 ? 2 : 0) | color); + byte rle = (byte) (((rep & 1) > 0 ? 128 : 0) | + ((rep & 2) > 0 ? 64 : 0) | + ((rep & 4) > 0 ? 32 : 0) | + ((rep & 8) > 0 ? 16 : 0) | + ((rep & 16) > 0 ? 8 : 0) | + ((rep & 32) > 0 ? 4 : 0) | + ((rep & 64) > 0 ? 2 : 0) | color); rawData.Add(rle); } for (int i = 0; i < imageLength; i++) { - //color = color <= 127 ? 0 : 255; // Sanitize no AA - byte thisColor = spanMat[i] <= 127 ? byte.MinValue : byte.MaxValue; // Sanitize no AA + byte thisColor = spanMat[i] <= 127 ? (byte)0 : (byte)1; // Sanitize no AA if (thisColor != color) { AddRep(); @@ -146,8 +154,13 @@ namespace UVtools.Core.FileFormats AddRep(); + if (totalPixels != imageLength) + { + throw new FileLoadException($"Error image ran shortly or off the end, expecting {imageLength} pixels, got {totalPixels} pixels."); + } + EncodedRle = rawData.ToArray(); - DataSize = (uint)(EncodedRle.Length * 8 + 4); + RleDataSize = (uint) EncodedRle.Length; return EncodedRle; } @@ -157,31 +170,43 @@ namespace UVtools.Core.FileFormats var matSpan = mat.GetBytePointer(); var imageLength = mat.GetLength(); - int pixel = 0; + uint pixel = 0; foreach (var run in EncodedRle) { - byte col = (byte) ((run & 0x01) * 255); - - var numPixelsInRun = - (((run & 128) > 0 ? 1 : 0) | - ((run & 64) > 0 ? 2 : 0) | - ((run & 32) > 0 ? 4 : 0) | - ((run & 16) > 0 ? 8 : 0) | - ((run & 8) > 0 ? 16 : 0) | - ((run & 4) > 0 ? 32 : 0) | - ((run & 2) > 0 ? 64 : 0)) + 1; - + byte brightness = (byte) ((run & 0x01) * 255); + + uint numPixelsInRun = + (uint) ((((run & 128) > 0 ? 1 : 0) | + ((run & 64) > 0 ? 2 : 0) | + ((run & 32) > 0 ? 4 : 0) | + ((run & 16) > 0 ? 8 : 0) | + ((run & 8) > 0 ? 16 : 0) | + ((run & 4) > 0 ? 32 : 0) | + ((run & 2) > 0 ? 64 : 0)) + 1); + + if (brightness == 0) // Don't fill black pixels + { + pixel += numPixelsInRun; + continue; + } + for (; numPixelsInRun > 0; numPixelsInRun--) { if (pixel > imageLength) { mat.Dispose(); - throw new FileLoadException($"Error image ran off the end, expecting {imageLength} pixels"); + throw new FileLoadException($"Error image ran off the end, expecting {imageLength} pixels."); } - matSpan[pixel++] = col; + matSpan[pixel++] = brightness; } } + if (pixel != imageLength && pixel-1 != imageLength) + { + mat.Dispose(); + throw new FileLoadException($"Error image ran shortly or off the end, expecting {imageLength} pixels, got {pixel} pixels."); + } + // Not required as mat is all black by default //for (;pixel < imageLength; pixel++) matSpan[pixel] = 0; @@ -197,8 +222,8 @@ namespace UVtools.Core.FileFormats #region Properties - public Header HeaderSettings { get; protected internal set; } = new Header(); - public LayerHeader LayerSettings { get; protected internal set; } = new LayerHeader(); + public Header HeaderSettings { get; protected internal set; } = new(); + public LayerHeader LayerSettings { get; protected internal set; } = new(); public override FileFormatType FileType => FileFormatType.Binary; public override FileExtension[] FileExtensions { get; } = { @@ -221,7 +246,7 @@ namespace UVtools.Core.FileFormats }; - public override Size[] ThumbnailsOriginalSize { get; } = {new(225, 168) }; + public override Size[] ThumbnailsOriginalSize { get; } = {new(224, 168) }; public override uint ResolutionX { @@ -261,7 +286,7 @@ namespace UVtools.Core.FileFormats public override float LayerHeight { - get => (float) Math.Round(HeaderSettings.LayerHeight); + get => (float) Layer.RoundHeight(HeaderSettings.LayerHeight); set { HeaderSettings.LayerHeight = Layer.RoundHeight(value); @@ -269,6 +294,12 @@ namespace UVtools.Core.FileFormats } } + public override float MachineZ + { + get => Header.BuildZ; + set { } + } + public override uint LayerCount { get => base.LayerCount; @@ -293,7 +324,7 @@ namespace UVtools.Core.FileFormats set => base.ExposureTime = (float) (HeaderSettings.ExposureSeconds = Math.Round(value, 2)); } - public override float BottomLiftHeight => LightOffDelay; + public override float BottomLiftHeight => LiftHeight; public override float LiftHeight { @@ -306,21 +337,13 @@ namespace UVtools.Core.FileFormats public override float LiftSpeed { get => (float) Math.Round(HeaderSettings.LiftSpeed * 60.0, 2); - set - { - HeaderSettings.LiftSpeed = Math.Round(value / 60.0, 2); - base.LiftSpeed = value; - } + set => base.LiftSpeed = (float) (HeaderSettings.LiftSpeed = Math.Round(value / 60.0, 2)); } public override float RetractSpeed { get => (float)Math.Round(HeaderSettings.RetractSpeed * 60.0, 2); - set - { - HeaderSettings.RetractSpeed = (float) Math.Round(value / 60.0, 2); - base.RetractSpeed = value; - } + set => base.RetractSpeed = (float) (HeaderSettings.RetractSpeed = (float) Math.Round(value / 60.0, 2)); } public override float BottomLightOffDelay => LightOffDelay; @@ -365,14 +388,14 @@ namespace UVtools.Core.FileFormats int index = 0; for (int i = 0; i < imageLength; i+=3) { + byte r = span[i + 2]; // 60 + byte g = span[i + 1]; byte b = span[i]; - byte g = span[i+1]; - byte r = span[i+2]; - ushort rgb15 = (ushort) (((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 0)); + ushort color = (ushort)(((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3)); - bytes[index++] = (byte) (rgb15 >> 8); - bytes[index++] = (byte) (rgb15 & 0xff); + bytes[index++] = (byte)color; + bytes[index++] = (byte)(color >> 8); } if (index != bytes.Length) @@ -383,41 +406,62 @@ namespace UVtools.Core.FileFormats return bytes; } + public unsafe Mat PreviewDecode(byte[] data) + { + Mat mat = new((int)HeaderSettings.PreviewResolutionY, (int)HeaderSettings.PreviewResolutionX, DepthType.Cv8U, 3); + var span = mat.GetBytePointer(); + int spanIndex = 0; + for (int i = 0; i < data.Length; i += 2) + { + ushort color16 = BitExtensions.ToUShortLittleEndian(data[i], data[i + 1]); + + //var r = (byte)((color16 & 0x1F) << 3); + //var g = (byte)(((color16 >> 5) & 0x3F) << 2); + //var b = (byte)(((color16 >> 11) & 0x1f) << 3); + var r = (byte)((color16 << 3) & 0xF8); // Mask: 11111000 + var g = (byte)((color16 >> 3) & 0xFC); // Mask: 11111100 + var b = (byte)((color16 >> 8) & 0xF8); // Mask: 11111000 + + span[spanIndex++] = b; + span[spanIndex++] = g; + span[spanIndex++] = r; + } + + return mat; + } + protected override void EncodeInternally(string fileFullPath, OperationProgress progress) { - throw new NotSupportedException("PhotonS is read-only format, please use pws instead!"); + //throw new NotSupportedException("PhotonS is read-only format, please use pws instead!"); //uint currentOffset = (uint)Helpers.Serializer.SizeOf(HeaderSettings); - using (var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write)) - { - outputFile.WriteSerialize(HeaderSettings); - outputFile.WriteBytes(PreviewEncode(Thumbnails[0])); - LayerSettings.LayerCount = LayerCount; - outputFile.WriteSerialize(LayerSettings); + using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write); + outputFile.WriteSerialize(HeaderSettings); + outputFile.WriteBytes(PreviewEncode(Thumbnails[0])); + outputFile.WriteSerialize(LayerSettings); - LayerData[] layerData = new LayerData[LayerCount]; + var layerData = new LayerData[LayerCount]; - Parallel.For(0, LayerCount, layerIndex => + Parallel.For(0, LayerCount, layerIndex => + { + if (progress.Token.IsCancellationRequested) return; + using (var mat = this[layerIndex].LayerMat) { - if (progress.Token.IsCancellationRequested) return; - using (var mat = this[layerIndex].LayerMat) - { - layerData[layerIndex] = new LayerData(); - layerData[layerIndex].Encode(mat); - } + layerData[layerIndex] = new LayerData(); + layerData[layerIndex].Encode(mat); + } - progress.LockAndIncrement(); - }); + progress.LockAndIncrement(); + }); - progress.ItemName = "Saving layers"; - progress.ProcessedItems = 0; + progress.ItemName = "Saving layers"; + progress.ProcessedItems = 0; - for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) - { - progress.Token.ThrowIfCancellationRequested(); - outputFile.WriteSerialize(layerData[layerIndex]); - outputFile.WriteBytes(layerData[layerIndex].EncodedRle); - progress++; - } + for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) + { + progress.Token.ThrowIfCancellationRequested(); + outputFile.WriteSerialize(layerData[layerIndex]); + outputFile.WriteBytes(layerData[layerIndex].EncodedRle); + progress++; } Debug.WriteLine("Encode Results:"); @@ -425,84 +469,57 @@ namespace UVtools.Core.FileFormats Debug.WriteLine("-End-"); } - public unsafe Mat PreviewDecode(byte []data) - { - Mat mat = new Mat((int) HeaderSettings.PreviewResolutionX, (int)HeaderSettings.PreviewResolutionY, DepthType.Cv8U, 3); - var span = mat.GetBytePointer(); - int spanIndex = 0; - for (int i = 0; i < data.Length; i+=2) - { - ushort color16 = (ushort)(data[i] + (data[i + 1] << 8)); - - var r = (color16 >> 11) & 0x1F; - var g = (color16 >> 5) & 0x3F; - var b = (color16 >> 0) & 0x1F; - - /*span[spanIndex++] = (byte)(b << 3); - span[spanIndex++] = (byte)(g << 2); - span[spanIndex++] = (byte)(r << 3);*/ - - span[spanIndex++] = (byte)((b << 3) | (b & 0x7)); - span[spanIndex++] = (byte)((g << 2) | (g & 0x3)); - span[spanIndex++] = (byte)((r << 3) | (r & 0x7)); - } - - return mat; - } - 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.Deserialize<Header>(inputFile); + if (HeaderSettings.Tag1 != Header.TAG1 || HeaderSettings.Tag2 != Header.TAG2) { - 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); - byte[] previewData = new byte[previewSize]; + int previewSize = (int) (HeaderSettings.PreviewResolutionX * HeaderSettings.PreviewResolutionY * 2); + byte[] previewData = new byte[previewSize]; - uint currentOffset = (uint) Helpers.Serializer.SizeOf(HeaderSettings); - currentOffset += inputFile.ReadBytes(previewData); - Thumbnails[0] = PreviewDecode(previewData); + uint currentOffset = (uint) Helpers.Serializer.SizeOf(HeaderSettings); + currentOffset += inputFile.ReadBytes(previewData); + Thumbnails[0] = PreviewDecode(previewData); - LayerSettings = Helpers.Deserialize<LayerHeader>(inputFile); - currentOffset += (uint)Helpers.Serializer.SizeOf(LayerSettings); + LayerSettings = Helpers.Deserialize<LayerHeader>(inputFile); + currentOffset += (uint)Helpers.Serializer.SizeOf(LayerSettings); - Debug.WriteLine(HeaderSettings); - Debug.WriteLine(LayerSettings); + Debug.WriteLine(HeaderSettings); + Debug.WriteLine(LayerSettings); - LayerData[] layerData = new LayerData[LayerSettings.LayerCount]; - progress.Reset(OperationProgress.StatusGatherLayers, LayerSettings.LayerCount); + var layerData = new LayerData[LayerSettings.LayerCount]; + progress.Reset(OperationProgress.StatusGatherLayers, LayerSettings.LayerCount); - for (int layerIndex = 0; layerIndex < LayerSettings.LayerCount; layerIndex++) - { - progress.Token.ThrowIfCancellationRequested(); - layerData[layerIndex] = Helpers.Deserialize<LayerData>(inputFile); - layerData[layerIndex].EncodedRle = new byte[layerData[layerIndex].RleDataSize]; - currentOffset += inputFile.ReadBytes(layerData[layerIndex].EncodedRle); - Debug.WriteLine($"Layer {layerIndex} -> {layerData[layerIndex]}"); - } + for (int layerIndex = 0; layerIndex < LayerSettings.LayerCount; layerIndex++) + { + progress.Token.ThrowIfCancellationRequested(); + layerData[layerIndex] = Helpers.Deserialize<LayerData>(inputFile); + layerData[layerIndex].EncodedRle = new byte[layerData[layerIndex].RleDataSize]; + currentOffset += inputFile.ReadBytes(layerData[layerIndex].EncodedRle); + Debug.WriteLine($"Layer {layerIndex} -> {layerData[layerIndex]}"); + } - LayerManager.Init(LayerSettings.LayerCount); - progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount); + LayerManager.Init(LayerSettings.LayerCount); + progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount); - Parallel.For(0, LayerCount, - //new ParallelOptions{MaxDegreeOfParallelism = 1}, - layerIndex => + Parallel.For(0, LayerCount, + //new ParallelOptions{MaxDegreeOfParallelism = 1}, + layerIndex => { if (progress.Token.IsCancellationRequested) return; using var image = layerData[layerIndex].Decode(); - this[layerIndex] = new Layer((uint) layerIndex, image, LayerManager); + this[layerIndex] = new Layer((uint) layerIndex, image, this); progress.LockAndIncrement(); }); - LayerManager.RebuildLayersProperties(); - } + LayerManager.RebuildLayersProperties(); } public override void SaveAs(string filePath = null, OperationProgress progress = null) @@ -524,12 +541,9 @@ 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); } #endregion |