diff --git a/CHANGELOG.md b/CHANGELOG.md index 45f00c4..5603b83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## ? - v0.4.3 + +* (Add) PWS and PW0 file formats +* (Add) Open image files as single layer and transform them in grayscale (jpg, jpeg, png, bmp, gif, tga) +* (Add) Shortcut "Home" go to first layer +* (Add) Shortcut "End" go to last layer +* (Add) Shortcut "+" and button go to next layer +* (Add) Shortcut "-" and button go to previous layer +* (Add) Show current layer and height near tracker position +* (Change) Scroll bar to track bar +* (Change) Keyword "LiftingSpeed" to "LiftSpeed" under PrusaSlicer notes (Please update printers notes or import them again) +* (Change) Keywords For Nova3D Elfin printer under PrusaSlicer notes (Please update printers notes or import them again) +* (Change) Keywords For Zortrax Inkspire printer under PrusaSlicer notes (Please update printers notes or import them again) +* (Improvement) Much faster layer scroll display +* (Improvement) Hide empty items for status bar, ie: if printer don't have them to display +* (Fix) Save layer preview image trigger an error +* (Fix) Implement missing "InheritsCummulative" key to SL1 files + ## 05/06/2020 - v0.4.2.2 - Beta * (Add) Shortcut "ESC" under Islands list view to deselect all items diff --git a/PrusaSL1Reader/CWSFile.cs b/PrusaSL1Reader/CWSFile.cs index 4344826..9604041 100644 --- a/PrusaSL1Reader/CWSFile.cs +++ b/PrusaSL1Reader/CWSFile.cs @@ -12,7 +12,6 @@ using System.IO.Compression; using System.Linq; using System.Reflection; using System.Text; -using System.Text.RegularExpressions; using PrusaSL1Reader.Extensions; namespace PrusaSL1Reader @@ -132,8 +131,6 @@ namespace PrusaSL1Reader public override float LayerHeight => SliceSettings.Thickness; - public override uint LayerCount => SliceSettings.LayersNum; - public override ushort InitialLayerCount => SliceSettings.HeadLayersNum; public override float InitialExposureTime => SliceSettings.HeadLayersExpoMs / 1000f; @@ -280,7 +277,7 @@ namespace PrusaSL1Reader } - LayerManager = new LayerManager(LayerCount); + LayerManager = new LayerManager(OutputSettings.LayersNum); foreach (var zipArchiveEntry in inputFile.Entries) { diff --git a/PrusaSL1Reader/ChituboxFile.cs b/PrusaSL1Reader/ChituboxFile.cs index adfb9e3..45b8e6f 100644 --- a/PrusaSL1Reader/ChituboxFile.cs +++ b/PrusaSL1Reader/ChituboxFile.cs @@ -25,11 +25,9 @@ namespace PrusaSL1Reader #region Constants private const uint MAGIC_CBDDLP = 0x12FD0019; private const uint MAGIC_CBT = 0x12FD0086; - private const int SPECIAL_BIT = 1 << 1; - private const int SPECIAL_BIT_MASK = ~SPECIAL_BIT; private const ushort REPEATRGB15MASK = 0x20; - private const byte RLE8EncodingLimit = 125; + private const byte RLE8EncodingLimit = 0x7d; // 125; private const ushort RLE16EncodingLimit = 0xFFF; #endregion @@ -514,8 +512,6 @@ namespace PrusaSL1Reader public override float LayerHeight => HeaderSettings.LayerHeightMilimeter; - public override uint LayerCount => HeaderSettings.LayerCount; - public override ushort InitialLayerCount => (ushort)HeaderSettings.BottomLayersCount; public override float InitialExposureTime => HeaderSettings.BottomExposureSeconds; @@ -826,36 +822,6 @@ namespace PrusaSL1Reader // Collect stragglers AddRep(); - /*byte color; - byte black = 0; - byte white = 1; - - byte nrOfColor = 0; - byte prevColor = byte.MaxValue; - - for (int y = 0; y < image.Height; y++) - { - Span pixelRowSpan = image.GetPixelRowSpan(y); - for (int x = 0; x < image.Width; x++) - { - color = pixelRowSpan[x].PackedValue < 128 ? black : white; - if (prevColor == byte.MaxValue) prevColor = color; - bool isLastPixel = x == (image.Width - 1) && y == (image.Height - 1); - - if (color == prevColor && nrOfColor < 0x7D && !isLastPixel) - { - nrOfColor++; - } - else - { - byte encValue = (byte)((prevColor << 7) | nrOfColor); // push color (B/W) to highest bit and repetitions to lowest 7 bits. - rawData.Add(encValue); - prevColor = color; - nrOfColor = 1; - } - } - }*/ - return rawData; } @@ -1070,7 +1036,7 @@ namespace PrusaSL1Reader } } - LayerManager = new LayerManager(LayerCount); + LayerManager = new LayerManager(HeaderSettings.LayerCount); Parallel.For(0, LayerCount, layerIndex => { var image = IsCbtFile ? DecodeCbtImage((uint) layerIndex) : DecodeCbddlpImage((uint) layerIndex); diff --git a/PrusaSL1Reader/FileFormat.cs b/PrusaSL1Reader/FileFormat.cs index 6cf5507..35010ad 100644 --- a/PrusaSL1Reader/FileFormat.cs +++ b/PrusaSL1Reader/FileFormat.cs @@ -8,10 +8,8 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using PrusaSL1Reader.Extensions; @@ -134,8 +132,10 @@ namespace PrusaSL1Reader new SL1File(), // Prusa SL1 new ChituboxFile(), // cbddlp, cbt, photon new PHZFile(), // phz + new PWSFile(), // PSW new ZCodexFile(), // zcodex new CWSFile(), // CWS + new ImageFile(), // images }; /// @@ -271,7 +271,7 @@ namespace PrusaSL1Reader public float TotalHeight => (float)Math.Round(LayerCount * LayerHeight, 2); - public abstract uint LayerCount { get; } + public uint LayerCount => LayerManager.Count; public abstract ushort InitialLayerCount { get; } @@ -448,6 +448,8 @@ namespace PrusaSL1Reader public virtual void Encode(string fileFullPath) { + FileFullPath = fileFullPath; + if (File.Exists(fileFullPath)) { File.Delete(fileFullPath); @@ -511,44 +513,58 @@ namespace PrusaSL1Reader if (genericConfigExtract) { - using (TextWriter tw = new StreamWriter(Path.Combine(path, $"{ExtractConfigFileName}.{ExtractConfigFileExtension}"), false)) + if (!ReferenceEquals(Configs, null)) { - foreach (var config in Configs) + using (TextWriter tw = new StreamWriter(Path.Combine(path, $"{ExtractConfigFileName}.{ExtractConfigFileExtension}"), false)) { - var type = config.GetType(); - tw.WriteLine($"[{type.Name}]"); - foreach (var property in type.GetProperties()) + foreach (var config in Configs) { - tw.WriteLine($"{property.Name} = {property.GetValue(config)}"); + var type = config.GetType(); + tw.WriteLine($"[{type.Name}]"); + foreach (var property in type.GetProperties()) + { + tw.WriteLine($"{property.Name} = {property.GetValue(config)}"); + } + + tw.WriteLine(); } - tw.WriteLine(); + + tw.Close(); } - tw.Close(); } } if (genericLayersExtract) { uint i = 0; - foreach (var thumbnail in Thumbnails) + if (!ReferenceEquals(Thumbnails, null)) { - if (ReferenceEquals(thumbnail, null)) + foreach (var thumbnail in Thumbnails) { - continue; + if (ReferenceEquals(thumbnail, null)) + { + continue; + } + + thumbnail.Save(Path.Combine(path, $"Thumbnail{i}.png"), Helpers.PngEncoder); + i++; } - thumbnail.Save(Path.Combine(path, $"Thumbnail{i}.png"), Helpers.PngEncoder); - i++; } - Parallel.ForEach(this, (layer) => + if (LayerCount > 0) { - var byteArr = layer.RawData; - using (FileStream stream = File.Create(Path.Combine(path, $"Layer{layer.Index}.png"), byteArr.Length)) + Parallel.ForEach(this, (layer) => { - stream.Write(byteArr, 0, byteArr.Length); - stream.Close(); - } - }); + var byteArr = layer.RawData; + using (FileStream stream = File.Create(Path.Combine(path, $"Layer{layer.Index}.png"), + byteArr.Length)) + { + stream.Write(byteArr, 0, byteArr.Length); + stream.Close(); + } + }); + } + /* Parallel.For(0, LayerCount, layerIndex => { var byteArr = this[layerIndex].RawData; using (FileStream stream = File.Create(Path.Combine(path, $"Layer{layerIndex}.png"), byteArr.Length)) diff --git a/PrusaSL1Reader/ImageFile.cs b/PrusaSL1Reader/ImageFile.cs new file mode 100644 index 0000000..2bdfe44 --- /dev/null +++ b/PrusaSL1Reader/ImageFile.cs @@ -0,0 +1,93 @@ +using System; +using System.IO; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using Size = System.Drawing.Size; + +namespace PrusaSL1Reader +{ + public class ImageFile : FileFormat + { + public override FileFormatType FileType { get; } = FileFormatType.Binary; + + public override FileExtension[] FileExtensions { get; } = + { + new FileExtension("jpg", "JPG"), + new FileExtension("jpeg", "JPEG"), + new FileExtension("png", "PNG"), + new FileExtension("bmp", "BMP"), + new FileExtension("gif", "GIF"), + new FileExtension("tga", "TGA"), + }; + + public override Type[] ConvertToFormats { get; } = null; + public override PrintParameterModifier[] PrintParameterModifiers { get; } = null; + public override byte ThumbnailsCount { get; } = 4; + public override Size[] ThumbnailsOriginalSize { get; } = null; + public override uint ResolutionX => (uint)ImageL8.Width; + public override uint ResolutionY => (uint)ImageL8.Height; + public override float LayerHeight { get; } = 0; + public override ushort InitialLayerCount { get; } = 1; + public override float InitialExposureTime { get; } = 0; + public override float LayerExposureTime { get; } = 0; + public override float LiftHeight { get; } = 0; + public override float RetractSpeed { get; } = 0; + public override float LiftSpeed { get; } = 0; + public override float PrintTime { get; } = 0; + public override float UsedMaterial { get; } = 0; + public override float MaterialCost { get; } = 0; + public override string MaterialName { get; } = null; + public override string MachineName { get; } = null; + public override object[] Configs { get; } = null; + + private Image ImageL8 { get; set; } + + public override bool SetValueFromPrintParameterModifier(PrintParameterModifier modifier, string value) + { + throw new NotImplementedException(); + } + + public override void Decode(string fileFullPath) + { + base.Decode(fileFullPath); + + using (var ms = new MemoryStream()) + { + using (var fs = File.Open(fileFullPath, FileMode.Open)) + { + fs.CopyTo(ms); + ms.Seek(0, SeekOrigin.Begin); + + var image = Image.Load(ms); + const byte startDivisor = 2; + for (int i = 0; i < ThumbnailsCount; i++) + { + Thumbnails[i] = image.CloneAs(); + var divisor = (i + startDivisor); + Thumbnails[i].Mutate(o => o.Resize(image.Width / divisor, image.Height / divisor)); + } + image.Mutate(o => o.Grayscale()); + ImageL8 = image.CloneAs(); + + LayerManager = new LayerManager(1); + this[0] = new Layer(0, ImageL8, Path.GetFileName(fileFullPath)); + + fs.Close(); + } + } + } + + public override void SaveAs(string filePath = null) + { + this[0].Image.Save(filePath); + } + + public override bool Convert(Type to, string fileFullPath) + { + throw new NotImplementedException(); + } + + + } +} diff --git a/PrusaSL1Reader/PHZFile.cs b/PrusaSL1Reader/PHZFile.cs index 62786bc..a33a1cc 100644 --- a/PrusaSL1Reader/PHZFile.cs +++ b/PrusaSL1Reader/PHZFile.cs @@ -457,8 +457,6 @@ namespace PrusaSL1Reader public override float LayerHeight => HeaderSettings.LayerHeightMilimeter; - public override uint LayerCount => HeaderSettings.LayerCount; - public override ushort InitialLayerCount => (ushort)HeaderSettings.BottomLayersCount; public override float InitialExposureTime => HeaderSettings.BottomExposureSeconds; @@ -854,7 +852,7 @@ namespace PrusaSL1Reader } } - LayerManager = new LayerManager(LayerCount); + LayerManager = new LayerManager(HeaderSettings.LayerCount); Parallel.For(0, LayerCount, layerIndex => { var image = DecodePhzImage((uint) layerIndex); diff --git a/PrusaSL1Reader/PWSFile.cs b/PrusaSL1Reader/PWSFile.cs new file mode 100644 index 0000000..283d1a2 --- /dev/null +++ b/PrusaSL1Reader/PWSFile.cs @@ -0,0 +1,1261 @@ +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. + * 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.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using BinarySerialization; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; + +namespace PrusaSL1Reader +{ + public class PWSFile : FileFormat + { + #region Constants + public const byte MarkSize = 12; + public const byte RLE1EncodingLimit = 0x7d; // 125; + public const ushort RLE4EncodingLimit = 0xfff; // 4095; + + // CRC-16-ANSI (aka CRC-16-IMB) Polynomial: x^16 + x^15 + x^2 + 1 + public static readonly int[] CRC16Table = { + 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, + 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, + 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, + 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, + 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, + 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, + 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, + 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, + 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, + 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, + 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, + 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, + 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, + 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, + 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, + 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, + 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, + 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, + 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, + 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, + 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, + 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, + 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, + 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, + 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, + 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, + 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, + 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, + 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, + 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, + 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, + 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040, + }; + + #endregion + + #region Enums + public enum LayerRleFormat + { + PWS, + PW0 + } + #endregion + + #region Sub Classes + + #region FileMark + public class FileMark + { + public const string SectionMarkFile = "ANYCUBIC"; + + private string _mark = SectionMarkFile; + /// + /// Gets the file mark placeholder + /// Fixed to "ANYCUBIC" + /// + [FieldOrder(0)] + [FieldLength(MarkSize)] + public string Mark + { + get => _mark; + set => _mark = value.TrimEnd('\0'); + } + + /// + /// Gets the file format version + /// + [FieldOrder(1)] public uint Version { get; set; } = 1; + + /// + /// Gets the area num + /// + [FieldOrder(2)] public uint AreaNum { get; set; } = 4; + + /// + /// Gets the header start address + /// + [FieldOrder(3)] public uint HeaderAddress { get; set; } + + [FieldOrder(4)] public uint Offset1 { get; set; } + + /// + /// Gets the preview start offset + /// + [FieldOrder(5)] public uint PreviewAddress { get; set; } + + [FieldOrder(6)] public uint Offset2 { get; set; } + + /// + /// Gets the layer definition start address + /// + [FieldOrder(7)] public uint LayerDefinitionAddress { get; set; } + + [FieldOrder(8)] public uint Offset3 { get; set; } + + /// + /// Gets layer image start address + /// + [FieldOrder(9)] public uint LayerImageAddress { get; set; } + + public override string ToString() + { + return $"{nameof(Mark)}: {Mark}, {nameof(Version)}: {Version}, {nameof(AreaNum)}: {AreaNum}, {nameof(HeaderAddress)}: {HeaderAddress}, {nameof(Offset1)}: {Offset1}, {nameof(PreviewAddress)}: {PreviewAddress}, {nameof(Offset2)}: {Offset2}, {nameof(LayerDefinitionAddress)}: {LayerDefinitionAddress}, {nameof(Offset3)}: {Offset3}, {nameof(LayerImageAddress)}: {LayerImageAddress}"; + } + } + #endregion + + #region Section + + public class Section + { + private string _mark; + + /// + /// Gets the section mark placeholder + /// + [FieldOrder(0)] + [FieldLength(MarkSize)] + public string Mark + { + get => _mark; + set => _mark = value.TrimEnd('\0'); + } + + /// + /// Gets the length of this section + /// + [FieldOrder(1)] public uint Length { get; set; } + + public Section() { } + + public Section(string mark, object obj) : this(mark, (uint)Helpers.Serializer.SizeOf(obj)) { } + + public Section(string mark, uint length = 0) + { + Mark = mark; + Length = length; + } + + + public void Validate(string mark, object obj = null) + { + Validate(mark, 0u, obj); + } + + public void Validate(string mark, uint length, object obj = null) + { + if (!Mark.Equals(mark)) + { + throw new FileLoadException( + $"'{Mark}' section expected, but got '{mark}'"); + } + + if (!ReferenceEquals(obj, null)) + { + length += (uint)Helpers.Serializer.SizeOf(obj); + } + + if (length > 0 && Length != length) + { + throw new FileLoadException( + $"{Mark} section bytes: expected {Length}, got {length}, difference: {(int)Length - length}"); + } + } + + public override string ToString() => $"{{{nameof(Mark)}: {Mark}, {nameof(Length)}: {Length}}}"; + } + + #endregion + + #region Header + public class Header + { + public const string SectionMark = "HEADER"; + + [Ignore] public Section Section { get; set; } + [FieldOrder(0)] public float PixelSize { get; set; } + [FieldOrder(1)] public float LayerHeight { get; set; } + [FieldOrder(2)] public float LayerExposureTime { get; set; } + [FieldOrder(3)] public float LayerOffTime { get; set; } = 1; + [FieldOrder(4)] public float BottomExposureSeconds { get; set; } + [FieldOrder(5)] public float BottomLayersCount { get; set; } + [FieldOrder(6)] public float LiftHeight { get; set; } = 6; + + /// + /// Gets the lift speed in mm/s + /// + [FieldOrder(7)] public float LiftSpeed { get; set; } = 3; // mm/s + + /// + /// Gets the retract speed in mm/s + /// + [FieldOrder(8)] public float RetractSpeed { get; set; } = 3; // mm/s + [FieldOrder(9)] public float Volume { get; set; } + [FieldOrder(10)] public uint AntiAlias { get; set; } = 1; + [FieldOrder(11)] public uint ResolutionX { get; set; } + [FieldOrder(12)] public uint ResolutionY { get; set; } + [FieldOrder(13)] public float Weight { get; set; } + [FieldOrder(14)] public float Price { get; set; } + [FieldOrder(15)] public uint ResinType { get; set; } // 0x24 ? + [FieldOrder(16)] public uint PerLayerOverride { get; set; } // bool + [FieldOrder(17)] public uint Offset1 { get; set; } + [FieldOrder(18)] public uint Offset2 { get; set; } + [FieldOrder(19)] public uint Offset3 { get; set; } + + public Header() + { + Section = new Section(SectionMark, this); + } + + public override string ToString() => $"{nameof(Section)}: {Section}, {nameof(PixelSize)}: {PixelSize}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(LayerExposureTime)}: {LayerExposureTime}, {nameof(LayerOffTime)}: {LayerOffTime}, {nameof(BottomExposureSeconds)}: {BottomExposureSeconds}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(Volume)}: {Volume}, {nameof(AntiAlias)}: {AntiAlias}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(Weight)}: {Weight}, {nameof(Price)}: {Price}, {nameof(ResinType)}: {ResinType}, {nameof(PerLayerOverride)}: {PerLayerOverride}, {nameof(Offset1)}: {Offset1}, {nameof(Offset2)}: {Offset2}, {nameof(Offset3)}: {Offset3}"; + + public void Validate() + { + Section.Validate(SectionMark, this); + } + } + + #endregion + + #region Preview + + /// + /// The files contain two preview images. + /// These are shown on the printer display when choosing which file to print, sparing the poor printer from needing to render a 3D image from scratch. + /// + public class Preview + { + public const string SectionMark = "PREVIEW"; + [Ignore] public Section Section { get; set; } + + /// + /// Gets the image width, in pixels. + /// + [FieldOrder(1)] public uint Width { get; set; } = 224; + + /// + /// Gets the resolution of the image, in dpi. + /// + [FieldOrder(2)] public uint Resolution { get; set; } = 42; + + /// + /// Gets the image height, in pixels. + /// + [FieldOrder(3)] public uint Height { get; set; } = 168; + + // little-endian 16bit colors, RGB 565 encoded. + //[FieldOrder(4)] + //[FieldLength("Section.Length")] + [Ignore] + public byte[] Data { get; set; } + + public Preview() + { + Section = new Section(SectionMark, this); + } + + public Image Decode(bool consumeData = true) + { + Image image = new Image((int) Width, (int) Height); + if (!image.TryGetSinglePixelSpan(out var span)) return null; + + int pixel = 0; + for (uint i = 0; i < Data.Length; i += 2) + { + ushort color16 = (ushort)((Data[i]) + (Data[i+1] << 8)); + + int r = (color16 >> 11) & 0x1f; + int g = (color16 >> 5) & 0x3f; + int b = (color16 >> 0) & 0x1f; + + span[pixel++] = new Rgba32( + (r << 3) | (r & 0x7), + (g << 2) | (g & 0x3), + (b << 3) | (b & 0x7), + byte.MaxValue); + } + + if (consumeData) + Data = null; + + return image; + } + + public static Preview Encode(Image image) + { + if (!image.TryGetSinglePixelSpan(out var span)) return null; + + Preview preview = new Preview + { + Width = (uint) image.Width, + Height = (uint) image.Height, + Resolution = (uint) image.Metadata.HorizontalResolution, + Data = new byte[span.Length * 2] + }; + + for (int i = 0; i < span.Length; i++) + { + int r = span[i].R >> 3; + int g = span[i].G >> 2; + int b = span[i].B >> 3; + + ushort color = (ushort) ((r << 11) | (g << 5) | (b << 0)); + + preview.Data[i * 2] = (byte) color; + preview.Data[i * 2 + 1] = (byte) (color >> 8); + } + + preview.Section.Length += (uint) preview.Data.Length; + return preview; + } + + public override string ToString() + { + return $"{nameof(Section)}: {Section}, {nameof(Width)}: {Width}, {nameof(Resolution)}: {Resolution}, {nameof(Height)}: {Height}, {nameof(Data)}: {Data}"; + } + + public void Validate(uint size) + { + Section.Validate(SectionMark, size, this); + } + } + + #endregion + + #region Layer + + public class LayerData + { + /// + /// Gets the layer image offset to encoded layer data, and its length in bytes. + /// + [FieldOrder(0)] + public uint DataAddress { get; set; } + + /// + /// Gets the layer image length in bytes. + /// + [FieldOrder(1)] + public uint DataLength { get; set; } + + [FieldOrder(2)] public float LiftHeight { get; set; } + + [FieldOrder(3)] public float LiftSpeed { get; set; } + + /// + /// Gets the exposure time for this layer, in seconds. + /// + [FieldOrder(4)] + public float LayerExposure { get; set; } + + /// + /// Gets the build platform Z position for this layer, measured in millimeters. + /// + [FieldOrder(5)] + public float LayerPositionZ { get; set; } + + [FieldOrder(6)] public float Offset1 { get; set; } + [FieldOrder(7)] public float Offset2 { get; set; } + + [Ignore] public byte[] EncodedRle { get; set; } + [Ignore] public PWSFile Parent { get; set; } + + public LayerData() + { + } + + public LayerData(PWSFile parent, uint layerIndex) + { + Parent = parent; + LiftHeight = Parent.HeaderSettings.LiftHeight; + LiftSpeed = Parent.HeaderSettings.LiftSpeed; + LayerExposure = layerIndex < Parent.InitialLayerCount ? Parent.HeaderSettings.BottomExposureSeconds : Parent.HeaderSettings.LayerExposureTime; + LayerPositionZ = Parent.GetHeightFromLayer(layerIndex); + } + + public Image Decode(bool consumeData = true) + { + var result = Parent.LayerFormat == LayerRleFormat.PWS ? DecodePWS() : DecodePW0(); + if (consumeData) + EncodedRle = null; + + return result; + } + + public byte[] Encode(Image image) + { + EncodedRle = Parent.LayerFormat == LayerRleFormat.PWS ? EncodePWS(image) : EncodePW0(image); + return EncodedRle; + } + + private Image DecodePWS() + { + var image = new Image((int) Parent.ResolutionX, (int) Parent.ResolutionY); + image.TryGetSinglePixelSpan(out var span); + + + for (int bit = 0; bit < Parent.HeaderSettings.AntiAlias; bit++) + { + byte bitValue = (byte) (byte.MaxValue / ((1 << (byte) Parent.HeaderSettings.AntiAlias) - 1) * + (1 << bit)); + + int n = 0; + for (int index = 0; index < EncodedRle.Length; index++) + { + // Lower 7 bits is the repeat count for the bit (0..127) + int reps = (EncodedRle[index] & 0x7f); + + + // We only need to set the non-zero pixels + // High bit is on for white, off for black + if ((EncodedRle[index] & 0x80) != 0) + { + for (int i = 0; i < reps; i++) + { + span[n + i].PackedValue |= bitValue; + } + } + + n += reps; + + + if (n == span.Length) + { + break; + } + + if (n > span.Length) + { + Debug.WriteLine("Error image ran off the end"); + } + } + } + + return image; + } + + public byte[] EncodePWS(Image image) + { + List rawData = new List(); + + for (byte aalevel = 0; aalevel < Parent.HeaderSettings.AntiAlias; aalevel++) + { + bool obit = false; + int rep = 0; + + void AddRep() + { + if (rep <= 0) return; + + byte by = (byte)rep; + + if (obit) + { + by |= 0x80; + //bitsOn += uint(rep) + } + + rawData.Add(by); + } + + for (int y = 0; y < image.Height; y++) + { + Span pixelRowSpan = image.GetPixelRowSpan(y); + for (int x = 0; x < image.Width; x++) + { + var nbit = (pixelRowSpan[x].PackedValue & + (1 << (int)(8 - Parent.HeaderSettings.AntiAlias + aalevel))) != 0; + + if (nbit == obit) + { + rep++; + + if (rep == RLE1EncodingLimit) + { + AddRep(); + rep = 0; + } + } + else + { + AddRep(); + obit = nbit; + rep = 1; + } + } + } + + // Collect stragglers + AddRep(); + } + + return rawData.ToArray(); + } + + private Image DecodePW0() + { + var image = new Image((int) Parent.ResolutionX, (int) Parent.ResolutionY); + image.TryGetSinglePixelSpan(out var span); + + uint n = 0; + for (int index = 0; index < EncodedRle.Length; index++) + { + byte b = EncodedRle[index]; + int code = (b >> 4); + uint reps = (uint) (b & 0xf); + byte color; + switch (code) + { + case 0x0: + color = 0x00; + index++; + reps = (reps * 256) + EncodedRle[index]; + break; + case 0xf: + color = 0xff; + index++; + reps = (reps * 256) + EncodedRle[index]; + break; + default: + color = (byte) ((code << 4) | code); + break; + } + + color &= 0xff; + + // We only need to set the non-zero pixels + if (color != 0) + { + for (int i = 0; i < reps; i++) + { + span[(int) (n + i)].PackedValue |= color; + } + } + + n += reps; + + + if (n == span.Length) + { + //index++; + break; + } + + if (n > span.Length) + { + Debug.WriteLine($"Error image ran off the end: {n-reps}({reps}) of {span.Length}"); + } + } + + if (n != span.Length) + { + Debug.WriteLine($"Error image ended short: {n} of {span.Length}"); + } + + return image; + } + + public byte[] EncodePW0(Image image) + { + List rawData = new List(); + + int lastColor = -1; + int reps = 0; + + void PutReps() + { + while (reps > 0) + { + int done = reps; + + if (lastColor == 0 || lastColor == 0xf) + { + if (done > RLE4EncodingLimit) + { + done = RLE4EncodingLimit; + } + //more:= []byte{ 0, 0} + //binary.BigEndian.PutUint16(more, uint16(done | (color << 12))) + + //rle = append(rle, more...) + + ushort more = (ushort)(done | (lastColor << 12)); + rawData.Add((byte)(more >> 8)); + rawData.Add((byte)more); + } + else + { + if (done > 0xf) + { + done = 0xf; + } + rawData.Add((byte)(done | lastColor << 4)); + } + + reps -= done; + } + } + + image.TryGetSinglePixelSpan(out var span); + + for (int i = 0; i < span.Length; i++) + { + int color = span[i].PackedValue >> 4; + + if (color == lastColor) + { + reps++; + } + else + { + PutReps(); + lastColor = color; + reps = 1; + } + } + + PutReps(); + + var bytes = rawData.ToArray(); + ushort crc = CRCRle4(bytes); + rawData.Add((byte)(crc >> 8)); + rawData.Add((byte)crc); + + return bytes; + } + + public static ushort CRCRle4(byte[] data) + { + ushort crc16 = 0; + for (int i = 0; i < data.Length; i++) + { + crc16 = (ushort) ((crc16 << 8) ^ CRC16Table[((crc16 >> 8) ^ CRC16Table[data[i]]) & 0xff]); + + } + + crc16 = (ushort) ((CRC16Table[crc16 & 0xff] * 0x100) + CRC16Table[(crc16 >> 8) & 0xff]); + + return crc16; + } + + public ushort CRCEncodedRle() + { + return CRCRle4(EncodedRle); + } + } + + #endregion + + #region LayerDefinition + public class LayerDefinition + { + public const string SectionMark = "LAYERDEF"; + + [Ignore] public Section Section { get; set; } = new Section(SectionMark); + + [FieldOrder(0)] public uint LayersCount { get; set; } + + [Ignore] public LayerData[] Layers; + + public LayerDefinition() + { + Section = new Section(SectionMark, this); + } + + public LayerDefinition(uint layersCount) : this() + { + LayersCount = layersCount; + Layers = new LayerData[layersCount]; + } + + public override string ToString() => $"{nameof(Section)}: {Section}, {nameof(LayersCount)}: {LayersCount}"; + + public void Validate() + { + Section.Validate(SectionMark, (uint) (LayersCount * Helpers.Serializer.SizeOf(new LayerData())), this); + } + } + #endregion + + #endregion + + #region Properties + + public FileMark FileMarkSettings { get; protected internal set; } = new FileMark(); + + public Header HeaderSettings { get; protected internal set; } = new Header(); + + public Preview PreviewSettings { get; protected internal set; } = new Preview(); + + public LayerDefinition LayersDefinition { get; private set; } = new LayerDefinition(); + + public Dictionary LayersHash { get; } = new Dictionary(); + + public override FileFormatType FileType => FileFormatType.Binary; + + public override FileExtension[] FileExtensions { get; } = { + new FileExtension("pws", "Photon Workshop PWS Files"), + new FileExtension("pw0", "Photon Workshop PW0 Files") + }; + + public override Type[] ConvertToFormats { get; } = + { + //typeof(PHZFile), + //typeof(ZCodexFile), + }; + + public override PrintParameterModifier[] PrintParameterModifiers { get; } = + { + PrintParameterModifier.InitialLayerCount, + PrintParameterModifier.InitialExposureSeconds, + PrintParameterModifier.ExposureSeconds, + + PrintParameterModifier.BottomLayerOffTime, + PrintParameterModifier.LayerOffTime, + PrintParameterModifier.BottomLiftHeight, + PrintParameterModifier.BottomLiftSpeed, + PrintParameterModifier.LiftHeight, + PrintParameterModifier.LiftSpeed, + PrintParameterModifier.RetractSpeed, + }; + + public override byte ThumbnailsCount { get; } = 1; + + public override System.Drawing.Size[] ThumbnailsOriginalSize { get; } = {new System.Drawing.Size(224, 168)}; + + public override uint ResolutionX => HeaderSettings.ResolutionX; + + public override uint ResolutionY => HeaderSettings.ResolutionY; + + public override float LayerHeight => HeaderSettings.LayerHeight; + + public override ushort InitialLayerCount => (ushort)HeaderSettings.BottomLayersCount; + + public override float InitialExposureTime => HeaderSettings.BottomExposureSeconds; + + public override float LayerExposureTime => HeaderSettings.LayerExposureTime; + public override float LiftHeight => HeaderSettings.LiftHeight; + public override float LiftSpeed => HeaderSettings.LiftSpeed * 60; + public override float RetractSpeed => HeaderSettings.RetractSpeed * 60; + + public override float PrintTime => 0; + + public override float UsedMaterial => HeaderSettings.Volume; + + public override float MaterialCost => HeaderSettings.Price; + + public override string MaterialName => null; + public override string MachineName => LayerFormat == LayerRleFormat.PWS ? "AnyCubic Photon S" : "AnyCubic Photon Zero"; + + public override object[] Configs => new object[] { FileMarkSettings, HeaderSettings, PreviewSettings, LayersDefinition }; + + public LayerRleFormat LayerFormat => FileFullPath.EndsWith(".pws") ? LayerRleFormat.PWS : LayerRleFormat.PW0; + + #endregion + + #region Constructors + public PWSFile() + { + } + #endregion + + #region Methods + public override void Clear() + { + base.Clear(); + + LayersDefinition = null; + } + + public override void Encode(string fileFullPath) + { + base.Encode(fileFullPath); + LayersHash.Clear(); + + LayersDefinition = new LayerDefinition(LayerCount); + + uint currentOffset = FileMarkSettings.HeaderAddress = (uint) Helpers.Serializer.SizeOf(FileMarkSettings); + using (var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write)) + { + outputFile.Seek((int) currentOffset, SeekOrigin.Begin); + currentOffset += Helpers.SerializeWriteFileStream(outputFile, HeaderSettings.Section); + currentOffset += Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); + + if (CreatedThumbnailsCount > 0) + { + FileMarkSettings.PreviewAddress = currentOffset; + Preview preview = Preview.Encode(Thumbnails[0]); + currentOffset += Helpers.SerializeWriteFileStream(outputFile, preview.Section); + currentOffset += Helpers.SerializeWriteFileStream(outputFile, preview); + currentOffset += Helpers.WriteFileStream(outputFile, preview.Data); + } + + FileMarkSettings.LayerDefinitionAddress = currentOffset; + + Parallel.For(0, LayerCount, layerIndex => + { + LayerData layer = new LayerData(this, (uint) layerIndex); + layer.Encode(this[layerIndex].Image); + LayersDefinition.Layers[layerIndex] = layer; + }); + + LayersDefinition.Section.Length += (uint)Helpers.Serializer.SizeOf(LayersDefinition.Layers[0]) * LayerCount; + currentOffset += Helpers.SerializeWriteFileStream(outputFile, LayersDefinition.Section); + uint offsetLayerRle = FileMarkSettings.LayerImageAddress = currentOffset + LayersDefinition.Section.Length; + + currentOffset += Helpers.SerializeWriteFileStream(outputFile, LayersDefinition); + + + foreach (var layer in LayersDefinition.Layers) + { + outputFile.Seek(offsetLayerRle, SeekOrigin.Begin); + string hash = Helpers.ComputeSHA1Hash(layer.EncodedRle); + + if (LayersHash.TryGetValue(hash, out var layerDataHash)) + { + layer.DataAddress = layerDataHash.DataAddress; + layer.DataLength = (uint)layerDataHash.EncodedRle.Length; + } + else + { + layer.DataAddress = offsetLayerRle; + offsetLayerRle += Helpers.SerializeWriteFileStream(outputFile, layer.EncodedRle); + layer.DataLength = (uint)layer.EncodedRle.Length; + LayersHash.Add(hash, layer); + } + + outputFile.Seek(currentOffset, SeekOrigin.Begin); + currentOffset += Helpers.SerializeWriteFileStream(outputFile, layer); + } + + // Rewind + outputFile.Seek(0, SeekOrigin.Begin); + Helpers.SerializeWriteFileStream(outputFile, FileMarkSettings); + + } + + + } + + public override void Decode(string fileFullPath) + { + base.Decode(fileFullPath); + + var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read); + + //HeaderSettings = Helpers.ByteToType(InputFile); + //HeaderSettings = Helpers.Serializer.Deserialize
(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header)))); + FileMarkSettings = Helpers.Deserialize(inputFile); + + Debug.Write("FileMark -> "); + Debug.WriteLine(FileMarkSettings); + + if (!FileMarkSettings.Mark.Equals(FileMark.SectionMarkFile)) + { + throw new FileLoadException($"Invalid Filemark {FileMarkSettings.Mark}, expected {FileMark.SectionMarkFile}", fileFullPath); + } + + if (FileMarkSettings.Version != 1) + { + throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expected 1", fileFullPath); + } + + FileFullPath = fileFullPath; + + inputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin); + //Section sectionHeader = Helpers.Deserialize
(inputFile); + //Debug.Write("SectionHeader -> "); + //Debug.WriteLine(sectionHeader); + + var section = Helpers.Deserialize
(inputFile); + HeaderSettings = Helpers.Deserialize
(inputFile); + HeaderSettings.Section = section; + + + Debug.Write("Header -> "); + Debug.WriteLine(HeaderSettings); + + HeaderSettings.Validate(); + + if (FileMarkSettings.PreviewAddress > 0) + { + inputFile.Seek(FileMarkSettings.PreviewAddress, SeekOrigin.Begin); + + section = Helpers.Deserialize
(inputFile); + PreviewSettings = Helpers.Deserialize(inputFile); + PreviewSettings.Section = section; + Debug.Write("Preview -> "); + Debug.WriteLine(PreviewSettings); + + uint datasize = PreviewSettings.Width * PreviewSettings.Height * 2; + + PreviewSettings.Validate(datasize); + + PreviewSettings.Data = new byte[datasize]; + inputFile.Read(PreviewSettings.Data, 0, PreviewSettings.Data.Length); + + Thumbnails[0] = PreviewSettings.Decode(true); + } + + inputFile.Seek(FileMarkSettings.LayerDefinitionAddress, SeekOrigin.Begin); + + section = Helpers.Deserialize
(inputFile); + LayersDefinition = Helpers.Deserialize(inputFile); + LayersDefinition.Section = section; + Debug.Write("LayersDefinition -> "); + Debug.WriteLine(LayersDefinition); + + LayerManager = new LayerManager(LayersDefinition.LayersCount); + LayersDefinition.Layers = new LayerData[LayerCount]; + + + LayersDefinition.Validate(); + + for (int i = 0; i < LayerCount; i++) + { + LayersDefinition.Layers[i] = Helpers.Deserialize(inputFile); + LayersDefinition.Layers[i].Parent = this; + } + + for (int i = 0; i < LayerCount; i++) + { + inputFile.Seek(LayersDefinition.Layers[i].DataAddress, SeekOrigin.Begin); + LayersDefinition.Layers[i].EncodedRle = new byte[LayersDefinition.Layers[i].DataLength]; + inputFile.Read(LayersDefinition.Layers[i].EncodedRle, 0, LayersDefinition.Layers[i].EncodedRle.Length); + + /*if (LayerFormat == LayerRleFormat.PW0) + { + var crcBytes = new byte[2]; + inputFile.Read(crcBytes, 0, 2); + ushort crcExpected = BitConverter.ToUInt16(crcBytes, 0); + ushort crcEncodedRle = LayersDefinition.Layers[i].CRCEncodedRle(); + + if (crcExpected != crcEncodedRle) + { + Debug.WriteLine($"Error: Checksum expected {crcExpected}, got {crcEncodedRle}"); + } + }*/ + } + + Parallel.For(0, LayerCount, layerIndex => { + this[layerIndex] = new Layer((uint)layerIndex, LayersDefinition.Layers[layerIndex].Decode()); + }); + } + + public override object GetValueFromPrintParameterModifier(PrintParameterModifier modifier) + { + if (ReferenceEquals(modifier, PrintParameterModifier.LayerOffTime)) return HeaderSettings.LayerOffTime; + if (ReferenceEquals(modifier, PrintParameterModifier.LiftSpeed)) return HeaderSettings.LiftSpeed * 60; + if (ReferenceEquals(modifier, PrintParameterModifier.RetractSpeed)) return HeaderSettings.RetractSpeed * 60; + + var baseValue = base.GetValueFromPrintParameterModifier(modifier); + return baseValue; + } + + public override bool SetValueFromPrintParameterModifier(PrintParameterModifier modifier, string value) + { + /* + void UpdateLayers() + { + for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++) + { + for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) + { + // Bottom : others + LayersDefinitions[layerIndex, aaIndex].LayerExposure = layerIndex < HeaderSettings.BottomLayersCount ? HeaderSettings.BottomExposureSeconds : HeaderSettings.LayerExposureSeconds; + LayersDefinitions[layerIndex, aaIndex].LayerOffTimeSeconds = layerIndex < HeaderSettings.BottomLayersCount ? PrintParametersSettings.BottomLightOffDelay : PrintParametersSettings.LightOffDelay; + } + } + } + + if (ReferenceEquals(modifier, PrintParameterModifier.InitialLayerCount)) + { + HeaderSettings.BottomLayersCount = + PrintParametersSettings.BottomLayerCount = value.Convert(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.InitialExposureSeconds)) + { + HeaderSettings.BottomExposureSeconds = value.Convert(); + UpdateLayers(); + return true; + } + + if (ReferenceEquals(modifier, PrintParameterModifier.ExposureSeconds)) + { + HeaderSettings.LayerExposureSeconds = value.Convert(); + UpdateLayers(); + return true; + } + + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLayerOffTime)) + { + PrintParametersSettings.BottomLightOffDelay = value.Convert(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.LayerOffTime)) + { + HeaderSettings.LayerOffTime = + PrintParametersSettings.LightOffDelay = value.Convert(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftHeight)) + { + PrintParametersSettings.BottomLiftHeight = value.Convert(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftSpeed)) + { + PrintParametersSettings.BottomLiftSpeed = value.Convert(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.LiftHeight)) + { + PrintParametersSettings.LiftHeight = value.Convert(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.LiftSpeed)) + { + PrintParametersSettings.LiftingSpeed = value.Convert(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.RetractSpeed)) + { + PrintParametersSettings.RetractSpeed = value.Convert(); + return true; + } + + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLightPWM)) + { + HeaderSettings.BottomLightPWM = value.Convert(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.LightPWM)) + { + HeaderSettings.LightPWM = value.Convert(); + return true; + }*/ + + return false; + } + + public override void SaveAs(string filePath = null) + { + if (LayerManager.IsModified) + { + if (!string.IsNullOrEmpty(filePath)) + { + FileFullPath = filePath; + } + Encode(FileFullPath); + return; + } + + + if (!string.IsNullOrEmpty(filePath)) + { + File.Copy(FileFullPath, filePath, true); + FileFullPath = filePath; + } + + using (var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write)) + { + + outputFile.Seek(0, SeekOrigin.Begin); + /*Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); + + if (HeaderSettings.Version == 2 && HeaderSettings.PrintParametersOffsetAddress > 0) + { + outputFile.Seek(HeaderSettings.PrintParametersOffsetAddress, SeekOrigin.Begin); + Helpers.SerializeWriteFileStream(outputFile, PrintParametersSettings); + Helpers.SerializeWriteFileStream(outputFile, SlicerInfoSettings); + } + + uint layerOffset = HeaderSettings.LayersDefinitionOffsetAddress; + for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++) + { + for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) + { + outputFile.Seek(layerOffset, SeekOrigin.Begin); + Helpers.SerializeWriteFileStream(outputFile, LayersDefinitions[layerIndex, aaIndex]); + layerOffset += (uint)Helpers.Serializer.SizeOf(LayersDefinitions[layerIndex, aaIndex]); + } + }*/ + outputFile.Close(); + } + + //Decode(FileFullPath); + } + + public override bool Convert(Type to, string fileFullPath) + { + /*if (to == typeof(PHZFile)) + { + PHZFile file = new PHZFile + { + LayerManager = LayerManager + }; + + + file.HeaderSettings.Version = 2; + file.HeaderSettings.BedSizeX = HeaderSettings.BedSizeX; + file.HeaderSettings.BedSizeY = HeaderSettings.BedSizeY; + file.HeaderSettings.BedSizeZ = HeaderSettings.BedSizeZ; + file.HeaderSettings.OverallHeightMilimeter = TotalHeight; + file.HeaderSettings.BottomExposureSeconds = InitialExposureTime; + file.HeaderSettings.BottomLayersCount = InitialLayerCount; + file.HeaderSettings.BottomLightPWM = HeaderSettings.BottomLightPWM; + file.HeaderSettings.LayerCount = LayerCount; + file.HeaderSettings.LayerExposureSeconds = LayerExposureTime; + file.HeaderSettings.LayerHeightMilimeter = LayerHeight; + file.HeaderSettings.LayerOffTime = HeaderSettings.LayerOffTime; + file.HeaderSettings.LightPWM = HeaderSettings.LightPWM; + file.HeaderSettings.PrintTime = HeaderSettings.PrintTime; + file.HeaderSettings.ProjectorType = HeaderSettings.ProjectorType; + file.HeaderSettings.ResolutionX = ResolutionX; + file.HeaderSettings.ResolutionY = ResolutionY; + + file.HeaderSettings.BottomLayerCount = InitialLayerCount; + file.HeaderSettings.BottomLiftHeight = PrintParametersSettings.BottomLiftHeight; + file.HeaderSettings.BottomLiftSpeed = PrintParametersSettings.BottomLiftSpeed; + file.HeaderSettings.BottomLightOffDelay = PrintParametersSettings.BottomLightOffDelay; + file.HeaderSettings.CostDollars = MaterialCost; + file.HeaderSettings.LiftHeight = PrintParametersSettings.LiftHeight; + file.HeaderSettings.LiftingSpeed = PrintParametersSettings.LiftingSpeed; + file.HeaderSettings.LayerOffTime = HeaderSettings.LayerOffTime; + file.HeaderSettings.RetractSpeed = PrintParametersSettings.RetractSpeed; + file.HeaderSettings.VolumeMl = UsedMaterial; + file.HeaderSettings.WeightG = PrintParametersSettings.WeightG; + + file.HeaderSettings.MachineName = MachineName; + file.HeaderSettings.MachineNameSize = (uint) MachineName.Length; + + file.SetThumbnails(Thumbnails); + file.Encode(fileFullPath); + + return true; + } + + if (to == typeof(ZCodexFile)) + { + TimeSpan ts = new TimeSpan(0, 0, (int)PrintTime); + ZCodexFile file = new ZCodexFile + { + ResinMetadataSettings = new ZCodexFile.ResinMetadata + { + MaterialId = 2, + Material = MaterialName, + AdditionalSupportLayerTime = 0, + BottomLayersNumber = InitialLayerCount, + BottomLayersTime = (uint)(InitialExposureTime * 1000), + LayerTime = (uint)(LayerExposureTime * 1000), + DisableSettingsChanges = false, + LayerThickness = LayerHeight, + PrintTime = (uint)PrintTime, + TotalLayersCount = LayerCount, + TotalMaterialVolumeUsed = UsedMaterial, + TotalMaterialWeightUsed = UsedMaterial, + }, + UserSettings = new ZCodexFile.UserSettingsdata + { + Printer = MachineName, + BottomLayersCount = InitialLayerCount, + PrintTime = $"{ts.Hours}h {ts.Minutes}m", + LayerExposureTime = (uint)(LayerExposureTime * 1000), + BottomLayerExposureTime = (uint)(InitialExposureTime * 1000), + MaterialId = 2, + LayerThickness = $"{LayerHeight} mm", + AntiAliasing = 0, + CrossSupportEnabled = 1, + ExposureOffTime = (uint) HeaderSettings.LayerOffTime, + HollowEnabled = 0, + HollowThickness = 0, + InfillDensity = 0, + IsAdvanced = 0, + MaterialType = MaterialName, + MaterialVolume = UsedMaterial, + MaxLayer = LayerCount - 1, + ModelLiftEnabled = 0, + ModelLiftHeight = 0, + RaftEnabled = 0, + RaftHeight = 0, + RaftOffset = 0, + SupportAdditionalExposureEnabled = 0, + SupportAdditionalExposureTime = 0, + XCorrection = 0, + YCorrection = 0, + ZLiftDistance = PrintParametersSettings.LiftHeight, + ZLiftFeedRate = PrintParametersSettings.LiftingSpeed, + ZLiftRetractRate = PrintParametersSettings.RetractSpeed, + }, + ZCodeMetadataSettings = new ZCodexFile.ZCodeMetadata + { + PrintTime = (uint)PrintTime, + PrinterName = MachineName, + Materials = new List + { + new ZCodexFile.ZCodeMetadata.MaterialsData + { + Name = MaterialName, + ExtruderType = "MAIN", + Id = 0, + Usage = 0, + Temperature = 0 + } + }, + }, + LayerManager = LayerManager + }; + + float usedMaterial = UsedMaterial / LayerCount; + for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) + { + file.ResinMetadataSettings.Layers.Add(new ZCodexFile.ResinMetadata.LayerData + { + Layer = layerIndex, + UsedMaterialVolume = usedMaterial + }); + } + + file.SetThumbnails(Thumbnails); + file.Encode(fileFullPath); + return true; + } + */ + return false; + } + #endregion + } +} diff --git a/PrusaSL1Reader/PrusaSL1Reader.csproj b/PrusaSL1Reader/PrusaSL1Reader.csproj index 5fc3b9e..36bf0c0 100644 --- a/PrusaSL1Reader/PrusaSL1Reader.csproj +++ b/PrusaSL1Reader/PrusaSL1Reader.csproj @@ -7,9 +7,9 @@ https://github.com/sn4k3/PrusaSL1Viewer https://github.com/sn4k3/PrusaSL1Viewer - 0.4.2.2 - 0.4.2.2 - 0.4.2.2 + 0.4.3.0 + 0.4.3.2 + 0.4.3 Open, view, edit, extract and convert DLP/SLA files generated from Slicers diff --git a/PrusaSL1Reader/SL1File.cs b/PrusaSL1Reader/SL1File.cs index 41a7519..1473f33 100644 --- a/PrusaSL1Reader/SL1File.cs +++ b/PrusaSL1Reader/SL1File.cs @@ -20,12 +20,27 @@ namespace PrusaSL1Reader { public class SL1File : FileFormat { + #region Constants + + public const string Keyword_BottomLightOffDelay = "BottomLightOffDelay"; + public const string Keyword_LayerOffTime = "LayerOffTime"; + public const string Keyword_LightOffDelay = "LightOffDelay"; + public const string Keyword_BottomLiftHeight = "BottomLiftHeight"; + public const string Keyword_BottomLiftSpeed = "BottomLiftSpeed"; + public const string Keyword_LiftHeight = "LiftHeight"; + public const string Keyword_LiftSpeed = "LiftSpeed"; + public const string Keyword_RetractSpeed = "RetractSpeed"; + public const string Keyword_BottomLightPWM = "BottomLightPWM"; + public const string Keyword_LightPWM = "LightPWM"; + #endregion + #region Sub Classes #region Printer public class Printer { #region Printer + public string InheritsCummulative { get; set; } public string PrinterSettingsId { get; set; } public string PrinterTechnology { get; set; } public string PrinterModel { get; set; } @@ -276,6 +291,7 @@ namespace PrusaSL1Reader public override Type[] ConvertToFormats { get; } = { typeof(ChituboxFile), + typeof(PWSFile), typeof(PHZFile), typeof(ZCodexFile), typeof(CWSFile), @@ -298,8 +314,6 @@ namespace PrusaSL1Reader public override float LayerHeight => OutputConfigSettings.LayerHeight; - public override uint LayerCount => (uint) (OutputConfigSettings.NumFast + OutputConfigSettings.NumSlow); - public override ushort InitialLayerCount => OutputConfigSettings.NumFade; public override float InitialExposureTime => OutputConfigSettings.ExpTimeFirst; @@ -431,7 +445,7 @@ namespace PrusaSL1Reader } } - LayerManager = new LayerManager(LayerCount); + LayerManager = new LayerManager((uint) (OutputConfigSettings.NumSlow + OutputConfigSettings.NumFast)); foreach (ZipArchiveEntry entity in inputFile.Entries) { @@ -565,45 +579,56 @@ namespace PrusaSL1Reader if (to == typeof(ChituboxFile)) { + ChituboxFile defaultFormat = (ChituboxFile)FindByType(typeof(ChituboxFile)); ChituboxFile file = new ChituboxFile { - LayerManager = LayerManager + LayerManager = LayerManager, + HeaderSettings = + { + Version = 2, + BedSizeX = PrinterSettings.DisplayWidth, + BedSizeY = PrinterSettings.DisplayHeight, + BedSizeZ = PrinterSettings.MaxPrintHeight, + OverallHeightMilimeter = TotalHeight, + BottomExposureSeconds = InitialExposureTime, + BottomLayersCount = InitialLayerCount, + BottomLightPWM = LookupCustomValue(Keyword_BottomLightPWM, defaultFormat.HeaderSettings.BottomLightPWM), + LayerCount = LayerCount, + LayerExposureSeconds = LayerExposureTime, + LayerHeightMilimeter = LayerHeight, + LayerOffTime = LookupCustomValue(Keyword_LayerOffTime, defaultFormat.HeaderSettings.LayerOffTime), + LightPWM = LookupCustomValue(Keyword_LightPWM, defaultFormat.HeaderSettings.LightPWM), + PrintTime = (uint) OutputConfigSettings.PrintTime, + ProjectorType = PrinterSettings.DisplayMirrorX ? 1u : 0u, + ResolutionX = ResolutionX, + ResolutionY = ResolutionY + }, + PrintParametersSettings = + { + BottomLayerCount = PrintSettings.FadedLayers, + BottomLiftHeight = LookupCustomValue(Keyword_BottomLiftHeight, + defaultFormat.PrintParametersSettings.BottomLiftHeight), + BottomLiftSpeed = LookupCustomValue(Keyword_BottomLiftSpeed, + defaultFormat.PrintParametersSettings.BottomLiftSpeed), + BottomLightOffDelay = LookupCustomValue(Keyword_BottomLightOffDelay, + defaultFormat.PrintParametersSettings.BottomLightOffDelay), + CostDollars = MaterialCost, + LiftHeight = LookupCustomValue(Keyword_LiftHeight, + defaultFormat.PrintParametersSettings.LiftHeight), + LiftingSpeed = LookupCustomValue(Keyword_LiftSpeed, + defaultFormat.PrintParametersSettings.LiftingSpeed), + LightOffDelay = LookupCustomValue(Keyword_LightOffDelay, + defaultFormat.PrintParametersSettings.LightOffDelay), + RetractSpeed = LookupCustomValue(Keyword_RetractSpeed, + defaultFormat.PrintParametersSettings.RetractSpeed), + VolumeMl = UsedMaterial, + WeightG = (float) Math.Round( + OutputConfigSettings.UsedMaterial * MaterialSettings.MaterialDensity, 2) + }, + SlicerInfoSettings = {MachineName = MachineName, MachineNameSize = (uint) MachineName.Length} }; - file.HeaderSettings.Version = 2; - file.HeaderSettings.BedSizeX = PrinterSettings.DisplayWidth; - file.HeaderSettings.BedSizeY = PrinterSettings.DisplayHeight; - file.HeaderSettings.BedSizeZ = PrinterSettings.MaxPrintHeight; - file.HeaderSettings.OverallHeightMilimeter = TotalHeight; - file.HeaderSettings.BottomExposureSeconds = InitialExposureTime; - file.HeaderSettings.BottomLayersCount = InitialLayerCount; - file.HeaderSettings.BottomLightPWM = LookupCustomValue("BottomLightPWM", file.HeaderSettings.BottomLightPWM); - file.HeaderSettings.LayerCount = LayerCount; - file.HeaderSettings.LayerExposureSeconds = LayerExposureTime; - file.HeaderSettings.LayerHeightMilimeter = LayerHeight; - file.HeaderSettings.LayerOffTime = LookupCustomValue("LayerOffTime", file.HeaderSettings.LayerOffTime); - file.HeaderSettings.LightPWM = LookupCustomValue("LightPWM", file.HeaderSettings.LightPWM); - file.HeaderSettings.PrintTime = (uint) OutputConfigSettings.PrintTime; - file.HeaderSettings.ProjectorType = PrinterSettings.DisplayMirrorX ? 1u : 0u; - file.HeaderSettings.ResolutionX = ResolutionX; - file.HeaderSettings.ResolutionY = ResolutionY; - - file.PrintParametersSettings.BottomLayerCount = PrintSettings.FadedLayers; - file.PrintParametersSettings.BottomLiftHeight = LookupCustomValue("BottomLiftHeight", file.PrintParametersSettings.BottomLiftHeight); - file.PrintParametersSettings.BottomLiftSpeed = LookupCustomValue("BottomLiftSpeed", file.PrintParametersSettings.BottomLiftSpeed); - file.PrintParametersSettings.BottomLightOffDelay = LookupCustomValue("BottomLightOffDelay", file.PrintParametersSettings.BottomLightOffDelay); - file.PrintParametersSettings.CostDollars = MaterialCost; - file.PrintParametersSettings.LiftHeight = LookupCustomValue("LiftHeight", file.PrintParametersSettings.LiftHeight); - file.PrintParametersSettings.LiftingSpeed = LookupCustomValue("LiftingSpeed", file.PrintParametersSettings.LiftingSpeed); - file.PrintParametersSettings.LightOffDelay = LookupCustomValue("LightOffDelay", file.PrintParametersSettings.LightOffDelay); - file.PrintParametersSettings.RetractSpeed = LookupCustomValue("RetractSpeed", file.PrintParametersSettings.RetractSpeed); - file.PrintParametersSettings.VolumeMl = UsedMaterial; - file.PrintParametersSettings.WeightG = (float) Math.Round(OutputConfigSettings.UsedMaterial * MaterialSettings.MaterialDensity, 2); - - file.SlicerInfoSettings.MachineName = MachineName; - file.SlicerInfoSettings.MachineNameSize = (uint)MachineName.Length; - if (LookupCustomValue("FLIP_XY", false, true)) { file.HeaderSettings.ResolutionX = PrinterSettings.DisplayPixelsY; @@ -616,48 +641,82 @@ namespace PrusaSL1Reader return true; } - if (to == typeof(PHZFile)) + if (to == typeof(PWSFile)) { - PHZFile file = new PHZFile + PWSFile defaultFormat = (PWSFile)FindByType(typeof(PWSFile)); + PWSFile file = new PWSFile { - LayerManager = LayerManager + LayerManager = LayerManager, + HeaderSettings = + { + ResolutionX = ResolutionX, + ResolutionY = ResolutionY, + LayerHeight = LayerHeight, + LayerExposureTime = LayerExposureTime, + LiftHeight = LookupCustomValue(Keyword_LiftHeight, defaultFormat.HeaderSettings.LiftHeight), + LiftSpeed = LookupCustomValue(Keyword_LiftSpeed, defaultFormat.HeaderSettings.LiftSpeed) / 60, + RetractSpeed = LookupCustomValue(Keyword_RetractSpeed, defaultFormat.HeaderSettings.RetractSpeed) / 60, + LayerOffTime = LookupCustomValue(Keyword_LayerOffTime, defaultFormat.HeaderSettings.LayerOffTime), + BottomLayersCount = InitialLayerCount, + BottomExposureSeconds = InitialExposureTime, + Price = MaterialCost, + Volume = UsedMaterial, + Weight = (float) Math.Round(OutputConfigSettings.UsedMaterial * MaterialSettings.MaterialDensity, 2) + } }; - file.HeaderSettings.Version = 2; - file.HeaderSettings.BedSizeX = PrinterSettings.DisplayWidth; - file.HeaderSettings.BedSizeY = PrinterSettings.DisplayHeight; - file.HeaderSettings.BedSizeZ = PrinterSettings.MaxPrintHeight; - file.HeaderSettings.OverallHeightMilimeter = TotalHeight; - file.HeaderSettings.BottomExposureSeconds = MaterialSettings.InitialExposureTime; - file.HeaderSettings.BottomLayersCount = PrintSettings.FadedLayers; - file.HeaderSettings.BottomLightPWM = LookupCustomValue("BottomLightPWM", file.HeaderSettings.BottomLightPWM); - file.HeaderSettings.LayerCount = LayerCount; - file.HeaderSettings.LayerExposureSeconds = MaterialSettings.ExposureTime; - file.HeaderSettings.LayerHeightMilimeter = PrintSettings.LayerHeight; - file.HeaderSettings.LayerOffTime = LookupCustomValue("LayerOffTime", file.HeaderSettings.LayerOffTime); - file.HeaderSettings.LightPWM = LookupCustomValue("LightPWM", file.HeaderSettings.LightPWM); - file.HeaderSettings.PrintTime = (uint)OutputConfigSettings.PrintTime; - file.HeaderSettings.ProjectorType = PrinterSettings.DisplayMirrorX ? 1u : 0u; - file.HeaderSettings.ResolutionX = PrinterSettings.DisplayPixelsX; - file.HeaderSettings.ResolutionY = PrinterSettings.DisplayPixelsY; + if (LookupCustomValue("FLIP_XY", false, true)) + { + file.HeaderSettings.ResolutionX = PrinterSettings.DisplayPixelsY; + file.HeaderSettings.ResolutionY = PrinterSettings.DisplayPixelsX; + } + file.SetThumbnails(Thumbnails); + file.Encode(fileFullPath); - file.HeaderSettings.BottomLayerCount = PrintSettings.FadedLayers; - file.HeaderSettings.BottomLiftHeight = LookupCustomValue("BottomLiftHeight", file.HeaderSettings.BottomLiftHeight); - file.HeaderSettings.BottomLiftSpeed = LookupCustomValue("BottomLiftSpeed", file.HeaderSettings.BottomLiftSpeed); - file.HeaderSettings.BottomLightOffDelay = LookupCustomValue("BottomLightOffDelay", file.HeaderSettings.BottomLightOffDelay); - file.HeaderSettings.CostDollars = MaterialCost; - file.HeaderSettings.LiftHeight = LookupCustomValue("LiftHeight", file.HeaderSettings.LiftHeight); - file.HeaderSettings.LiftingSpeed = LookupCustomValue("LiftingSpeed", file.HeaderSettings.LiftingSpeed); - file.HeaderSettings.LayerOffTime = LookupCustomValue("LayerOffTime", file.HeaderSettings.LayerOffTime); - file.HeaderSettings.RetractSpeed = LookupCustomValue("RetractSpeed", file.HeaderSettings.RetractSpeed); - file.HeaderSettings.VolumeMl = OutputConfigSettings.UsedMaterial; - file.HeaderSettings.WeightG = (float)Math.Round(OutputConfigSettings.UsedMaterial * MaterialSettings.MaterialDensity, 2); + return true; + } - - file.HeaderSettings.MachineName = MachineName; - file.HeaderSettings.MachineNameSize = (uint)MachineName.Length; + if (to == typeof(PHZFile)) + { + PHZFile defaultFormat = (PHZFile)FindByType(typeof(PHZFile)); + PHZFile file = new PHZFile + { + LayerManager = LayerManager, + HeaderSettings = + { + Version = 2, + BedSizeX = PrinterSettings.DisplayWidth, + BedSizeY = PrinterSettings.DisplayHeight, + BedSizeZ = PrinterSettings.MaxPrintHeight, + OverallHeightMilimeter = TotalHeight, + BottomExposureSeconds = MaterialSettings.InitialExposureTime, + BottomLayersCount = PrintSettings.FadedLayers, + BottomLightPWM = LookupCustomValue(Keyword_BottomLightPWM, defaultFormat.HeaderSettings.BottomLightPWM), + LayerCount = LayerCount, + LayerExposureSeconds = MaterialSettings.ExposureTime, + LayerHeightMilimeter = PrintSettings.LayerHeight, + LayerOffTime = LookupCustomValue(Keyword_LayerOffTime, defaultFormat.HeaderSettings.LayerOffTime), + LightPWM = LookupCustomValue(Keyword_LightPWM, defaultFormat.HeaderSettings.LightPWM), + PrintTime = (uint) OutputConfigSettings.PrintTime, + ProjectorType = PrinterSettings.DisplayMirrorX ? 1u : 0u, + ResolutionX = PrinterSettings.DisplayPixelsX, + ResolutionY = PrinterSettings.DisplayPixelsY, + BottomLayerCount = PrintSettings.FadedLayers, + BottomLiftHeight = LookupCustomValue(Keyword_BottomLiftHeight, defaultFormat.HeaderSettings.BottomLiftHeight), + BottomLiftSpeed = LookupCustomValue(Keyword_BottomLiftSpeed, defaultFormat.HeaderSettings.BottomLiftSpeed), + BottomLightOffDelay = LookupCustomValue(Keyword_BottomLightOffDelay, defaultFormat.HeaderSettings.BottomLightOffDelay), + CostDollars = MaterialCost, + LiftHeight = LookupCustomValue(Keyword_LiftHeight, defaultFormat.HeaderSettings.LiftHeight), + LiftingSpeed = LookupCustomValue(Keyword_LiftSpeed, defaultFormat.HeaderSettings.LiftingSpeed), + RetractSpeed = LookupCustomValue(Keyword_RetractSpeed, defaultFormat.HeaderSettings.RetractSpeed), + VolumeMl = OutputConfigSettings.UsedMaterial, + WeightG = (float)Math.Round(OutputConfigSettings.UsedMaterial * MaterialSettings.MaterialDensity, 2), + MachineName = MachineName, + MachineNameSize = (uint)MachineName.Length + } + }; if (LookupCustomValue("FLIP_XY", false, true)) { @@ -673,6 +732,7 @@ namespace PrusaSL1Reader if (to == typeof(ZCodexFile)) { + ZCodexFile defaultFormat = (ZCodexFile)FindByType(typeof(ZCodexFile)); TimeSpan ts = new TimeSpan(0, 0, (int)PrintTime); ZCodexFile file = new ZCodexFile { @@ -702,7 +762,7 @@ namespace PrusaSL1Reader LayerThickness = $"{LayerHeight} mm", AntiAliasing = 0, CrossSupportEnabled = 1, - ExposureOffTime = LookupCustomValue("ExposureOffTime", 5)*1000, + ExposureOffTime = LookupCustomValue(Keyword_LayerOffTime, defaultFormat.UserSettings.ExposureOffTime) *1000, HollowEnabled = PrintSettings.HollowingEnable ? (byte)1 : (byte)0, HollowThickness = PrintSettings.HollowingMinThickness, InfillDensity = 0, @@ -719,9 +779,9 @@ namespace PrusaSL1Reader SupportAdditionalExposureTime = 0, XCorrection = PrinterSettings.AbsoluteCorrection, YCorrection = PrinterSettings.AbsoluteCorrection, - ZLiftDistance = (float)Math.Round(LookupCustomValue("ZLiftDistance", 5), 2), - ZLiftFeedRate = (float)Math.Round(LookupCustomValue("ZLiftFeedRate", 100), 2), - ZLiftRetractRate = (float)Math.Round(LookupCustomValue("ZLiftRetractRate", 100), 2), + ZLiftDistance = (float)Math.Round(LookupCustomValue(Keyword_LiftHeight, defaultFormat.UserSettings.ZLiftDistance), 2), + ZLiftFeedRate = (float)Math.Round(LookupCustomValue(Keyword_LiftSpeed, defaultFormat.UserSettings.ZLiftFeedRate), 2), + ZLiftRetractRate = (float)Math.Round(LookupCustomValue(Keyword_RetractSpeed, defaultFormat.UserSettings.ZLiftRetractRate), 2), }, ZCodeMetadataSettings = new ZCodexFile.ZCodeMetadata { @@ -774,9 +834,9 @@ namespace PrusaSL1Reader file.SliceSettings.LayersExpoMs = file.OutputSettings.LayerTime = (uint) LayerExposureTime * 1000; file.SliceSettings.HeadLayersExpoMs = file.OutputSettings.BottomLayersTime = (uint) InitialExposureTime * 1000; file.SliceSettings.WaitBeforeExpoMs = LookupCustomValue("WaitBeforeExpoMs", file.SliceSettings.WaitBeforeExpoMs); - file.SliceSettings.LiftDistance = file.OutputSettings.LiftDistance = (float) Math.Round(LookupCustomValue("LiftDistance", file.SliceSettings.LiftDistance), 2); - file.SliceSettings.LiftUpSpeed = file.OutputSettings.ZLiftFeedRate = file.OutputSettings.ZBottomLiftFeedRate = (float) Math.Round(LookupCustomValue("LiftUpSpeed", file.SliceSettings.LiftUpSpeed), 2); - file.SliceSettings.LiftDownSpeed = file.OutputSettings.ZLiftRetractRate = (float) Math.Round(LookupCustomValue("LiftDownSpeed", file.SliceSettings.LiftDownSpeed), 2); + file.SliceSettings.LiftDistance = file.OutputSettings.LiftDistance = (float) Math.Round(LookupCustomValue(Keyword_LiftHeight, file.SliceSettings.LiftDistance), 2); + file.SliceSettings.LiftUpSpeed = file.OutputSettings.ZLiftFeedRate = file.OutputSettings.ZBottomLiftFeedRate = (float) Math.Round(LookupCustomValue(Keyword_LiftSpeed, file.SliceSettings.LiftUpSpeed), 2); + file.SliceSettings.LiftDownSpeed = file.OutputSettings.ZLiftRetractRate = (float) Math.Round(LookupCustomValue(Keyword_RetractSpeed, file.SliceSettings.LiftDownSpeed), 2); file.SliceSettings.LiftWhenFinished = LookupCustomValue("LiftWhenFinished", file.SliceSettings.LiftWhenFinished); file.OutputSettings.BlankingLayerTime = LookupCustomValue("BlankingLayerTime", file.OutputSettings.BlankingLayerTime); diff --git a/PrusaSL1Reader/ZCodexFile.cs b/PrusaSL1Reader/ZCodexFile.cs index 0c069c9..1b3fe30 100644 --- a/PrusaSL1Reader/ZCodexFile.cs +++ b/PrusaSL1Reader/ZCodexFile.cs @@ -79,14 +79,14 @@ namespace PrusaSL1Reader public byte CrossSupportEnabled { get; set; } public uint LayerExposureTime { get; set; } //public uint LayerThicknessesDisplayTime { get; set; } arr - public uint ExposureOffTime { get; set; } + public uint ExposureOffTime { get; set; } = 5; public uint BottomLayerExposureTime { get; set; } public uint BottomLayersCount { get; set; } public byte SupportAdditionalExposureEnabled { get; set; } public uint SupportAdditionalExposureTime { get; set; } - public float ZLiftDistance { get; set; } - public float ZLiftRetractRate { get; set; } - public float ZLiftFeedRate { get; set; } + public float ZLiftDistance { get; set; } = 5; + public float ZLiftRetractRate { get; set; } = 100; + public float ZLiftFeedRate { get; set; } = 100; public byte AntiAliasing { get; set; } public byte XCorrection { get; set; } public byte YCorrection { get; set; } @@ -170,8 +170,6 @@ namespace PrusaSL1Reader public override float LayerHeight => ResinMetadataSettings.LayerThickness; - public override uint LayerCount => ResinMetadataSettings.TotalLayersCount; - public override ushort InitialLayerCount => ResinMetadataSettings.BottomLayersNumber; public override float InitialExposureTime => UserSettings.BottomLayerExposureTime / 1000; @@ -294,7 +292,7 @@ namespace PrusaSL1Reader throw new FileLoadException("ResinGCodeData not found", fileFullPath); } - LayerManager = new LayerManager(LayerCount); + LayerManager = new LayerManager(ResinMetadataSettings.TotalLayersCount); GCode = new StringBuilder(); using (TextReader tr = new StreamReader(entry.Open())) { diff --git a/PrusaSL1Viewer/FrmMain.Designer.cs b/PrusaSL1Viewer/FrmMain.Designer.cs index 6303139..73416c4 100644 --- a/PrusaSL1Viewer/FrmMain.Designer.cs +++ b/PrusaSL1Viewer/FrmMain.Designer.cs @@ -55,10 +55,7 @@ this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator(); this.menuHelpInstallPrinters = new System.Windows.Forms.ToolStripMenuItem(); this.statusBar = new System.Windows.Forms.StatusStrip(); - this.sbLayers = new System.Windows.Forms.VScrollBar(); this.mainTable = new System.Windows.Forms.TableLayoutPanel(); - this.splitContainer1 = new System.Windows.Forms.SplitContainer(); - this.lbLayers = new System.Windows.Forms.Label(); this.scCenter = new System.Windows.Forms.SplitContainer(); this.pbLayer = new Cyotek.Windows.Forms.ImageBox(); this.tsLayer = new System.Windows.Forms.ToolStrip(); @@ -121,12 +118,16 @@ this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator(); this.tsIslandsRepair = new System.Windows.Forms.ToolStripButton(); this.imageList16x16 = new System.Windows.Forms.ImageList(this.components); + this.tlRight = new System.Windows.Forms.TableLayoutPanel(); + this.btnPreviousLayer = new System.Windows.Forms.Button(); + this.btnNextLayer = new System.Windows.Forms.Button(); + this.lbMaxLayer = new System.Windows.Forms.Label(); + this.lbInitialLayer = new System.Windows.Forms.Label(); + this.panel1 = new System.Windows.Forms.Panel(); + this.lbLayerActual = new System.Windows.Forms.Label(); + this.tbLayer = new System.Windows.Forms.TrackBar(); this.menu.SuspendLayout(); this.mainTable.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); - this.splitContainer1.Panel1.SuspendLayout(); - this.splitContainer1.Panel2.SuspendLayout(); - this.splitContainer1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.scCenter)).BeginInit(); this.scCenter.Panel1.SuspendLayout(); this.scCenter.Panel2.SuspendLayout(); @@ -145,6 +146,9 @@ this.tsGCode.SuspendLayout(); this.tabPageIslands.SuspendLayout(); this.tsIslands.SuspendLayout(); + this.tlRight.SuspendLayout(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tbLayer)).BeginInit(); this.SuspendLayout(); // // menu @@ -187,7 +191,7 @@ this.menuFileOpen.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); this.menuFileOpen.Size = new System.Drawing.Size(261, 22); this.menuFileOpen.Text = "&Open"; - this.menuFileOpen.Click += new System.EventHandler(this.ItemClicked); + this.menuFileOpen.Click += new System.EventHandler(this.EventClick); // // menuFileOpenNewWindow // @@ -197,7 +201,7 @@ | System.Windows.Forms.Keys.O))); this.menuFileOpenNewWindow.Size = new System.Drawing.Size(261, 22); this.menuFileOpenNewWindow.Text = "Open in new window"; - this.menuFileOpenNewWindow.Click += new System.EventHandler(this.ItemClicked); + this.menuFileOpenNewWindow.Click += new System.EventHandler(this.EventClick); // // menuFileReload // @@ -206,7 +210,7 @@ this.menuFileReload.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F5))); this.menuFileReload.Size = new System.Drawing.Size(261, 22); this.menuFileReload.Text = "&Reload"; - this.menuFileReload.Click += new System.EventHandler(this.ItemClicked); + this.menuFileReload.Click += new System.EventHandler(this.EventClick); // // menuFileSave // @@ -216,7 +220,7 @@ this.menuFileSave.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); this.menuFileSave.Size = new System.Drawing.Size(261, 22); this.menuFileSave.Text = "&Save"; - this.menuFileSave.Click += new System.EventHandler(this.ItemClicked); + this.menuFileSave.Click += new System.EventHandler(this.EventClick); // // menuFileSaveAs // @@ -227,7 +231,7 @@ | System.Windows.Forms.Keys.S))); this.menuFileSaveAs.Size = new System.Drawing.Size(261, 22); this.menuFileSaveAs.Text = "Save As"; - this.menuFileSaveAs.Click += new System.EventHandler(this.ItemClicked); + this.menuFileSaveAs.Click += new System.EventHandler(this.EventClick); // // menuFileClose // @@ -237,7 +241,7 @@ this.menuFileClose.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.W))); this.menuFileClose.Size = new System.Drawing.Size(261, 22); this.menuFileClose.Text = "&Close"; - this.menuFileClose.Click += new System.EventHandler(this.ItemClicked); + this.menuFileClose.Click += new System.EventHandler(this.EventClick); // // toolStripSeparator1 // @@ -252,7 +256,7 @@ this.menuFileExtract.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); this.menuFileExtract.Size = new System.Drawing.Size(261, 22); this.menuFileExtract.Text = "&Extract"; - this.menuFileExtract.Click += new System.EventHandler(this.ItemClicked); + this.menuFileExtract.Click += new System.EventHandler(this.EventClick); // // menuFileConvert // @@ -274,7 +278,7 @@ this.menuFileExit.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); this.menuFileExit.Size = new System.Drawing.Size(261, 22); this.menuFileExit.Text = "&Exit"; - this.menuFileExit.Click += new System.EventHandler(this.ItemClicked); + this.menuFileExit.Click += new System.EventHandler(this.EventClick); // // menuEdit // @@ -308,7 +312,7 @@ | System.Windows.Forms.Keys.R))); this.menuToolsRepairLayers.Size = new System.Drawing.Size(204, 22); this.menuToolsRepairLayers.Text = "&Repair layers"; - this.menuToolsRepairLayers.Click += new System.EventHandler(this.ItemClicked); + this.menuToolsRepairLayers.Click += new System.EventHandler(this.EventClick); // // viewToolStripMenuItem // @@ -337,7 +341,7 @@ | System.Windows.Forms.Keys.W))); this.menuHelpWebsite.Size = new System.Drawing.Size(229, 22); this.menuHelpWebsite.Text = "&Website"; - this.menuHelpWebsite.Click += new System.EventHandler(this.ItemClicked); + this.menuHelpWebsite.Click += new System.EventHandler(this.EventClick); // // menuHelpDonate // @@ -346,7 +350,7 @@ this.menuHelpDonate.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D))); this.menuHelpDonate.Size = new System.Drawing.Size(229, 22); this.menuHelpDonate.Text = "&Donate"; - this.menuHelpDonate.Click += new System.EventHandler(this.ItemClicked); + this.menuHelpDonate.Click += new System.EventHandler(this.EventClick); // // menuHelpAbout // @@ -355,7 +359,7 @@ this.menuHelpAbout.ShortcutKeys = System.Windows.Forms.Keys.F1; this.menuHelpAbout.Size = new System.Drawing.Size(229, 22); this.menuHelpAbout.Text = "&About"; - this.menuHelpAbout.Click += new System.EventHandler(this.ItemClicked); + this.menuHelpAbout.Click += new System.EventHandler(this.EventClick); // // toolStripSeparator10 // @@ -368,7 +372,7 @@ this.menuHelpInstallPrinters.Name = "menuHelpInstallPrinters"; this.menuHelpInstallPrinters.Size = new System.Drawing.Size(229, 22); this.menuHelpInstallPrinters.Text = "Instal printers into PrusaSlicer"; - this.menuHelpInstallPrinters.Click += new System.EventHandler(this.ItemClicked); + this.menuHelpInstallPrinters.Click += new System.EventHandler(this.EventClick); // // statusBar // @@ -378,26 +382,15 @@ this.statusBar.TabIndex = 1; this.statusBar.Text = "statusStrip1"; // - // sbLayers - // - this.sbLayers.Dock = System.Windows.Forms.DockStyle.Fill; - this.sbLayers.Enabled = false; - this.sbLayers.LargeChange = 1; - this.sbLayers.Location = new System.Drawing.Point(0, 0); - this.sbLayers.Name = "sbLayers"; - this.sbLayers.Size = new System.Drawing.Size(124, 673); - this.sbLayers.TabIndex = 4; - this.sbLayers.ValueChanged += new System.EventHandler(this.sbLayers_ValueChanged); - // // mainTable // this.mainTable.ColumnCount = 3; this.mainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 400F)); this.mainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.mainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 130F)); - this.mainTable.Controls.Add(this.splitContainer1, 2, 0); this.mainTable.Controls.Add(this.scCenter, 1, 0); this.mainTable.Controls.Add(this.tabControlLeft, 0, 0); + this.mainTable.Controls.Add(this.tlRight, 2, 0); this.mainTable.Dock = System.Windows.Forms.DockStyle.Fill; this.mainTable.Location = new System.Drawing.Point(0, 24); this.mainTable.Name = "mainTable"; @@ -406,36 +399,6 @@ this.mainTable.Size = new System.Drawing.Size(1684, 740); this.mainTable.TabIndex = 5; // - // splitContainer1 - // - this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; - this.splitContainer1.IsSplitterFixed = true; - this.splitContainer1.Location = new System.Drawing.Point(1557, 3); - this.splitContainer1.Name = "splitContainer1"; - this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; - // - // splitContainer1.Panel1 - // - this.splitContainer1.Panel1.Controls.Add(this.sbLayers); - // - // splitContainer1.Panel2 - // - this.splitContainer1.Panel2.Controls.Add(this.lbLayers); - this.splitContainer1.Size = new System.Drawing.Size(124, 734); - this.splitContainer1.SplitterDistance = 673; - this.splitContainer1.TabIndex = 0; - // - // lbLayers - // - this.lbLayers.Dock = System.Windows.Forms.DockStyle.Fill; - this.lbLayers.Location = new System.Drawing.Point(0, 0); - this.lbLayers.Name = "lbLayers"; - this.lbLayers.Size = new System.Drawing.Size(124, 57); - this.lbLayers.TabIndex = 0; - this.lbLayers.Text = "Layers"; - this.lbLayers.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // // scCenter // this.scCenter.Dock = System.Windows.Forms.DockStyle.Fill; @@ -510,7 +473,7 @@ this.tsLayerImageExport.Size = new System.Drawing.Size(23, 22); this.tsLayerImageExport.Text = "Save Layer"; this.tsLayerImageExport.ToolTipText = "Save layer image to file"; - this.tsLayerImageExport.Click += new System.EventHandler(this.ItemClicked); + this.tsLayerImageExport.Click += new System.EventHandler(this.EventClick); // // tsLayerResolution // @@ -532,7 +495,7 @@ this.tsLayerImageRotate.Text = "Rotate Image 90º"; this.tsLayerImageRotate.ToolTipText = "Auto rotate layer preview image at 90º (This can slow down the layer preview) [CT" + "RL+R]"; - this.tsLayerImageRotate.Click += new System.EventHandler(this.ItemClicked); + this.tsLayerImageRotate.Click += new System.EventHandler(this.EventClick); // // toolStripSeparator5 // @@ -549,7 +512,7 @@ this.tsLayerImageLayerDifference.Text = "Difference"; this.tsLayerImageLayerDifference.ToolTipText = "Show layer differences where daker pixels were also present on previous layer and" + " the white pixels the difference between previous and current layer."; - this.tsLayerImageLayerDifference.Click += new System.EventHandler(this.ItemClicked); + this.tsLayerImageLayerDifference.Click += new System.EventHandler(this.EventClick); // // toolStripSeparator6 // @@ -581,7 +544,7 @@ this.tsLayerImageHighlightIslands.Size = new System.Drawing.Size(63, 22); this.tsLayerImageHighlightIslands.Text = "Islands"; this.tsLayerImageHighlightIslands.ToolTipText = "Highlight islands on current layer.\r\nValid only if Islands are calculated."; - this.tsLayerImageHighlightIslands.Click += new System.EventHandler(this.ItemClicked); + this.tsLayerImageHighlightIslands.Click += new System.EventHandler(this.EventClick); // // toolStripSeparator7 // @@ -597,7 +560,7 @@ this.tsLayerImageLayerOutline.Size = new System.Drawing.Size(66, 22); this.tsLayerImageLayerOutline.Text = "Outline"; this.tsLayerImageLayerOutline.ToolTipText = "Show layer outlines only"; - this.tsLayerImageLayerOutline.Click += new System.EventHandler(this.ItemClicked); + this.tsLayerImageLayerOutline.Click += new System.EventHandler(this.EventClick); // // toolStripSeparator9 // @@ -735,7 +698,7 @@ this.tsThumbnailsPrevious.Size = new System.Drawing.Size(23, 22); this.tsThumbnailsPrevious.Text = "toolStripButton1"; this.tsThumbnailsPrevious.ToolTipText = "Show previous thumbnail"; - this.tsThumbnailsPrevious.Click += new System.EventHandler(this.ItemClicked); + this.tsThumbnailsPrevious.Click += new System.EventHandler(this.EventClick); // // tsThumbnailsCount // @@ -755,7 +718,7 @@ this.tsThumbnailsNext.Size = new System.Drawing.Size(23, 22); this.tsThumbnailsNext.Text = "toolStripButton2"; this.tsThumbnailsNext.ToolTipText = "Show next thumbnail"; - this.tsThumbnailsNext.Click += new System.EventHandler(this.ItemClicked); + this.tsThumbnailsNext.Click += new System.EventHandler(this.EventClick); // // tsThumbnailsExport // @@ -768,7 +731,7 @@ this.tsThumbnailsExport.Size = new System.Drawing.Size(23, 22); this.tsThumbnailsExport.Text = "Save Thumbnail"; this.tsThumbnailsExport.ToolTipText = "Save thumbnail to file"; - this.tsThumbnailsExport.Click += new System.EventHandler(this.ItemClicked); + this.tsThumbnailsExport.Click += new System.EventHandler(this.EventClick); // // tsThumbnailsResolution // @@ -846,7 +809,7 @@ this.tsPropertiesButtonSave.Size = new System.Drawing.Size(23, 22); this.tsPropertiesButtonSave.Text = "Save Thumbnail"; this.tsPropertiesButtonSave.ToolTipText = "Save properties to a file"; - this.tsPropertiesButtonSave.Click += new System.EventHandler(this.ItemClicked); + this.tsPropertiesButtonSave.Click += new System.EventHandler(this.EventClick); // // tabPageGCode // @@ -911,7 +874,7 @@ this.tsGCodeButtonSave.Size = new System.Drawing.Size(23, 22); this.tsGCodeButtonSave.Text = "Save GCode"; this.tsGCodeButtonSave.ToolTipText = "Save GCode to file"; - this.tsGCodeButtonSave.Click += new System.EventHandler(this.ItemClicked); + this.tsGCodeButtonSave.Click += new System.EventHandler(this.EventClick); // // tabPageIslands // @@ -994,7 +957,7 @@ this.tsIslandsPrevious.Size = new System.Drawing.Size(23, 22); this.tsIslandsPrevious.Text = "Previous"; this.tsIslandsPrevious.ToolTipText = "Show previous island"; - this.tsIslandsPrevious.Click += new System.EventHandler(this.ItemClicked); + this.tsIslandsPrevious.Click += new System.EventHandler(this.EventClick); // // tsIslandsCount // @@ -1013,7 +976,7 @@ this.tsIslandsNext.Size = new System.Drawing.Size(23, 22); this.tsIslandsNext.Text = "tsIslandsNext"; this.tsIslandsNext.ToolTipText = "Show next island"; - this.tsIslandsNext.Click += new System.EventHandler(this.ItemClicked); + this.tsIslandsNext.Click += new System.EventHandler(this.EventClick); // // toolStripSeparator13 // @@ -1030,7 +993,7 @@ this.tsIslandsRefresh.Size = new System.Drawing.Size(61, 22); this.tsIslandsRefresh.Text = "Detect"; this.tsIslandsRefresh.ToolTipText = "Compute Islands"; - this.tsIslandsRefresh.Click += new System.EventHandler(this.ItemClicked); + this.tsIslandsRefresh.Click += new System.EventHandler(this.EventClick); // // tsIslandsRemove // @@ -1041,7 +1004,7 @@ this.tsIslandsRemove.Size = new System.Drawing.Size(70, 22); this.tsIslandsRemove.Text = "Remove"; this.tsIslandsRemove.ToolTipText = "Remove selected islands"; - this.tsIslandsRemove.Click += new System.EventHandler(this.ItemClicked); + this.tsIslandsRemove.Click += new System.EventHandler(this.EventClick); // // toolStripSeparator12 // @@ -1059,7 +1022,7 @@ this.tsIslandsRepair.Size = new System.Drawing.Size(60, 22); this.tsIslandsRepair.Text = "Repair"; this.tsIslandsRepair.ToolTipText = "Attempt to repair islands"; - this.tsIslandsRepair.Click += new System.EventHandler(this.ItemClicked); + this.tsIslandsRepair.Click += new System.EventHandler(this.EventClick); // // imageList16x16 // @@ -1070,6 +1033,103 @@ this.imageList16x16.Images.SetKeyName(2, "GCode-16x16.png"); this.imageList16x16.Images.SetKeyName(3, "island-16x16.png"); // + // tlRight + // + this.tlRight.ColumnCount = 1; + this.tlRight.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlRight.Controls.Add(this.btnPreviousLayer, 0, 3); + this.tlRight.Controls.Add(this.btnNextLayer, 0, 1); + this.tlRight.Controls.Add(this.lbMaxLayer, 0, 0); + this.tlRight.Controls.Add(this.lbInitialLayer, 0, 4); + this.tlRight.Controls.Add(this.panel1, 0, 2); + this.tlRight.Dock = System.Windows.Forms.DockStyle.Fill; + this.tlRight.Location = new System.Drawing.Point(1557, 3); + this.tlRight.Name = "tlRight"; + this.tlRight.RowCount = 5; + this.tlRight.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tlRight.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 32F)); + this.tlRight.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlRight.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 32F)); + this.tlRight.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tlRight.Size = new System.Drawing.Size(124, 734); + this.tlRight.TabIndex = 6; + // + // btnPreviousLayer + // + this.btnPreviousLayer.Dock = System.Windows.Forms.DockStyle.Fill; + this.btnPreviousLayer.Enabled = false; + this.btnPreviousLayer.Image = global::PrusaSL1Viewer.Properties.Resources.arrow_down_16x16; + this.btnPreviousLayer.Location = new System.Drawing.Point(3, 655); + this.btnPreviousLayer.Name = "btnPreviousLayer"; + this.btnPreviousLayer.Size = new System.Drawing.Size(118, 26); + this.btnPreviousLayer.TabIndex = 14; + this.btnPreviousLayer.Text = "-"; + this.btnPreviousLayer.UseVisualStyleBackColor = true; + this.btnPreviousLayer.Click += new System.EventHandler(this.EventClick); + // + // btnNextLayer + // + this.btnNextLayer.Dock = System.Windows.Forms.DockStyle.Fill; + this.btnNextLayer.Enabled = false; + this.btnNextLayer.Image = global::PrusaSL1Viewer.Properties.Resources.arrow_up_16x16; + this.btnNextLayer.Location = new System.Drawing.Point(3, 53); + this.btnNextLayer.Name = "btnNextLayer"; + this.btnNextLayer.Size = new System.Drawing.Size(118, 26); + this.btnNextLayer.TabIndex = 8; + this.btnNextLayer.Text = "+"; + this.btnNextLayer.UseVisualStyleBackColor = true; + this.btnNextLayer.Click += new System.EventHandler(this.EventClick); + // + // lbMaxLayer + // + this.lbMaxLayer.Dock = System.Windows.Forms.DockStyle.Fill; + this.lbMaxLayer.Location = new System.Drawing.Point(3, 0); + this.lbMaxLayer.Name = "lbMaxLayer"; + this.lbMaxLayer.Size = new System.Drawing.Size(118, 50); + this.lbMaxLayer.TabIndex = 12; + this.lbMaxLayer.Text = "Layers"; + this.lbMaxLayer.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // lbInitialLayer + // + this.lbInitialLayer.Dock = System.Windows.Forms.DockStyle.Fill; + this.lbInitialLayer.Location = new System.Drawing.Point(3, 684); + this.lbInitialLayer.Name = "lbInitialLayer"; + this.lbInitialLayer.Size = new System.Drawing.Size(118, 50); + this.lbInitialLayer.TabIndex = 11; + this.lbInitialLayer.Text = "Layers"; + this.lbInitialLayer.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // panel1 + // + this.panel1.Controls.Add(this.lbLayerActual); + this.panel1.Controls.Add(this.tbLayer); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(3, 85); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(118, 564); + this.panel1.TabIndex = 13; + // + // lbLayerActual + // + this.lbLayerActual.AutoSize = true; + this.lbLayerActual.Location = new System.Drawing.Point(3, 551); + this.lbLayerActual.Name = "lbLayerActual"; + this.lbLayerActual.Size = new System.Drawing.Size(13, 13); + this.lbLayerActual.TabIndex = 9; + this.lbLayerActual.Text = "?"; + // + // tbLayer + // + this.tbLayer.Dock = System.Windows.Forms.DockStyle.Right; + this.tbLayer.Location = new System.Drawing.Point(73, 0); + this.tbLayer.Name = "tbLayer"; + this.tbLayer.Orientation = System.Windows.Forms.Orientation.Vertical; + this.tbLayer.Size = new System.Drawing.Size(45, 564); + this.tbLayer.TabIndex = 8; + this.tbLayer.TickStyle = System.Windows.Forms.TickStyle.TopLeft; + this.tbLayer.ValueChanged += new System.EventHandler(this.ValueChanged); + // // FrmMain // this.AllowDrop = true; @@ -1089,10 +1149,6 @@ this.menu.ResumeLayout(false); this.menu.PerformLayout(); this.mainTable.ResumeLayout(false); - this.splitContainer1.Panel1.ResumeLayout(false); - this.splitContainer1.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); - this.splitContainer1.ResumeLayout(false); this.scCenter.Panel1.ResumeLayout(false); this.scCenter.Panel1.PerformLayout(); this.scCenter.Panel2.ResumeLayout(false); @@ -1121,6 +1177,10 @@ this.tabPageIslands.PerformLayout(); this.tsIslands.ResumeLayout(false); this.tsIslands.PerformLayout(); + this.tlRight.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tbLayer)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -1137,10 +1197,7 @@ private System.Windows.Forms.ToolStripMenuItem menuHelpWebsite; private System.Windows.Forms.ToolStripMenuItem menuHelpDonate; private System.Windows.Forms.ToolStripMenuItem menuHelpAbout; - private System.Windows.Forms.VScrollBar sbLayers; private System.Windows.Forms.TableLayoutPanel mainTable; - private System.Windows.Forms.SplitContainer splitContainer1; - private System.Windows.Forms.Label lbLayers; private System.Windows.Forms.ToolStripMenuItem menuEdit; private System.Windows.Forms.SplitContainer scCenter; private System.Windows.Forms.ProgressBar pbLayers; @@ -1219,6 +1276,14 @@ private System.Windows.Forms.ToolStripButton tsIslandsRepair; private System.Windows.Forms.ToolStripSeparator toolStripSeparator14; private System.Windows.Forms.ToolStripButton tsLayerImageHighlightIslands; + private System.Windows.Forms.TrackBar tbLayer; + private System.Windows.Forms.TableLayoutPanel tlRight; + private System.Windows.Forms.Label lbMaxLayer; + private System.Windows.Forms.Label lbInitialLayer; + private System.Windows.Forms.Button btnNextLayer; + private System.Windows.Forms.Button btnPreviousLayer; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label lbLayerActual; } } diff --git a/PrusaSL1Viewer/FrmMain.cs b/PrusaSL1Viewer/FrmMain.cs index 296dd10..16ca130 100644 --- a/PrusaSL1Viewer/FrmMain.cs +++ b/PrusaSL1Viewer/FrmMain.cs @@ -23,6 +23,7 @@ using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using Color = System.Drawing.Color; +using Image = SixLabors.ImageSharp.Image; using Point = System.Drawing.Point; using Size = System.Drawing.Size; @@ -101,6 +102,8 @@ namespace PrusaSL1Viewer public uint TotalIslands { get; set; } + public bool IsChagingLayer { get; set; } + #endregion #region Constructors @@ -123,7 +126,7 @@ namespace PrusaSL1Viewer { ToolTipText = Mutations[mutate].Description, Tag = mutate, AutoToolTip = true, Image = Properties.Resources.filter_filled_16x16 }; - item.Click += ItemClicked; + item.Click += EventClick; menuMutate.DropDownItems.Add(item); } } @@ -138,20 +141,59 @@ namespace PrusaSL1Viewer ProcessFile(Program.Args); } + protected override void OnKeyPress(KeyPressEventArgs e) + { + if (ReferenceEquals(SlicerFile, null) || IsChagingLayer) + { + return; + } + + if (e.KeyChar == '-') + { + ShowLayer(false); + e.Handled = true; + return; + } + + if (e.KeyChar == '+') + { + ShowLayer(true); + e.Handled = true; + return; + } + + base.OnKeyPress(e); + } + protected override void OnKeyUp(KeyEventArgs e) { - base.OnKeyUp(e); - + if (ReferenceEquals(SlicerFile, null)) { return; } + if (e.KeyCode == Keys.Home) + { + ShowLayer(0); + e.Handled = true; + return; + } + + + + if (e.KeyCode == Keys.End) + { + ShowLayer(SlicerFile.LayerCount-1); + e.Handled = true; + return; + } + if (e.Control) { if (e.KeyCode == Keys.F) { - using (FrmInputBox inputBox = new FrmInputBox("Go to layer", "Select a layer index to go to.", ActualLayer, null, 0, SlicerFile.LayerCount-1, 0, "Layer")) + using (FrmInputBox inputBox = new FrmInputBox("Go to layer", "Select a layer index to go to", ActualLayer, null, 0, SlicerFile.LayerCount-1, 0, "Layer")) { if (inputBox.ShowDialog() == DialogResult.OK) { @@ -176,19 +218,25 @@ namespace PrusaSL1Viewer return; } } + base.OnKeyUp(e); } protected override void OnResize(EventArgs e) { base.OnResize(e); pbLayer.ZoomToFit(); + lbLayerActual.Location = new Point(lbLayerActual.Location.X, + Math.Max(1, + Math.Min(tbLayer.Height - 40, + (int)(tbLayer.Height - tbLayer.Value * ((float)tbLayer.Height / tbLayer.Maximum)) - lbLayerActual.Height / 2) + )); } #endregion #region Events - private void ItemClicked(object sender, EventArgs e) + private void EventClick(object sender, EventArgs e) { if (sender.GetType() == typeof(ToolStripMenuItem)) { @@ -261,7 +309,8 @@ namespace PrusaSL1Viewer } finally { - Invoke((MethodInvoker)delegate { + Invoke((MethodInvoker) delegate + { // Running on the UI thread EnableGUI(true); }); @@ -271,9 +320,9 @@ namespace PrusaSL1Viewer }); FrmLoading.ShowDialog(); - + menuFileSave.Enabled = - menuFileSaveAs.Enabled = false; + menuFileSaveAs.Enabled = false; return; } @@ -304,7 +353,8 @@ namespace PrusaSL1Viewer } finally { - Invoke((MethodInvoker)delegate { + Invoke((MethodInvoker) delegate + { // Running on the UI thread EnableGUI(true); }); @@ -314,15 +364,15 @@ namespace PrusaSL1Viewer }); FrmLoading.ShowDialog(); - + menuFileSave.Enabled = - menuFileSaveAs.Enabled = false; + menuFileSaveAs.Enabled = false; UpdateTitle(); //ProcessFile(dialog.FileName); } } - + return; } @@ -337,6 +387,7 @@ namespace PrusaSL1Viewer return; } } + Clear(); return; } @@ -352,6 +403,7 @@ namespace PrusaSL1Viewer return; } } + Application.Exit(); return; } @@ -363,7 +415,8 @@ namespace PrusaSL1Viewer { string fileNameNoExt = Path.GetFileNameWithoutExtension(SlicerFile.FileFullPath); folder.SelectedPath = Path.GetDirectoryName(SlicerFile.FileFullPath); - folder.Description = $"A \"{fileNameNoExt}\" folder will be created on your selected folder to dump the content."; + folder.Description = + $"A \"{fileNameNoExt}\" folder will be created on your selected folder to dump the content."; if (folder.ShowDialog() == DialogResult.OK) { string finalPath = Path.Combine(folder.SelectedPath, fileNameNoExt); @@ -375,16 +428,17 @@ namespace PrusaSL1Viewer var task = Task.Factory.StartNew(() => { SlicerFile.Extract(finalPath); - Invoke((MethodInvoker)delegate { + Invoke((MethodInvoker) delegate + { // Running on the UI thread EnableGUI(true); }); }); FrmLoading.ShowDialog(); - + if (MessageBox.Show( - $"Extraction was successful ({FrmLoading.StopWatch.ElapsedMilliseconds/1000}s), browser folder to see it contents.\n{finalPath}\nPress 'Yes' if you want open the target folder, otherwise select 'No' to continue.", + $"Extraction was successful ({FrmLoading.StopWatch.ElapsedMilliseconds / 1000}s), browser folder to see it contents.\n{finalPath}\nPress 'Yes' if you want open the target folder, otherwise select 'No' to continue.", "Extraction completed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { @@ -419,14 +473,15 @@ namespace PrusaSL1Viewer if (!SlicerFile.SetValueFromPrintParameterModifier(modifier, value)) { MessageBox.Show( - $"Unable to set '{modifier.Name}' value, was not found, it may not implemented yet.", "Operation error", MessageBoxButtons.OK, MessageBoxIcon.Error); + $"Unable to set '{modifier.Name}' value, was not found, it may not implemented yet.", + "Operation error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } RefreshInfo(); menuFileSave.Enabled = - menuFileSaveAs.Enabled = true; + menuFileSaveAs.Enabled = true; } return; @@ -435,7 +490,7 @@ namespace PrusaSL1Viewer if (item.Tag.GetType() == typeof(Mutation.Mutates)) { - Mutation.Mutates mutate = (Mutation.Mutates)item.Tag; + Mutation.Mutates mutate = (Mutation.Mutates) item.Tag; MutateLayers(mutate); return; } @@ -468,7 +523,7 @@ namespace PrusaSL1Viewer bool result = false; try { - + Parallel.For(layerStart, layerEnd + 1, i => { Layer layer = SlicerFile[i]; @@ -483,8 +538,8 @@ namespace PrusaSL1Viewer if (openingIterations > 0) { - imageEgmu = imageEgmu.Erode((int)openingIterations); - imageEgmu = imageEgmu.Dilate((int)openingIterations); + imageEgmu = imageEgmu.Erode((int) openingIterations); + imageEgmu = imageEgmu.Dilate((int) openingIterations); } layer.Image = imageEgmu.ToImageSharpL8(); @@ -498,7 +553,8 @@ namespace PrusaSL1Viewer } finally { - Invoke((MethodInvoker)delegate { + Invoke((MethodInvoker) delegate + { // Running on the UI thread EnableGUI(true); }); @@ -514,7 +570,7 @@ namespace PrusaSL1Viewer ComputeIslands(); menuFileSave.Enabled = - menuFileSaveAs.Enabled = true; + menuFileSaveAs.Enabled = true; return; } @@ -544,7 +600,8 @@ namespace PrusaSL1Viewer if (ReferenceEquals(sender, menuHelpInstallPrinters)) { - string printerFolder = $"{Application.StartupPath}{Path.DirectorySeparatorChar}PrusaSlicer{Path.DirectorySeparatorChar}printer"; + string printerFolder = + $"{Application.StartupPath}{Path.DirectorySeparatorChar}PrusaSlicer{Path.DirectorySeparatorChar}printer"; try { string[] profiles = Directory.GetFiles(printerFolder); @@ -563,7 +620,8 @@ namespace PrusaSL1Viewer "Click 'Yes' to override all profiles\n" + "Click 'No' to install only missing profiles without override\n" + "Clock 'Abort' to cancel this operation", - "Install printers into PrusaSlicer", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); + "Install printers into PrusaSlicer", MessageBoxButtons.YesNoCancel, + MessageBoxIcon.Question); if (result == DialogResult.Abort) @@ -572,11 +630,13 @@ namespace PrusaSL1Viewer } bool overwrite = result == DialogResult.Yes; - string targetFolder = $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}PrusaSlicer{Path.DirectorySeparatorChar}printer"; + string targetFolder = + $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}PrusaSlicer{Path.DirectorySeparatorChar}printer"; foreach (var profile in profiles) { - string targetFile = $"{targetFolder}{Path.DirectorySeparatorChar}{Path.GetFileName(profile)}"; + string targetFile = + $"{targetFolder}{Path.DirectorySeparatorChar}{Path.GetFileName(profile)}"; if (!overwrite && File.Exists(targetFile)) continue; File.Copy(profile, targetFile, overwrite); } @@ -590,9 +650,9 @@ namespace PrusaSL1Viewer { MessageBox.Show(exception.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } - - + + return; } } @@ -602,7 +662,7 @@ namespace PrusaSL1Viewer ***********************/ if (ReferenceEquals(sender, tsThumbnailsPrevious)) { - byte i = (byte)tsThumbnailsCount.Tag; + byte i = (byte) tsThumbnailsCount.Tag; if (i == 0) { // This should never happen! @@ -619,7 +679,7 @@ namespace PrusaSL1Viewer pbThumbnail.Image = SlicerFile.Thumbnails[i]?.ToBitmap(); - tsThumbnailsCount.Text = $"{i+1}/{SlicerFile.CreatedThumbnailsCount}"; + tsThumbnailsCount.Text = $"{i + 1}/{SlicerFile.CreatedThumbnailsCount}"; tsThumbnailsNext.Enabled = true; tsThumbnailsResolution.Text = pbThumbnail.Image.PhysicalDimension.ToString(); @@ -631,7 +691,7 @@ namespace PrusaSL1Viewer if (ReferenceEquals(sender, tsThumbnailsNext)) { byte i = byte.Parse(tsThumbnailsCount.Tag.ToString()); - if (i >= SlicerFile.CreatedThumbnailsCount-1) + if (i >= SlicerFile.CreatedThumbnailsCount - 1) { // This should never happen! tsThumbnailsNext.Enabled = false; @@ -640,14 +700,14 @@ namespace PrusaSL1Viewer tsThumbnailsCount.Tag = ++i; - if (i >= SlicerFile.CreatedThumbnailsCount-1) + if (i >= SlicerFile.CreatedThumbnailsCount - 1) { tsThumbnailsNext.Enabled = false; } pbThumbnail.Image = SlicerFile.Thumbnails[i]?.ToBitmap(); - tsThumbnailsCount.Text = $"{i+1}/{SlicerFile.CreatedThumbnailsCount}"; + tsThumbnailsCount.Text = $"{i + 1}/{SlicerFile.CreatedThumbnailsCount}"; tsThumbnailsPrevious.Enabled = true; tsThumbnailsResolution.Text = pbThumbnail.Image.PhysicalDimension.ToString(); @@ -661,14 +721,15 @@ namespace PrusaSL1Viewer using (SaveFileDialog dialog = new SaveFileDialog()) { byte i = byte.Parse(tsThumbnailsCount.Tag.ToString()); - if(ReferenceEquals(SlicerFile.Thumbnails[i], null)) + if (ReferenceEquals(SlicerFile.Thumbnails[i], null)) { return; // This should never happen! } dialog.Filter = "Image Files|.*png"; dialog.AddExtension = true; - dialog.FileName = $"{Path.GetFileNameWithoutExtension(SlicerFile.FileFullPath)}_thumbnail{i+1}.png"; + dialog.FileName = + $"{Path.GetFileNameWithoutExtension(SlicerFile.FileFullPath)}_thumbnail{i + 1}.png"; if (dialog.ShowDialog() == DialogResult.OK) { @@ -678,6 +739,7 @@ namespace PrusaSL1Viewer stream.Close(); } } + return; } } @@ -705,8 +767,10 @@ namespace PrusaSL1Viewer { tw.WriteLine($"{property.Name} = {property.GetValue(config)}"); } + tw.WriteLine(); } + tw.Close(); } @@ -718,6 +782,7 @@ namespace PrusaSL1Viewer Process.Start(dialog.FileName); } } + return; } } @@ -749,6 +814,7 @@ namespace PrusaSL1Viewer Process.Start(dialog.FileName); } } + return; } } @@ -783,12 +849,13 @@ namespace PrusaSL1Viewer if (MessageBox.Show("Are you sure you want to remove all selected islands from image?\n" + "Warning: Removing a island can cause another island to appears if the next layer have land in top of the removed island.\n" + - "Always check previous and next layer before perform a island removal to ensure safe operation.", "Remove islands?", + "Always check previous and next layer before perform a island removal to ensure safe operation.", + "Remove islands?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return; foreach (ListViewItem item in lvIslands.SelectedItems) { - if(!(item.Tag is LayerIsland island)) continue; + if (!(item.Tag is LayerIsland island)) continue; var image = ActualLayer == island.Owner.Index ? ActualLayerImage : island.Owner.Image; @@ -806,7 +873,7 @@ namespace PrusaSL1Viewer y = pixel.X; } - ((Bitmap)pbLayer.Image).SetPixel(x, y, Color.DarkRed); + ((Bitmap) pbLayer.Image).SetPixel(x, y, Color.DarkRed); } } @@ -819,15 +886,15 @@ namespace PrusaSL1Viewer } UpdateIslandsInfo(); - menuFileSave.Enabled = - menuFileSaveAs.Enabled = true; + menuFileSave.Enabled = + menuFileSaveAs.Enabled = true; return; } if (ReferenceEquals(sender, tsIslandsRepair)) { - ItemClicked(menuToolsRepairLayers, e); + EventClick(menuToolsRepairLayers, e); return; } @@ -844,7 +911,9 @@ namespace PrusaSL1Viewer /************************ * Layer Menu * ***********************/ - if (ReferenceEquals(sender, tsLayerImageRotate) || ReferenceEquals(sender, tsLayerImageLayerDifference) || ReferenceEquals(sender, tsLayerImageHighlightIslands) || ReferenceEquals(sender, tsLayerImageLayerOutline)) + if (ReferenceEquals(sender, tsLayerImageRotate) || ReferenceEquals(sender, tsLayerImageLayerDifference) || + ReferenceEquals(sender, tsLayerImageHighlightIslands) || + ReferenceEquals(sender, tsLayerImageLayerOutline)) { ShowLayer(); return; @@ -861,14 +930,15 @@ namespace PrusaSL1Viewer dialog.Filter = "Image Files|.*png"; dialog.AddExtension = true; - dialog.FileName = $"{Path.GetFileNameWithoutExtension(SlicerFile.FileFullPath)}_layer{ActualLayer}.png"; + dialog.FileName = + $"{Path.GetFileNameWithoutExtension(SlicerFile.FileFullPath)}_layer{ActualLayer}.png"; if (dialog.ShowDialog() == DialogResult.OK) { using (var stream = dialog.OpenFile()) { - Image image = (Image)pbLayer.Image.Tag; - image.Save(stream, new PngEncoder()); + Image image = (Image) pbLayer.Image.Tag; + image.Save(stream, Helpers.PngEncoder); stream.Close(); } } @@ -877,13 +947,32 @@ namespace PrusaSL1Viewer } } + + if (ReferenceEquals(sender, btnPreviousLayer)) + { + ShowLayer(false); + return; + } + + if (ReferenceEquals(sender, btnNextLayer)) + { + ShowLayer(true); + return; + } } - private void sbLayers_ValueChanged(object sender, EventArgs e) + private void ValueChanged(object sender, EventArgs e) { - ActualLayer = (uint) (sbLayers.Maximum - sbLayers.Value); - ShowLayer(); + if (ReferenceEquals(sender, tbLayer)) + { + if (tbLayer.Value == ActualLayer) return; + /*Debug.WriteLine($"{tbLayer.Height} + {tbLayer.Value} * ({tbLayer.Height} / {tbLayer.Maximum})"); + lbLayerActual.Location = new Point(lbLayerActual.Location.X, (int) (tbLayer.Height - tbLayer.Value * ((float)tbLayer.Height / tbLayer.Maximum))); + Debug.WriteLine(lbLayerActual.Location);*/ + ShowLayer((uint) tbLayer.Value); + return; + } } private void ConvertToItemOnClick(object sender, EventArgs e) @@ -912,8 +1001,9 @@ namespace PrusaSL1Viewer { result = SlicerFile.Convert(fileFormat, dialog.FileName); } - catch (Exception) + catch (Exception ex) { + MessageBox.Show($"Convertion was unsuccessful! Maybe not implemented...\n{ex.Message}", "Convertion unsuccessful", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { @@ -940,7 +1030,7 @@ namespace PrusaSL1Viewer } else { - MessageBox.Show("Convertion was unsuccessful! Maybe not implemented...", "Convertion unsuccessful", MessageBoxButtons.OK, MessageBoxIcon.Error); + //MessageBox.Show("Convertion was unsuccessful! Maybe not implemented...", "Convertion unsuccessful", MessageBoxButtons.OK, MessageBoxIcon.Error); } } @@ -1006,7 +1096,7 @@ namespace PrusaSL1Viewer if (!(item.Tag is LayerIsland island)) return; if (island.Owner.Index != ActualLayer) { - sbLayers.Value = (int)(SlicerFile.LayerCount - island.Owner.Index - 1); + ShowLayer(island.Owner.Index); //ShowLayer(island.Owner.Index); } @@ -1044,6 +1134,7 @@ namespace PrusaSL1Viewer Text = $"{FrmAbout.AssemblyTitle} Version: {FrmAbout.AssemblyVersion}"; SlicerFile?.Dispose(); SlicerFile = null; + ActualLayer = 0; // GUI CLEAN pbThumbnail.Image = null; @@ -1059,13 +1150,15 @@ namespace PrusaSL1Viewer lvIslands.EndUpdate(); UpdateIslandsInfo(); - lbLayers.Text = "Layers"; + lbMaxLayer.Text = + lbLayerActual.Text = + lbInitialLayer.Text = "???"; lvProperties.BeginUpdate(); lvProperties.Items.Clear(); lvProperties.Groups.Clear(); lvProperties.EndUpdate(); pbLayers.Value = 0; - sbLayers.Value = 0; + tbLayer.Value = 0; statusBar.Items.Clear(); menuFileConvert.DropDownItems.Clear(); @@ -1111,11 +1204,13 @@ namespace PrusaSL1Viewer menuFileClose.Enabled = menuFileExtract.Enabled = menuFileConvert.Enabled = - sbLayers.Enabled = + tbLayer.Enabled = pbLayers.Enabled = menuEdit.Enabled = menuMutate.Enabled = menuTools.Enabled = + btnNextLayer.Enabled = + btnPreviousLayer.Enabled = false; @@ -1200,6 +1295,10 @@ namespace PrusaSL1Viewer ActualLayerImage = SlicerFile[0].Image; + lbMaxLayer.Text = $"{SlicerFile.TotalHeight}mm\n{SlicerFile.LayerCount}"; + lbInitialLayer.Text = $"{SlicerFile.LayerHeight}mm\n0"; + + tsLayerImageRotate.Checked = ActualLayerImage.Height > ActualLayerImage.Width; if (!ReferenceEquals(SlicerFile.ConvertToFormats, null)) @@ -1264,8 +1363,8 @@ namespace PrusaSL1Viewer menuFileReload.Enabled = menuFileClose.Enabled = menuFileExtract.Enabled = - - sbLayers.Enabled = + + tbLayer.Enabled = pbLayers.Enabled = menuEdit.Enabled = menuMutate.Enabled = @@ -1286,10 +1385,9 @@ namespace PrusaSL1Viewer tabControlLeft.SelectedIndex = 0; tsLayerResolution.Text = $"{{Width={SlicerFile.ResolutionX}, Height={SlicerFile.ResolutionY}}}"; - sbLayers.SmallChange = 1; - sbLayers.Minimum = 0; - sbLayers.Maximum = (int)SlicerFile.LayerCount - 1; - sbLayers.Value = sbLayers.Maximum; + tbLayer.Maximum = (int)SlicerFile.LayerCount - 1; + ShowLayer(); + RefreshInfo(); @@ -1307,47 +1405,57 @@ namespace PrusaSL1Viewer void RefreshInfo() { menuEdit.DropDownItems.Clear(); - foreach (var modifier in SlicerFile.PrintParameterModifiers) - { - ToolStripItem item = new ToolStripMenuItem - { - Text = $"{modifier.Name} ({SlicerFile.GetValueFromPrintParameterModifier(modifier)}{modifier.ValueUnit})", - Tag = modifier, - Image = Properties.Resources.Wrench_16x16, - }; - menuEdit.DropDownItems.Add(item); - item.Click += ItemClicked; + if (!ReferenceEquals(SlicerFile.PrintParameterModifiers, null)) + { + foreach (var modifier in SlicerFile.PrintParameterModifiers) + { + ToolStripItem item = new ToolStripMenuItem + { + Text = + $"{modifier.Name} ({SlicerFile.GetValueFromPrintParameterModifier(modifier)}{modifier.ValueUnit})", + Tag = modifier, + Image = Properties.Resources.Wrench_16x16, + }; + menuEdit.DropDownItems.Add(item); + + item.Click += EventClick; + } } lvProperties.BeginUpdate(); lvProperties.Items.Clear(); - foreach (object config in SlicerFile.Configs) + if (!ReferenceEquals(SlicerFile.Configs, null)) { - ListViewGroup group = new ListViewGroup(config.GetType().Name); - lvProperties.Groups.Add(group); - foreach (PropertyInfo propertyInfo in config.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) + foreach (object config in SlicerFile.Configs) { - ListViewItem item = new ListViewItem(propertyInfo.Name, group); - object obj = new object(); - var value = propertyInfo.GetValue(config); - if (!ReferenceEquals(value, null)) + ListViewGroup group = new ListViewGroup(config.GetType().Name); + lvProperties.Groups.Add(group); + foreach (PropertyInfo propertyInfo in config.GetType() + .GetProperties(BindingFlags.Public | BindingFlags.Instance)) { - if (value is IList list) + ListViewItem item = new ListViewItem(propertyInfo.Name, group); + object obj = new object(); + var value = propertyInfo.GetValue(config); + if (!ReferenceEquals(value, null)) { - item.SubItems.Add(list.Count.ToString()); - } - else - { - item.SubItems.Add(value.ToString()); - } - - } + if (value is IList list) + { + item.SubItems.Add(list.Count.ToString()); + } + else + { + item.SubItems.Add(value.ToString()); + } - lvProperties.Items.Add(item); + } + + lvProperties.Items.Add(item); + } } } + lvProperties.EndUpdate(); tsPropertiesLabelCount.Text = $"Properties: {lvProperties.Items.Count}"; @@ -1377,6 +1485,24 @@ namespace PrusaSL1Viewer ///
void ShowLayer() => ShowLayer(ActualLayer); + void ShowLayer(bool direction) + { + if (direction) + { + if (ActualLayer < SlicerFile.LayerCount - 1) + { + ShowLayer(ActualLayer + 1); + } + + return; + } + + if (ActualLayer > 0) + { + ShowLayer(ActualLayer - 1); + } + } + /// /// Shows a layer number /// @@ -1384,13 +1510,21 @@ namespace PrusaSL1Viewer void ShowLayer(uint layerNum) { if (ReferenceEquals(SlicerFile, null)) return; - int layerOnSlider = (int)(SlicerFile.LayerCount - layerNum - 1); - if (sbLayers.Value != layerOnSlider) + + //int layerOnSlider = (int)(SlicerFile.LayerCount - layerNum - 1); + if (tbLayer.Value != layerNum) { - sbLayers.Value = layerOnSlider; + tbLayer.Value = (int) layerNum; return; } + if (IsChagingLayer) return ; + IsChagingLayer = true; + + ActualLayer = layerNum; + btnNextLayer.Enabled = layerNum < SlicerFile.LayerCount - 1; + btnPreviousLayer.Enabled = layerNum > 0; + try { // OLD @@ -1402,6 +1536,7 @@ namespace PrusaSL1Viewer Stopwatch watch = Stopwatch.StartNew(); ActualLayerImage = SlicerFile[layerNum].Image; + //ActualLayerImage = image; var imageRgba = ActualLayerImage.CloneAs(); @@ -1409,13 +1544,22 @@ namespace PrusaSL1Viewer if (tsLayerImageLayerOutline.Checked) { Image grayscale = ActualLayerImage.ToEmguImage(); - grayscale = grayscale.Canny(100, 200, 3, true); + grayscale = grayscale.Canny(80, 40, 3, true); + /*grayscale = grayscale.Dilate(1).Erode(1); + + Gray gray = new Gray(255); + Mat external = new Mat(); + VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); + CvInvoke.FindContours(grayscale, contours, external, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple); + + for (int i = 0; i < contours.Size; i++) + { + grayscale.FillConvexPoly(contours[i].ToArray(), gray, LineType.FourConnected); + } + */ + imageRgba = grayscale.ToImageSharpL8().CloneAs(); grayscale.Dispose(); - /*imageRgba.Mutate(imgMaskIn => - { - imgMaskIn.DetectEdges(); - });*/ } else if (tsLayerImageLayerDifference.Checked) { @@ -1554,21 +1698,36 @@ namespace PrusaSL1Viewer watch.Stop(); tsLayerPreviewTime.Text = $"{watch.ElapsedMilliseconds}ms"; - lbLayers.Text = $"{SlicerFile.GetHeightFromLayer(layerNum)} / {SlicerFile.TotalHeight}mm\n{layerNum} / {SlicerFile.LayerCount-1}\n{percent}%"; - pbLayers.Value = percent; + //lbLayers.Text = $"{SlicerFile.GetHeightFromLayer(layerNum)} / {SlicerFile.TotalHeight}mm\n{layerNum} / {SlicerFile.LayerCount-1}\n{percent}%"; + lbLayerActual.Text = $"{SlicerFile.GetHeightFromLayer(ActualLayer)}mm\n{ActualLayer}\n{percent}%"; + lbLayerActual.Location = new Point(lbLayerActual.Location.X, + Math.Max(1, + Math.Min(tbLayer.Height- lbLayerActual.Height, + (int)(tbLayer.Height - tbLayer.Value * ((float)tbLayer.Height / tbLayer.Maximum)) - lbLayerActual.Height/2) + )); + + pbLayers.Value = percent; + lbLayerActual.Invalidate(); + lbLayerActual.Update(); + lbLayerActual.Refresh(); + pbLayer.Invalidate(); + pbLayer.Update(); + pbLayer.Refresh(); + //Application.DoEvents(); - } catch (Exception e) { Debug.WriteLine(e); } - + IsChagingLayer = false; } void AddStatusBarItem(string name, object item, string extraText = "") { + if (ReferenceEquals(item, null)) return; + //if (item.ToString().Equals(0)) return; if (statusBar.Items.Count > 0) statusBar.Items.Add(new ToolStripSeparator()); @@ -1733,12 +1892,10 @@ namespace PrusaSL1Viewer imageEgmu = imageEgmu.Dilate((int) iterations); break; case Mutation.Mutates.Opening: - imageEgmu = imageEgmu.Erode((int)iterations); - imageEgmu = imageEgmu.Dilate((int)iterations); + imageEgmu = imageEgmu.Erode((int)iterations).Dilate((int)iterations); break; case Mutation.Mutates.Closing: - imageEgmu = imageEgmu.Dilate((int)iterations); - imageEgmu = imageEgmu.Erode((int)iterations); + imageEgmu = imageEgmu.Dilate((int)iterations).Erode((int)iterations); break; case Mutation.Mutates.Gradient: imageEgmu = imageEgmu.MorphologyEx(MorphOp.Gradient, Program.KernelStar3x3, new Point(-1, -1), (int) iterations, @@ -1889,7 +2046,5 @@ namespace PrusaSL1Viewer UpdateIslandsInfo(); } - - } } diff --git a/PrusaSL1Viewer/FrmMain.resx b/PrusaSL1Viewer/FrmMain.resx index cae7af6..30ef5f8 100644 --- a/PrusaSL1Viewer/FrmMain.resx +++ b/PrusaSL1Viewer/FrmMain.resx @@ -146,61 +146,61 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAD2 - DQAAAk1TRnQBSQFMAgEBBAEAAZgBAgGYAQIBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + DQAAAk1TRnQBSQFMAgEBBAEAAUgBAwFIAQMBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AZgADUAGjA1IBqQNS AakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1ABo1wAAxYBHgMjATMDIwEz AyMBMwMjATMDGAEhAwIBAwwAA1UBtANZAccDLwFJAwABAQMbASYDHAEnAxwBJwMcAScDHAEnAxwBJwMc AScDHAEnAxwBJwMcAScDHAEnAwIBAwQAA1IBqTAAA1IBqRAAAycBOgMwAUwDMAFMAzABTAMwAUwDMAFM - AzABTAMwAUwDMAFMAycBOhwAAwQBBgMjATMDUgGpAbMBTgEUAf8BsgFNARIB/wGyAUwBEgH/AbMBTQET + AzABTAMwAUwDMAFMAycBOhwAAwQBBgMjATMDUgGpAbMBOAEAAf8BsgE3AQAB/wGyATYBAAH/AbMBNwEA Af8CWAFWAbkDKQE/AwQBBgsAAf8DAAH/A0MBdwMpAT4DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ AwAB/wMAAf8DAAH/AwAB/wMyAVEEAANSAakEAANQAZ0DUwGqA1MBqgNTAaoDUwGqA1MBqgNTAaoDUAGd DAADUgGpEAADTgH7AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DTgH7GAADBQEHAzABTAGz - AU0BEwH/AdkBswGMAf8B9QHfAcUB/wH+Ae4B2AH/Af4B7gHYAf8B+gHnAc8B/wHZAbMBjAH/AbMBTQES + ATcBAAH/AdkBswGMAf8B9QHfAcUB/wH+Ae4B2AH/Af4B7gHYAf8B+gHnAc8B/wHZAbMBjAH/AbMBNwEA Af8CMQEwAU0DAgEDBAADUQGiA1YBtgMqAUAEAAMQARUDEQEXAxEBFwMRARcDEQEXAxEBFwMRARcDEQEX AxEBFwMRARcDEAEWCAADUgGpBAADUAGdA1MBqgNTAaoDHwEsHAADUgGpEwAB/wMAAf8DAAH/AwAB/wMA - Af8DAAH/AwAB/wMAAf8DAAH/AwAB/xgAAjEBMAFNAbcBgQEcAf8B6gHNAawB/wH6AeUBywH/AfgB4QHG - Af8B9gHgAcQB/wH2Ad8BxAH/AfcB4QHFAf8B+gHlAcsB/wHvAdUBtwH/AbMBTQETAf8DIAEuBAADCgEO + Af8DAAH/AwAB/wMAAf8DAAH/AwAB/xgAAjEBMAFNAbcBgQEGAf8B6gHNAawB/wH6AeUBywH/AfgB4QHG + Af8B9gHgAcQB/wH2Ad8BxAH/AfcB4QHFAf8B+gHlAcsB/wHvAdUBtwH/AbMBNwEAAf8DIAEuBAADCgEO AxEBFwMAAQE4AANSAakwAANSAakTAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ GAACagFEAfkB5QHHAaQB/wH3Ad8BwgH/AfMB2wG7Af8B8wHaAbsB/wHzAdsBvAH/AfMB2wG8Af8B8wHb AbwB/wHzAdwBvQH/AfYB4QHDAf8B1QGvAYQB/wJYAVYBuQQAA1IB9AMAAf8DPgFsAw4BEwNCAXYDQwF3 A0MBdwNDAXcDQwF3A0MBdwNDAXcDQwF3A0MBdwNDAXcDQgF2AxQBGwQAA1IBqQMiATIDUgGpA1IBqQNS AakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpAyIBMgNSAakTAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8DAAH/AwAB/wMAAf8DAAH/GAABtAFPARUC/wHwAdwC/wHvAdwB/wH+AesB1wH/AfkB5AHKAf8B8QHW - AbQB/wHxAdYBswH/AfEB1gG0Af8B8QHWAbQB/wHyAdgBtgH/AfMB2QG3Af8BswFPARUB/wcAAf4DAAH/ + Af8DAAH/AwAB/wMAAf8DAAH/GAABtAE5AQAC/wHwAdwC/wHvAdwB/wH+AesB1wH/AfkB5AHKAf8B8QHW + AbQB/wHxAdYBswH/AfEB1gG0Af8B8QHWAbQB/wHyAdgBtgH/AfMB2QG3Af8BswE5AQAB/wcAAf4DAAH/ A0MBdwMeASsDVwHFA1kBxwNZAccDWQHHA1kBxwNZAccDWQHHA1kBxwNZAccDWQHHA1gBxgMmATkEAANS AakDNAFVAzQBVSAAAzQBVQM0AVUDUgGpEwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ - AwAB/xgAA0gBhQG4AYIBHAH/AccBlwE4Af8BzwGlAUoB/wHtAdIBtAH/Af0B6AHSAf8B7wHSAa0B/wHu - AdIBrAH/Ae4B0gGtAf8B7gHSAa0B/wH1AdwBvAH/AbMBTQEUAf8EAAMzAVMDPAFnAxQBHDgAA1IBqQM0 + AwAB/xgAA0gBhQG4AYIBBgH/AccBlwEiAf8BzwGlATQB/wHtAdIBtAH/Af0B6AHSAf8B7wHSAa0B/wHu + AdIBrAH/Ae4B0gGtAf8B7gHSAa0B/wH1AdwBvAH/AbMBNwEAAf8EAAMzAVMDPAFnAxQBHDgAA1IBqQM0 AVUDNAFVA0YBgANSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNFAX8DNAFVAzQBVQNSAakTAAH/AwAB/wMA Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/EAADCgEOAyEBMQMjATMDIwEzAjEBMAFNAzMBUwGz - AUwBDwH/AeMBxQGiAf8B+QHjAckB/wHrAc4BpAH/AesBzgGmAf8B6wHOAaUB/wH3Ad8BwAH/AbMBTQET + ATYBAAH/AeMBxQGiAf8B+QHjAckB/wHrAc4BpAH/AesBzgGmAf8B6wHOAaUB/wH3Ad8BwAH/AbMBNwEA Af8EAAMzAVMDPAFnAxQBHDgAA1IBqQM0AVUDNAFVAz8BbgMyAVAQAAMnATsDRAF8AzQBVQM0AVUDUgGp EwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wwAAwoBDgM/AW0DXAH4AYUBiQGN - Af8BTwFSAYQB/wNfAfMDOgFiAwkBDAGzAUwBDwH/Ae0B0QG0Af8B6QHJAZ0B/wHpAckBnQH/AekByAGb - Af8B/AHoAdIB/wGzAU4BFAH/BwAB/gMAAf8DQwF3Ax8BLANXAcUDWQHHA1kBxwNZAccDWQHHA1kBxwNZ + Af8BOQE8AYQB/wNfAfMDOgFiAwkBDAGzATYBAAH/Ae0B0QG0Af8B6QHJAZ0B/wHpAckBnQH/AekByAGb + Af8B/AHoAdIB/wGzATgBAAH/BwAB/gMAAf8DQwF3Ax8BLANXAcUDWQHHA1kBxwNZAccDWQHHA1kBxwNZ AccDWQHHA1kBxwNZAccDWAHGAyYBOQQAA1IBqQM0AVUDNAFVAwUBBwNVAbUDEQEXA1IBqQMpAT4EAANQ AZ8DEQEXAzQBVQM0AVUDUgGpEwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wwA - Az4BawOAAf8C0gHRAf8B7wHuAe0B/wLvAe4B/wHSAdMB0gH/AVEBgAGBAf8DOgFgAzIBUAHQAacBTwH/ + Az4BawOAAf8C0gHRAf8B7wHuAe0B/wLvAe4B/wHSAdMB0gH/ATsBgAGBAf8DOgFgAzIBUAHQAacBOQH/ AeoByQGcAf8B5AHDAZIB/wHyAdcBtQH/AdoBtgGQAf8CUwFSAagEAANSAfQDAAH/Az4BbAMOARMDQgF1 A0MBdwNDAXcDQwF3A0MBdwNDAXcDQwF3A0MBdwNDAXcDQwF3A0MBdwMUARsEAANSAakDNAFVAzQBVQQA AzwBaANWAb4DIwE0A1UBtQMSARkDUQGgBAADNAFVAzQBVQNSAakTAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8DAAH/AwUB/wMFAf8DXAHfDAADXAH4As0BzAH/AeMB4gHhAf8B3wHeAd0B/wHfAd4B3QH/AeMB4gHh - Af8DzAH/A2cB8gMZASMByAGYATsB/wHzAdoBtwH/AfEB1gGyAf8B/gHtAdkB/wG3AYEBGwH/AwoBDQQA + Af8DAAH/AwAB/wMAAf8DXAHfDAADXAH4As0BzAH/AeMB4gHhAf8B3wHeAd0B/wHfAd4B3QH/AeMB4gHh + Af8DzAH/A2cB8gMZASMByAGYASUB/wHzAdoBtwH/AfEB1gGyAf8B/gHtAdkB/wG3AYEBBQH/AwoBDQQA AwoBDgMRARcDAAEBOAADUgGpAzQBVQM0AVUDAAEBAy0BRgMKAQ4EAAM5AV8DXAHOAygBPAQAAzQBVQM0 - AVUDUgGpEwAB/wOCAf8DGwH/AwUB/wMAAf8DAAH/Aw8B/wMWAf8DXAHfAxcBIAwAA0wB/wHjAeIB4QH/ - AdcB1gHUAf8B1wHWAdQB/wHXAdYB1AH/AdcB1gHUAf8B4gHhAeAB/wGDAYgBjQH/BAABtwGAARgC/wHw - AdwB/wH6AeYBzgH/AcEBkAEvAf8DQAFuCAADUQGiA1YBtgMqAUAEAAMQARUDEQEXAxEBFwMRARcDEQEX + AVUDUgGpEwAB/wOCAf8DBQH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DXAHfAxcBIAwAAzYB/wHjAeIB4QH/ + AdcB1gHUAf8B1wHWAdQB/wHXAdYB1AH/AdcB1gHUAf8B4gHhAeAB/wGDAYgBjQH/BAABtwGAAQIC/wHw + AdwB/wH6AeYBzgH/AcEBkAEZAf8DQAFuCAADUQGiA1YBtgMqAUAEAAMQARUDEQEXAxEBFwMRARcDEQEX AxEBFwMRARcDEQEXAxEBFwMRARcDEAEWCAADUgGpAzQBVQM0AVUDMwFTA1IBpgNKAYwHAAEBA0cBgwgA - AzQBVQM0AVUDUgGpEwAB/wOZAf8DhQH/AygB/wMAAf8DAAH/Aw8B/wNcAd8DFwEgEAADTAH/AfIB8QHw - Af8BzwHNAcsB/wHQAc4BywH/AdABzgHLAf8BzwHNAcsB/wHyAvAB/wFQAYEBhQH/BAADNwFbAbQBTwEV - Af8BtAFPARQB/wNAAW8PAAH/AwAB/wNDAXcDKQE+AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA + AzQBVQM0AVUDUgGpEwAB/wOZAf8DhQH/AxIB/wMAAf8DAAH/AwAB/wNcAd8DFwEgEAADNgH/AfIB8QHw + Af8BzwHNAcsB/wHQAc4BywH/AdABzgHLAf8BzwHNAcsB/wHyAvAB/wE6AYEBhQH/BAADNwFbAbQBOQEA + Af8BtAE5AQAB/wNAAW8PAAH/AwAB/wNDAXcDKQE+AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA Af8DAAH/AwAB/wMAAf8DMgFRBAADUgGpAzQBVQM0AVUDEQEXA1ABngMkATYUAAM0AVUDNAFVA1IBqRAA - A1AB+wMHAf8DBwH/AwcB/wMAAf8DAAH/A1wB3wMXASAUAANiAfYB2wLaAf8B6AHnAeYB/wHRAc8BzgH/ + A1AB+wMAAf8DAAH/AwAB/wMAAf8DAAH/A1wB3wMXASAUAANiAfYB2wLaAf8B6AHnAeYB/wHRAc8BzgH/ AdEBzwHOAf8B6AHnAeYB/wHbAtoB/wNiAfYgAANVAbQDWQHHAy8BSQMAAQEDGwEmAxwBJwMcAScDHAEn AxwBJwMcAScDHAEnAxwBJwMcAScDHAEnAxwBJwMCAQMEAANSAakDIgEyA1IBqQNSAakDUgGpA1IBqQNS AakDUgGpA1IBqQNSAakDUgGpA1IBqQMiATIDUgGpEAADIAEuAykBPwMpAT8DKQE/AykBPwMpAT8DEQEX GAADLgFIA4AB/wHYAtcB/wH3AvYB/wH3AvYB/wHYAtcB/wOAAf8DLgFIZAADUAGjA1IBqQNSAakDUgGp - A1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1ABo0gAAy4BSANiAfYDSwH/A0sB/wNi + A1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1ABo0gAAy4BSANiAfYDNQH/AzUB/wNi AfYDLgFIJAABQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEBFgAD/4EAAv8BgAEBAv8B/AEH AgABvwH9AeABBwHwAQMCAAGgAR0B4AEHAeABAQEQAQEBoQH9AeABBwHgAQEBHwH/Ab8B/QHgAQcB4AEB AgABgAEBAeABBwHgAQECAAGPAfEB4AEHAeABAQEfAf8BgAEBAeABBwGAAQEBHwH/AYMBwQHgAQcBAAEB diff --git a/PrusaSL1Viewer/ImageSharpExtensions.cs b/PrusaSL1Viewer/ImageSharpExtensions.cs index a15d286..6a67601 100644 --- a/PrusaSL1Viewer/ImageSharpExtensions.cs +++ b/PrusaSL1Viewer/ImageSharpExtensions.cs @@ -24,7 +24,7 @@ namespace PrusaSL1Viewer Helpers.BmpEncoder.SupportTransparency = true; image.Save(memoryStream, Helpers.BmpEncoder); - //memoryStream.Seek(0, SeekOrigin.Begin); + memoryStream.Seek(0, SeekOrigin.Begin); return new System.Drawing.Bitmap(memoryStream); } diff --git a/PrusaSL1Viewer/Images/Screenshots/PrusaSL1Viewer_GUI.png b/PrusaSL1Viewer/Images/Screenshots/PrusaSL1Viewer_GUI.png index 5e50c21..d417773 100644 Binary files a/PrusaSL1Viewer/Images/Screenshots/PrusaSL1Viewer_GUI.png and b/PrusaSL1Viewer/Images/Screenshots/PrusaSL1Viewer_GUI.png differ diff --git a/PrusaSL1Viewer/Images/Screenshots/PrusaSL1Viewer_GUI_Islands.png b/PrusaSL1Viewer/Images/Screenshots/PrusaSL1Viewer_GUI_Islands.png new file mode 100644 index 0000000..305a643 Binary files /dev/null and b/PrusaSL1Viewer/Images/Screenshots/PrusaSL1Viewer_GUI_Islands.png differ diff --git a/PrusaSL1Viewer/Images/arrow-down-16x16.png b/PrusaSL1Viewer/Images/arrow-down-16x16.png new file mode 100644 index 0000000..9ce51bb Binary files /dev/null and b/PrusaSL1Viewer/Images/arrow-down-16x16.png differ diff --git a/PrusaSL1Viewer/Images/arrow-down.ico b/PrusaSL1Viewer/Images/arrow-down.ico new file mode 100644 index 0000000..ff5240c Binary files /dev/null and b/PrusaSL1Viewer/Images/arrow-down.ico differ diff --git a/PrusaSL1Viewer/Images/arrow-up-16x16.png b/PrusaSL1Viewer/Images/arrow-up-16x16.png new file mode 100644 index 0000000..585744a Binary files /dev/null and b/PrusaSL1Viewer/Images/arrow-up-16x16.png differ diff --git a/PrusaSL1Viewer/Images/arrow-up.ico b/PrusaSL1Viewer/Images/arrow-up.ico new file mode 100644 index 0000000..19ee15f Binary files /dev/null and b/PrusaSL1Viewer/Images/arrow-up.ico differ diff --git a/PrusaSL1Viewer/Images/plus.ico b/PrusaSL1Viewer/Images/plus.ico new file mode 100644 index 0000000..2bfd834 Binary files /dev/null and b/PrusaSL1Viewer/Images/plus.ico differ diff --git a/PrusaSL1Viewer/Properties/AssemblyInfo.cs b/PrusaSL1Viewer/Properties/AssemblyInfo.cs index 6e58985..3062482 100644 --- a/PrusaSL1Viewer/Properties/AssemblyInfo.cs +++ b/PrusaSL1Viewer/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.4.2.2")] -[assembly: AssemblyFileVersion("0.4.2.2")] +[assembly: AssemblyVersion("0.4.3.0")] +[assembly: AssemblyFileVersion("0.4.3.0")] diff --git a/PrusaSL1Viewer/Properties/Resources.Designer.cs b/PrusaSL1Viewer/Properties/Resources.Designer.cs index f465407..3adcdb1 100644 --- a/PrusaSL1Viewer/Properties/Resources.Designer.cs +++ b/PrusaSL1Viewer/Properties/Resources.Designer.cs @@ -60,6 +60,46 @@ namespace PrusaSL1Viewer.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap arrow_down { + get { + object obj = ResourceManager.GetObject("arrow-down", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap arrow_down_16x16 { + get { + object obj = ResourceManager.GetObject("arrow-down-16x16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap arrow_up { + get { + object obj = ResourceManager.GetObject("arrow-up", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap arrow_up_16x16 { + get { + object obj = ResourceManager.GetObject("arrow-up-16x16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -370,6 +410,16 @@ namespace PrusaSL1Viewer.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap plus { + get { + object obj = ResourceManager.GetObject("plus", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/PrusaSL1Viewer/Properties/Resources.resx b/PrusaSL1Viewer/Properties/Resources.resx index 79c59b0..de52dd1 100644 --- a/PrusaSL1Viewer/Properties/Resources.resx +++ b/PrusaSL1Viewer/Properties/Resources.resx @@ -121,12 +121,12 @@ ..\Images\Error-128x128.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\Cancel-24x24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\layers-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Images\gui\mutation_closing.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Images\eye-24x24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -154,6 +154,9 @@ ..\Images\refresh-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\arrow-up-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\Save-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -163,6 +166,9 @@ ..\PrusaSL1Viewer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\arrow-up.ico;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\Ok-24x24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -181,6 +187,9 @@ ..\Images\Open-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\pointer-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\File-Close-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -193,8 +202,8 @@ ..\Images\gui\mutation_tophat.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Images\CNCMachine-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\plus.ico;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Images\Convert-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -214,20 +223,23 @@ ..\Images\SaveAs-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\CNCMachine-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\delete-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Images\pointer-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Images\gui\mutation_opening.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Images\gui\mutation_blackhat.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Images\Cancel-24x24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\gui\mutation_closing.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Images\arrow-down.ico;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Images\Donate-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -235,4 +247,7 @@ ..\Images\island-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\arrow-down-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/PrusaSL1Viewer/PrusaSL1Viewer.csproj b/PrusaSL1Viewer/PrusaSL1Viewer.csproj index c3479c0..ff5b2df 100644 --- a/PrusaSL1Viewer/PrusaSL1Viewer.csproj +++ b/PrusaSL1Viewer/PrusaSL1Viewer.csproj @@ -291,6 +291,11 @@ + + + + + diff --git a/PrusaSlicerFolderShortcut.lnk b/PrusaSlicerFolderShortcut.lnk new file mode 100644 index 0000000..b75a007 Binary files /dev/null and b/PrusaSlicerFolderShortcut.lnk differ