mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-08 17:42:31 +02:00
Allow open known filetypes + More abstraction
This commit is contained in:
@@ -10,7 +10,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using BinarySerialization;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Advanced;
|
||||
@@ -202,13 +201,33 @@ namespace PrusaSL1Reader
|
||||
|
||||
#region Overrides
|
||||
|
||||
public override string FileFullPath { get; protected set; }
|
||||
public override string FileFullPath { get; set; }
|
||||
|
||||
public override FileExtension[] ValidFiles { get; } = {
|
||||
new FileExtension("cbddlp", "Chitubox DLP Files"),
|
||||
new FileExtension("photon", "Photon Files"),
|
||||
};
|
||||
|
||||
public override uint ResolutionX => HeaderSettings.ResolutionX;
|
||||
|
||||
public override uint ResolutionY => HeaderSettings.ResolutionY;
|
||||
|
||||
|
||||
public override byte ThumbnailsCount { get; } = 2;
|
||||
public override Image<Rgba32>[] Thumbnails { get; protected internal set; }
|
||||
public override Image<Rgba32>[] Thumbnails { get; set; }
|
||||
public override uint LayerCount => HeaderSettings.LayerCount;
|
||||
public override float InitialExposureTime => HeaderSettings.BottomExposureSeconds;
|
||||
public override float LayerExposureTime => HeaderSettings.LayerExposureSeconds;
|
||||
public override float PrintTime => HeaderSettings.PrintTime;
|
||||
public override float UsedMaterial => PrintParametersSettings.VolumeMl;
|
||||
|
||||
public override float MaterialCost => PrintParametersSettings.CostDollars;
|
||||
|
||||
public override string MaterialName => "Unknown";
|
||||
public override string MachineName => MachineInfoSettings.MachineName;
|
||||
public override float LayerHeight => HeaderSettings.LayerHeightMilimeter;
|
||||
|
||||
public override object[] Configs => new[] { (object)HeaderSettings, PrintParametersSettings, MachineInfoSettings };
|
||||
|
||||
public override void BeginEncode(string fileFullPath)
|
||||
{
|
||||
@@ -224,7 +243,6 @@ namespace PrusaSL1Reader
|
||||
|
||||
OutputFile.Seek((int)CurrentOffset, SeekOrigin.Begin);
|
||||
|
||||
|
||||
/*for (int i = 0; i < ThumbnailsCount; i++)
|
||||
{
|
||||
if (i == 1)
|
||||
@@ -299,7 +317,7 @@ namespace PrusaSL1Reader
|
||||
Helpers.SerializeWriteFileStream(OutputFile, preview);
|
||||
CurrentOffset += Helpers.SerializeWriteFileStream(OutputFile, rawData.ToArray());
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
if (HeaderSettings.Version == 2)
|
||||
{
|
||||
@@ -392,7 +410,7 @@ namespace PrusaSL1Reader
|
||||
|
||||
public override void Decode(string fileFullPath)
|
||||
{
|
||||
DecodeInternal(fileFullPath);
|
||||
base.Decode(fileFullPath);
|
||||
|
||||
InputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
@@ -503,6 +521,11 @@ namespace PrusaSL1Reader
|
||||
}
|
||||
}
|
||||
|
||||
public override void Extract(string path, bool emptyFirst = true)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Image<Gray8> GetLayerImage(uint layerIndex)
|
||||
{
|
||||
if (layerIndex >= HeaderSettings.LayerCount)
|
||||
@@ -569,7 +592,7 @@ namespace PrusaSL1Reader
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
ClearInternal();
|
||||
base.Clear();
|
||||
|
||||
for (byte i = 0; i < ThumbnailsCount; i++)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
@@ -18,16 +19,39 @@ namespace PrusaSL1Reader
|
||||
/// </summary>
|
||||
public abstract class FileFormat : IFileFormat, IDisposable
|
||||
{
|
||||
public static FileFormat[] AvaliableFormats { get; } =
|
||||
{
|
||||
new SL1File(),
|
||||
new CbddlpFile(),
|
||||
};
|
||||
|
||||
public static string AllFileFilters => AvaliableFormats.Aggregate(string.Empty, (current, fileFormat) => string.IsNullOrEmpty(current) ? fileFormat.GetFileFilter() : $"{current}|" + fileFormat.GetFileFilter());
|
||||
|
||||
/// <summary>
|
||||
/// Find <see cref="FileFormat"/> by an extension
|
||||
/// </summary>
|
||||
/// <param name="extension">Extension name to find</param>
|
||||
/// <param name="isFilePath">True if <see cref="extension"/> is a file path rather than only a extension name</param>
|
||||
/// <param name="createNewInstance">True to create a new instance of found file format, otherwise will return a pre created one which should be used for read-only purpose</param>
|
||||
/// <returns><see cref="FileFormat"/> object or null if not found</returns>
|
||||
public static FileFormat FindByExtension(string extension, bool isFilePath = false, bool createNewInstance = false)
|
||||
{
|
||||
return (from fileFormat in AvaliableFormats where fileFormat.IsExtensionValid(extension, isFilePath) select createNewInstance ? (FileFormat) Activator.CreateInstance(fileFormat.GetType()) : fileFormat).FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the input file path loaded into this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
public abstract string FileFullPath { get; protected set; }
|
||||
public abstract string FileFullPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the valid file extensions for this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
public abstract FileExtension[] ValidFiles { get; }
|
||||
|
||||
public abstract uint ResolutionX { get; }
|
||||
public abstract uint ResolutionY { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the thumbnails count present in this file format
|
||||
/// </summary>
|
||||
@@ -36,17 +60,31 @@ namespace PrusaSL1Reader
|
||||
/// <summary>
|
||||
/// Gets the thumbnails for this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
public abstract Image<Rgba32>[] Thumbnails { get; protected internal set; }
|
||||
public abstract Image<Rgba32>[] Thumbnails { get; set; }
|
||||
|
||||
public abstract uint LayerCount { get; }
|
||||
|
||||
public abstract float InitialExposureTime { get; }
|
||||
|
||||
public abstract float LayerExposureTime { get; }
|
||||
public abstract float PrintTime { get; }
|
||||
public abstract float UsedMaterial { get; }
|
||||
|
||||
public abstract float MaterialCost { get; }
|
||||
|
||||
public abstract string MaterialName { get; }
|
||||
public abstract string MachineName { get; }
|
||||
public abstract float LayerHeight { get; }
|
||||
public float TotalHeight => (float)Math.Round(LayerCount * LayerHeight, 2);
|
||||
|
||||
protected FileFormat()
|
||||
{
|
||||
Thumbnails = new Image<Rgba32>[ThumbnailsCount];
|
||||
}
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
return !ReferenceEquals(FileFullPath, null);
|
||||
}
|
||||
public abstract object[] Configs { get; }
|
||||
public bool IsValid => !ReferenceEquals(FileFullPath, null);
|
||||
|
||||
|
||||
public abstract void BeginEncode(string fileFullPath);
|
||||
|
||||
@@ -54,20 +92,38 @@ namespace PrusaSL1Reader
|
||||
|
||||
public abstract void EndEncode();
|
||||
|
||||
public abstract void Decode(string fileFullPath);
|
||||
public abstract Image<Gray8> GetLayerImage(uint layerIndex);
|
||||
|
||||
protected void DecodeInternal(string fileFullPath)
|
||||
public virtual void Decode(string fileFullPath)
|
||||
{
|
||||
Clear();
|
||||
FileValidation(fileFullPath);
|
||||
FileFullPath = fileFullPath;
|
||||
}
|
||||
|
||||
public virtual void Extract(string path, bool emptyFirst = true)
|
||||
{
|
||||
if (emptyFirst)
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
DirectoryInfo di = new DirectoryInfo(path);
|
||||
|
||||
foreach (FileInfo file in di.GetFiles())
|
||||
{
|
||||
file.Delete();
|
||||
}
|
||||
foreach (DirectoryInfo dir in di.GetDirectories())
|
||||
{
|
||||
dir.Delete(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Image<Gray8> GetLayerImage(uint layerIndex);
|
||||
|
||||
public abstract float GetHeightFromLayer(uint layerNum);
|
||||
|
||||
public abstract void Clear();
|
||||
|
||||
protected void ClearInternal()
|
||||
public virtual void Clear()
|
||||
{
|
||||
FileFullPath = null;
|
||||
if (!ReferenceEquals(Thumbnails, null))
|
||||
@@ -78,7 +134,12 @@ namespace PrusaSL1Reader
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract bool Convert(Type to, string fileFullPath);
|
||||
public bool Convert(FileFormat to, string fileFullPath)
|
||||
{
|
||||
return Convert(to.GetType(), fileFullPath);
|
||||
}
|
||||
|
||||
public void FileValidation(string fileFullPath)
|
||||
{
|
||||
@@ -101,7 +162,7 @@ namespace PrusaSL1Reader
|
||||
|
||||
public string GetFileFilter()
|
||||
{
|
||||
string result = String.Empty;
|
||||
string result = string.Empty;
|
||||
|
||||
foreach (var fileExt in ValidFiles)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
@@ -17,10 +18,6 @@ namespace PrusaSL1Reader
|
||||
{
|
||||
public static class Helpers
|
||||
{
|
||||
public static Type[] AvaliableFileFormats { get; } = {
|
||||
typeof(SL1File),
|
||||
typeof(CbddlpFile)
|
||||
};
|
||||
public static BinarySerializer Serializer { get; } = new BinarySerializer {Endianness = Endianness.Little };
|
||||
public static Gray8 Gray8White { get; } = new Gray8(255);
|
||||
public static T ByteToType<T>(BinaryReader reader)
|
||||
|
||||
@@ -19,10 +19,58 @@ namespace PrusaSL1Reader
|
||||
public interface IFileFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Check if this file is valid to read
|
||||
/// Gets the input file path loaded into this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool IsValid();
|
||||
string FileFullPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the valid file extensions for this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
FileExtension[] ValidFiles { get; }
|
||||
|
||||
uint ResolutionX { get; }
|
||||
uint ResolutionY { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the thumbnails count present in this file format
|
||||
/// </summary>
|
||||
byte ThumbnailsCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the thumbnails for this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
Image<Rgba32>[] Thumbnails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of layers present in this file
|
||||
/// </summary>
|
||||
uint LayerCount { get; }
|
||||
float InitialExposureTime { get; }
|
||||
float LayerExposureTime { get; }
|
||||
float PrintTime { get; }
|
||||
float UsedMaterial { get; }
|
||||
float MaterialCost { get; }
|
||||
string MaterialName { get; }
|
||||
string MachineName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Layer Height in mm
|
||||
/// </summary>
|
||||
float LayerHeight { get; }
|
||||
|
||||
float TotalHeight { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get all configuration objects with properties and values
|
||||
/// </summary>
|
||||
object[] Configs { get; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If this file is valid to read
|
||||
/// </summary>
|
||||
bool IsValid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Begin encode to an output file
|
||||
@@ -48,6 +96,13 @@ namespace PrusaSL1Reader
|
||||
/// <param name="fileFullPath"></param>
|
||||
void Decode(string fileFullPath);
|
||||
|
||||
/// <summary>
|
||||
/// Extract contents to a folder
|
||||
/// </summary>
|
||||
/// <param name="path">Path to folder where content will be extracted</param>
|
||||
/// <param name="emptyFirst">Empty target folder first</param>
|
||||
void Extract(string path, bool emptyFirst = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a image from layer
|
||||
/// </summary>
|
||||
@@ -70,9 +125,17 @@ namespace PrusaSL1Reader
|
||||
/// <summary>
|
||||
/// Converts this file type to another file type
|
||||
/// </summary>
|
||||
/// <param name="to">Target type</param>
|
||||
/// <param name="to">Target file format</param>
|
||||
/// <param name="fileFullPath">Output path file</param>
|
||||
/// <returns>True if convert succeed, otherwise false</returns>
|
||||
bool Convert(Type to, string fileFullPath);
|
||||
|
||||
/// <summary>
|
||||
/// Converts this file type to another file type
|
||||
/// </summary>
|
||||
/// <param name="to">Target file format</param>
|
||||
/// <param name="fileFullPath">Output path file</param>
|
||||
/// <returns>True if convert succeed, otherwise false</returns>
|
||||
bool Convert(FileFormat to, string fileFullPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
namespace PrusaSL1Reader
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a line, only white pixels
|
||||
/// </summary>
|
||||
public class LayerLine
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the x start position
|
||||
/// </summary>
|
||||
public uint X { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the x end position
|
||||
/// </summary>
|
||||
public uint X2 => X + Length;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the y position
|
||||
/// </summary>
|
||||
public uint Y { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of pixels to fill
|
||||
/// </summary>
|
||||
public uint Length { get; }
|
||||
|
||||
public LayerLine(uint x, uint y, uint length)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Length = length;
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
-30
@@ -263,30 +263,48 @@ namespace PrusaSL1Reader
|
||||
public Material MaterialSettings { get; private set; }
|
||||
|
||||
public Print PrintSettings { get; private set; }
|
||||
|
||||
public OutputConfig OutputConfigSettings { get; private set; }
|
||||
|
||||
public Statistics Statistics { get; } = new Statistics();
|
||||
|
||||
public override byte ThumbnailsCount { get; } = 2;
|
||||
|
||||
public override Image<Rgba32>[] Thumbnails { get; protected internal set; }
|
||||
|
||||
//public List<ZipArchiveEntry> Thumbnails { get; } = new List<ZipArchiveEntry>(2);
|
||||
public List<ZipArchiveEntry> LayerImages { get; } = new List<ZipArchiveEntry>();
|
||||
|
||||
public uint GetLayerCount => (uint)LayerImages.Count;
|
||||
|
||||
public double TotalHeight => Math.Round(MaterialSettings.InitialLayerHeight + (LayerImages.Count - 1) * OutputConfigSettings.LayerHeight, 2);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
|
||||
public override string FileFullPath { get; protected set; }
|
||||
public override string FileFullPath { get; set; }
|
||||
|
||||
public override uint ResolutionY => PrinterSettings.DisplayPixelsY;
|
||||
|
||||
public override byte ThumbnailsCount { get; } = 2;
|
||||
public override Image<Rgba32>[] Thumbnails { get; set; }
|
||||
public override uint LayerCount => (uint)LayerImages.Count;
|
||||
|
||||
public override float InitialExposureTime => OutputConfigSettings.ExpTimeFirst;
|
||||
|
||||
public override float LayerExposureTime => OutputConfigSettings.ExpTime;
|
||||
|
||||
public override float PrintTime => OutputConfigSettings.PrintTime;
|
||||
|
||||
public override float UsedMaterial => OutputConfigSettings.UsedMaterial;
|
||||
|
||||
public override float MaterialCost => OutputConfigSettings.UsedMaterial * MaterialSettings.BottleCost / MaterialSettings.BottleVolume;
|
||||
|
||||
public override string MaterialName => OutputConfigSettings.MaterialName;
|
||||
|
||||
public override string MachineName => PrinterSettings.PrinterSettingsId;
|
||||
|
||||
public override float LayerHeight => OutputConfigSettings.LayerHeight;
|
||||
public override object[] Configs => new object[] { PrinterSettings, MaterialSettings, PrintSettings, OutputConfigSettings };
|
||||
|
||||
public override FileExtension[] ValidFiles { get; } = {
|
||||
new FileExtension("sl1", "Prusa SL1 Files")
|
||||
};
|
||||
|
||||
public override uint ResolutionX => PrinterSettings.DisplayPixelsX;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as SL1File);
|
||||
@@ -306,7 +324,7 @@ namespace PrusaSL1Reader
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(FileFullPath)}: {FileFullPath}, {nameof(MaterialSettings)}: {MaterialSettings}, {nameof(PrintSettings)}: {PrintSettings}, {nameof(OutputConfigSettings)}: {OutputConfigSettings}, {nameof(Statistics)}: {Statistics}, {nameof(GetLayerCount)}: {GetLayerCount}, {nameof(TotalHeight)}: {TotalHeight}";
|
||||
return $"{nameof(FileFullPath)}: {FileFullPath}, {nameof(MaterialSettings)}: {MaterialSettings}, {nameof(PrintSettings)}: {PrintSettings}, {nameof(OutputConfigSettings)}: {OutputConfigSettings}, {nameof(Statistics)}: {Statistics}, {nameof(LayerCount)}: {LayerCount}, {nameof(TotalHeight)}: {TotalHeight}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -321,10 +339,6 @@ namespace PrusaSL1Reader
|
||||
|
||||
#region Methods
|
||||
|
||||
|
||||
|
||||
private List<Image<Gray8>> images = new List<Image<Gray8>>();
|
||||
|
||||
public override void BeginEncode(string fileFullPath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@@ -342,7 +356,7 @@ namespace PrusaSL1Reader
|
||||
|
||||
public override void Decode(string fileFullPath)
|
||||
{
|
||||
DecodeInternal(fileFullPath);
|
||||
base.Decode(fileFullPath);
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
@@ -353,12 +367,12 @@ namespace PrusaSL1Reader
|
||||
|
||||
Statistics.ExecutionTime.Restart();
|
||||
|
||||
var parseTypes = new[]
|
||||
var parseObjects = new object[]
|
||||
{
|
||||
new KeyValuePair<Type, object>(typeof(Printer), PrinterSettings),
|
||||
new KeyValuePair<Type, object>(typeof(Material), MaterialSettings),
|
||||
new KeyValuePair<Type, object>(typeof(Print), PrintSettings),
|
||||
new KeyValuePair<Type, object>(typeof(OutputConfig), OutputConfigSettings),
|
||||
PrinterSettings,
|
||||
MaterialSettings,
|
||||
PrintSettings,
|
||||
OutputConfigSettings,
|
||||
};
|
||||
|
||||
Archive = ZipFile.OpenRead(FileFullPath);
|
||||
@@ -380,11 +394,11 @@ namespace PrusaSL1Reader
|
||||
var fieldName = IniKeyToMemberName(keyValue[0]);
|
||||
bool foundMember = false;
|
||||
|
||||
foreach (var kv in parseTypes)
|
||||
foreach (var obj in parseObjects)
|
||||
{
|
||||
var attribute = kv.Key.GetProperty(fieldName);
|
||||
var attribute = obj.GetType().GetProperty(fieldName);
|
||||
if (attribute == null) continue;
|
||||
SetValue(attribute, kv.Value, keyValue[1]);
|
||||
SetValue(attribute, obj, keyValue[1]);
|
||||
Statistics.ImplementedKeys.Add(keyValue[0]);
|
||||
foundMember = true;
|
||||
}
|
||||
@@ -423,6 +437,12 @@ namespace PrusaSL1Reader
|
||||
Debug.WriteLine(Statistics);
|
||||
}
|
||||
|
||||
public override void Extract(string path, bool emptyFirst = true)
|
||||
{
|
||||
base.Extract(path, emptyFirst);
|
||||
Archive.ExtractToDirectory(path);
|
||||
}
|
||||
|
||||
public override Image<Gray8> GetLayerImage(uint layerIndex)
|
||||
{
|
||||
return Image.Load<Gray8>(LayerImages[(int)layerIndex].Open());
|
||||
@@ -435,7 +455,7 @@ namespace PrusaSL1Reader
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
ClearInternal();
|
||||
base.Clear();
|
||||
Archive?.Dispose();
|
||||
LayerImages.Clear();
|
||||
Statistics.Clear();
|
||||
@@ -443,7 +463,7 @@ namespace PrusaSL1Reader
|
||||
|
||||
public override bool Convert(Type to, string fileFullPath)
|
||||
{
|
||||
if (!IsValid()) return false;
|
||||
if (!IsValid) return false;
|
||||
|
||||
if (to == typeof(CbddlpFile))
|
||||
{
|
||||
@@ -459,7 +479,7 @@ namespace PrusaSL1Reader
|
||||
BottomExposureSeconds = MaterialSettings.InitialExposureTime,
|
||||
BottomLayersCount = PrintSettings.FadedLayers,
|
||||
BottomLightPWM = LookupCustomValue<ushort>("BottomLightPWM", 255), // TODO
|
||||
LayerCount = GetLayerCount,
|
||||
LayerCount = LayerCount,
|
||||
LayerExposureSeconds = MaterialSettings.ExposureTime,
|
||||
LayerHeightMilimeter = PrintSettings.LayerHeight,
|
||||
LayerOffTime = LookupCustomValue<float>("LayerOffTime", 0), // TODO
|
||||
@@ -475,8 +495,7 @@ namespace PrusaSL1Reader
|
||||
BottomLiftHeight = LookupCustomValue<float>("BottomLiftHeight", 5), // TODO
|
||||
BottomLiftSpeed = LookupCustomValue<float>("BottomLiftSpeed", 60), // TODO
|
||||
BottomLightOffDelay = LookupCustomValue<float>("BottomLightOffDelay", 0), // TODO
|
||||
CostDollars = OutputConfigSettings.UsedMaterial * MaterialSettings.BottleCost /
|
||||
MaterialSettings.BottleVolume,
|
||||
CostDollars = MaterialCost,
|
||||
LiftHeight = LookupCustomValue<float>("LiftHeight", 5), // TODO, // TODO
|
||||
LiftingSpeed = LookupCustomValue<float>("LiftingSpeed", 60), // TODO
|
||||
LightOffDelay = LookupCustomValue<float>("LightOffDelay", 0), // TODO
|
||||
@@ -502,7 +521,7 @@ namespace PrusaSL1Reader
|
||||
|
||||
file.BeginEncode(fileFullPath);
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < GetLayerCount; layerIndex++)
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
file.InsertLayerImageEncode(GetLayerImage(layerIndex), layerIndex);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Advanced;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace PrusaSL1Reader
|
||||
{
|
||||
public class UniversalLayer : List<LayerLine>
|
||||
{
|
||||
public List<LayerLine> Lines { get; } = new List<LayerLine>();
|
||||
|
||||
public UniversalLayer(Image<Gray8> image)
|
||||
{
|
||||
AddFromImage(image);
|
||||
}
|
||||
|
||||
public void AddFromImage(Image<Gray8> image)
|
||||
{
|
||||
for (int y = 0; y < image.Height; y++)
|
||||
{
|
||||
var span = image.GetPixelRowSpan(y);
|
||||
for (int x = 0; x < image.Width; x++)
|
||||
{
|
||||
if(span[x].PackedValue < 125) continue;
|
||||
int startX = x;
|
||||
while (++x < image.Width)
|
||||
{
|
||||
if (span[x].PackedValue < 125 || x == (image.Width-1))
|
||||
{
|
||||
Add(new LayerLine((uint)startX, (uint)y, (uint)(x-startX)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Image<Gray8> ToImage(int resolutionX, int resolutionY)
|
||||
{
|
||||
Image <Gray8> image = new Image<Gray8>(resolutionX, resolutionY);
|
||||
|
||||
foreach (var line in Lines)
|
||||
{
|
||||
var span = image.GetPixelRowSpan((int)line.Y);
|
||||
for (uint i = line.X; i <= line.X2; i++)
|
||||
{
|
||||
span[(int)i] = Helpers.Gray8White;
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,10 @@
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using PrusaSL1Reader;
|
||||
|
||||
namespace PrusaSL1Viewer
|
||||
{
|
||||
@@ -16,12 +18,12 @@ namespace PrusaSL1Viewer
|
||||
public FrmAbout()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.Text = String.Format("About {0}", AssemblyTitle);
|
||||
this.labelProductName.Text = AssemblyProduct;
|
||||
this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion);
|
||||
this.labelCopyright.Text = AssemblyCopyright;
|
||||
this.labelCompanyName.Text = AssemblyCompany;
|
||||
this.textBoxDescription.Text = AssemblyDescription;
|
||||
Text = String.Format("About {0}", AssemblyTitle);
|
||||
labelProductName.Text = AssemblyProduct;
|
||||
labelVersion.Text = String.Format("Version {0}", AssemblyVersion);
|
||||
labelCopyright.Text = AssemblyCopyright;
|
||||
labelCompanyName.Text = AssemblyCompany;
|
||||
textBoxDescription.Text = AssemblyDescription;
|
||||
}
|
||||
|
||||
#region Assembly Attribute Accessors
|
||||
@@ -60,7 +62,10 @@ namespace PrusaSL1Viewer
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return ((AssemblyDescriptionAttribute)attributes[0]).Description;
|
||||
|
||||
string description = ((AssemblyDescriptionAttribute) attributes[0]).Description + $"{Environment.NewLine}{Environment.NewLine}Available File Formats:";
|
||||
|
||||
return FileFormat.AvaliableFormats.SelectMany(fileFormat => fileFormat.ValidFiles).Aggregate(description, (current, fileExtension) => current + $"{Environment.NewLine}- {fileExtension.Description} (.{fileExtension.Extension})");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
+26
-19
@@ -28,10 +28,6 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.Windows.Forms.ListViewGroup listViewGroup1 = new System.Windows.Forms.ListViewGroup("Printer", System.Windows.Forms.HorizontalAlignment.Left);
|
||||
System.Windows.Forms.ListViewGroup listViewGroup2 = new System.Windows.Forms.ListViewGroup("Material", System.Windows.Forms.HorizontalAlignment.Left);
|
||||
System.Windows.Forms.ListViewGroup listViewGroup3 = new System.Windows.Forms.ListViewGroup("Print", System.Windows.Forms.HorizontalAlignment.Left);
|
||||
System.Windows.Forms.ListViewGroup listViewGroup4 = new System.Windows.Forms.ListViewGroup("Output", System.Windows.Forms.HorizontalAlignment.Left);
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmMain));
|
||||
this.menu = new System.Windows.Forms.MenuStrip();
|
||||
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -40,6 +36,8 @@
|
||||
this.menuEdit = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuEditExtract = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuEditConvert = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuViewRotateImage = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuAboutWebsite = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuAboutDonate = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -80,6 +78,7 @@
|
||||
this.menu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.fileToolStripMenuItem,
|
||||
this.menuEdit,
|
||||
this.viewToolStripMenuItem,
|
||||
this.helpToolStripMenuItem});
|
||||
this.menu.Location = new System.Drawing.Point(0, 0);
|
||||
this.menu.Name = "menu";
|
||||
@@ -131,7 +130,7 @@
|
||||
this.menuEditExtract.Name = "menuEditExtract";
|
||||
this.menuEditExtract.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Alt)
|
||||
| System.Windows.Forms.Keys.E)));
|
||||
this.menuEditExtract.Size = new System.Drawing.Size(180, 22);
|
||||
this.menuEditExtract.Size = new System.Drawing.Size(173, 22);
|
||||
this.menuEditExtract.Text = "&Extract";
|
||||
this.menuEditExtract.Click += new System.EventHandler(this.MenuItemClicked);
|
||||
//
|
||||
@@ -140,9 +139,28 @@
|
||||
this.menuEditConvert.Enabled = false;
|
||||
this.menuEditConvert.Image = global::PrusaSL1Viewer.Properties.Resources.Convert_16x16;
|
||||
this.menuEditConvert.Name = "menuEditConvert";
|
||||
this.menuEditConvert.Size = new System.Drawing.Size(180, 22);
|
||||
this.menuEditConvert.Size = new System.Drawing.Size(173, 22);
|
||||
this.menuEditConvert.Text = "&Convert To";
|
||||
//
|
||||
// viewToolStripMenuItem
|
||||
//
|
||||
this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.menuViewRotateImage});
|
||||
this.viewToolStripMenuItem.Name = "viewToolStripMenuItem";
|
||||
this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
|
||||
this.viewToolStripMenuItem.Text = "&View";
|
||||
//
|
||||
// menuViewRotateImage
|
||||
//
|
||||
this.menuViewRotateImage.Checked = true;
|
||||
this.menuViewRotateImage.CheckOnClick = true;
|
||||
this.menuViewRotateImage.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.menuViewRotateImage.Image = global::PrusaSL1Viewer.Properties.Resources.Rotate_16x16;
|
||||
this.menuViewRotateImage.Name = "menuViewRotateImage";
|
||||
this.menuViewRotateImage.Size = new System.Drawing.Size(164, 22);
|
||||
this.menuViewRotateImage.Text = "&Rotate Image 90º";
|
||||
this.menuViewRotateImage.ToolTipText = "Auto rotate layer preview image at 90º (This can slow down the layer preview)";
|
||||
//
|
||||
// helpToolStripMenuItem
|
||||
//
|
||||
this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
@@ -288,19 +306,6 @@
|
||||
this.lvProperties.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lvProperties.FullRowSelect = true;
|
||||
this.lvProperties.GridLines = true;
|
||||
listViewGroup1.Header = "Printer";
|
||||
listViewGroup1.Name = "lvGroupPrinter";
|
||||
listViewGroup2.Header = "Material";
|
||||
listViewGroup2.Name = "lvGroupMaterial";
|
||||
listViewGroup3.Header = "Print";
|
||||
listViewGroup3.Name = "lvGroupPrint";
|
||||
listViewGroup4.Header = "Output";
|
||||
listViewGroup4.Name = "lvGroupOutput";
|
||||
this.lvProperties.Groups.AddRange(new System.Windows.Forms.ListViewGroup[] {
|
||||
listViewGroup1,
|
||||
listViewGroup2,
|
||||
listViewGroup3,
|
||||
listViewGroup4});
|
||||
this.lvProperties.HideSelection = false;
|
||||
this.lvProperties.Location = new System.Drawing.Point(0, 0);
|
||||
this.lvProperties.Name = "lvProperties";
|
||||
@@ -422,6 +427,8 @@
|
||||
private System.Windows.Forms.PictureBox pbLayer;
|
||||
private System.Windows.Forms.ProgressBar pbLayers;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuEditConvert;
|
||||
private System.Windows.Forms.ToolStripMenuItem viewToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuViewRotateImage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+62
-60
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Reflection;
|
||||
@@ -24,18 +25,6 @@ namespace PrusaSL1Viewer
|
||||
InitializeComponent();
|
||||
Text = $"{FrmAbout.AssemblyTitle} Version: {FrmAbout.AssemblyVersion}";
|
||||
|
||||
foreach (var type in Helpers.AvaliableFileFormats)
|
||||
{
|
||||
if(type == typeof(SL1File)) continue;
|
||||
ToolStripMenuItem menuItem = new ToolStripMenuItem(type.Name.Replace("File", string.Empty))
|
||||
{
|
||||
Tag = type,
|
||||
Image = Properties.Resources.layers_16x16
|
||||
};
|
||||
menuItem.Click += ConvertToItemOnClick;
|
||||
menuEditConvert.DropDownItems.Add(menuItem);
|
||||
}
|
||||
|
||||
DragEnter += (s, e) => { if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy; };
|
||||
DragDrop += (s, e) => { ProcessFile((string[])e.Data.GetData(DataFormats.FileDrop)); };
|
||||
|
||||
@@ -57,7 +46,7 @@ namespace PrusaSL1Viewer
|
||||
using (OpenFileDialog openFile = new OpenFileDialog())
|
||||
{
|
||||
openFile.CheckFileExists = true;
|
||||
openFile.Filter = Program.SL1File.GetFileFilter();
|
||||
openFile.Filter = FileFormat.AllFileFilters;
|
||||
openFile.FilterIndex = 0;
|
||||
if (openFile.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
@@ -89,20 +78,7 @@ namespace PrusaSL1Viewer
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(folder.SelectedPath))
|
||||
{
|
||||
DirectoryInfo di = new DirectoryInfo(folder.SelectedPath);
|
||||
|
||||
foreach (FileInfo file in di.GetFiles())
|
||||
{
|
||||
file.Delete();
|
||||
}
|
||||
foreach (DirectoryInfo dir in di.GetDirectories())
|
||||
{
|
||||
dir.Delete(true);
|
||||
}
|
||||
}
|
||||
Program.SL1File.Archive.ExtractToDirectory(folder.SelectedPath);
|
||||
Program.SlicerFile.Extract(folder.SelectedPath);
|
||||
if (MessageBox.Show(
|
||||
$"Extraction was successful, browser folder to see it contents.\n{folder.SelectedPath}\nPress 'Yes' if you want open the target folder, otherwise select 'No' to continue.",
|
||||
"Extraction completed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
|
||||
@@ -144,21 +120,21 @@ namespace PrusaSL1Viewer
|
||||
private void ConvertToItemOnClick(object sender, EventArgs e)
|
||||
{
|
||||
ToolStripMenuItem menuItem = (ToolStripMenuItem)sender;
|
||||
Type type = (Type)menuItem.Tag;
|
||||
FileFormat fileFormat = (FileFormat)menuItem.Tag;
|
||||
using (SaveFileDialog dialog = new SaveFileDialog())
|
||||
{
|
||||
dialog.FileName = Path.GetFileNameWithoutExtension(Program.SL1File.FileFullPath);
|
||||
dialog.FileName = Path.GetFileNameWithoutExtension(Program.SlicerFile.FileFullPath);
|
||||
|
||||
using (FileFormat instance = (FileFormat)Activator.CreateInstance(type))
|
||||
//using (FileFormat instance = (FileFormat)Activator.CreateInstance(type))
|
||||
//using (CbddlpFile file = new CbddlpFile())
|
||||
{
|
||||
dialog.Filter = instance.GetFileFilter();
|
||||
dialog.Filter = fileFormat.GetFileFilter();
|
||||
}
|
||||
|
||||
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
Program.SL1File.Convert(type, dialog.FileName);
|
||||
Program.SlicerFile.Convert(fileFormat, dialog.FileName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -171,7 +147,6 @@ namespace PrusaSL1Viewer
|
||||
if (ReferenceEquals(files, null)) return;
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (!Program.SL1File.IsExtensionValid(file, true)) continue;
|
||||
try
|
||||
{
|
||||
ProcessFile(file);
|
||||
@@ -187,20 +162,31 @@ namespace PrusaSL1Viewer
|
||||
}
|
||||
|
||||
void ProcessFile(string fileName)
|
||||
{
|
||||
/* if (!ReferenceEquals(Program.SL1File, null))
|
||||
{
|
||||
Program.SlicerFile?.Dispose();
|
||||
Program.SlicerFile = FileFormat.FindByExtension(fileName, true, true);
|
||||
if (ReferenceEquals(Program.SlicerFile, null)) return;
|
||||
Program.SlicerFile.Decode(fileName);
|
||||
|
||||
menuEditConvert.DropDownItems.Clear();
|
||||
foreach (var fileFormat in FileFormat.AvaliableFormats)
|
||||
{
|
||||
Program.SL1File.Dispose();
|
||||
}*/
|
||||
if (fileFormat.GetType() == Program.SlicerFile.GetType()) continue;
|
||||
ToolStripMenuItem menuItem = new ToolStripMenuItem(fileFormat.GetType().Name.Replace("File", string.Empty))
|
||||
{
|
||||
Tag = fileFormat,
|
||||
Image = Properties.Resources.layers_16x16
|
||||
};
|
||||
menuItem.Click += ConvertToItemOnClick;
|
||||
menuEditConvert.DropDownItems.Add(menuItem);
|
||||
}
|
||||
|
||||
Program.SL1File.Decode(fileName);
|
||||
|
||||
pbThumbnail.Image = Program.SL1File.Thumbnails[0].ToBitmap();
|
||||
pbThumbnail.Image = Program.SlicerFile.Thumbnails[0]?.ToBitmap();
|
||||
//ShowLayer(0);
|
||||
|
||||
sbLayers.SmallChange = 1;
|
||||
sbLayers.Minimum = 0;
|
||||
sbLayers.Maximum = (int)Program.SL1File.GetLayerCount-1;
|
||||
sbLayers.Maximum = (int)Program.SlicerFile.LayerCount-1;
|
||||
sbLayers.Value = sbLayers.Maximum;
|
||||
|
||||
sbLayers.Enabled =
|
||||
@@ -211,31 +197,32 @@ namespace PrusaSL1Viewer
|
||||
lvProperties.BeginUpdate();
|
||||
lvProperties.Items.Clear();
|
||||
|
||||
object[] configs = { Program.SL1File.PrinterSettings, Program.SL1File.MaterialSettings, Program.SL1File.PrintSettings, Program.SL1File.OutputConfigSettings };
|
||||
byte configNum = 0;
|
||||
foreach (object config in configs)
|
||||
lvProperties.Groups.Clear();
|
||||
|
||||
foreach (object config in Program.SlicerFile.Configs)
|
||||
{
|
||||
ListViewGroup group = new ListViewGroup(config.GetType().Name);
|
||||
lvProperties.Groups.Add(group);
|
||||
foreach (PropertyInfo propertyInfo in config.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
ListViewItem item = new ListViewItem(propertyInfo.Name, lvProperties.Groups[configNum]);
|
||||
ListViewItem item = new ListViewItem(propertyInfo.Name, group);
|
||||
object obj = new object();
|
||||
item.SubItems.Add(propertyInfo.GetValue(config)?.ToString());
|
||||
lvProperties.Items.Add(item);
|
||||
}
|
||||
|
||||
configNum++;
|
||||
}
|
||||
lvProperties.EndUpdate();
|
||||
|
||||
statusBar.Items.Clear();
|
||||
|
||||
AddStatusBarItem(nameof(Program.SL1File.OutputConfigSettings.LayerHeight), Program.SL1File.OutputConfigSettings.LayerHeight, "mm");
|
||||
AddStatusBarItem(nameof(Program.SL1File.OutputConfigSettings.ExpTimeFirst), Program.SL1File.OutputConfigSettings.ExpTimeFirst);
|
||||
AddStatusBarItem(nameof(Program.SL1File.OutputConfigSettings.ExpTime), Program.SL1File.OutputConfigSettings.ExpTime);
|
||||
AddStatusBarItem(nameof(Program.SL1File.OutputConfigSettings.PrintTime), Math.Round(Program.SL1File.OutputConfigSettings.PrintTime/ 3600, 2), "h");
|
||||
AddStatusBarItem(nameof(Program.SL1File.OutputConfigSettings.UsedMaterial), Math.Round(Program.SL1File.OutputConfigSettings.UsedMaterial, 2), "ml");
|
||||
AddStatusBarItem(nameof(Program.SL1File.OutputConfigSettings.MaterialName), Program.SL1File.OutputConfigSettings.MaterialName);
|
||||
AddStatusBarItem(nameof(Program.SL1File.OutputConfigSettings.PrinterProfile), Program.SL1File.OutputConfigSettings.PrinterProfile);
|
||||
AddStatusBarItem(nameof(Program.SlicerFile.LayerHeight), Program.SlicerFile.LayerHeight, "mm");
|
||||
AddStatusBarItem(nameof(Program.SlicerFile.InitialExposureTime), Program.SlicerFile.InitialExposureTime, "s");
|
||||
AddStatusBarItem(nameof(Program.SlicerFile.LayerExposureTime), Program.SlicerFile.LayerExposureTime, "s");
|
||||
AddStatusBarItem(nameof(Program.SlicerFile.PrintTime), Math.Round(Program.SlicerFile.PrintTime / 3600, 2), "h");
|
||||
AddStatusBarItem(nameof(Program.SlicerFile.UsedMaterial), Math.Round(Program.SlicerFile.UsedMaterial, 2), "ml");
|
||||
AddStatusBarItem(nameof(Program.SlicerFile.MaterialCost), Program.SlicerFile.MaterialCost, "€");
|
||||
AddStatusBarItem(nameof(Program.SlicerFile.MaterialName), Program.SlicerFile.MaterialName);
|
||||
AddStatusBarItem(nameof(Program.SlicerFile.MachineName), Program.SlicerFile.MachineName);
|
||||
|
||||
Text = $"{FrmAbout.AssemblyTitle} Version: {FrmAbout.AssemblyVersion} File: {Path.GetFileName(fileName)}";
|
||||
}
|
||||
@@ -244,17 +231,32 @@ namespace PrusaSL1Viewer
|
||||
{
|
||||
//if(!ReferenceEquals(pbLayer.Image, null))
|
||||
// pbLayer.Image.Dispose(); SLOW! LET GC DO IT
|
||||
//pbLayer.Image = Image.FromStream(Program.SL1File.LayerImages[layerNum].Open());
|
||||
//pbLayer.Image = Image.FromStream(Program.SlicerFile.LayerImages[layerNum].Open());
|
||||
//pbLayer.Image.RotateFlip(RotateFlipType.Rotate90FlipNone);
|
||||
var image = Program.SL1File.GetLayerImage(layerNum);
|
||||
image.Mutate(x => x.Rotate(RotateMode.Rotate90));
|
||||
//Stopwatch watch = Stopwatch.StartNew();
|
||||
var image = Program.SlicerFile.GetLayerImage(layerNum);
|
||||
//Debug.Write(watch.ElapsedMilliseconds.ToString());
|
||||
if (menuViewRotateImage.Checked)
|
||||
{
|
||||
//watch.Restart();
|
||||
image.Mutate(x => x.Rotate(RotateMode.Rotate90));
|
||||
//Debug.Write($"/{watch.ElapsedMilliseconds}");
|
||||
}
|
||||
|
||||
//watch.Restart();
|
||||
pbLayer.Image = image.ToBitmap();
|
||||
//Debug.WriteLine($"/{watch.ElapsedMilliseconds}");
|
||||
|
||||
byte percent = (byte)((layerNum + 1) * 100 / Program.SL1File.GetLayerCount);
|
||||
//UniversalLayer layer = new UniversalLayer(image);
|
||||
//pbLayer.Image = layer.ToBitmap(image.Width, image.Height);
|
||||
|
||||
|
||||
lbLayers.Text = $"{Program.SL1File.TotalHeight}mm\n{layerNum+1} / {Program.SL1File.GetLayerCount}\n{Program.SL1File.GetHeightFromLayer((uint)layerNum+1)}mm\n{percent}%";
|
||||
byte percent = (byte)((layerNum + 1) * 100 / Program.SlicerFile.LayerCount);
|
||||
|
||||
|
||||
lbLayers.Text = $"{Program.SlicerFile.TotalHeight}mm\n{layerNum+1} / {Program.SlicerFile.LayerCount}\n{Program.SlicerFile.GetHeightFromLayer((uint)layerNum+1)}mm\n{percent}%";
|
||||
pbLayers.Value = percent;
|
||||
|
||||
}
|
||||
|
||||
void AddStatusBarItem(string name, object item, string extraText = "")
|
||||
@@ -262,7 +264,7 @@ namespace PrusaSL1Viewer
|
||||
if (statusBar.Items.Count > 0)
|
||||
statusBar.Items.Add(new ToolStripSeparator());
|
||||
|
||||
ToolStripLabel label = new ToolStripLabel($"{name}: {item.ToString()}{extraText}");
|
||||
ToolStripLabel label = new ToolStripLabel($"{name}: {item}{extraText}");
|
||||
statusBar.Items.Add(label);
|
||||
}
|
||||
#endregion
|
||||
|
||||
Generated
+46
@@ -0,0 +1,46 @@
|
||||
namespace PrusaSL1Viewer
|
||||
{
|
||||
partial class ImageBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// ImageBox
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.Black;
|
||||
this.Name = "ImageBox";
|
||||
this.Size = new System.Drawing.Size(393, 251);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Advanced;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
|
||||
namespace PrusaSL1Viewer
|
||||
{
|
||||
public partial class ImageBox : UserControl
|
||||
{
|
||||
private static SolidBrush Brush { get; } = new SolidBrush(System.Drawing.Color.White);
|
||||
public Image<Gray8> Image { get; private set; }
|
||||
|
||||
public ImageBox()
|
||||
{
|
||||
SetStyle(ControlStyles.UserPaint, true);
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
|
||||
UpdateStyles();
|
||||
InitializeComponent();
|
||||
|
||||
}
|
||||
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
base.OnPaint(e);
|
||||
if (ReferenceEquals(Image, null)) return;
|
||||
|
||||
var newImage = Image.Clone();
|
||||
|
||||
newImage.Mutate(x => x.Resize(Width, Height));
|
||||
|
||||
for (int y = 0; y < newImage.Height; y++)
|
||||
{
|
||||
var span = newImage.GetPixelRowSpan(y);
|
||||
for (int x = 0; x < newImage.Width; x++)
|
||||
{
|
||||
if (span[x].PackedValue > 125)
|
||||
e.Graphics.FillRectangle(Brush, x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetImage(Image<Gray8> image)
|
||||
{
|
||||
Image = image;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -8,7 +8,6 @@
|
||||
using System.IO;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Advanced;
|
||||
using SixLabors.ImageSharp.Formats.Png;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace PrusaSL1Viewer
|
||||
@@ -19,7 +18,7 @@ namespace PrusaSL1Viewer
|
||||
{
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
var imageEncoder = image.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance);
|
||||
var imageEncoder = image.GetConfiguration().ImageFormatsManager.FindEncoder(SixLabors.ImageSharp.Formats.Bmp.BmpFormat.Instance);
|
||||
image.Save(memoryStream, imageEncoder);
|
||||
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 384 B |
@@ -13,7 +13,7 @@ namespace PrusaSL1Viewer
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
public static SL1File SL1File { get; } = new SL1File();
|
||||
public static FileFormat SlicerFile { get; set; }
|
||||
public static FrmMain FrmMain { get; private set; }
|
||||
public static FrmAbout FrmAbout { get; private set; }
|
||||
/// <summary>
|
||||
|
||||
+10
@@ -149,5 +149,15 @@ namespace PrusaSL1Viewer.Properties {
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap Rotate_16x16 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("Rotate-16x16", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,9 @@
|
||||
<data name="Open-16x16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Images\Open-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="layers-16x16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Images\layers-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="PrusaSL1Viewer" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\PrusaSL1Viewer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
@@ -142,7 +145,7 @@
|
||||
<data name="Extract-object-16x16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Images\Extract-object-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="layers-16x16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Images\layers-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="Rotate-16x16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Images\Rotate-16x16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -138,15 +138,25 @@
|
||||
<Compile Include="FrmMain.Designer.cs">
|
||||
<DependentUpon>FrmMain.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ImageBox.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ImageBox.Designer.cs">
|
||||
<DependentUpon>ImageBox.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ImageSharpExtensions.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UniversalLayerExtensions.cs" />
|
||||
<EmbeddedResource Include="FrmAbout.resx">
|
||||
<DependentUpon>FrmAbout.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="FrmMain.resx">
|
||||
<DependentUpon>FrmMain.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="ImageBox.resx">
|
||||
<DependentUpon>ImageBox.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
@@ -197,6 +207,7 @@
|
||||
<None Include="Images\Global-Network-icon-16x16.png" />
|
||||
<None Include="Images\Convert-16x16.png" />
|
||||
<None Include="Images\layers-16x16.png" />
|
||||
<None Include="Images\Rotate-16x16.png" />
|
||||
<Content Include="PrusaSL1Viewer.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using PrusaSL1Reader;
|
||||
using SixLabors.ImageSharp;
|
||||
|
||||
namespace PrusaSL1Viewer
|
||||
{
|
||||
public static class UniversalLayerExtensions
|
||||
{
|
||||
public static Bitmap ToBitmap(this UniversalLayer layer, int width, int height)
|
||||
{
|
||||
Bitmap buffer = new Bitmap(width, height);//set the size of the image
|
||||
Graphics gfx = Graphics.FromImage(buffer);//set the graphics to draw on the image
|
||||
|
||||
foreach (var line in layer)
|
||||
{
|
||||
gfx.DrawRectangle(Pens.White, line.X, line.Y, line.Length, 1);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user