diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-07-03 03:16:17 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-07-03 03:16:17 +0300 |
commit | ac51b7c4e017f4e5abea87ad4def061584bc77f4 (patch) | |
tree | 8586e3cb34c97426e2824f07f6553c9738441fbd /UVtools.Core | |
parent | 2329074efb137136db3597c95c040b3a8afdeeab (diff) |
v2.14.0v2.14.0
- **File Formats:**
- (Add) SL1S: Prusa SL1S Speed
- (Add) CTB v4 support (318570758)
- (Improvement) PHOTON, CBDDLP, CTB v2, PHZ: Disallow per layer settings, beside the format support, printers never use it
- (Improvement) Longer Orange format with new found keys
- (Improvement) CXDLP: Fix the resolution from CL-60 and trigger an error when a invalid resolution was set and unable to detect the printer model
- **Prusa Slicer:**
- (Add) UVtools Prusa SL1S SPEED
- (Add) Longer Orange 120
- (Fix) Creality HALOT-ONE CL-60: Flip resolution & display and remove mirror
- (Fix) Creality HALOT-SKY CL-89: Remove mirror
- (Improvement) Longer Orange printers with better default settings
- (Add) Button on `Help - Sponsor`: Open github sponsor webpage
Diffstat (limited to 'UVtools.Core')
-rw-r--r-- | UVtools.Core/About.cs | 1 | ||||
-rw-r--r-- | UVtools.Core/EmguCV/Contour.cs | 240 | ||||
-rw-r--r-- | UVtools.Core/Extensions/FileStreamExtensions.cs | 20 | ||||
-rw-r--r-- | UVtools.Core/FileFormats/CWSFile.cs | 2 | ||||
-rw-r--r-- | UVtools.Core/FileFormats/CXDLPFile.cs | 6 | ||||
-rw-r--r-- | UVtools.Core/FileFormats/ChituboxFile.cs | 224 | ||||
-rw-r--r-- | UVtools.Core/FileFormats/FileFormat.cs | 36 | ||||
-rw-r--r-- | UVtools.Core/FileFormats/LGSFile.cs | 155 | ||||
-rw-r--r-- | UVtools.Core/FileFormats/PHZFile.cs | 4 | ||||
-rw-r--r-- | UVtools.Core/FileFormats/PhotonWorkshopFile.cs | 14 | ||||
-rw-r--r-- | UVtools.Core/FileFormats/SL1File.cs | 4 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationCalibrateExposureFinder.cs | 2 | ||||
-rw-r--r-- | UVtools.Core/UVtools.Core.csproj | 2 |
13 files changed, 593 insertions, 117 deletions
diff --git a/UVtools.Core/About.cs b/UVtools.Core/About.cs index 35373a1..ba904d5 100644 --- a/UVtools.Core/About.cs +++ b/UVtools.Core/About.cs @@ -7,7 +7,6 @@ */ using System; -using System.IO; using System.Reflection; namespace UVtools.Core diff --git a/UVtools.Core/EmguCV/Contour.cs b/UVtools.Core/EmguCV/Contour.cs new file mode 100644 index 0000000..20d216e --- /dev/null +++ b/UVtools.Core/EmguCV/Contour.cs @@ -0,0 +1,240 @@ +/* + * 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 System.Collections; +using System.Collections.Generic; +using System.Drawing; +using Emgu.CV; +using Emgu.CV.CvEnum; +using Emgu.CV.Structure; +using Emgu.CV.Util; +using UVtools.Core.Extensions; + +namespace UVtools.Core.EmguCV +{ + /// <summary> + /// A contour cache for OpenCV + /// </summary> + public class Contour : IReadOnlyCollection<Point>, IDisposable + { + #region Members + + private VectorOfPoint _points; + private Rectangle? _bounds; + private RotatedRect? _boundsBestFit; + private CircleF? _minEnclosingCircle; + private bool? _isConvex; + private double _area = double.NaN; + private double _perimeter = double.NaN; + private Moments _moments; + private Point? _centroid; + + #endregion + + #region Properties + public int XMin => Bounds.X; + + public int YMin => Bounds.Y; + + public int XMax => Bounds.Right; + + public int YMax => Bounds.Bottom; + + public Rectangle Bounds => _bounds ??= CvInvoke.BoundingRectangle(_points); + + public RotatedRect BoundsBestFit => _boundsBestFit ??= CvInvoke.MinAreaRect(_points); + + public CircleF MinEnclosingCircle => _minEnclosingCircle ??= CvInvoke.MinEnclosingCircle(_points); + + public bool IsConvex => _isConvex ??= CvInvoke.IsContourConvex(_points); + + /// <summary> + /// Gets the area of the contour + /// </summary> + public double Area + { + get + { + if (double.IsNaN(_area)) + { + _area = CvInvoke.ContourArea(_points); + } + + return _area; + } + } + + /// <summary> + /// Gets the perimeter of the contours + /// </summary> + public double Perimeter + { + get + { + if (double.IsNaN(_perimeter)) + { + _perimeter = CvInvoke.ArcLength(_points, true); + } + return _perimeter; + } + } + + public Moments Moments => _moments ??= CvInvoke.Moments(_points); + + /// <summary> + /// Gets the centroid of the contour + /// </summary> + public Point Centroid => _centroid ??= Moments.M00 == 0 ? Point.Empty : + new Point( + (int)Math.Round(_moments.M10 / _moments.M00), + (int)Math.Round(_moments.M01 / _moments.M00)); + + /// <summary> + /// Gets or sets the contour <see cref="Point"/> + /// </summary> + public VectorOfPoint Points + { + get => _points; + set + { + Dispose(); + _points = value ?? throw new ArgumentNullException(nameof(Points)); + } + } + + + /// <summary> + /// Gets if this contour have any point + /// </summary> + public bool IsEmpty => _points.Size == 0; + #endregion + + #region Constructor + public Contour(VectorOfPoint points) : this(points.ToArray()) + { } + + public Contour(Point[] points) + { + Points = new VectorOfPoint(points); + } + #endregion + + #region Methods + + /// <summary> + /// Checks if a given <see cref="Point"/> is inside the contour rectangle bounds + /// </summary> + /// <param name="point"></param> + /// <returns></returns> + public bool IsInsideBounds(Point point) => Bounds.Contains(point); + + /// <summary> + /// Gets if a given <see cref="Point"/> is inside the contour + /// </summary> + /// <param name="point"></param> + /// <returns></returns> + public bool IsInside(Point point) + { + if (!IsInsideBounds(point)) return false; + return CvInvoke.PointPolygonTest(_points, point, false) >= 0; + } + + public double MeasureDist(Point point) + { + if (!IsInsideBounds(point)) return -1; + return CvInvoke.PointPolygonTest(_points, point, true); + } + + public IOutputArray ContourApproximation(double epsilon = 0.1) + { + var mat = new Mat(); + CvInvoke.ApproxPolyDP(_points, mat, epsilon*Perimeter, true); + return mat; + } + + /* + /// <summary> + /// Calculate the X/Y min/max boundary + /// </summary> + private void CalculateMinMax() + { + Bounds = Rectangle.Empty; + + if (_contourPoints.Length == 0) + { + _xMin = -1; + _yMin = -1; + _xMax = -1; + _yMax = -1; + return; + } + + _xMin = int.MaxValue; + _yMin = int.MaxValue; + _xMax = int.MinValue; + _yMax = int.MinValue; + + for (int i = 0; i < _contourPoints.Length; i++) + { + _xMin = Math.Min(_xMin, _contourPoints[i].X); + _yMin = Math.Min(_yMin, _contourPoints[i].Y); + + _xMax = Math.Max(_xMax, _contourPoints[i].X); + _yMax = Math.Max(_yMax, _contourPoints[i].Y); + } + + Bounds = new Rectangle(_xMin, _yMin, _xMax - _xMin, _yMax - _yMin); + } + */ + + public void FitCircle(Mat src, MCvScalar color, int thickness = 1, LineType lineType = LineType.EightConnected, int shift = 0) + { + CvInvoke.Circle(src, + MinEnclosingCircle.Center.ToPoint(), + (int) Math.Round(MinEnclosingCircle.Radius), + color, + thickness, + lineType, + shift); + } + + /*public void FitEllipse(Mat src, MCvScalar color, int thickness = 1, LineType lineType = LineType.EightConnected, int shift = 0) + { + var ellipse = CvInvoke.FitEllipse(_points); + CvInvoke.Ellipse(src, ellipse.Center.ToPoint(), ellipse.Size.ToSize(), ellipse.Angle, 0, 0); + }*/ + #endregion + + #region Implementations + + public IEnumerator<Point> GetEnumerator() + { + return (IEnumerator<Point>) _points.ToArray().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public int Count => _points.Size; + + public Point this[int index] => _points[index]; + public Point this[uint index] => _points[(int) index]; + public Point this[long index] => _points[(int) index]; + public Point this[ulong index] => _points[(int) index]; + + public void Dispose() + { + _points?.Dispose(); + _moments?.Dispose(); + } + #endregion + } +} diff --git a/UVtools.Core/Extensions/FileStreamExtensions.cs b/UVtools.Core/Extensions/FileStreamExtensions.cs index b0370f2..02fba02 100644 --- a/UVtools.Core/Extensions/FileStreamExtensions.cs +++ b/UVtools.Core/Extensions/FileStreamExtensions.cs @@ -24,6 +24,26 @@ namespace UVtools.Core.Extensions return buffer; } + public static uint ReadUShortLittleEndian(this FileStream fs, int offset = 0) + { + return BitExtensions.ToUShortLittleEndian(fs.ReadBytes(2, offset)); + } + + public static uint ReadUShortBigEndian(this FileStream fs, int offset = 0) + { + return BitExtensions.ToUShortBigEndian(fs.ReadBytes(2, offset)); + } + + public static uint ReadUIntLittleEndian(this FileStream fs, int offset = 0) + { + return BitExtensions.ToUIntLittleEndian(fs.ReadBytes(4, offset)); + } + + public static uint ReadUIntBigEndian(this FileStream fs, int offset = 0) + { + return BitExtensions.ToUIntBigEndian(fs.ReadBytes(4, offset)); + } + public static uint WriteStream(this FileStream fs, MemoryStream stream, int offset = 0) { return fs.WriteBytes(stream.ToArray(), offset); diff --git a/UVtools.Core/FileFormats/CWSFile.cs b/UVtools.Core/FileFormats/CWSFile.cs index 832628a..192f5a2 100644 --- a/UVtools.Core/FileFormats/CWSFile.cs +++ b/UVtools.Core/FileFormats/CWSFile.cs @@ -532,7 +532,7 @@ namespace UVtools.Core.FileFormats Printer = PrinterType.Elfin; for (int i = 0; i < FileExtensions.Length; i++) { - if (!fileFullPath.EndsWith(FileExtensions[i].Extension) && !fileFullPath.EndsWith($"{FileExtensions[i].Extension}{TemporaryFileAppend}")) continue; + if (!FileEndsWith(FileExtensions[i].Extension)) continue; Printer = (PrinterType) i+1; } } diff --git a/UVtools.Core/FileFormats/CXDLPFile.cs b/UVtools.Core/FileFormats/CXDLPFile.cs index 5d0d881..aaabbbf 100644 --- a/UVtools.Core/FileFormats/CXDLPFile.cs +++ b/UVtools.Core/FileFormats/CXDLPFile.cs @@ -560,7 +560,7 @@ namespace UVtools.Core.FileFormats { using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write); - if (ResolutionX == 2560 && ResolutionY == 1620) + if (ResolutionX == 1620 && ResolutionY == 2560) { MachineName = "CL-60"; } @@ -568,6 +568,10 @@ namespace UVtools.Core.FileFormats { MachineName = "CL-89"; } + else if (!MachineName.StartsWith("CL-")) + { + throw new Exception("Unable to detect printer model from resolution, check if resolution is well defined on slicer for your printer model."); + } var pageBreak = PageBreak.Bytes; diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs index 4e0cbc6..05cf03f 100644 --- a/UVtools.Core/FileFormats/ChituboxFile.cs +++ b/UVtools.Core/FileFormats/ChituboxFile.cs @@ -14,6 +14,7 @@ using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; +using System.Text; using System.Threading.Tasks; using BinarySerialization; using Emgu.CV; @@ -29,6 +30,7 @@ namespace UVtools.Core.FileFormats #region Constants private const uint MAGIC_CBDDLP = 0x12FD0019; // 318570521 private const uint MAGIC_CBT = 0x12FD0086; // 318570630 + private const uint MAGIC_CBTv4 = 0x12FD0106; // 318570758 private const ushort REPEATRGB15MASK = 0x20; private const byte RLE8EncodingLimit = 0x7d; // 125; @@ -36,7 +38,11 @@ namespace UVtools.Core.FileFormats private const uint ENCRYPTYION_MODE_CBDDLP = 0x8; // 0 or 8 private const uint ENCRYPTYION_MODE_CTBv2 = 0xF; // 15 for ctb v2 files - private const uint ENCRYPTYION_MODE_CTBv3 = 0x2000000F; // 536870927 for ctb v3 files (This allow per layer settings, while 0xF don't) + private const uint ENCRYPTYION_MODE_CTBv3 = 536870927; // 536870927 for ctb v3 files (This allow per layer settings, while 15 don't) + private const uint ENCRYPTYION_MODE_CTBv4 = 1073741839; // 1073741839 for ctb v3 files (This allow per layer settings, while 15 don't) + + private const string CTBv4_DISCLAIMER = "Layout and record format for the ctb and cbddlp file types are the copyrighted programs or codes of CBD Technology (China) Inc..The Customer or User shall not in any manner reproduce, distribute, modify, decompile, disassemble, decrypt, extract, reverse engineer, lease, assign, or sublicense the said programs or codes."; + private const ushort CTBv4_DISCLAIMER_SIZE = 320; #endregion #region Sub Classes @@ -270,13 +276,13 @@ namespace UVtools.Core.FileFormats public class SlicerInfo { private string _machineName; - [FieldOrder(0)] public uint Padding1 { get; set; } - [FieldOrder(1)] public uint Padding2 { get; set; } - [FieldOrder(2)] public uint Padding3 { get; set; } - [FieldOrder(3)] public uint Padding4 { get; set; } - [FieldOrder(4)] public uint Padding5 { get; set; } - [FieldOrder(5)] public uint Padding6 { get; set; } - [FieldOrder(6)] public uint Padding7 { get; set; } + [FieldOrder(0)] public float BottomLiftDistance2 { get; set; } + [FieldOrder(1)] public float BottomLiftSpeed2 { get; set; } + [FieldOrder(2)] public float LiftHeight2 { get; set; } + [FieldOrder(3)] public float LiftSpeed2 { get; set; } + [FieldOrder(4)] public float RetractHeight2 { get; set; } + [FieldOrder(5)] public float RetractSpeed2 { get; set; } + [FieldOrder(6)] public float RestTimeAfterLift { get; set; } /// <summary> /// Gets the machine name offset to a string naming the machine type, and its length in bytes. @@ -290,14 +296,14 @@ namespace UVtools.Core.FileFormats /// <summary> /// Gets the parameter used to control encryption. - /// Not totally understood. 0/8 for cbddlp files, 0xF (15) for ctb files, 0x2000000F (536870927) for v3 ctb files allow per layer parameters + /// Not totally understood. 0/8 for cbddlp files, 0xF (15) for ctb files, 0x2000000F (536870927) for v3 ctb and 1073741839 for v4 ctb files to allow per layer parameters /// </summary> [FieldOrder(9)] public uint EncryptionMode { get; set; } = ENCRYPTYION_MODE_CTBv3; /// <summary> /// Gets a number that increments with time or number of models sliced, or both. Zeroing it in output seems to have no effect. Possibly a user tracking bug. /// </summary> - [FieldOrder(10)] public uint MysteriousId { get; set; } + [FieldOrder(10)] public uint MysteriousId { get; set; } = 305419896; // v3 = 305419896 | v4 = 27087675 /// <summary> /// Gets the user-selected antialiasing level. For cbddlp files this will match the level_set_count. For ctb files, this number is essentially arbitrary. @@ -309,13 +315,13 @@ namespace UVtools.Core.FileFormats /// (No provision is made to name the software being used, so this assumes that only one software package can generate the files. /// Probably best to hardcode it at 0x01060300.) /// </summary> - [FieldOrder(12)] public uint SoftwareVersion { get; set; } = 0x01060300; - [FieldOrder(13)] public uint Unknown1 { get; set; } - [FieldOrder(14)] public uint Padding8 { get; set; } + [FieldOrder(12)] public uint SoftwareVersion { get; set; } = 0x01060300; // ctb v3 = 17171200 | ctb v4 = 16777216 + [FieldOrder(13)] public float RestTimeAfterRetract { get; set; } + [FieldOrder(14)] public float RestTimeAfterLift2 { get; set; } [FieldOrder(15)] public uint TransitionLayerCount { get; set; } // CTB not all printers - [FieldOrder(16)] public uint Padding10 { get; set; } - [FieldOrder(17)] public uint Padding11 { get; set; } - [FieldOrder(18)] public uint Padding12 { get; set; } + [FieldOrder(16)] public uint Padding1 { get; set; } + [FieldOrder(17)] public uint Padding2 { get; set; } + [FieldOrder(18)] public uint Padding3 { get; set; } /// <summary> /// Gets the machine name. string is not nul-terminated. @@ -337,12 +343,90 @@ namespace UVtools.Core.FileFormats public override string ToString() { - return $"{nameof(Padding1)}: {Padding1}, {nameof(Padding2)}: {Padding2}, {nameof(Padding3)}: {Padding3}, {nameof(Padding4)}: {Padding4}, {nameof(Padding5)}: {Padding5}, {nameof(Padding6)}: {Padding6}, {nameof(Padding7)}: {Padding7}, {nameof(MachineNameAddress)}: {MachineNameAddress}, {nameof(MachineNameSize)}: {MachineNameSize}, {nameof(EncryptionMode)}: {EncryptionMode}, {nameof(MysteriousId)}: {MysteriousId}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(Unknown1)}: {Unknown1}, {nameof(Padding8)}: {Padding8}, {nameof(TransitionLayerCount)}: {TransitionLayerCount}, {nameof(Padding10)}: {Padding10}, {nameof(Padding11)}: {Padding11}, {nameof(Padding12)}: {Padding12}, {nameof(MachineName)}: {MachineName}"; + return $"{nameof(BottomLiftDistance2)}: {BottomLiftDistance2}, {nameof(BottomLiftSpeed2)}: {BottomLiftSpeed2}, {nameof(LiftHeight2)}: {LiftHeight2}, {nameof(LiftSpeed2)}: {LiftSpeed2}, {nameof(RetractHeight2)}: {RetractHeight2}, {nameof(RetractSpeed2)}: {RetractSpeed2}, {nameof(RestTimeAfterLift)}: {RestTimeAfterLift}, {nameof(MachineNameAddress)}: {MachineNameAddress}, {nameof(MachineNameSize)}: {MachineNameSize}, {nameof(EncryptionMode)}: {EncryptionMode}, {nameof(MysteriousId)}: {MysteriousId}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(RestTimeAfterRetract)}: {RestTimeAfterRetract}, {nameof(RestTimeAfterLift2)}: {RestTimeAfterLift2}, {nameof(TransitionLayerCount)}: {TransitionLayerCount}, {nameof(Padding1)}: {Padding1}, {nameof(Padding2)}: {Padding2}, {nameof(Padding3)}: {Padding3}, {nameof(MachineName)}: {MachineName}"; } } #endregion + #region PrintParametersV4 + public sealed class PrintParametersV4 + { + [FieldOrder(1)] + [FieldLength(CTBv4_DISCLAIMER_SIZE)] + public string Disclaimer { get; set; } = CTBv4_DISCLAIMER; // 320 bytes + + [FieldOrder(2)] + public float BottomRetractSpeed { get; set; } + + [FieldOrder(3)] + public float BottomRetractSpeed2 { get; set; } + + [FieldOrder(4)] + public uint Padding1 { get; set; } + + [FieldOrder(5)] + public float Four1 { get; set; } = 4; // 4? + + [FieldOrder(6)] + public uint Padding2 { get; set; } + + [FieldOrder(7)] + public float Four2 { get; set; } = 4; // ? + + [FieldOrder(8)] + public float RestTimeAfterRetract { get; set; } + + [FieldOrder(9)] + public float RestTimeAfterLift { get; set; } + + [FieldOrder(10)] + public float RestTimeBeforeLift { get; set; } + + [FieldOrder(11)] + public float BottomRetractHeight2 { get; set; } + + [FieldOrder(12)] + public float Unknown1 { get; set; } // 2955.996 or uint:1161347054 but changes + + [FieldOrder(13)] + public uint Unknown2 { get; set; } // 73470 but changes + + [FieldOrder(14)] + public uint Unknown3 { get; set; } = 5; // 5? + + [FieldOrder(15)] + public uint Unknown4 { get; set; } // 139 but changes + + [FieldOrder(16)] + public uint Padding3 { get; set; } + + [FieldOrder(17)] + public uint Padding4 { get; set; } + + [FieldOrder(18)] + public uint Padding5 { get; set; } + + [FieldOrder(19)] + public uint Padding6 { get; set; } + + [FieldOrder(20)] + public uint Unknown5 { get; set; } // 23047 but changes + + [FieldOrder(21)] + public uint Unknown6 { get; set; } // 320 but changes + + [FieldOrder(22)] + [FieldCount(420)] + private byte[] Reserved { get; set; } = new byte[420]; // 420 bytes + + public override string ToString() + { + return $"{nameof(Disclaimer)}: {Disclaimer}, {nameof(BottomRetractSpeed)}: {BottomRetractSpeed}, {nameof(BottomRetractSpeed2)}: {BottomRetractSpeed2}, {nameof(Padding1)}: {Padding1}, {nameof(Four1)}: {Four1}, {nameof(Padding2)}: {Padding2}, {nameof(Four2)}: {Four2}, {nameof(RestTimeAfterRetract)}: {RestTimeAfterRetract}, {nameof(RestTimeAfterLift)}: {RestTimeAfterLift}, {nameof(RestTimeBeforeLift)}: {RestTimeBeforeLift}, {nameof(BottomRetractHeight2)}: {BottomRetractHeight2}, {nameof(Unknown1)}: {Unknown1}, {nameof(Unknown2)}: {Unknown2}, {nameof(Unknown3)}: {Unknown3}, {nameof(Unknown4)}: {Unknown4}, {nameof(Padding3)}: {Padding3}, {nameof(Padding4)}: {Padding4}, {nameof(Padding5)}: {Padding5}, {nameof(Padding6)}: {Padding6}, {nameof(Unknown5)}: {Unknown5}, {nameof(Unknown6)}: {Unknown6}, {nameof(Reserved)}: {Reserved}"; + } + } + #endregion + #region Preview /// <summary> /// The files contain two preview images. @@ -524,8 +608,6 @@ namespace UVtools.Core.FileFormats [Ignore] public byte[] EncodedRle { get; set; } [Ignore] public ChituboxFile Parent { get; set; } - [Ignore] public uint Version { get; set; } = 2; - public LayerData() { } @@ -814,7 +896,6 @@ namespace UVtools.Core.FileFormats rawData.Add((byte)(stride >> 8)); rawData.Add((byte)stride); } - } @@ -864,7 +945,7 @@ namespace UVtools.Core.FileFormats /// <summary> /// Gets a copy of layer data defenition /// </summary> - [FieldOrder(0)] public LayerData LayerData { get; set; } = new LayerData(); + [FieldOrder(0)] public LayerData LayerData { get; set; } = new(); /// <summary> /// Gets the total size of ctbImageInfo and Image data @@ -872,14 +953,14 @@ namespace UVtools.Core.FileFormats [FieldOrder(1)] public uint TotalSize { get; set; } [FieldOrder(2)] public float LiftHeight { get; set; } [FieldOrder(3)] public float LiftSpeed { get; set; } - [FieldOrder(4)] public uint Unknown6 { get; set; } - [FieldOrder(5)] public uint Unknown7 { get; set; } + [FieldOrder(4)] public float LiftHeight2 { get; set; } + [FieldOrder(5)] public float LiftSpeed2 { get; set; } [FieldOrder(6)] public float RetractSpeed { get; set; } - [FieldOrder(7)] public uint Unknown8 { get; set; } - [FieldOrder(8)] public uint Unknown9 { get; set; } - [FieldOrder(9)] public uint Unknown10 { get; set; } - [FieldOrder(10)] public uint Unknown11 { get; set; } - [FieldOrder(11)] public uint Unknown12 { get; set; } = 28672; // 28672 v3? + [FieldOrder(7)] public float RetractHeight2 { get; set; } + [FieldOrder(8)] public float RetractSpeed2 { get; set; } + [FieldOrder(9)] public float RestTimeBeforeLift { get; set; } + [FieldOrder(10)] public float RestTimeAfterLift { get; set; } + [FieldOrder(11)] public float RestTimeAfterRetract { get; set; } // 28672 v3? [FieldOrder(12)] public float LightPWM { get; set; } public LayerDataEx() @@ -905,7 +986,7 @@ namespace UVtools.Core.FileFormats public override string ToString() { - return $"{nameof(LayerData)}: {LayerData}, {nameof(TotalSize)}: {TotalSize}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(Unknown6)}: {Unknown6}, {nameof(Unknown7)}: {Unknown7}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(Unknown8)}: {Unknown8}, {nameof(Unknown9)}: {Unknown9}, {nameof(Unknown10)}: {Unknown10}, {nameof(Unknown11)}: {Unknown11}, {nameof(Unknown12)}: {Unknown12}, {nameof(LightPWM)}: {LightPWM}"; + return $"{nameof(LayerData)}: {LayerData}, {nameof(TotalSize)}: {TotalSize}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(LiftHeight2)}: {LiftHeight2}, {nameof(LiftSpeed2)}: {LiftSpeed2}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(RetractHeight2)}: {RetractHeight2}, {nameof(RetractSpeed2)}: {RetractSpeed2}, {nameof(RestTimeBeforeLift)}: {RestTimeBeforeLift}, {nameof(RestTimeAfterLift)}: {RestTimeAfterLift}, {nameof(RestTimeAfterRetract)}: {RestTimeAfterRetract}, {nameof(LightPWM)}: {LightPWM}"; } } @@ -965,10 +1046,11 @@ namespace UVtools.Core.FileFormats #region Properties - public Header HeaderSettings { get; protected internal set; } = new Header(); - public PrintParameters PrintParametersSettings { get; protected internal set; } = new PrintParameters(); + public Header HeaderSettings { get; protected internal set; } = new(); + public PrintParameters PrintParametersSettings { get; protected internal set; } = new(); - public SlicerInfo SlicerInfoSettings { get; protected internal set; } = new SlicerInfo(); + public SlicerInfo SlicerInfoSettings { get; protected internal set; } = new(); + public PrintParametersV4 PrintParametersV4Settings { get; protected internal set; } = new(); public Preview[] Previews { get; protected internal set; } @@ -1005,6 +1087,7 @@ namespace UVtools.Core.FileFormats public override PrintParameterModifier[] PrintParameterPerLayerModifiers { get { + if (!IsCbtFile) return null; // Only ctb files if (HeaderSettings.Version >= 3) { return new[] @@ -1018,14 +1101,15 @@ namespace UVtools.Core.FileFormats }; } - if (HeaderSettings.Version <= 2) + /* Disable for v2 beside the fields on format they are not used + if (HeaderSettings.Version <= 2) { return new[] { PrintParameterModifier.ExposureSeconds, PrintParameterModifier.LightOffDelay, }; - } + }*/ return null; } @@ -1192,7 +1276,7 @@ namespace UVtools.Core.FileFormats public override float RetractSpeed { get => PrintParametersSettings.RetractSpeed; - set => base.RetractSpeed = PrintParametersSettings.RetractSpeed = (float)Math.Round(value, 2); + set => base.RetractSpeed = PrintParametersV4Settings.BottomRetractSpeed = PrintParametersSettings.RetractSpeed = (float)Math.Round(value, 2); } public override byte BottomLightPWM @@ -1249,10 +1333,22 @@ namespace UVtools.Core.FileFormats } } - public override object[] Configs => new[] { (object)HeaderSettings, PrintParametersSettings, SlicerInfoSettings }; + public override object[] Configs + { + get + { + if (HeaderSettings.Version <= 1) + return new object[] { HeaderSettings }; + + if (HeaderSettings.Version <= 3) + return new object[] {HeaderSettings, PrintParametersSettings, SlicerInfoSettings}; + + return new object[] { HeaderSettings, PrintParametersSettings, SlicerInfoSettings, PrintParametersV4Settings }; + } + } public bool IsCbddlpFile => HeaderSettings.Magic == MAGIC_CBDDLP; - public bool IsCbtFile => HeaderSettings.Magic == MAGIC_CBT; + public bool IsCbtFile => HeaderSettings.Magic is MAGIC_CBT or MAGIC_CBTv4; public bool CanHash => !IsCbtFile && HeaderSettings.Version <= 2; #endregion @@ -1281,7 +1377,7 @@ namespace UVtools.Core.FileFormats { LayersHash.Clear(); - HeaderSettings.Magic = fileFullPath.EndsWith(".ctb") || fileFullPath.EndsWith($".ctb{TemporaryFileAppend}") ? MAGIC_CBT : MAGIC_CBDDLP; + HeaderSettings.Magic = FileEndsWith(".ctb") ? MAGIC_CBT : MAGIC_CBDDLP; HeaderSettings.PrintParametersSize = (uint)Helpers.Serializer.SizeOf(PrintParametersSettings); if (IsCbtFile) @@ -1295,23 +1391,33 @@ namespace UVtools.Core.FileFormats if (HeaderSettings.Version <= 2) { - if (SlicerInfoSettings.Unknown1 == 0) - SlicerInfoSettings.Unknown1 = 0x200; // 512 for v2 | 0 for v3 + //if (SlicerInfoSettings.RestTimeAfterRetract == 0) + //SlicerInfoSettings.RestTimeAfterRetract = 0x200; // 512 for v2 | 0 for v3 SlicerInfoSettings.EncryptionMode = ENCRYPTYION_MODE_CTBv2; PrintParametersSettings.Padding4 = 0x1234; // 4660 + + if (SlicerInfoSettings.MysteriousId == 0) + SlicerInfoSettings.MysteriousId = 305419896; } - else + else if(HeaderSettings.Version == 3) { SlicerInfoSettings.EncryptionMode = ENCRYPTYION_MODE_CTBv3; + + if (SlicerInfoSettings.MysteriousId == 0) + SlicerInfoSettings.MysteriousId = 305419896; + } + else + { + SlicerInfoSettings.EncryptionMode = ENCRYPTYION_MODE_CTBv4; + + if (SlicerInfoSettings.MysteriousId == 0) + SlicerInfoSettings.MysteriousId = 27087820; } - - if(SlicerInfoSettings.MysteriousId == 0) - SlicerInfoSettings.MysteriousId = 0x12345678; if (HeaderSettings.EncryptionKey == 0) { - Random rnd = new(); + var rnd = new Random(); HeaderSettings.EncryptionKey = (uint)rnd.Next(byte.MaxValue, int.MaxValue); } } @@ -1374,6 +1480,11 @@ namespace UVtools.Core.FileFormats currentOffset += Helpers.SerializeWriteFileStream(outputFile, SlicerInfoSettings); + + if (HeaderSettings.Version >= 4) + { + currentOffset += Helpers.SerializeWriteFileStream(outputFile, PrintParametersV4Settings); + } } HeaderSettings.LayersDefinitionOffsetAddress = currentOffset; @@ -1449,6 +1560,7 @@ namespace UVtools.Core.FileFormats Debug.WriteLine(Previews[1]); Debug.WriteLine(PrintParametersSettings); Debug.WriteLine(SlicerInfoSettings); + Debug.WriteLine(PrintParametersV4Settings); Debug.WriteLine("-End-"); } @@ -1459,9 +1571,14 @@ namespace UVtools.Core.FileFormats //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_CBDDLP && HeaderSettings.Magic != MAGIC_CBT) + + /*if (HeaderSettings.Magic == MAGIC_CBTv4) { - throw new FileLoadException("Not a valid CBDDLP nor CTB nor Photon file!", fileFullPath); + throw new FileLoadException("CTB v4 not supported!", fileFullPath); + }*/ + if (HeaderSettings.Magic is not MAGIC_CBDDLP and not MAGIC_CBT and not MAGIC_CBTv4) + { + throw new FileLoadException($"Not a valid PHOTON nor CBDDLP nor CTB file! Magic Value: {HeaderSettings.Magic}", fileFullPath); } if (HeaderSettings.Version == 1 || HeaderSettings.AntiAliasLevel == 0) @@ -1521,6 +1638,13 @@ namespace UVtools.Core.FileFormats Debug.WriteLine($"{nameof(MachineName)}: {MachineName}");*/ //} + if (HeaderSettings.Version >= 4) + { + PrintParametersV4Settings = Helpers.Deserialize<PrintParametersV4>(inputFile); + Debug.Write("Print Parameters V4 -> "); + Debug.WriteLine(PrintParametersV4Settings); + } + LayerDefinitions = new LayerData[HeaderSettings.AntiAliasLevel, HeaderSettings.LayerCount]; var LayerDefinitionsEx = HeaderSettings.Version >= 3 ? new LayerDataEx[HeaderSettings.LayerCount] : null; @@ -1652,6 +1776,12 @@ namespace UVtools.Core.FileFormats Helpers.SerializeWriteFileStream(outputFile, new LayerDataEx(LayerDefinitions[0, layerIndex], layerIndex)); } } + + if (HeaderSettings.Version >= 4) + { + outputFile.Seek(SlicerInfoSettings.MachineNameAddress + SlicerInfoSettings.MachineNameSize, SeekOrigin.Begin); + Helpers.SerializeWriteFileStream(outputFile, PrintParametersV4Settings); + } } #endregion diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs index c98eef2..a639fae 100644 --- a/UVtools.Core/FileFormats/FileFormat.cs +++ b/UVtools.Core/FileFormats/FileFormat.cs @@ -367,12 +367,12 @@ namespace UVtools.Core.FileFormats public abstract FileExtension[] FileExtensions { get; } /// <summary> - /// Gets the available <see cref="FileFormat.PrintParameterModifier"/> + /// Gets the available <see cref="PrintParameterModifier"/> /// </summary> public virtual PrintParameterModifier[] PrintParameterModifiers => null; /// <summary> - /// Gets the available <see cref="FileFormat.PrintParameterModifier"/> per layer + /// Gets the available <see cref="PrintParameterModifier"/> per layer /// </summary> public virtual PrintParameterModifier[] PrintParameterPerLayerModifiers => null; @@ -385,12 +385,12 @@ namespace UVtools.Core.FileFormats PrintParameterModifiers is not null && PrintParameterModifiers.Contains(modifier); /// <summary> - /// Checks if a <see cref="PrintParameterModifier"/> exists on print parameters + /// Checks if a <see cref="PrintParameterModifier"/> exists on layer parameters /// </summary> /// <param name="modifier"></param> /// <returns>True if exists, otherwise false</returns> - public bool HavePrintParameterPerLayerModifier(PrintParameterModifier modifier) => - PrintParameterPerLayerModifiers is not null && PrintParameterPerLayerModifiers.Contains(modifier); + public bool HaveLayerParameterModifier(PrintParameterModifier modifier) => + SupportPerLayerSettings && PrintParameterPerLayerModifiers.Contains(modifier); /// <summary> /// Gets the file filter for open and save dialogs @@ -917,7 +917,7 @@ namespace UVtools.Core.FileFormats public bool CanUseAnyLiftHeight => CanUseBottomLiftHeight || CanUseLiftHeight; public bool CanUseBottomLiftSpeed => HavePrintParameterModifier(PrintParameterModifier.BottomLiftSpeed); - public bool CanUseLiftSpeed => HavePrintParameterModifier(PrintParameterModifier.LiftHeight); + public bool CanUseLiftSpeed => HavePrintParameterModifier(PrintParameterModifier.LiftSpeed); public bool CanUseAnyLiftSpeed => CanUseBottomLiftSpeed || CanUseLiftSpeed; public bool CanUseRetractSpeed => HavePrintParameterModifier(PrintParameterModifier.RetractSpeed); @@ -930,6 +930,13 @@ namespace UVtools.Core.FileFormats public bool CanUseLightPWM => HavePrintParameterModifier(PrintParameterModifier.LightPWM); public bool CanUseAnyLightPWM => CanUseBottomLightPWM || CanUseLightPWM; + public bool CanUseLayerExposureTime => HaveLayerParameterModifier(PrintParameterModifier.ExposureSeconds); + public bool CanUseLayerLiftHeight => HaveLayerParameterModifier(PrintParameterModifier.LiftHeight); + public bool CanUseLayerLiftSpeed => HaveLayerParameterModifier(PrintParameterModifier.LiftSpeed); + public bool CanUseLayerRetractSpeed => HaveLayerParameterModifier(PrintParameterModifier.RetractSpeed); + public bool CanUseLayerLightOffDelay => HaveLayerParameterModifier(PrintParameterModifier.LightOffDelay); + public bool CanUseLayerLightPWM => HaveLayerParameterModifier(PrintParameterModifier.LightPWM); + public string ExposureRepresentation { get @@ -1368,6 +1375,13 @@ namespace UVtools.Core.FileFormats return result; } + public bool FileEndsWith(string extension) + { + if (extension[0] != '.') extension = $".{extension}"; + return FileFullPath.EndsWith(extension, StringComparison.OrdinalIgnoreCase) || + FileFullPath.EndsWith($"{extension}{TemporaryFileAppend}", StringComparison.OrdinalIgnoreCase); + } + /// <summary> /// Gets a thumbnail by it height or lower /// </summary> @@ -1617,15 +1631,15 @@ namespace UVtools.Core.FileFormats tw.WriteLine($"{nameof(layer.PositionZ)}: {layer.PositionZ}"); tw.WriteLine($"{nameof(layer.ExposureTime)}: {layer.ExposureTime}"); - if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LightOffDelay)) + if (HaveLayerParameterModifier(PrintParameterModifier.LightOffDelay)) tw.WriteLine($"{nameof(layer.LightOffDelay)}: {layer.LightOffDelay}"); - if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LiftHeight)) + if (HaveLayerParameterModifier(PrintParameterModifier.LiftHeight)) tw.WriteLine($"{nameof(layer.LiftHeight)}: {layer.LiftHeight}"); - if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LiftSpeed)) + if (HaveLayerParameterModifier(PrintParameterModifier.LiftSpeed)) tw.WriteLine($"{nameof(layer.LiftSpeed)}: {layer.LiftSpeed}"); - if (HavePrintParameterPerLayerModifier(PrintParameterModifier.RetractSpeed)) + if (HaveLayerParameterModifier(PrintParameterModifier.RetractSpeed)) tw.WriteLine($"{nameof(layer.RetractSpeed)}: {layer.RetractSpeed}"); - if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LightPWM)) + if (HaveLayerParameterModifier(PrintParameterModifier.LightPWM)) tw.WriteLine($"{nameof(layer.LightPWM)}: {layer.LightPWM}"); var materialMillilitersPercent = layer.MaterialMillilitersPercent; diff --git a/UVtools.Core/FileFormats/LGSFile.cs b/UVtools.Core/FileFormats/LGSFile.cs index 9e88da8..ecffe6e 100644 --- a/UVtools.Core/FileFormats/LGSFile.cs +++ b/UVtools.Core/FileFormats/LGSFile.cs @@ -6,6 +6,7 @@ * of this license document, but changing it is not allowed. */ +using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; @@ -28,17 +29,16 @@ namespace UVtools.Core.FileFormats public class Header { public const string NameValue = "Longer3D"; - //[FieldOrder(0)] public uint Offset1 { get; set; } - + /// <summary> /// Gets the model name /// </summary> [FieldOrder(0)] [FieldLength(8)] public string Name { get; set; } = NameValue; // 0x00: - [FieldOrder(1)] public uint Uint_08 { get; set; } = 4278190081; // 0x08: 0xff000001 ? + [FieldOrder(1)] public uint Uint_08 { get; set; } = 1; // 0x08: 0xff000001 ? [FieldOrder(2)] public uint Uint_0c { get; set; } = 1; // 0x0c: 1 ? - [FieldOrder(3)] public uint Uint_10 { get; set; } = 30; // 0x10: 30 ? + [FieldOrder(3)] public uint PrinterModel { get; set; } = 30; // 10, 30, 120, 4000 (4k), 4500 (4k mono) [FieldOrder(4)] public uint Uint_14 { get; set; } = 0; // 0x14: 0 ? - [FieldOrder(5)] public uint Uint_18 { get; set; } = 34; // 0x18: 34 ? + [FieldOrder(5)] public uint MagicKey { get; set; } = 34; // 0x18: 34 [FieldOrder(6)] public float PixelPerMmX { get; set; } = 15.404f; [FieldOrder(7)] public float PixelPerMmY { get; set; } = 4.866f; [FieldOrder(8)] public float ResolutionX { get; set; } @@ -69,7 +69,7 @@ namespace UVtools.Core.FileFormats [FieldOrder(33)] public float Float_88 { get; set; } = 6; // 0x88: 6? [FieldOrder(34)] public float Float_8c { get; set; } = 150; // 0x8c: 150 ? [FieldOrder(35)] public float Float_90 { get; set; } = 1001; // 0x90: 1001 ? - [FieldOrder(36)] public float Float_94 { get; set; } = 140;// 0x94: 140 for lgs10, 170 for lgs30, 190 for lgs4k + [FieldOrder(36)] public float MachineZ { get; set; } = 140;// 0x94: 140 for lgs10, 170 for lgs30, 150 for lgs120, 190 for lgs4k [FieldOrder(37)] public uint Uint_98 { get; set; } // 0x98: 0 ? [FieldOrder(38)] public uint Uint_9c { get; set; } // 0x9c: 0 ? [FieldOrder(39)] public uint Uint_a0 { get; set; } // 0xa0: 0 ? @@ -81,6 +81,45 @@ namespace UVtools.Core.FileFormats #endregion + #region LGS120PngPreview + + public class LGS120PngPreview + { + public const ushort ResolutionX = 1200; + public const ushort ResolutionY = 1600; + + [FieldOrder(0)] public uint DataSize { get; set; } + + [FieldOrder(1)] + [FieldLength(nameof(DataSize))] + public byte[] EncodedRle { get; set; } + + public void Encode(Mat mat) + { + if (mat.Width != ResolutionX || mat.Height != ResolutionY) + { + using var resizeMat = new Mat(); + CvInvoke.Resize(mat, resizeMat, new Size(ResolutionX, ResolutionY)); + EncodedRle = resizeMat.GetPngByes(); + } + else + { + EncodedRle = mat.GetPngByes(); + } + } + + public Mat Decode(bool consumeRle = true) + { + var mat = new Mat(); + CvInvoke.Imdecode(EncodedRle, ImreadModes.AnyColor, mat); + if (consumeRle) + EncodedRle = null; + return mat; + } + } + + #endregion + #region LayerData public class LayerData @@ -200,12 +239,14 @@ namespace UVtools.Core.FileFormats #region Properties - public Header HeaderSettings { get; protected internal set; } = new Header(); + public Header HeaderSettings { get; protected internal set; } = new(); public override FileFormatType FileType => FileFormatType.Binary; public override FileExtension[] FileExtensions { get; } = { new ("lgs", "Longer Orange 10"), new ("lgs30", "Longer Orange 30"), + //new ("lgs120", "Longer Orange 120"), + //new ("lgs4k", "Longer Orange 4k"), }; public override PrintParameterModifier[] PrintParameterModifiers { get; } = @@ -276,6 +317,12 @@ namespace UVtools.Core.FileFormats set { } } + public override float MachineZ + { + get => HeaderSettings.MachineZ > 0 ? HeaderSettings.MachineZ : base.MachineZ; + set => base.MachineZ = HeaderSettings.MachineZ = (float)Math.Round(value, 2); + } + public override bool MirrorDisplay { get => true; @@ -389,6 +436,7 @@ namespace UVtools.Core.FileFormats public override string MaterialName => "Unknown"; public override string MachineName => null;*/ + public override object[] Configs => new object[] { HeaderSettings }; #endregion @@ -450,18 +498,34 @@ namespace UVtools.Core.FileFormats protected override void EncodeInternally(string fileFullPath, OperationProgress progress) { - if (ResolutionY >= 2560) // Longer Orange 30 + if (FileEndsWith(".lgs")) // Longer Orange 10 { - HeaderSettings.Float_94 = 170; + MachineZ = 140; + HeaderSettings.PrinterModel = 10; } - + else if (FileEndsWith(".lgs30")) // Longer Orange 30 + { + MachineZ = 170; + HeaderSettings.PrinterModel = 30; + } + else if (FileEndsWith(".lgs120")) // Longer Orange 120 + { + MachineZ = 150; + HeaderSettings.PrinterModel = 120; + } + else if (FileEndsWith(".lgs4k")) // Longer Orange 4K & Mono + { + MachineZ = 190; + if(HeaderSettings.PrinterModel is not 4000 and not 4500) HeaderSettings.PrinterModel = 4500; + } + //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])); - LayerData[] layerData = new LayerData[LayerCount]; + var layerData = new LayerData[LayerCount]; Parallel.For(0, LayerCount, layerIndex => { @@ -493,47 +557,51 @@ namespace UVtools.Core.FileFormats 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.Name != Header.NameValue) { - 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); + } - // Fix inconsistencies found of different version of plugin and slicers - if (ResolutionX > ResolutionY) - { - var oldX = ResolutionX; - ResolutionX = ResolutionY; - ResolutionY = oldX; - } + // Fix inconsistencies found of different version of plugin and slicers + if (ResolutionX > ResolutionY) + { + var oldX = ResolutionX; + ResolutionX = ResolutionY; + ResolutionY = oldX; + } - int previewSize = (int) (HeaderSettings.PreviewSizeX * HeaderSettings.PreviewSizeY * 2); - byte[] previewData = new byte[previewSize]; + int previewSize = (int) (HeaderSettings.PreviewSizeX * HeaderSettings.PreviewSizeY * 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); + + if (FileEndsWith(".lgs120")) + { + var pngPreview = Helpers.Deserialize<LGS120PngPreview>(inputFile); + } - LayerData[] layerData = new LayerData[HeaderSettings.LayerCount]; - progress.Reset(OperationProgress.StatusGatherLayers, HeaderSettings.LayerCount); + LayerData[] layerData = new LayerData[HeaderSettings.LayerCount]; + progress.Reset(OperationProgress.StatusGatherLayers, HeaderSettings.LayerCount); - for (int layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) - { - progress.Token.ThrowIfCancellationRequested(); - layerData[layerIndex] = Helpers.Deserialize<LayerData>(inputFile); - layerData[layerIndex].Parent = this; - } + for (int layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) + { + progress.Token.ThrowIfCancellationRequested(); + layerData[layerIndex] = Helpers.Deserialize<LayerData>(inputFile); + layerData[layerIndex].Parent = this; + } - LayerManager.Init(HeaderSettings.LayerCount); - progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount); + LayerManager.Init(HeaderSettings.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; @@ -543,8 +611,7 @@ namespace UVtools.Core.FileFormats progress.LockAndIncrement(); }); - LayerManager.RebuildLayersProperties(); - } + LayerManager.RebuildLayersProperties(); } public override void SaveAs(string filePath = null, OperationProgress progress = null) diff --git a/UVtools.Core/FileFormats/PHZFile.cs b/UVtools.Core/FileFormats/PHZFile.cs index 92cac2b..59c9eb7 100644 --- a/UVtools.Core/FileFormats/PHZFile.cs +++ b/UVtools.Core/FileFormats/PHZFile.cs @@ -710,10 +710,10 @@ namespace UVtools.Core.FileFormats PrintParameterModifier.LightPWM, }; - public override PrintParameterModifier[] PrintParameterPerLayerModifiers { get; } = { + /*public override PrintParameterModifier[] PrintParameterPerLayerModifiers { get; } = { PrintParameterModifier.ExposureSeconds, PrintParameterModifier.LightOffDelay, - }; + };*/ public override Size[] ThumbnailsOriginalSize { get; } = { diff --git a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs index f4a7220..4003f8a 100644 --- a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs +++ b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs @@ -1187,7 +1187,7 @@ namespace UVtools.Core.FileFormats public override object[] Configs => new object[] { FileMarkSettings, HeaderSettings, PreviewSettings, LayersDefinition }; public LayerRleFormat LayerFormat => - FileFullPath.EndsWith(".pws") || FileFullPath.EndsWith($".pws{TemporaryFileAppend}") + FileEndsWith(".pws") ? LayerRleFormat.PWS : LayerRleFormat.PW0; @@ -1195,32 +1195,32 @@ namespace UVtools.Core.FileFormats { get { - if (FileFullPath.EndsWith(".pws") || FileFullPath.EndsWith($".pws{TemporaryFileAppend}")) + if (FileEndsWith(".pws")) { return AnyCubicMachine.AnyCubicPhotonS; } - if (FileFullPath.EndsWith(".pw0") || FileFullPath.EndsWith($".pw0{TemporaryFileAppend}")) + if (FileEndsWith(".pw0")) { return AnyCubicMachine.AnyCubicPhotonZero; } - if (FileFullPath.EndsWith(".pwx") || FileFullPath.EndsWith($".pwx{TemporaryFileAppend}")) + if (FileEndsWith(".pwx")) { return AnyCubicMachine.AnyCubicPhotonX; } - if (FileFullPath.EndsWith(".pwmo") || FileFullPath.EndsWith($".pwmo{TemporaryFileAppend}")) + if (FileEndsWith(".pwmo")) { return AnyCubicMachine.AnyCubicPhotonMono; } - if (FileFullPath.EndsWith(".pwms") || FileFullPath.EndsWith($".pwms{TemporaryFileAppend}")) + if (FileEndsWith(".pwms")) { return AnyCubicMachine.AnyCubicPhotonMonoSE; } - if (FileFullPath.EndsWith(".pwmx") || FileFullPath.EndsWith($".pwmx{TemporaryFileAppend}")) + if (FileEndsWith(".pwmx")) { return AnyCubicMachine.AnyCubicPhotonMonoX; } diff --git a/UVtools.Core/FileFormats/SL1File.cs b/UVtools.Core/FileFormats/SL1File.cs index 97e34eb..fca0818 100644 --- a/UVtools.Core/FileFormats/SL1File.cs +++ b/UVtools.Core/FileFormats/SL1File.cs @@ -264,6 +264,7 @@ namespace UVtools.Core.FileFormats var now = DateTime.Now; return $"{now.Year}-{now.Month:D2}-{now.Day:D2} at {now.Hour:D2}:{now.Minute:D2}:{now.Second:D2} {now.Kind}"; } + set{} } public float LayerHeight { get; set; } public string MaterialName { get; set; } = About.Software; @@ -303,7 +304,8 @@ namespace UVtools.Core.FileFormats public override FileFormatType FileType => FileFormatType.Archive; public override FileExtension[] FileExtensions { get; } = { - new("sl1", "PrusaSlicer SL1") + new("sl1", "PrusaSlicer SL1"), + new("sl1s", "PrusaSlicer SL1S Speed") }; public override PrintParameterModifier[] PrintParameterModifiers { get; } = { PrintParameterModifier.BottomLayerCount, diff --git a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs index bdcc7ec..2da010f 100644 --- a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs +++ b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs @@ -980,7 +980,7 @@ namespace UVtools.Core.Operations if (_multipleBrightnessGenExposureTime == 0) _multipleBrightnessGenExposureTime = (decimal)SlicerFile.ExposureTime; - if (!SlicerFile.HavePrintParameterPerLayerModifier(FileFormat.PrintParameterModifier.ExposureSeconds)) + if (!SlicerFile.HaveLayerParameterModifier(FileFormat.PrintParameterModifier.ExposureSeconds)) { _multipleLayerHeight = false; _multipleExposures = false; diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 1b7ca18..1e4bc6c 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -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.13.4</Version> + <Version>2.14.0</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> <Platforms>AnyCPU;x64</Platforms> |