mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-08 17:42:31 +02:00
Anycubic file format improvements
- (Add) Compatibility with the next version 517 of the format - (Improvement) Discovered and implemented more unknown fields - (Improvement) Dispose layer RLE bytes after encoding - (Fix) When creating or converting to anycubic file, it don't set the extra table mark name - (Fix) Only attempt to activate the advanced mode (TSMC) when the BottomLiftHeight2 or LiftHeight2 gets changed
This commit is contained in:
@@ -7,25 +7,32 @@
|
||||
|
||||
LittleEndian();
|
||||
|
||||
enum <ubyte> BOOL { False, True };
|
||||
|
||||
struct FILEMARK {
|
||||
char Mark[12] <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint Version <fgcolor=cBlack, bgcolor=cRed>; // 1 or 515 or 516
|
||||
uint AreaNum <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint NumberOfTables <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint HeaderAddress <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint Unknown <fgcolor=cBlack, bgcolor=cRed>; // 6357060 for 516
|
||||
uint SoftwareAddress <fgcolor=cBlack, bgcolor=cRed>; // 6357060 for 516
|
||||
uint PreviewAddress <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint PreviewEndAddress <fgcolor=cBlack, bgcolor=cRed>; // Version 515 only
|
||||
uint LayerImageColorAddress <fgcolor=cBlack, bgcolor=cRed>; // Version 515 only
|
||||
uint LayerDefinitionAddress <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint ExtraAddress <fgcolor=cBlack, bgcolor=cRed>;
|
||||
|
||||
if(Version < 516)
|
||||
if(Version <= 515)
|
||||
{
|
||||
uint LayerImageAddress <fgcolor=cBlack, bgcolor=cRed>;
|
||||
}
|
||||
else{
|
||||
else{ // >= 516
|
||||
uint MachineAddress <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint LayerImageAddress <fgcolor=cBlack, bgcolor=cRed>;
|
||||
}
|
||||
|
||||
if(Version >= 517)
|
||||
{
|
||||
uint ModelAddress <fgcolor=cBlack, bgcolor=cRed>;
|
||||
}
|
||||
} fileMark;
|
||||
|
||||
struct SECTION {
|
||||
@@ -56,12 +63,19 @@ struct HEADER {
|
||||
uint PerLayerOverride <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint PrintTime <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint TransitionLayerCount <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint Padding <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint TransitionLayerType <fgcolor=cBlack, bgcolor=cRed>;
|
||||
|
||||
if(fileMark.Version >= 516){
|
||||
// 0 = Basic mode | 1 = Advanced mode which allows TSMC
|
||||
uint AdvancedMode <fgcolor=cBlack, bgcolor=cRed>;
|
||||
}
|
||||
|
||||
if(fileMark.Version >= 517){
|
||||
|
||||
ushort Gray <fgcolor=cBlack, bgcolor=cRed>;
|
||||
ushort BlurLevel <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint ResinCode <fgcolor=cBlack, bgcolor=cRed>; // 1579548560, somekind of hash?
|
||||
}
|
||||
};
|
||||
|
||||
if(fileMark.HeaderAddress > 0){
|
||||
@@ -73,25 +87,31 @@ if(fileMark.HeaderAddress > 0){
|
||||
struct PREVIEW {
|
||||
SECTION section;
|
||||
uint ResolutionX <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint DpiResolution <fgcolor=cBlack, bgcolor=cRed>;
|
||||
wstring Mark <fgcolor=cBlack, bgcolor=cRed>; // x or *
|
||||
uint ResolutionY <fgcolor=cBlack, bgcolor=cRed>;
|
||||
|
||||
ubyte Data[ResolutionX*ResolutionY*2] <fgcolor=cBlack, bgcolor=cGreen>;
|
||||
|
||||
/*uint Unknown1 <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint Unknown2 <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint Unknown3 <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint Unknown4 <fgcolor=cBlack, bgcolor=cRed>;*/
|
||||
};
|
||||
|
||||
if(fileMark.PreviewAddress > 0){
|
||||
FSeek(fileMark.PreviewAddress);
|
||||
PREVIEW preview;
|
||||
}
|
||||
|
||||
if(fileMark.Version >= 515)
|
||||
{
|
||||
uint Reserved[7] <fgcolor=cWhite, bgcolor=cBlack>;
|
||||
}
|
||||
if(fileMark.Version >= 515 && fileMark.LayerImageColorAddress > 0)
|
||||
{
|
||||
FSeek(fileMark.LayerImageColorAddress);
|
||||
struct LAYER_IMAGE_COLOR {
|
||||
uint UseFullGreyscale <fgcolor=cWhite, bgcolor=cBlack>;
|
||||
uint GreyMaxCount <fgcolor=cWhite, bgcolor=cBlack>;
|
||||
local uint i;
|
||||
|
||||
for(i = 0; i < GreyMaxCount; i++ ){
|
||||
ubyte Grey <fgcolor=cWhite, bgcolor=cBlack>;
|
||||
}
|
||||
|
||||
uint Unknown <fgcolor=cWhite, bgcolor=cBlack>;
|
||||
} layerImageColor;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +132,7 @@ struct LAYER_DEF {
|
||||
float ExposureTime <fgcolor=cWhite, bgcolor=cBlue>;
|
||||
float LayerHeight <fgcolor=cWhite, bgcolor=cBlue>;
|
||||
uint NonZeroPixelCount <fgcolor=cWhite, bgcolor=cBlue>;
|
||||
uint Padding1 <fgcolor=cWhite, bgcolor=cBlue>;
|
||||
uint ZeroPixelCount <fgcolor=cWhite, bgcolor=cBlue>;
|
||||
|
||||
local uint currentPos = FTell();
|
||||
FSeek(DataAddress);
|
||||
@@ -125,14 +145,14 @@ if(fileMark.Version >= 516 && fileMark.ExtraAddress > 0){
|
||||
FSeek(fileMark.ExtraAddress);
|
||||
struct EXTRA {
|
||||
SECTION section;
|
||||
uint Unknown <fgcolor=cBlack, bgcolor=cRed>; // 2
|
||||
uint BottomStateNumber <fgcolor=cBlack, bgcolor=cRed>; // 2
|
||||
float BottomLiftHeight0 <fgcolor=cBlack, bgcolor=cGreen>;
|
||||
float BottomLiftSpeed0 <fgcolor=cBlack, bgcolor=cGreen>;
|
||||
float BottomRetractSpeed0 <fgcolor=cBlack, bgcolor=cGreen>;
|
||||
float BottomLiftHeight1 <fgcolor=cBlack, bgcolor=cGreen>;
|
||||
float BottomLiftSpeed1 <fgcolor=cBlack, bgcolor=cGreen>;
|
||||
float BottomRetractSpeed1 <fgcolor=cBlack, bgcolor=cGreen>;
|
||||
uint Unknown <fgcolor=cBlack, bgcolor=cGreen>; // 2
|
||||
uint StateNumber <fgcolor=cBlack, bgcolor=cGreen>; // 2
|
||||
float LiftHeight0 <fgcolor=cBlack, bgcolor=cGreen>;
|
||||
float LiftSpeed0 <fgcolor=cBlack, bgcolor=cGreen>;
|
||||
float RetractSpeed0 <fgcolor=cBlack, bgcolor=cGreen>;
|
||||
@@ -143,18 +163,48 @@ if(fileMark.Version >= 516 && fileMark.ExtraAddress > 0){
|
||||
}
|
||||
|
||||
if(fileMark.Version >= 516 && fileMark.MachineAddress > 0){
|
||||
FSeek(fileMark.MachineAddress);
|
||||
struct MACHINE {
|
||||
SECTION section;
|
||||
char MachineName[96] <fgcolor=cBlack, bgcolor=cRed>;
|
||||
char ImageFormat[24] <fgcolor=cWhite, bgcolor=cRed>;
|
||||
char ImageFormat[16] <fgcolor=cWhite, bgcolor=cRed>;
|
||||
uint MaxAntialiasingLevel <fgcolor=cWhite, bgcolor=cRed>; // Machine maximum antialiasing level, 16
|
||||
uint PropertyFields <fgcolor=cWhite, bgcolor=cRed>; // Machine property fields
|
||||
float DisplayWidth <fgcolor=cBlack, bgcolor=cRed>;
|
||||
float DisplayHeight <fgcolor=cBlack, bgcolor=cRed>;
|
||||
float MachineZ <fgcolor=cBlack, bgcolor=cRed>;
|
||||
uint Version <fgcolor=cBlack, bgcolor=cRed>; // Version again? 516
|
||||
uint Unknown <fgcolor=cBlack, bgcolor=cRed>; // 6506241
|
||||
uint MaxFileVersion <fgcolor=cBlack, bgcolor=cRed>; // Highest file version supported, 516?
|
||||
char BackgroundColor[4] <fgcolor=cBlack, bgcolor=cRed>; // Machine background color
|
||||
} machine;
|
||||
}
|
||||
|
||||
if(fileMark.Version >= 517 && fileMark.SoftwareAddress > 0){
|
||||
FSeek(fileMark.SoftwareAddress);
|
||||
struct SOFTWARE {
|
||||
char Name[32] <fgcolor=cWhite, bgcolor=cBlue>; // ANYCUBIC-PC
|
||||
uint TableLength <fgcolor=cWhite, bgcolor=cBlue>; // 164
|
||||
char Version[32] <fgcolor=cWhite, bgcolor=cBlue>; // 2.2.16
|
||||
char OperativeSystem[64] <fgcolor=cWhite, bgcolor=cBlue>; // win-x64
|
||||
char OpenGLVersion[32] <fgcolor=cWhite, bgcolor=cBlue>; // 3.3-CoreProfile
|
||||
} software;
|
||||
}
|
||||
|
||||
if(fileMark.Version >= 517 && fileMark.ModelAddress > 0){
|
||||
FSeek(fileMark.ModelAddress);
|
||||
struct MODEL {
|
||||
SECTION section <fgcolor=cWhite, bgcolor=cRed>; // MODEL
|
||||
float MinX <fgcolor=cWhite, bgcolor=cRed>;
|
||||
float MinY <fgcolor=cWhite, bgcolor=cRed>;
|
||||
float MinZ <fgcolor=cWhite, bgcolor=cRed>;
|
||||
float MaxX <fgcolor=cWhite, bgcolor=cRed>;
|
||||
float MaxY <fgcolor=cWhite, bgcolor=cRed>;
|
||||
float MaxZ <fgcolor=cWhite, bgcolor=cRed>;
|
||||
uint SupportsEnabled <fgcolor=cWhite, bgcolor=cRed>;
|
||||
float SupportsDensity <fgcolor=cWhite, bgcolor=cRed>;
|
||||
} model;
|
||||
}
|
||||
|
||||
|
||||
if(fileMark.LayerDefinitionAddress > 0){
|
||||
FSeek(fileMark.LayerDefinitionAddress);
|
||||
LayerDefinition layerDefinition;
|
||||
|
||||
@@ -14,6 +14,7 @@ using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using UVtools.Core.Converters;
|
||||
using UVtools.Core.Extensions;
|
||||
@@ -25,25 +26,15 @@ namespace UVtools.Core.FileFormats;
|
||||
public class PhotonWorkshopFile : FileFormat
|
||||
{
|
||||
#region Constants
|
||||
public const byte VERSION_1 = 1;
|
||||
public const ushort VERSION_515 = 515;
|
||||
public const ushort VERSION_516 = 516;
|
||||
public const byte VERSION_1 = 1; // 0x1
|
||||
public const ushort VERSION_515 = 515; // 0x203
|
||||
public const ushort VERSION_516 = 516; // 0x204
|
||||
public const ushort VERSION_517 = 517; // 0x205
|
||||
|
||||
public const byte MarkSize = 12;
|
||||
public const byte RLE1EncodingLimit = 0x7d; // 125;
|
||||
public const ushort RLE4EncodingLimit = 0xfff; // 4095;
|
||||
|
||||
public static readonly uint[] ReservedUintsAfterPreview =
|
||||
{
|
||||
0,
|
||||
16,
|
||||
uint.MaxValue,
|
||||
uint.MaxValue,
|
||||
uint.MaxValue,
|
||||
uint.MaxValue,
|
||||
0
|
||||
};
|
||||
|
||||
// CRC-16-ANSI (aka CRC-16-IBM) Polynomial: x^16 + x^15 + x^2 + 1
|
||||
public static readonly int[] CRC16Table = {
|
||||
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
|
||||
@@ -103,6 +94,7 @@ public class PhotonWorkshopFile : FileFormat
|
||||
AnyCubicPhotonMonoSQ,
|
||||
AnyCubicPhotonM3,
|
||||
AnyCubicPhotonM3Max,
|
||||
AnyCubicCustom,
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -133,7 +125,7 @@ public class PhotonWorkshopFile : FileFormat
|
||||
/// Gets the area num
|
||||
/// 10, 4 for v1, 5 for v515, 8 for v516?
|
||||
/// </summary>
|
||||
[FieldOrder(2)] public uint AreaNum { get; set; }
|
||||
[FieldOrder(2)] public uint NumberOfTables { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the header start address
|
||||
@@ -144,7 +136,7 @@ public class PhotonWorkshopFile : FileFormat
|
||||
/// <summary>
|
||||
/// 18
|
||||
/// </summary>
|
||||
[FieldOrder(4)] public uint Padding1 { get; set; }
|
||||
[FieldOrder(4)] public uint SoftwareAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the preview start offset
|
||||
@@ -155,7 +147,7 @@ public class PhotonWorkshopFile : FileFormat
|
||||
/// <summary>
|
||||
/// 20, Spotted on version 515 only
|
||||
/// </summary>
|
||||
[FieldOrder(6)] public uint PreviewEndAddress { get; set; }
|
||||
[FieldOrder(6)] public uint LayerImageColorTableAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the layer definition start address
|
||||
@@ -179,9 +171,15 @@ public class PhotonWorkshopFile : FileFormat
|
||||
/// </summary>
|
||||
[FieldOrder(10)] public uint LayerImageAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Spotted on version 517 only
|
||||
/// </summary>
|
||||
[SerializeWhen(nameof(Version), VERSION_517, ComparisonOperator.GreaterThanOrEqual)]
|
||||
[FieldOrder(11)] public uint ModelAddress { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Mark)}: {Mark}, {nameof(Version)}: {Version}, {nameof(AreaNum)}: {AreaNum}, {nameof(HeaderAddress)}: {HeaderAddress}, {nameof(Padding1)}: {Padding1}, {nameof(PreviewAddress)}: {PreviewAddress}, {nameof(PreviewEndAddress)}: {PreviewEndAddress}, {nameof(LayerDefinitionAddress)}: {LayerDefinitionAddress}, {nameof(ExtraAddress)}: {ExtraAddress}, {nameof(MachineAddress)}: {MachineAddress}, {nameof(LayerImageAddress)}: {LayerImageAddress}";
|
||||
return $"{nameof(Mark)}: {Mark}, {nameof(Version)}: {Version}, {nameof(NumberOfTables)}: {NumberOfTables}, {nameof(HeaderAddress)}: {HeaderAddress}, {nameof(SoftwareAddress)}: {SoftwareAddress}, {nameof(PreviewAddress)}: {PreviewAddress}, {nameof(LayerImageColorTableAddress)}: {LayerImageColorTableAddress}, {nameof(LayerDefinitionAddress)}: {LayerDefinitionAddress}, {nameof(ExtraAddress)}: {ExtraAddress}, {nameof(MachineAddress)}: {MachineAddress}, {nameof(LayerImageAddress)}: {LayerImageAddress}, {nameof(ModelAddress)}: {ModelAddress}";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -337,8 +335,8 @@ public class PhotonWorkshopFile : FileFormat
|
||||
/// 24 00 00 00 $ or ¥ C2 A5 00 00 or € = E2 82 AC 00
|
||||
/// 7C
|
||||
/// </summary>
|
||||
[FieldOrder(16)] public uint PriceCurrencyDec { get; set; } = 0x24;
|
||||
[Ignore] public char PriceCurrencySymbol
|
||||
[FieldOrder(16)][FieldLength(4)] [SerializeAs(SerializedType.TerminatedString)] public string PriceCurrencySymbol { get; set; } = "$";
|
||||
/*[Ignore] public char PriceCurrencySymbol
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -350,7 +348,7 @@ public class PhotonWorkshopFile : FileFormat
|
||||
_ => '$'
|
||||
};
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// 80
|
||||
@@ -368,9 +366,9 @@ public class PhotonWorkshopFile : FileFormat
|
||||
[FieldOrder(19)] public uint TransitionLayerCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 8C
|
||||
/// 8C, spotted on 516
|
||||
/// </summary>
|
||||
[FieldOrder(20)] public uint Padding2 { get; set; }
|
||||
[FieldOrder(20)] public uint TransitionLayerType { get; set; }
|
||||
|
||||
//[SerializeUntil((char)'P')] [FieldOrder(21)] public List<byte> Offset { get; set; } = new();
|
||||
|
||||
@@ -380,7 +378,7 @@ public class PhotonWorkshopFile : FileFormat
|
||||
}
|
||||
|
||||
|
||||
public override string ToString() => $"{nameof(Section)}: {Section}, {nameof(PixelSizeUm)}: {PixelSizeUm}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(ExposureTime)}: {ExposureTime}, {nameof(WaitTimeBeforeCure)}: {WaitTimeBeforeCure}, {nameof(BottomExposureTime)}: {BottomExposureTime}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(VolumeMl)}: {VolumeMl}, {nameof(AntiAliasing)}: {AntiAliasing}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(WeightG)}: {WeightG}, {nameof(Price)}: {Price}, {nameof(PriceCurrencyDec)}: {PriceCurrencyDec}, {nameof(PerLayerOverride)}: {PerLayerOverride}, {nameof(PrintTime)}: {PrintTime}, {nameof(TransitionLayerCount)}: {TransitionLayerCount}, {nameof(Padding2)}: {Padding2}";
|
||||
public override string ToString() => $"{nameof(Section)}: {Section}, {nameof(PixelSizeUm)}: {PixelSizeUm}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(ExposureTime)}: {ExposureTime}, {nameof(WaitTimeBeforeCure)}: {WaitTimeBeforeCure}, {nameof(BottomExposureTime)}: {BottomExposureTime}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(VolumeMl)}: {VolumeMl}, {nameof(AntiAliasing)}: {AntiAliasing}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(WeightG)}: {WeightG}, {nameof(Price)}: {Price}, {nameof(PriceCurrencySymbol)}: {PriceCurrencySymbol}, {nameof(PerLayerOverride)}: {PerLayerOverride}, {nameof(PrintTime)}: {PrintTime}, {nameof(TransitionLayerCount)}: {TransitionLayerCount}, {nameof(TransitionLayerType)}: {TransitionLayerType}";
|
||||
|
||||
public void Validate(int offset = 0)
|
||||
{
|
||||
@@ -388,6 +386,31 @@ public class PhotonWorkshopFile : FileFormat
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HeaderV516
|
||||
{
|
||||
/// <summary>
|
||||
/// 0 = Basic mode | 1 = Advanced mode which allows TSMC
|
||||
/// </summary>
|
||||
[FieldOrder(0)] public uint AdvancedMode { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(AdvancedMode)}: {AdvancedMode}";
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HeaderV517
|
||||
{
|
||||
[FieldOrder(0)] public ushort Grey { get; set; }
|
||||
[FieldOrder(1)] public ushort BlurLevel { get; set; }
|
||||
[FieldOrder(2)] public uint ResinCode { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Grey)}: {Grey}, {nameof(BlurLevel)}: {BlurLevel}, {nameof(ResinCode)}: {ResinCode}";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Preview
|
||||
@@ -412,10 +435,10 @@ public class PhotonWorkshopFile : FileFormat
|
||||
[FieldOrder(1)] public uint ResolutionX { get; set; } = 224;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the resolution of the image, in dpi.
|
||||
/// Gets the operation mark 'x'
|
||||
/// A4
|
||||
/// </summary>
|
||||
[FieldOrder(2)] public uint DpiResolution { get; set; } = 42;
|
||||
[FieldOrder(2)] [FieldLength(4)] [SerializeAs(SerializedType.TerminatedString)] public string Mark { get; set; } = "x";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image height, in pixels.
|
||||
@@ -423,15 +446,8 @@ public class PhotonWorkshopFile : FileFormat
|
||||
/// </summary>
|
||||
[FieldOrder(3)] public uint ResolutionY { get; set; } = 168;
|
||||
|
||||
/*[FieldOrder(4)] public uint Unknown1 { get; set; }
|
||||
[FieldOrder(5)] public uint Unknown2 { get; set; }
|
||||
[FieldOrder(6)] public uint Unknown3 { get; set; }
|
||||
[FieldOrder(7)] public uint Unknown4 { get; set; }*/
|
||||
|
||||
[Ignore] public uint DataSize => ResolutionX * ResolutionY * 2;
|
||||
|
||||
// little-endian 16bit colors, RGB 565 encoded.
|
||||
//[FieldOrder(4)] [FieldLength(nameof(Section)+"."+nameof(SectionHeader.Length))]
|
||||
[Ignore] public byte[] Data { get; set; } = null!;
|
||||
|
||||
public Preview()
|
||||
@@ -439,67 +455,17 @@ public class PhotonWorkshopFile : FileFormat
|
||||
Section = new SectionHeader(SectionMark, this);
|
||||
}
|
||||
|
||||
public Preview(uint resolutionX, uint resolutionY, uint dpiResolution = 42) : this()
|
||||
public Preview(uint resolutionX, uint resolutionY) : this()
|
||||
{
|
||||
ResolutionX = resolutionX;
|
||||
ResolutionY = resolutionY;
|
||||
DpiResolution = dpiResolution;
|
||||
Data = new byte[DataSize];
|
||||
Section.Length += (uint)Data.Length;
|
||||
}
|
||||
|
||||
/*public unsafe Mat Decode(bool consumeData = true)
|
||||
{
|
||||
Mat image = new(new Size((int)ResolutionX, (int)ResolutionY), DepthType.Cv8U, 3);
|
||||
var span = image.GetBytePointer();
|
||||
|
||||
int pixel = 0;
|
||||
for (uint i = 0; i < Data.Length; i += 2)
|
||||
{
|
||||
ushort color16 = BitExtensions.ToUShortLittleEndian(Data[i], Data[i+1]);
|
||||
byte r = (byte)((color16 >> 11) & 0x1f);
|
||||
byte g = (byte)((color16 >> 5) & 0x3f);
|
||||
byte b = (byte)((color16 >> 0) & 0x1f);
|
||||
|
||||
span[pixel++] = (byte) ((b << 3) | (b & 0x7));
|
||||
span[pixel++] = (byte) ((g << 2) | (g & 0x3));
|
||||
span[pixel++] = (byte) ((r << 3) | (r & 0x7));
|
||||
}
|
||||
|
||||
if (consumeData)
|
||||
Data = null;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
public static unsafe Preview Encode(Mat image)
|
||||
{
|
||||
var span = image.GetBytePointer();
|
||||
var imageLength = image.GetLength();
|
||||
|
||||
Preview preview = new((uint) image.Width, (uint) image.Height);
|
||||
|
||||
int i = 0;
|
||||
for (int pixel = 0; pixel < imageLength; pixel += image.NumberOfChannels)
|
||||
{
|
||||
// BGR
|
||||
byte b = (byte)(span[pixel] >> 3);
|
||||
byte g = (byte)(span[pixel+1] >> 2);
|
||||
byte r = (byte)(span[pixel+2] >> 3);
|
||||
|
||||
|
||||
ushort color = (ushort) ((r << 11) | (g << 5) | (b << 0));
|
||||
|
||||
preview.Data[i++] = (byte) color;
|
||||
preview.Data[i++] = (byte) (color >> 8);
|
||||
}
|
||||
|
||||
return preview;
|
||||
}*/
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Section)}: {Section}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(DpiResolution)}: {DpiResolution}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(Data)}: {Data?.Length ?? 0}";
|
||||
return $"{nameof(Section)}: {Section}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(Mark)}: {Mark}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(Data)}: {Data?.Length ?? 0}";
|
||||
}
|
||||
|
||||
public void Validate(int size)
|
||||
@@ -510,6 +476,173 @@ public class PhotonWorkshopFile : FileFormat
|
||||
|
||||
#endregion
|
||||
|
||||
#region LayerColorTable
|
||||
|
||||
public sealed class LayerImageColorTable
|
||||
{
|
||||
[FieldOrder(0)] public uint UseFullGreyscale { get; set; }
|
||||
[FieldOrder(1)] public uint GreyMaxCount { get; set; } = 16;
|
||||
[FieldOrder(2)] [FieldCount(nameof(GreyMaxCount))] public byte[] Grey { get; set; } = {
|
||||
// AA16: 255, 239, 223, 207, 191, 175, 159, 143, 127, 111, 95, 79, 63, 47, 31, 15
|
||||
15, 31, 47, // 1,2,3
|
||||
63, 79, 95, // 4,5,6
|
||||
111, 127, 143, // 7,8,9
|
||||
159, 175, 191, // 10,11,12
|
||||
207, 223, 239, // 13,14,15
|
||||
byte.MaxValue // 16
|
||||
};
|
||||
|
||||
[FieldOrder(3)] public uint Unknown { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(UseFullGreyscale)}: {UseFullGreyscale}, {nameof(GreyMaxCount)}: {GreyMaxCount}, {nameof(Grey)}: {Grey}, {nameof(Unknown)}: {Unknown}";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Extra
|
||||
public class Extra
|
||||
{
|
||||
public const string SectionMark = "EXTRA";
|
||||
|
||||
//[FieldOrder(0)] public SectionHeader Section { get; set; }
|
||||
[FieldOrder(0)][FieldLength(MarkSize)][SerializeAs(SerializedType.TerminatedString)] public string Marker { get; set; } = SectionMark;
|
||||
[FieldOrder(1)] public uint Unknown0 { get; set; } = 24;
|
||||
[FieldOrder(2)] public uint BottomStateNumber { get; set; } = 2;
|
||||
[FieldOrder(3)] public float BottomLiftHeight1 { get; set; }
|
||||
[FieldOrder(4)] public float BottomLiftSpeed1 { get; set; } = SpeedConverter.Convert(DefaultBottomLiftSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(5)] public float BottomRetractSpeed1 { get; set; } = SpeedConverter.Convert(DefaultBottomRetractSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(6)] public float BottomLiftHeight2 { get; set; }
|
||||
[FieldOrder(7)] public float BottomLiftSpeed2 { get; set; } = SpeedConverter.Convert(DefaultBottomLiftSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(8)] public float BottomRetractSpeed2 { get; set; } = SpeedConverter.Convert(DefaultBottomRetractSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(9)] public uint StateNumber { get; set; } = 2;
|
||||
[FieldOrder(10)] public float LiftHeight1 { get; set; }
|
||||
[FieldOrder(11)] public float LiftSpeed1 { get; set; } = SpeedConverter.Convert(DefaultLiftSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(12)] public float RetractSpeed1 { get; set; } = SpeedConverter.Convert(DefaultRetractSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(13)] public float LiftHeight2 { get; set; }
|
||||
[FieldOrder(14)] public float LiftSpeed2 { get; set; } = SpeedConverter.Convert(DefaultLiftSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(15)] public float RetractSpeed2 { get; set; } = SpeedConverter.Convert(DefaultRetractSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
|
||||
public Extra()
|
||||
{
|
||||
//Section = new SectionHeader(SectionMark, this);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Marker)}: {Marker}, {nameof(Unknown0)}: {Unknown0}, {nameof(BottomStateNumber)}: {BottomStateNumber}, {nameof(BottomLiftHeight1)}: {BottomLiftHeight1}, {nameof(BottomLiftSpeed1)}: {BottomLiftSpeed1}, {nameof(BottomRetractSpeed1)}: {BottomRetractSpeed1}, {nameof(BottomLiftHeight2)}: {BottomLiftHeight2}, {nameof(BottomLiftSpeed2)}: {BottomLiftSpeed2}, {nameof(BottomRetractSpeed2)}: {BottomRetractSpeed2}, {nameof(StateNumber)}: {StateNumber}, {nameof(LiftHeight1)}: {LiftHeight1}, {nameof(LiftSpeed1)}: {LiftSpeed1}, {nameof(RetractSpeed1)}: {RetractSpeed1}, {nameof(LiftHeight2)}: {LiftHeight2}, {nameof(LiftSpeed2)}: {LiftSpeed2}, {nameof(RetractSpeed2)}: {RetractSpeed2}";
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
//Section.Validate(SectionMark, (int)-Helpers.Serializer.SizeOf(Section), this);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Machine
|
||||
public class Machine
|
||||
{
|
||||
public const string SectionMark = "MACHINE";
|
||||
|
||||
[FieldOrder(0)] public SectionHeader Section { get; set; }
|
||||
[FieldOrder(1)][FieldLength(96)][SerializeAs(SerializedType.TerminatedString)] public string MachineName { get; set; } = null!;
|
||||
[FieldOrder(2)][FieldLength(16)][SerializeAs(SerializedType.TerminatedString)] public string LayerImageFormat { get; set; } = "pw0img";
|
||||
[FieldOrder(3)] public uint MaxAntialiasingLevel { get; set; } = 16;
|
||||
[FieldOrder(4)] public uint PropertyFields { get; set; }
|
||||
[FieldOrder(5)] public float DisplayWidth { get; set; }
|
||||
[FieldOrder(6)] public float DisplayHeight { get; set; }
|
||||
[FieldOrder(7)] public float MachineZ { get; set; }
|
||||
[FieldOrder(8)] public uint MaxFileVersion { get; set; } = VERSION_517;
|
||||
[FieldOrder(9)] public uint MachineBackground { get; set; } = 6506241;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Section)}: {Section}, {nameof(MachineName)}: {MachineName}, {nameof(LayerImageFormat)}: {LayerImageFormat}, {nameof(MaxAntialiasingLevel)}: {MaxAntialiasingLevel}, {nameof(PropertyFields)}: {PropertyFields}, {nameof(DisplayWidth)}: {DisplayWidth}, {nameof(DisplayHeight)}: {DisplayHeight}, {nameof(MachineZ)}: {MachineZ}, {nameof(MaxFileVersion)}: {MaxFileVersion}, {nameof(MachineBackground)}: {MachineBackground}";
|
||||
}
|
||||
|
||||
|
||||
public Machine()
|
||||
{
|
||||
Section = new SectionHeader(SectionMark, this);
|
||||
}
|
||||
|
||||
public Machine(int extraLength)
|
||||
{
|
||||
Section = new SectionHeader(SectionMark, this, extraLength);
|
||||
}
|
||||
|
||||
|
||||
public Machine(bool includeSectionOnLength)
|
||||
{
|
||||
Section = new SectionHeader(SectionMark, this, includeSectionOnLength ? 16 : 0);
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
Section.Validate(SectionMark, 0, this);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Software
|
||||
public sealed class Software
|
||||
{
|
||||
public const uint TableSize = 164;
|
||||
[FieldOrder(0)][FieldLength(32)][SerializeAs(SerializedType.TerminatedString)] public string Name { get; set; } = About.Software;
|
||||
[FieldOrder(1)] public uint TableLength { get; set; } = TableSize;
|
||||
[FieldOrder(2)][FieldLength(32)][SerializeAs(SerializedType.TerminatedString)] public string Version { get; set; } = About.VersionStr;
|
||||
[FieldOrder(3)][FieldLength(64)][SerializeAs(SerializedType.TerminatedString)] public string OperativeSystem { get; set; } = RuntimeInformation.RuntimeIdentifier;
|
||||
[FieldOrder(4)][FieldLength(32)][SerializeAs(SerializedType.TerminatedString)] public string OpenGLVersion { get; set; } = "3.3-CoreProfile";
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Name)}: {Name}, {nameof(TableLength)}: {TableLength}, {nameof(Version)}: {Version}, {nameof(OperativeSystem)}: {OperativeSystem}, {nameof(OpenGLVersion)}: {OpenGLVersion}";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Model
|
||||
public sealed class Model
|
||||
{
|
||||
public const string SectionMark = "MODEL";
|
||||
|
||||
[FieldOrder(0)] public SectionHeader Section { get; set; }
|
||||
[FieldOrder(1)] public float MinX { get; set; }
|
||||
[FieldOrder(2)] public float MinY { get; set; }
|
||||
[FieldOrder(3)] public float MinZ { get; set; }
|
||||
[FieldOrder(4)] public float MaxX { get; set; }
|
||||
[FieldOrder(5)] public float MaxY { get; set; }
|
||||
[FieldOrder(6)] public float MaxZ { get; set; }
|
||||
[FieldOrder(7)] public uint SupportsEnabled { get; set; }
|
||||
[FieldOrder(8)] public float SupportsDensity { get; set; }
|
||||
|
||||
public Model()
|
||||
{
|
||||
Section = new SectionHeader(SectionMark, this);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Section)}: {Section}, {nameof(MinX)}: {MinX}, {nameof(MinY)}: {MinY}, {nameof(MinZ)}: {MinZ}, {nameof(MaxX)}: {MaxX}, {nameof(MaxY)}: {MaxY}, {nameof(MaxZ)}: {MaxZ}, {nameof(SupportsEnabled)}: {SupportsEnabled}, {nameof(SupportsDensity)}: {SupportsDensity}";
|
||||
}
|
||||
|
||||
public void Parse(FileFormat slicerFile)
|
||||
{
|
||||
var rect = slicerFile.BoundingRectangleMillimeters;
|
||||
MaxX = (float)Math.Round(rect.Width / 2, 3);
|
||||
MinX = -MaxX;
|
||||
|
||||
MaxY = (float)Math.Round(rect.Height / 2, 3);
|
||||
MinY = -MaxY;
|
||||
|
||||
MinZ = 0;
|
||||
MaxZ = slicerFile.PrintHeight;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Layer
|
||||
|
||||
public class LayerDef
|
||||
@@ -935,88 +1068,7 @@ public class PhotonWorkshopFile : FileFormat
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Extra
|
||||
public class Extra
|
||||
{
|
||||
public const string SectionMark = "EXTRA";
|
||||
|
||||
//[FieldOrder(0)] public SectionHeader Section { get; set; }
|
||||
[FieldOrder(0)] [FieldLength(MarkSize)] [SerializeAs(SerializedType.TerminatedString)] public string Marker { get; set; } = null!;
|
||||
[FieldOrder(1)] public uint Unknown0 { get; set; } = 24;
|
||||
[FieldOrder(2)] public uint Unknown1 { get; set; } = 2;
|
||||
[FieldOrder(3)] public float BottomLiftHeight1 { get; set; }
|
||||
[FieldOrder(4)] public float BottomLiftSpeed1 { get; set; } = SpeedConverter.Convert(DefaultBottomLiftSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(5)] public float BottomRetractSpeed1 { get; set; } = SpeedConverter.Convert(DefaultBottomRetractSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(6)] public float BottomLiftHeight2 { get; set; }
|
||||
[FieldOrder(7)] public float BottomLiftSpeed2 { get; set; } = SpeedConverter.Convert(DefaultBottomLiftSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(8)] public float BottomRetractSpeed2 { get; set; } = SpeedConverter.Convert(DefaultBottomRetractSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(9)] public uint Unknown2 { get; set; } = 2;
|
||||
[FieldOrder(10)] public float LiftHeight1 { get; set; }
|
||||
[FieldOrder(11)] public float LiftSpeed1 { get; set; } = SpeedConverter.Convert(DefaultLiftSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(12)] public float RetractSpeed1 { get; set; } = SpeedConverter.Convert(DefaultRetractSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(13)] public float LiftHeight2 { get; set; }
|
||||
[FieldOrder(14)] public float LiftSpeed2 { get; set; } = SpeedConverter.Convert(DefaultLiftSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
[FieldOrder(15)] public float RetractSpeed2 { get; set; } = SpeedConverter.Convert(DefaultRetractSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond);
|
||||
|
||||
public Extra()
|
||||
{
|
||||
//Section = new SectionHeader(SectionMark, this);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Marker)}: {Marker}, {nameof(Unknown0)}: {Unknown0}, {nameof(Unknown1)}: {Unknown1}, {nameof(BottomLiftHeight1)}: {BottomLiftHeight1}, {nameof(BottomLiftSpeed1)}: {BottomLiftSpeed1}, {nameof(BottomRetractSpeed1)}: {BottomRetractSpeed1}, {nameof(BottomLiftHeight2)}: {BottomLiftHeight2}, {nameof(BottomLiftSpeed2)}: {BottomLiftSpeed2}, {nameof(BottomRetractSpeed2)}: {BottomRetractSpeed2}, {nameof(Unknown2)}: {Unknown2}, {nameof(LiftHeight1)}: {LiftHeight1}, {nameof(LiftSpeed1)}: {LiftSpeed1}, {nameof(RetractSpeed1)}: {RetractSpeed1}, {nameof(LiftHeight2)}: {LiftHeight2}, {nameof(LiftSpeed2)}: {LiftSpeed2}, {nameof(RetractSpeed2)}: {RetractSpeed2}";
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
//Section.Validate(SectionMark, (int)-Helpers.Serializer.SizeOf(Section), this);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Machine
|
||||
public class Machine
|
||||
{
|
||||
public const string SectionMark = "MACHINE";
|
||||
|
||||
[FieldOrder(0)] public SectionHeader Section { get; set; }
|
||||
[FieldOrder(1)] [FieldLength(96)] [SerializeAs(SerializedType.TerminatedString)] public string MachineName { get; set; } = null!;
|
||||
[FieldOrder(2)] [FieldLength(24)] [SerializeAs(SerializedType.TerminatedString)] public string LayerImageFormat { get; set; } = "pw0img";
|
||||
[FieldOrder(3)] public float DisplayWidth { get; set; }
|
||||
[FieldOrder(4)] public float DisplayHeight { get; set; }
|
||||
[FieldOrder(5)] public float MachineZ { get; set; }
|
||||
[FieldOrder(6)] public uint Version { get; set; } = VERSION_516;
|
||||
[FieldOrder(7)] public uint Unknown { get; set; } = 6506241;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Section)}: {Section}, {nameof(MachineName)}: {MachineName}, {nameof(LayerImageFormat)}: {LayerImageFormat}, {nameof(DisplayWidth)}: {DisplayWidth}, {nameof(DisplayHeight)}: {DisplayHeight}, {nameof(MachineZ)}: {MachineZ}, {nameof(Version)}: {Version}, {nameof(Unknown)}: {Unknown}";
|
||||
}
|
||||
|
||||
|
||||
public Machine()
|
||||
{
|
||||
Section = new SectionHeader(SectionMark, this);
|
||||
}
|
||||
|
||||
public Machine(int extraLength)
|
||||
{
|
||||
Section = new SectionHeader(SectionMark, this, extraLength);
|
||||
}
|
||||
|
||||
|
||||
public Machine(bool includeSectionOnLength)
|
||||
{
|
||||
Section = new SectionHeader(SectionMark, this, includeSectionOnLength ? 16 : 0);
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
Section.Validate(SectionMark, 0, this);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1025,12 +1077,17 @@ public class PhotonWorkshopFile : FileFormat
|
||||
public FileMark FileMarkSettings { get; protected internal set; } = new();
|
||||
|
||||
public Header HeaderSettings { get; protected internal set; } = new();
|
||||
public HeaderV516 HeaderV516Settings { get; protected internal set; } = new();
|
||||
public HeaderV517 HeaderV517Settings { get; protected internal set; } = new();
|
||||
|
||||
public Preview PreviewSettings { get; protected internal set; } = new();
|
||||
public LayerImageColorTable LayerImageColorSettings { get; protected internal set; } = new();
|
||||
|
||||
public LayerDefinition LayersDefinition { get; protected internal set; } = new();
|
||||
public Extra ExtraSettings { get; protected internal set; } = new();
|
||||
public Machine MachineSettings { get; protected internal set; } = new(true);
|
||||
public Software SoftwareSettings { get; protected internal set; } = new();
|
||||
public Model ModelSettings { get; protected internal set; } = new();
|
||||
|
||||
public override FileFormatType FileType => FileFormatType.Binary;
|
||||
|
||||
@@ -1115,7 +1172,7 @@ public class PhotonWorkshopFile : FileFormat
|
||||
|
||||
public override Size[]? ThumbnailsOriginalSize { get; } = {new(224, 168)};
|
||||
|
||||
public override uint[] AvailableVersions { get; } = { VERSION_1, VERSION_515, VERSION_516 };
|
||||
public override uint[] AvailableVersions { get; } = { VERSION_1, VERSION_515, VERSION_516, VERSION_517 };
|
||||
|
||||
public override uint DefaultVersion => VERSION_1;
|
||||
|
||||
@@ -1381,6 +1438,7 @@ public class PhotonWorkshopFile : FileFormat
|
||||
ExtraSettings.BottomLiftHeight2 = (float)Math.Round(value, 2);
|
||||
BottomLiftHeight = bottomLiftHeight;
|
||||
base.BottomLiftHeight2 = ExtraSettings.BottomLiftHeight2;
|
||||
HeaderV516Settings.AdvancedMode = System.Convert.ToUInt32(IsUsingTSMC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1406,6 +1464,7 @@ public class PhotonWorkshopFile : FileFormat
|
||||
ExtraSettings.LiftHeight2 = (float)Math.Round(value, 2);
|
||||
LiftHeight = liftHeight;
|
||||
base.BottomLiftHeight2 = ExtraSettings.LiftHeight2;
|
||||
HeaderV516Settings.AdvancedMode = System.Convert.ToUInt32(IsUsingTSMC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1519,13 +1578,14 @@ public class PhotonWorkshopFile : FileFormat
|
||||
AnyCubicMachine.AnyCubicPhotonMonoSQ => "Photon Mono SQ",
|
||||
AnyCubicMachine.AnyCubicPhotonM3 => "Photon M3",
|
||||
AnyCubicMachine.AnyCubicPhotonM3Max => "Photon M3 Max",
|
||||
AnyCubicMachine.AnyCubicCustom => "Custom",
|
||||
_ => base.MachineName
|
||||
};
|
||||
}
|
||||
set => base.MachineName = MachineSettings.MachineName = value;
|
||||
}
|
||||
|
||||
public override object[] Configs => new object[] { FileMarkSettings, HeaderSettings, PreviewSettings, LayersDefinition, ExtraSettings, MachineSettings };
|
||||
public override object[] Configs => new object[] { FileMarkSettings, HeaderSettings, PreviewSettings, ExtraSettings, MachineSettings, SoftwareSettings, ModelSettings, LayerImageColorSettings, LayersDefinition };
|
||||
|
||||
public LayerRleFormat LayerImageFormat =>
|
||||
FileEndsWith(".pws")
|
||||
@@ -1617,35 +1677,43 @@ public class PhotonWorkshopFile : FileFormat
|
||||
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
/*if (FileMarkSettings.AreaNum == 0)
|
||||
{*/
|
||||
FileMarkSettings.AreaNum = FileMarkSettings.Version switch
|
||||
FileMarkSettings.NumberOfTables = FileMarkSettings.Version switch
|
||||
{
|
||||
VERSION_1 => 4,
|
||||
VERSION_515 => 5,
|
||||
VERSION_516 => 8,
|
||||
VERSION_517 => 9,
|
||||
_ => 4
|
||||
};
|
||||
//}
|
||||
|
||||
HeaderSettings.PixelSizeUm = PixelSizeMicronsMax;
|
||||
MachineSettings.LayerImageFormat = $"{LayerImageFormat.ToString().ToLower()}Img";
|
||||
|
||||
HeaderSettings.PerLayerOverride = (byte)(AllLayersAreUsingGlobalParameters ? 0 : 1);
|
||||
|
||||
|
||||
FileMarkSettings.HeaderAddress = (uint) Helpers.Serializer.SizeOf(FileMarkSettings);
|
||||
using var outputFile = new FileStream(TemporaryOutputFileFullPath, FileMode.Create, FileAccess.Write);
|
||||
if (FileMarkSettings.Version >= VERSION_516)
|
||||
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_517)
|
||||
{
|
||||
HeaderSettings.Section.Length = 92;
|
||||
}
|
||||
else if (FileMarkSettings.Version >= VERSION_516)
|
||||
{
|
||||
HeaderSettings.Section.Length = 84;
|
||||
}
|
||||
|
||||
|
||||
outputFile.Seek((int)FileMarkSettings.HeaderAddress, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
outputFile.WriteSerialize(HeaderSettings);
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_516)
|
||||
{
|
||||
outputFile.WriteUIntLittleEndian(System.Convert.ToUInt32(IsUsingTSMC));
|
||||
//outputFile.Seek(4, SeekOrigin.Current); // Extra padding
|
||||
outputFile.WriteSerialize(HeaderV516Settings);
|
||||
}
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_517)
|
||||
{
|
||||
outputFile.WriteSerialize(HeaderV517Settings);
|
||||
}
|
||||
|
||||
if (CreatedThumbnailsCount > 0)
|
||||
@@ -1656,23 +1724,20 @@ public class PhotonWorkshopFile : FileFormat
|
||||
{
|
||||
Data = EncodeImage(DATATYPE_RGB565, Thumbnails[0]!)
|
||||
};
|
||||
Helpers.SerializeWriteFileStream(outputFile, preview);
|
||||
outputFile.WriteSerialize(preview);
|
||||
outputFile.WriteBytes(preview.Data);
|
||||
FileMarkSettings.PreviewEndAddress = (uint)outputFile.Position;
|
||||
}
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_515)
|
||||
{
|
||||
foreach (var uint32 in ReservedUintsAfterPreview)
|
||||
{
|
||||
outputFile.WriteUIntLittleEndian(uint32);
|
||||
}
|
||||
FileMarkSettings.LayerImageColorTableAddress = (uint)outputFile.Position;
|
||||
outputFile.WriteSerialize(LayerImageColorSettings);
|
||||
}
|
||||
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
FileMarkSettings.LayerDefinitionAddress = (uint)outputFile.Position;
|
||||
LayersDefinition = new LayerDefinition(LayerCount);
|
||||
Helpers.SerializeWriteFileStream(outputFile, LayersDefinition);
|
||||
outputFile.WriteSerialize(LayersDefinition);
|
||||
uint layerDefOffset = (uint)outputFile.Position;
|
||||
uint layerRleOffset = (uint)(layerDefOffset + Helpers.Serializer.SizeOf(new LayerDef()) * LayerCount);
|
||||
|
||||
@@ -1680,16 +1745,29 @@ public class PhotonWorkshopFile : FileFormat
|
||||
{
|
||||
outputFile.Seek(layerRleOffset, SeekOrigin.Begin);
|
||||
FileMarkSettings.ExtraAddress = layerRleOffset;
|
||||
Helpers.SerializeWriteFileStream(outputFile, ExtraSettings);
|
||||
outputFile.WriteSerialize(ExtraSettings);
|
||||
|
||||
FileMarkSettings.MachineAddress = (uint)outputFile.Position;
|
||||
Helpers.SerializeWriteFileStream(outputFile, MachineSettings);
|
||||
outputFile.WriteSerialize(MachineSettings);
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_517)
|
||||
{
|
||||
FileMarkSettings.SoftwareAddress = (uint)outputFile.Position;
|
||||
SoftwareSettings = new Software();
|
||||
outputFile.WriteSerialize(SoftwareSettings);
|
||||
|
||||
FileMarkSettings.ModelAddress = (uint)outputFile.Position;
|
||||
ModelSettings.Parse(this);
|
||||
outputFile.WriteSerialize(ModelSettings);
|
||||
}
|
||||
|
||||
layerRleOffset = (uint)outputFile.Position;
|
||||
outputFile.Seek(layerDefOffset, SeekOrigin.Begin);
|
||||
}
|
||||
else if (FileMarkSettings.Version == VERSION_515)
|
||||
{
|
||||
FileMarkSettings.ExtraAddress = layerRleOffset;
|
||||
}
|
||||
|
||||
|
||||
FileMarkSettings.LayerImageAddress = layerRleOffset;
|
||||
|
||||
@@ -1727,17 +1805,22 @@ public class PhotonWorkshopFile : FileFormat
|
||||
layerDef.DataAddress = layerRleOffset;
|
||||
|
||||
outputFile.Seek(layerRleOffset, SeekOrigin.Begin);
|
||||
layerRleOffset += Helpers.SerializeWriteFileStream(outputFile, layerDef.EncodedRle);
|
||||
layerRleOffset += outputFile.WriteBytes(layerDef.EncodedRle);
|
||||
}
|
||||
|
||||
outputFile.Seek(layerDefOffset, SeekOrigin.Begin);
|
||||
layerDefOffset += Helpers.SerializeWriteFileStream(outputFile, layerDef);
|
||||
layerDefOffset += outputFile.WriteSerialize(layerDef);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var layerDef in LayersDefinition.Layers)
|
||||
{
|
||||
layerDef.EncodedRle = null!;
|
||||
}
|
||||
|
||||
// Rewind
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, FileMarkSettings);
|
||||
outputFile.WriteSerialize(FileMarkSettings);
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
@@ -1750,26 +1833,37 @@ public class PhotonWorkshopFile : FileFormat
|
||||
|
||||
if (!FileMarkSettings.Mark.Equals(FileMark.SectionMarkFile))
|
||||
{
|
||||
throw new FileLoadException(
|
||||
$"Invalid Filemark {FileMarkSettings.Mark}, expected {FileMark.SectionMarkFile}", FileFullPath);
|
||||
throw new FileLoadException($"Invalid Filemark {FileMarkSettings.Mark}, expected {FileMark.SectionMarkFile}", FileFullPath);
|
||||
}
|
||||
|
||||
if (FileMarkSettings.Version is not VERSION_1 and not VERSION_515 and not VERSION_516)
|
||||
if (!AvailableVersions.Contains(FileMarkSettings.Version))
|
||||
{
|
||||
throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expected {VERSION_1} or {VERSION_515} or {VERSION_516}", FileFullPath);
|
||||
throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expecting {string.Join(" or ", AvailableVersions)}", FileFullPath);
|
||||
}
|
||||
|
||||
inputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin);
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
if (FileMarkSettings.Version >= VERSION_516)
|
||||
{
|
||||
inputFile.Seek(4, SeekOrigin.Current); // Extra padding
|
||||
}
|
||||
|
||||
Debug.Write("Header -> ");
|
||||
Debug.WriteLine(HeaderSettings);
|
||||
|
||||
HeaderSettings.Validate(FileMarkSettings.Version >= VERSION_516 ? 4 : 0);
|
||||
var extraBytes = 0;
|
||||
if (FileMarkSettings.Version >= VERSION_516)
|
||||
{
|
||||
HeaderV516Settings = Helpers.Deserialize<HeaderV516>(inputFile);
|
||||
Debug.Write("HeaderV516 -> ");
|
||||
Debug.WriteLine(HeaderV516Settings);
|
||||
extraBytes += (int)Helpers.Serializer.SizeOf(HeaderV516Settings);
|
||||
}
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_517)
|
||||
{
|
||||
HeaderV517Settings = Helpers.Deserialize<HeaderV517>(inputFile);
|
||||
Debug.Write("HeaderV517 -> ");
|
||||
Debug.WriteLine(HeaderV517Settings);
|
||||
extraBytes += (int)Helpers.Serializer.SizeOf(HeaderV517Settings);
|
||||
}
|
||||
|
||||
HeaderSettings.Validate(extraBytes);
|
||||
|
||||
if (FileMarkSettings.PreviewAddress > 0)
|
||||
{
|
||||
@@ -1789,6 +1883,14 @@ public class PhotonWorkshopFile : FileFormat
|
||||
PreviewSettings.Data = null!;
|
||||
}
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_515 && FileMarkSettings.LayerImageColorTableAddress > 0)
|
||||
{
|
||||
inputFile.Seek(FileMarkSettings.LayerImageColorTableAddress, SeekOrigin.Begin);
|
||||
LayerImageColorSettings = Helpers.Deserialize<LayerImageColorTable>(inputFile);
|
||||
Debug.Write("LayerImageColorTable -> ");
|
||||
Debug.WriteLine(LayerImageColorSettings);
|
||||
}
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_516 && FileMarkSettings.ExtraAddress > 0)
|
||||
{
|
||||
inputFile.Seek(FileMarkSettings.ExtraAddress, SeekOrigin.Begin);
|
||||
@@ -1807,6 +1909,22 @@ public class PhotonWorkshopFile : FileFormat
|
||||
Debug.WriteLine(MachineSettings);
|
||||
}
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_517 && FileMarkSettings.SoftwareAddress > 0)
|
||||
{
|
||||
inputFile.Seek(FileMarkSettings.SoftwareAddress, SeekOrigin.Begin);
|
||||
SoftwareSettings = Helpers.Deserialize<Software>(inputFile);
|
||||
Debug.Write("Software -> ");
|
||||
Debug.WriteLine(SoftwareSettings);
|
||||
}
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_517 && FileMarkSettings.ModelAddress > 0)
|
||||
{
|
||||
inputFile.Seek(FileMarkSettings.ModelAddress, SeekOrigin.Begin);
|
||||
ModelSettings = Helpers.Deserialize<Model>(inputFile);
|
||||
Debug.Write("Model -> ");
|
||||
Debug.WriteLine(ModelSettings);
|
||||
}
|
||||
|
||||
inputFile.Seek(FileMarkSettings.LayerDefinitionAddress, SeekOrigin.Begin);
|
||||
|
||||
LayersDefinition = Helpers.Deserialize<LayerDefinition>(inputFile);
|
||||
@@ -1874,31 +1992,84 @@ public class PhotonWorkshopFile : FileFormat
|
||||
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
HeaderSettings.PerLayerOverride = AllLayersAreUsingGlobalParameters ? 0 : 1u;
|
||||
|
||||
using var outputFile = new FileStream(TemporaryOutputFileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
outputFile.WriteSerialize(HeaderSettings);
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_516 && FileMarkSettings.ExtraAddress > 0)
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_516)
|
||||
{
|
||||
outputFile.Seek(FileMarkSettings.ExtraAddress, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, ExtraSettings);
|
||||
outputFile.WriteSerialize(HeaderV516Settings);
|
||||
}
|
||||
|
||||
if (FileMarkSettings.MachineAddress > 0)
|
||||
if (FileMarkSettings.Version >= VERSION_517)
|
||||
{
|
||||
outputFile.Seek(FileMarkSettings.MachineAddress, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, MachineSettings);
|
||||
outputFile.WriteSerialize(HeaderV517Settings);
|
||||
}
|
||||
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_516)
|
||||
{
|
||||
if (FileMarkSettings.ExtraAddress > 0)
|
||||
{
|
||||
outputFile.Seek(FileMarkSettings.ExtraAddress, SeekOrigin.Begin);
|
||||
outputFile.WriteSerialize(ExtraSettings);
|
||||
}
|
||||
|
||||
if (FileMarkSettings.MachineAddress > 0)
|
||||
{
|
||||
outputFile.Seek(FileMarkSettings.MachineAddress, SeekOrigin.Begin);
|
||||
outputFile.WriteSerialize(MachineSettings);
|
||||
}
|
||||
}
|
||||
|
||||
if (FileMarkSettings.Version >= VERSION_517)
|
||||
{
|
||||
if (FileMarkSettings.SoftwareAddress > 0)
|
||||
{
|
||||
outputFile.Seek(FileMarkSettings.SoftwareAddress, SeekOrigin.Begin);
|
||||
SoftwareSettings = new Software();
|
||||
outputFile.WriteSerialize(SoftwareSettings);
|
||||
}
|
||||
|
||||
if (FileMarkSettings.ModelAddress > 0)
|
||||
{
|
||||
outputFile.Seek(FileMarkSettings.ModelAddress, SeekOrigin.Begin);
|
||||
ModelSettings.Parse(this);
|
||||
outputFile.WriteSerialize(ModelSettings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
outputFile.Seek(FileMarkSettings.LayerDefinitionAddress + Helpers.Serializer.SizeOf(LayersDefinition), SeekOrigin.Begin);
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
LayersDefinition[layerIndex].SetFrom(this[layerIndex]);
|
||||
Helpers.SerializeWriteFileStream(outputFile, LayersDefinition[layerIndex]);
|
||||
outputFile.WriteSerialize(LayersDefinition[layerIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnBeforeEncode(bool isPartialEncode)
|
||||
{
|
||||
HeaderSettings.PerLayerOverride = System.Convert.ToUInt32(AllLayersAreUsingGlobalParameters);
|
||||
MachineSettings.MaxFileVersion = PrinterModel switch
|
||||
{
|
||||
AnyCubicMachine.AnyCubicPhotonS => VERSION_1,
|
||||
AnyCubicMachine.AnyCubicPhotonZero => VERSION_1,
|
||||
AnyCubicMachine.AnyCubicPhotonX => VERSION_1,
|
||||
AnyCubicMachine.AnyCubicPhotonUltra => VERSION_515,
|
||||
AnyCubicMachine.AnyCubicPhotonMono => VERSION_515,
|
||||
AnyCubicMachine.AnyCubicPhotonMonoSE => VERSION_515,
|
||||
AnyCubicMachine.AnyCubicPhotonMono4K => VERSION_516,
|
||||
AnyCubicMachine.AnyCubicPhotonMonoX => VERSION_516,
|
||||
AnyCubicMachine.AnyCubicPhotonMonoX6KM3Plus => VERSION_517,
|
||||
AnyCubicMachine.AnyCubicPhotonMonoSQ => VERSION_515,
|
||||
AnyCubicMachine.AnyCubicPhotonM3 => VERSION_516,
|
||||
AnyCubicMachine.AnyCubicPhotonM3Max => VERSION_516,
|
||||
AnyCubicMachine.AnyCubicCustom => VERSION_516,
|
||||
_ => VERSION_517
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user