* (Add) File format: Zcode (Uniz IBEE)
* (Add) PrusaSlicer Printer: Uniz IBEE
* (Add) Extract: Output an "Layer.ini" file containing per layer data and include the Configuration.ini for Zip file formats
* (Improvement) Zip: Increase the GCode parsing performance
* (Fix) File formats: Wasn't set bottom / light off delay per individual layer on generic formats, defaulting every layer to 0
* (Fix) Edit print paramenters: When changing bottom layer count, layers didnt update thier properties
This commit is contained in:
Tiago Conceição
2021-03-02 01:42:53 +00:00
parent 8d0e607d08
commit 5fc722e203
18 changed files with 944 additions and 52 deletions
+9
View File
@@ -1,5 +1,14 @@
# Changelog
## 25/02/2021 - v2.6.0
* (Add) File format: Zcode (Uniz IBEE)
* (Add) PrusaSlicer Printer: Uniz IBEE
* (Add) Extract: Output an "Layer.ini" file containing per layer data and include the Configuration.ini for Zip file formats
* (Improvement) Zip: Increase the GCode parsing performance
* (Fix) File formats: Wasn't set bottom / light off delay per individual layer on generic formats, defaulting every layer to 0
* (Fix) Edit print paramenters: When changing bottom layer count, layers didnt update thier properties
## 25/02/2021 - v2.5.1
* (Add) Calibration - Exposure time finder: Option to "Do not perform the lifting sequence for layers with same Z positioning"
+6 -1
View File
@@ -31,7 +31,7 @@ class FixedEncoder : System.Text.UTF8Encoding {
####################################
$enableMSI = $true
$buildOnly = $null
#$buildOnly = "osx-x64"#"win-x64"
#$buildOnly = "win-x64"
# Profilling
$stopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
$deployStopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
@@ -103,6 +103,11 @@ $runtimes =
"exclude" = @()
"include" = @("libcvextern.so")
}
"linux-arm64" = @{
"extraCmd" = "-p:PublishReadyToRun=true"
"exclude" = @()
"include" = @("libcvextern.so")
}
#"unix-x64" = @{
# "extraCmd" = "-p:PublishReadyToRun=true"
# "exclude" = @("x86", "x64", "libcvextern.dylib")
+1
View File
@@ -63,6 +63,7 @@ SET files[53]=Voxelab Ceres 8.9.ini
SET files[54]=Longer Orange 10.ini
SET files[55]=Longer Orange 30.ini
SET files[56]=Longer Orange4K.ini
SET files[57]=Uniz IBEE.ini
echo PrusaSlicer Printers Instalation
echo This will replace printers, all changes will be discarded
+38
View File
@@ -0,0 +1,38 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-02 at 01:39:35 UTC
absolute_correction = 0
area_fill = 50
bed_custom_model =
bed_custom_texture =
bed_shape = 0x0,192x0,192x120,0x120
default_sla_material_profile = Prusa Orange Tough 0.05
default_sla_print_profile = 0.05 Normal
display_height = 120
display_mirror_x = 0
display_mirror_y = 1
display_orientation = landscape
display_pixels_x = 3840
display_pixels_y = 2400
display_width = 192
elefant_foot_compensation = 0.2
elefant_foot_min_width = 0.2
fast_tilt_time = 5
gamma_correction = 1
host_type = octoprint
inherits = Original Prusa SL1
max_exposure_time = 120
max_initial_exposure_time = 300
max_print_height = 220
min_exposure_time = 1
min_initial_exposure_time = 1
print_host =
printer_model = SL1
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_UNIZ\nPRINTER_MODEL_IBEE\nFILEFORMAT_ZCODE\n\nSTART_CUSTOM_VALUES\nLightOffDelay_2\nBottomLightOffDelay_4\nBottomLiftHeight_15\nLiftHeight_7\nBottomLiftSpeed_20\nLiftSpeed_80\nRetractSpeed_80\nEND_CUSTOM_VALUES
printer_settings_id =
printer_technology = SLA
printer_variant = default
printer_vendor =
printhost_apikey =
printhost_cafile =
relative_correction = 1,1
slow_tilt_time = 8
thumbnails = 400x400,800x480
+3 -1
View File
@@ -66,6 +66,7 @@ But also, i need victims for test subject. Proceed at your own risk!
* PWMO (Photon Workshop)
* PWMS (Photon Workshop)
* PWMX (Photon Workshop)
* ZCode (UnizMaker)
* ZCodex (Z-Suite)
* CWS (NovaMaker)
* RGB.CWS (Nova Bene4 Mono / Elfin2 Mono SE)
@@ -86,7 +87,6 @@ But also, i need victims for test subject. Proceed at your own risk!
* X133 4K Mono
* X156 4K Color
* X1K 2K Mono
* **Zortrax Inkspire**
* **Nova3D**
* Elfin
* Bene4 Mono
@@ -140,6 +140,8 @@ But also, i need victims for test subject. Proceed at your own risk!
* Orange 10
* Orange 30
* Orange4K
* **Uniz IBEE**
* **Zortrax Inkspire**
# Available profiles for PrusaSlicer
+8 -1
View File
@@ -1,4 +1,11 @@
using System;
/*
* 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.Drawing;
namespace UVtools.Core.Extensions
+8 -1
View File
@@ -1,4 +1,11 @@
using System;
/*
* 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.Generic;
using System.Drawing;
using System.Text;
-6
View File
@@ -533,12 +533,6 @@ namespace UVtools.Core.FileFormats
#region Methods
public override void Clear()
{
base.Clear();
GCode = null;
}
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
{
//var filename = fileFullPath.EndsWith(TemporaryFileAppend) ? Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(fileFullPath)) : Path.GetFileNameWithoutExtension(fileFullPath);
+2 -2
View File
@@ -531,8 +531,8 @@ namespace UVtools.Core.FileFormats
var startStr = $";LAYER_START:{layerIndex}";
var stripGcode = gcode.Substring(gcode.IndexOf(startStr, StringComparison.InvariantCultureIgnoreCase) + startStr.Length);
stripGcode = stripGcode.Substring(0, stripGcode.IndexOf(";LAYER_END")).Trim(' ', '\n', '\r', '\t');
gcode = gcode.Substring(gcode.IndexOf(startStr, StringComparison.InvariantCultureIgnoreCase) + startStr.Length);
var stripGcode = gcode.Substring(0, gcode.IndexOf(";LAYER_END")).Trim(' ', '\n', '\r', '\t');
//var startCurrPos = stripGcode.Remove(0, ";currPos:".Length);
float posZ = lastPostZ;
+60 -36
View File
@@ -10,7 +10,6 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
@@ -37,6 +36,8 @@ namespace UVtools.Core.FileFormats
private const string ExtractConfigFileName = "Configuration";
private const string ExtractConfigFileExtension = "ini";
public const float DefaultLayerHeight = 0.5f;
public const ushort DefaultBottomLayerCount = 4;
public const float DefaultBottomExposureTime = 30;
@@ -206,8 +207,9 @@ namespace UVtools.Core.FileFormats
new PHZFile(), // phz
new FDGFile(), // fdg
new PhotonWorkshopFile(), // PSW
new ZCodexFile(), // zcodex
new CWSFile(), // CWS
new ZCodeFile(), // zcode
new ZCodexFile(), // zcodex
//new MakerbaseFile(), // MKS
new LGSFile(), // LGS, LGS30
new UVJFile(), // UVJ
@@ -546,7 +548,7 @@ namespace UVtools.Core.FileFormats
/// <summary>
/// Gets or sets if images need to be mirrored on lcd to print on the correct orientation
/// </summary>
public abstract bool MirrorDisplay { get; set; }
public virtual bool MirrorDisplay { get; set; }
/// <summary>
/// Gets or sets the maximum printer build Z volume
@@ -1272,22 +1274,10 @@ namespace UVtools.Core.FileFormats
//{
Directory.CreateDirectory(path);
//}
if (FileType == FileFormatType.Archive)
{
progress.CanCancel = false;
//ZipFile.ExtractToDirectory(FileFullPath, path);
ZipArchiveExtensions.ImprovedExtractToDirectory(FileFullPath, path, ZipArchiveExtensions.Overwrite.Always);
return;
}
progress.ItemCount = LayerCount;
if (genericConfigExtract)
{
if (!ReferenceEquals(Configs, null))
if (Configs is not null)
{
using TextWriter tw = new StreamWriter(Path.Combine(path, $"{ExtractConfigFileName}.{ExtractConfigFileExtension}"), false);
foreach (var config in Configs)
@@ -1307,14 +1297,66 @@ namespace UVtools.Core.FileFormats
}
}
if (genericLayersExtract)
{
if (LayerCount > 0)
{
using (TextWriter tw = new StreamWriter(Path.Combine(path, "Layers.ini")))
{
for (int layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
var layer = this[layerIndex];
tw.WriteLine($"[{layerIndex}]");
tw.WriteLine($"{nameof(layer.NonZeroPixelCount)}: {layer.NonZeroPixelCount}");
tw.WriteLine($"{nameof(layer.BoundingRectangle)}: {layer.BoundingRectangle}");
tw.WriteLine($"{nameof(layer.IsBottomLayer)}: {layer.IsBottomLayer}");
tw.WriteLine($"{nameof(layer.LayerHeight)}: {layer.LayerHeight}");
tw.WriteLine($"{nameof(layer.PositionZ)}: {layer.PositionZ}");
tw.WriteLine($"{nameof(layer.ExposureTime)}: {layer.ExposureTime}");
if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LightOffDelay))
tw.WriteLine($"{nameof(layer.LightOffDelay)}: {layer.LightOffDelay}");
if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LiftHeight))
tw.WriteLine($"{nameof(layer.LiftHeight)}: {layer.LiftHeight}");
if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LiftSpeed))
tw.WriteLine($"{nameof(layer.LiftSpeed)}: {layer.LiftSpeed}");
if (HavePrintParameterPerLayerModifier(PrintParameterModifier.RetractSpeed))
tw.WriteLine($"{nameof(layer.RetractSpeed)}: {layer.RetractSpeed}");
if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LightPWM))
tw.WriteLine($"{nameof(layer.LightPWM)}: {layer.LightPWM}");
var materialMillilitersPercent = layer.MaterialMillilitersPercent;
if (!float.IsNaN(materialMillilitersPercent))
{
tw.WriteLine($"{nameof(layer.MaterialMilliliters)}: {layer.MaterialMilliliters}ml ({materialMillilitersPercent:F2}%)");
}
tw.WriteLine();
}
tw.Close();
}
}
}
if (FileType == FileFormatType.Archive)
{
progress.CanCancel = false;
ZipArchiveExtensions.ImprovedExtractToDirectory(FileFullPath, path, ZipArchiveExtensions.Overwrite.Always);
return;
}
progress.ItemCount = LayerCount;
if (genericLayersExtract)
{
uint i = 0;
if (!ReferenceEquals(Thumbnails, null))
if (Thumbnails is not null)
{
foreach (var thumbnail in Thumbnails)
{
if (ReferenceEquals(thumbnail, null))
if (thumbnail is null)
{
continue;
}
@@ -1342,24 +1384,6 @@ namespace UVtools.Core.FileFormats
}
});
}
/* Parallel.For(0, LayerCount, layerIndex => {
var byteArr = this[layerIndex].RawData;
using (FileStream stream = File.Create(Path.Combine(path, $"Layer{layerIndex}.png"), byteArr.Length))
{
stream.Write(byteArr, 0, byteArr.Length);
stream.Close();
}
});*/
/*for (i = 0; i < LayerCount; i++)
{
var byteArr = GetLayer(i);
using (FileStream stream = File.Create(Path.Combine(path, $"Layer{i}.png"), byteArr.Length))
{
stream.Write(byteArr, 0, byteArr.Length);
stream.Close();
}
}*/
}
}
+795
View File
@@ -0,0 +1,795 @@
/*
* 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.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.OpenSsl;
using UVtools.Core.Extensions;
using UVtools.Core.Operations;
namespace UVtools.Core.FileFormats
{
[Serializable]
[XmlRoot(ElementName = "Print")]
public class ZCodePrint
{
[Serializable]
[XmlRoot(ElementName = "Device")]
public class ZcodePrintDevice
{
[XmlAttribute("z")]
public ushort MachineZ { get; set; } = 220;
[XmlAttribute("height")]
public uint ResolutionY { get; set; } = 2400;
[XmlAttribute("width")]
public uint ResolutionX { get; set; } = 3840;
[XmlAttribute("type")]
public string MachineModel { get; set; } = "IBEE";
[XmlAttribute("pixel_size")]
public float PixelSize { get; set; } = 50;
}
[Serializable]
[XmlRoot(ElementName = "Profile")]
public class ZcodePrintProfile
{
[XmlAttribute("name")]
public string Name { get; set; } = "UVtools";
[Serializable]
[XmlRoot(ElementName = "Slice")]
public class ZcodePrintProfileSlice
{
[XmlAttribute("bottom_layers")]
public ushort BottomLayerCount { get; set; } = FileFormat.DefaultBottomLayerCount;
[XmlAttribute("exposure_bottom")]
public uint BottomExposureTime { get; set; } = (uint) (FileFormat.DefaultBottomExposureTime * 1000);
[XmlAttribute("exposure")]
public uint ExposureTime { get; set; } = (uint) (FileFormat.DefaultExposureTime * 1000);
[XmlAttribute("height_bottom")]
public float BottomLiftHeight { get; set; } = FileFormat.DefaultBottomLiftHeight;
[XmlAttribute("speed_bottom")]
public float BottomLiftSpeed { get; set; } = FileFormat.DefaultBottomLiftSpeed;
[XmlAttribute("height")]
public float LiftHeight { get; set; } = FileFormat.DefaultLiftHeight;
[XmlAttribute("speed")]
public float LiftSpeed { get; set; } = FileFormat.DefaultLiftSpeed;
[XmlAttribute("cooldown_bottom")]
public uint BottomLightOffDelay { get; set; } = (uint) (FileFormat.DefaultBottomLightOffDelay * 1000);
[XmlAttribute("cooldown")]
public uint LightOffDelay { get; set; } = (uint) (FileFormat.DefaultLightOffDelay * 1000);
[XmlAttribute("thickness")]
public float LayerHeight { get; set; } = FileFormat.DefaultLayerHeight;
[XmlAttribute("anti_aliasing_level")]
public byte AntiAliasing { get; set; }
[XmlAttribute("anti_aliasing_grey_level")]
public byte AntiAliasingGrey { get; set; }
[XmlAttribute("led_power")]
public ushort LedPower { get; set; } = 300;
}
public ZcodePrintProfileSlice Slice { get; set; } = new();
}
[Serializable]
[XmlRoot(ElementName = "Job")]
public class ZcodePrintJob
{
[XmlElement("name")]
public string StlName { get; set; }
[XmlElement("previewImage")]
public string PreviewImage { get; set; } = ZCodeFile.PreviewFilename;
[XmlElement("layers")]
public uint LayerCount { get; set; }
[XmlElement("time")]
public uint PrintTime { get; set; }
[XmlElement("volumn")]
public float VolumeMl { get; set; }
[XmlElement("thickness")]
public float LayerHeight { get; set; }
[XmlElement("price")]
public float Price { get; set; }
[XmlElement("weight")]
public float WeightG { get; set; }
}
public ZcodePrintDevice Device = new();
public ZcodePrintProfile Profile = new();
public ZcodePrintJob Job = new();
}
public class ZCodeFile : FileFormat
{
#region Constants
public const string GCodeFilename = "lcd.gcode";
public const string ManifestFilename = "task.xml";
public const string PreviewFilename = "preview.png";
public const string GCodeStart = "G21;{0}" + // Set units to be mm
"G90;{0}" + // Absolute Positioning
"M106 S0;{0}" + // Light Off
"G28 Z0;{0}"; // Home
public const string GCodeEnd = "M106 S0{0}" + // Light Off
"G1 Z{1} F10;{0}" + // Raize Z
"M18;{0}"; // Disable Motors
public const string GCodeRSAPrivateKey =
"-----BEGIN PRIVATE KEY-----\n" +
"MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA6BnF3oT9Ap+OyZFs" +
"p02ZRtTpbMUA96PpctTXev1cPCclLuowXWNa3f2JBpPbPrzMwLam3JSQN3HjvYfS" +
"Vx7e6wIDAQABAkBibCNzQ/PCfAThxxBLNeXMmpbNsBDD8rcZIdaqaewF+UjUlqI7" +
"eI0Yp2V2Ez28FjKCEiM34DxU9PZTzYS3rCShAiEA9qp9+RwYvcvQUXlT2bqKIo3s" +
"xu7LQFM4VIddQ1SMVhsCIQDw4i74LqF285Iz77vw1MXE06LHKKBBBa3Air1QNBhn" +
"cQIgYfO4TLk8lfoewovkoVyzSB+F/EWNjwC9KMwMXBVyGSsCIQDisxudOtV+y3C3" +
"LFHmL3kI6lxxrsxTJXMGmAvfJYgqIQIhAKBtzYeZB46EToDSpeYlrMQitSWvjgNG" +
"mw+8aB/HYEIr\n" +
"-----END PRIVATE KEY-----";
public const string GCodeRSAPublicKey =
"-----BEGIN PUBLIC KEY-----\n" +
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAOgZxd6E/QKfjsmRbKdNmUbU6WzFAPej" +
"6XLU13r9XDwnJS7qMF1jWt39iQaT2z68zMC2ptyUkDdx472H0lce3usCAwEAAQ==\n" +
"-----END PUBLIC KEY-----";
#endregion
#region Sub Classes
#endregion
#region Properties
public ZCodePrint ManifestFile { get; set; } = new ();
public override FileFormatType FileType => FileFormatType.Archive;
public override FileExtension[] FileExtensions { get; } = {
new("zcode", "UnizMaker ZCode files")
};
public override PrintParameterModifier[] PrintParameterModifiers { get; } = {
PrintParameterModifier.BottomLayerCount,
PrintParameterModifier.BottomExposureSeconds,
PrintParameterModifier.ExposureSeconds,
PrintParameterModifier.BottomLightOffDelay,
PrintParameterModifier.LightOffDelay,
PrintParameterModifier.BottomLiftHeight,
PrintParameterModifier.BottomLiftSpeed,
PrintParameterModifier.LiftHeight,
PrintParameterModifier.LiftSpeed,
PrintParameterModifier.RetractSpeed,
//PrintParameterModifier.BottomLightPWM,
//PrintParameterModifier.LightPWM,
};
public override PrintParameterModifier[] PrintParameterPerLayerModifiers { get; } = {
PrintParameterModifier.ExposureSeconds,
PrintParameterModifier.LightOffDelay,
PrintParameterModifier.LiftHeight,
PrintParameterModifier.LiftSpeed,
PrintParameterModifier.RetractSpeed,
//PrintParameterModifier.LightPWM,
};
public override byte ThumbnailsCount { get; } = 1;
public override Size[] ThumbnailsOriginalSize { get; } = {new(640, 480)};
public override uint ResolutionX
{
get => ManifestFile.Device.ResolutionX;
set
{
ManifestFile.Device.ResolutionX = value;
RaisePropertyChanged();
}
}
public override uint ResolutionY
{
get => ManifestFile.Device.ResolutionY;
set
{
ManifestFile.Device.ResolutionY = value;
RaisePropertyChanged();
}
}
public override float DisplayWidth
{
get => (float) Math.Round(ManifestFile.Device.ResolutionX * ManifestFile.Device.PixelSize / 1000, 2);
set => RaisePropertyChanged();
}
public override float DisplayHeight
{
get => (float)Math.Round(ManifestFile.Device.ResolutionY * ManifestFile.Device.PixelSize / 1000, 2);
set => RaisePropertyChanged();
}
public override float MaxPrintHeight
{
get => ManifestFile.Device.MachineZ > 0 ? ManifestFile.Device.MachineZ : base.MaxPrintHeight;
set
{
ManifestFile.Device.MachineZ = (ushort) value;
RaisePropertyChanged();
}
}
public override bool MirrorDisplay => true;
public override byte AntiAliasing
{
get => ManifestFile.Profile.Slice.AntiAliasing;
set
{
ManifestFile.Profile.Slice.AntiAliasing = value.Clamp(1, 16);
RaisePropertyChanged();
}
}
public override float LayerHeight
{
get => ManifestFile.Job.LayerHeight;
set
{
ManifestFile.Job.LayerHeight = ManifestFile.Profile.Slice.LayerHeight = (float)Math.Round(value, 2);
RaisePropertyChanged();
}
}
public override uint LayerCount
{
set
{
ManifestFile.Job.LayerCount = LayerCount;
RaisePropertyChanged();
RaisePropertyChanged(nameof(NormalLayerCount));
}
}
public override ushort BottomLayerCount
{
get => ManifestFile.Profile.Slice.BottomLayerCount;
set
{
ManifestFile.Profile.Slice.BottomLayerCount = value;
RaisePropertyChanged();
}
}
public override float BottomExposureTime
{
get => (float)Math.Round(ManifestFile.Profile.Slice.BottomExposureTime / 1000f, 2);
set
{
ManifestFile.Profile.Slice.BottomExposureTime = (uint) (value * 1000);
RaisePropertyChanged();
}
}
public override float ExposureTime
{
get => (float)Math.Round(ManifestFile.Profile.Slice.ExposureTime / 1000f, 2);
set
{
ManifestFile.Profile.Slice.ExposureTime = (uint)(value * 1000);
RaisePropertyChanged();
}
}
public override float BottomLightOffDelay
{
get => (float)Math.Round(ManifestFile.Profile.Slice.BottomLightOffDelay / 1000f, 2);
set
{
ManifestFile.Profile.Slice.BottomLightOffDelay = (uint)(value * 1000);
RaisePropertyChanged();
}
}
public override float LightOffDelay
{
get => (float)Math.Round(ManifestFile.Profile.Slice.LightOffDelay / 1000f, 2);
set
{
ManifestFile.Profile.Slice.LightOffDelay = (uint)(value * 1000);
RaisePropertyChanged();
}
}
public override float BottomLiftHeight
{
get => ManifestFile.Profile.Slice.BottomLiftHeight;
set
{
ManifestFile.Profile.Slice.BottomLiftHeight = (float)Math.Round(value, 2);
RaisePropertyChanged();
}
}
public override float LiftHeight
{
get => ManifestFile.Profile.Slice.LiftHeight;
set
{
ManifestFile.Profile.Slice.LiftHeight = (float)Math.Round(value, 2);
RaisePropertyChanged();
}
}
public override float BottomLiftSpeed
{
get => ManifestFile.Profile.Slice.BottomLiftSpeed;
set
{
ManifestFile.Profile.Slice.BottomLiftSpeed = (float)Math.Round(value, 2);
RaisePropertyChanged();
}
}
public override float LiftSpeed
{
get => ManifestFile.Profile.Slice.LiftSpeed;
set
{
ManifestFile.Profile.Slice.LiftSpeed = (float)Math.Round(value, 2);
RaisePropertyChanged();
}
}
/*public override float RetractSpeed
{
get => HeaderSettings.RetractSpeed;
set
{
HeaderSettings.RetractSpeed = (float)Math.Round(value, 2);
RaisePropertyChanged();
}
}*/
public override float PrintTime
{
get => base.PrintTime;
set
{
base.PrintTime = value;
ManifestFile.Job.PrintTime = (uint) base.PrintTime;
}
}
public override float MaterialMilliliters
{
get => base.MaterialMilliliters;
set
{
base.MaterialMilliliters = value;
ManifestFile.Job.VolumeMl = base.MaterialMilliliters;
}
}
public override float MaterialGrams
{
get => ManifestFile.Job.WeightG;
set
{
ManifestFile.Job.WeightG = (float)Math.Round(value, 3);
RaisePropertyChanged();
}
}
public override float MaterialCost
{
get => ManifestFile.Job.Price;
set
{
ManifestFile.Job.Price = (float)Math.Round(value, 3);
RaisePropertyChanged();
}
}
/*public override string MaterialName
{
get => HeaderSettings.Resin;
set
{
HeaderSettings.Resin = value;
RaisePropertyChanged();
}
}*/
public override string MachineName
{
get => ManifestFile.Device.MachineModel;
set
{
ManifestFile.Device.MachineModel = value;
RequireFullEncode = true;
RaisePropertyChanged();
}
}
public override object[] Configs => new object[] { ManifestFile.Device, ManifestFile.Job, ManifestFile.Profile.Slice };
#endregion
#region Methods
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
{
using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create))
{
if (Thumbnails.Length > 0 && Thumbnails[0] is not null)
{
using var thumbnailsStream = outputFile.CreateEntry(PreviewFilename).Open();
using var vec = new VectorOfByte();
CvInvoke.Imencode(".png", Thumbnails[0], vec);
thumbnailsStream.WriteBytes(vec.ToArray());
thumbnailsStream.Close();
}
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
progress.Token.ThrowIfCancellationRequested();
var layer = this[layerIndex];
outputFile.PutFileContent($"{layerIndex + 1}.png", layer.CompressedBytes, ZipArchiveMode.Create);
progress++;
}
XmlSerializer serializer = new XmlSerializer(ManifestFile.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
var entry = outputFile.CreateEntry(ManifestFilename);
using (var stream = entry.Open())
{
serializer.Serialize(stream, ManifestFile, ns);
}
outputFile.PutFileContent(GCodeFilename, EncryptGCode(progress), ZipArchiveMode.Create);
}
}
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
{
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
{
var entry = inputFile.GetEntry(ManifestFilename);
if (entry is null)
{
Clear();
throw new FileLoadException($"{ManifestFilename} not found", fileFullPath);
}
try
{
var serializer = new XmlSerializer(ManifestFile.GetType());
using var stream = entry.Open();
ManifestFile = (ZCodePrint)serializer.Deserialize(stream);
}
catch (Exception e)
{
Clear();
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
}
entry = inputFile.GetEntry(GCodeFilename);
if (entry is null)
{
Clear();
throw new FileLoadException($"{GCodeFilename} not found", fileFullPath);
}
GCode = new();
var encryptEngine = new RsaEngine();
using var txtreader = new StringReader(GCodeRSAPublicKey);
var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();
encryptEngine.Init(true, keyParameter);
using (TextReader tr = new StreamReader(entry.Open()))
{
string line;
progress.Reset("Decrypting GCode", (uint) (entry.Length / 88));
while ((line = tr.ReadLine()) != null)
{
if (string.IsNullOrEmpty(line)) continue;
if (!line.EndsWith("=="))
{
continue;
}
byte[] data = System.Convert.FromBase64String(line);
var decodedBytes = encryptEngine.ProcessBlock(data, 0, data.Length);
decodedBytes = decodedBytes.Skip(2).SkipWhile(b => b == 255 || b == 0).ToArray();
GCode.AppendLine(Encoding.UTF8.GetString(decodedBytes));
progress++;
}
tr.Close();
}
LayerManager = new LayerManager(ManifestFile.Job.LayerCount, this);
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
var gcode = GCode.ToString();
float lastPostZ = LayerHeight;
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
if (progress.Token.IsCancellationRequested) break;
entry = inputFile.GetEntry($"{layerIndex+1}.png");
if (entry is null)
{
Clear();
throw new FileLoadException($"Layer {layerIndex+1} not found", fileFullPath);
}
var startStr = $"M6054 \"{layerIndex+1}.png\"";
gcode = gcode.Substring(gcode.IndexOf(startStr, StringComparison.InvariantCultureIgnoreCase) + startStr.Length + 1);
var stripGcode = gcode.Substring(0, gcode.IndexOf("M106 S0")).Trim(' ', '\n', '\r', '\t');
//var startCurrPos = stripGcode.Remove(0, ";currPos:".Length);
float posZ = lastPostZ;
float liftHeight = GetInitialLayerValueOrNormal(layerIndex, BottomLiftHeight, LiftHeight);
float liftSpeed = GetInitialLayerValueOrNormal(layerIndex, BottomLiftSpeed, LiftSpeed);
float retractSpeed = RetractSpeed;
float lightOffDelay = 0;
byte pwm = GetInitialLayerValueOrNormal(layerIndex, BottomLightPWM, LightPWM); ;
float exposureTime = GetInitialLayerValueOrNormal(layerIndex, BottomExposureTime, ExposureTime);
//var currPosRegex = Regex.Match(stripGcode, @";currPos:([+-]?([0-9]*[.])?[0-9]+)", RegexOptions.IgnoreCase);
var moveG0Regex = Regex.Match(stripGcode, @"G0 Z([+-]?([0-9]*[.])?[0-9]+) F(\d+)", RegexOptions.IgnoreCase);
var waitG4Regex = Regex.Match(stripGcode, @"G4 P(\d+)", RegexOptions.IgnoreCase);
var pwmM106Regex = Regex.Match(stripGcode, @"M106 S(\d+)", RegexOptions.IgnoreCase);
if (moveG0Regex.Success)
{
float liftHeightTemp = float.Parse(moveG0Regex.Groups[1].Value, CultureInfo.InvariantCulture);
float liftSpeedTemp = float.Parse(moveG0Regex.Groups[3].Value, CultureInfo.InvariantCulture);
moveG0Regex = moveG0Regex.NextMatch();
if (moveG0Regex.Success)
{
float retractHeight = float.Parse(moveG0Regex.Groups[1].Value, CultureInfo.InvariantCulture);
retractSpeed = float.Parse(moveG0Regex.Groups[3].Value, CultureInfo.InvariantCulture) * 10;
liftHeight = (float) Math.Round(liftHeightTemp - retractHeight, 2);
liftSpeed = liftSpeedTemp * 10;
lastPostZ = posZ = retractHeight;
}
else
{
lastPostZ = posZ = liftHeightTemp;
}
}
if (pwmM106Regex.Success)
{
//pwm = byte.Parse(pwmM106Regex.Groups[1].Value);
}
if (waitG4Regex.Success)
{
lightOffDelay = (float) Math.Round(float.Parse(waitG4Regex.Groups[1].Value, CultureInfo.InvariantCulture) / 1000f, 2);
waitG4Regex = waitG4Regex.NextMatch();
if (waitG4Regex.Success)
{
exposureTime = (float) Math.Round(float.Parse(waitG4Regex.Groups[1].Value, CultureInfo.InvariantCulture) / 1000f, 2);
}
else // Only one match, meaning light off delay is not present
{
lightOffDelay = GetInitialLayerValueOrNormal(layerIndex, BottomLightOffDelay, LightOffDelay);
}
}
this[layerIndex] = new Layer(layerIndex, entry.Open(), LayerManager)
{
PositionZ = posZ,
ExposureTime = exposureTime,
LiftHeight = liftHeight,
LiftSpeed = liftSpeed,
RetractSpeed = retractSpeed,
LightOffDelay = lightOffDelay,
LightPWM = pwm,
};
progress++;
}
entry = inputFile.GetEntry(PreviewFilename);
if (entry is not null)
{
Thumbnails[0] = new Mat();
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
}
}
LayerManager.GetBoundingRectangle(progress);
}
public override void RebuildGCode()
{
GCode = new();
GCode.AppendFormat(GCodeStart, Environment.NewLine);
float lastZPosition = 0;
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
var layer = this[layerIndex];
var exposureTime = layer.ExposureTime * 1000;
var liftHeight = layer.LiftHeight;
var liftZHeight = Math.Round(liftHeight + layer.PositionZ, 2);
var liftSpeed = Math.Round(layer.LiftSpeed / 10, 2);
var retractSpeed = Math.Round(layer.RetractSpeed / 10, 2);
var lightOffDelay = layer.LightOffDelay * 1000;
var pwmValue = layer.LightPWM;
if (layer.ExposureTime > 0 && pwmValue > 0)
{
GCode.AppendLine($"M6054 \"{layerIndex + 1}.png\";");
}
// Absolute gcode
if (liftHeight > 0 && liftZHeight > layer.PositionZ)
{
GCode.AppendLine($"G0 Z{liftZHeight} F{liftSpeed};");
GCode.AppendLine($"G0 Z{layer.PositionZ} F{retractSpeed};");
}
else if (lastZPosition < layer.PositionZ)
{
GCode.AppendLine($"G0 Z{layer.PositionZ} F{retractSpeed};");
}
GCode.AppendLine($"G4 P{lightOffDelay};");
if (layer.ExposureTime > 0 && pwmValue > 0)
{
GCode.AppendLine($"M106 S300;");
GCode.AppendLine($"G4 P{exposureTime};");
GCode.AppendLine("M106 S0;");
}
lastZPosition = layer.PositionZ;
}
GCode.AppendFormat(GCodeEnd, Environment.NewLine, MaxPrintHeight);
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
{
if (RequireFullEncode)
{
if (!string.IsNullOrEmpty(filePath))
{
FileFullPath = filePath;
}
Encode(FileFullPath, progress);
return;
}
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(FileFullPath, filePath, true);
FileFullPath = filePath;
}
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
bool deleted;
do
{
deleted = false;
foreach (var zipentry in outputFile.Entries)
{
if (!zipentry.Name.EndsWith(".gcode") && !zipentry.Name.EndsWith(".xml")) continue;
zipentry.Delete();
deleted = true;
break;
}
} while (deleted);
XmlSerializer serializer = new XmlSerializer(ManifestFile.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
var entry = outputFile.CreateEntry(ManifestFilename);
using var stream = entry.Open();
serializer.Serialize(stream, ManifestFile, ns);
outputFile.PutFileContent(GCodeFilename, EncryptGCode(progress), ZipArchiveMode.Update);
//Decode(FileFullPath, progress);
}
private string EncryptGCode(OperationProgress progress)
{
RebuildGCode();
progress.Reset("Encrypting GCode", (uint) GCode.Length);
StringBuilder sb = new();
var encryptEngine = new RsaEngine();
using var txtreader = new StringReader(GCodeRSAPrivateKey);
var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();
encryptEngine.Init(true, keyParameter);
using StringReader sr = new StringReader(GCode.ToString());
string line;
while ((line = sr.ReadLine()) != null)
{
progress += (uint)line.Length;
byte[] data = Encoding.UTF8.GetBytes(line);
List<byte> padData = new(64) {0, 1, 0};
padData.AddRange(data);
if (padData.Count > 64)
{
throw new ArgumentOutOfRangeException($"Too long gcode line to encrypt, got: {padData.Count} bytes while expecting less than 64 bytes");
}
while (padData.Count < 64)
{
padData.Insert(2, 255);
}
var padDataArray = padData.ToArray();
var encodedBytes = encryptEngine.ProcessBlock(padDataArray, 0, padDataArray.Length);
sb.AppendLine(System.Convert.ToBase64String(encodedBytes));
}
return sb.ToString();
}
#endregion
}
}
+1
View File
@@ -370,6 +370,7 @@ namespace UVtools.Core
_exposureTime = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomExposureTime, SlicerFile.ExposureTime);
_liftHeight = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLiftHeight, SlicerFile.LiftHeight);
_liftSpeed = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLiftSpeed, SlicerFile.LiftSpeed);
_lightOffDelay = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLightOffDelay, SlicerFile.LightOffDelay);
_retractSpeed = SlicerFile.RetractSpeed;
_lightPwm = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLightPWM, SlicerFile.LightPWM);
}
+1 -1
View File
@@ -222,7 +222,7 @@ namespace UVtools.Core
var layer = this[layerIndex];
layer.Index = layerIndex;
if (property is null)
if (property is null || property == nameof(SlicerFile.BottomLayerCount))
{
layer.ExposureTime = SlicerFile.GetInitialLayerValueOrNormal(layerIndex, SlicerFile.BottomExposureTime, SlicerFile.ExposureTime);
layer.LiftHeight = SlicerFile.GetInitialLayerValueOrNormal(layerIndex, SlicerFile.BottomLiftHeight, SlicerFile.LiftHeight);
+3 -1
View File
@@ -5,7 +5,9 @@ namespace UVtools.Core.Objects
{
public static class StaticObjects
{
public static SHA256 Sha256 { get; } = SHA256.Create();
public static readonly SHA256 Sha256 = SHA256.Create();
public static readonly string[] LineBreakCharacters = {"\r\n", "\r", "\n"};
// Compute the file's hash.
public static byte[] GetHashSha256(string filename)
+2 -1
View File
@@ -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.5.1</Version>
<Version>2.6.0</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
@@ -47,6 +47,7 @@
<PackageReference Include="BinarySerializer" Version="8.6.0" />
<PackageReference Include="Emgu.CV" Version="4.5.1.4349" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.10" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.7.0" />
</ItemGroup>
@@ -221,6 +221,9 @@
<Component Id="owc0F7CC7ACEA840EC81FADDEE08D4B54C3" Guid="8de4454d-fc84-51cf-d44c-612dcea01607">
<File Id="owf0F7CC7ACEA840EC81FADDEE08D4B54C3" Source="$(var.SourceDir)\BinarySerializer.dll" KeyPath="yes" />
</Component>
<Component Id="owc0D5E901B0EDC9AC66EDED7744C9C0EC4" Guid="bf900338-6ac3-e652-0358-b6c5a433ead1">
<File Id="owf0D5E901B0EDC9AC66EDED7744C9C0EC4" Source="$(var.SourceDir)\BouncyCastle.Crypto.dll" KeyPath="yes" />
</Component>
<Component Id="owc3D4C6D44ECDB03E5FE1F04B44BCF854F" Guid="7357d916-7bf8-aecc-ec52-30bed411500d">
<File Id="owf3D4C6D44ECDB03E5FE1F04B44BCF854F" Source="$(var.SourceDir)\clrcompression.dll" KeyPath="yes" />
</Component>
@@ -1023,6 +1026,9 @@
<Component Id="owc696F0AF8084A6AA7624CA0947E245A47" Guid="6aa7d092-d68b-a44d-f2c7-0a590404b19f">
<File Id="owf696F0AF8084A6AA7624CA0947E245A47" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\QIDI Shadow6.0 Pro.ini" KeyPath="yes" />
</Component>
<Component Id="owc58F08D198616611A088F5E8CA9BAB684" Guid="f0f9d4c3-c4d4-ab8b-ff79-f93dc13fbbbb">
<File Id="owf58F08D198616611A088F5E8CA9BAB684" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\Uniz IBEE.ini" KeyPath="yes" />
</Component>
<Component Id="owcD0FD9259BE924EB58AE9F7A85AE0A9E8" Guid="360b089c-8765-92db-0c8f-367d80202d8f">
<File Id="owfD0FD9259BE924EB58AE9F7A85AE0A9E8" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\UVtools Prusa SL1.ini" KeyPath="yes" />
</Component>
+1 -1
View File
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<Version>2.5.1</Version>
<Version>2.6.0</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">