Allow open known filetypes + More abstraction

This commit is contained in:
Tiago Conceição
2020-04-14 00:18:49 +01:00
parent f99c1eddc4
commit 531fd9bac7
20 changed files with 696 additions and 150 deletions
+30 -7
View File
@@ -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++)
{
+75 -14
View File
@@ -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)
{
+1 -4
View File
@@ -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)
+67 -4
View File
@@ -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);
}
}
+35
View File
@@ -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
View File
@@ -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);
}
+52
View File
@@ -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;
}
}
}
+12 -7
View File
@@ -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})");
}
}
+26 -19
View File
@@ -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
View File
@@ -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
+46
View File
@@ -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
}
}
+65
View File
@@ -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;
}
}
}
+120
View File
@@ -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>
+1 -2
View File
@@ -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

+1 -1
View File
@@ -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
View File
@@ -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));
}
}
}
}
+5 -2
View File
@@ -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>
+11
View File
@@ -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;
}
}
}