Fix blank mats

This commit is contained in:
Tiago Conceição
2020-10-10 21:28:09 +01:00
parent 27cbfc2aef
commit d88b2dd455
9 changed files with 184 additions and 101 deletions
+5
View File
@@ -9,6 +9,11 @@
* (Improvement) GUI is now scalable
* (Fix) Some bug found and fixed during convertion
## /10/2020 - v0.8.4.2
* (Fix) pws and pw0: Error when try to save or copy to clipboard the slicer information / properties
* (Fix) phton, ctb, cbbdlp, pws, pw0, phz: Rare cases were decoding image generate noise and malformed image
## 10/10/2020 - v0.8.4.1
* (Add) Tool - Modify print parameters: Value unit to confirmation text
+2 -2
View File
@@ -62,8 +62,8 @@ But also, i need victims for test subject. Proceed at your own risk!
* ZCodex (Z-Suite)
* CWS (NovaMaker)
* LGS (Longer Orange 10)
* LGS30 (onger Orange 30)
* UVJ
* LGS30 (Longer Orange 30)
* UVJ (Zip file for manual manipulation format)
* Image files (png, jpg, jpeg, gif, bmp)
## Available printers for PrusaSlicer
+11 -1
View File
@@ -11,11 +11,14 @@ using System.Drawing;
using System.Runtime.InteropServices;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
namespace UVtools.Core.Extensions
{
public static class EmguExtensions
{
public static readonly MCvScalar BlackByte = new MCvScalar(0);
public static unsafe byte* GetBytePointer(this Mat mat)
{
return (byte*)mat.DataPointer.ToPointer();
@@ -181,7 +184,7 @@ namespace UVtools.Core.Extensions
/// <returns>Blanked <see cref="Mat"/></returns>
public static Mat CloneBlank(this Mat mat)
{
return new Mat(new Size(mat.Width, mat.Height), mat.Depth, mat.NumberOfChannels);
return InitMat(mat.Size, mat.Depth, mat.NumberOfChannels);
}
public static byte GetByte(this Mat mat, int pos)
@@ -210,5 +213,12 @@ namespace UVtools.Core.Extensions
public static void SetBytes(this Mat mat, byte[] value) =>
Marshal.Copy(value, 0, mat.DataPointer, value.Length);
public static Mat InitMat(Size size, DepthType depthType = DepthType.Cv8U, int channels = 1)
{
var mat = new Mat(size, depthType, channels);
mat.SetTo(BlackByte);
return mat;
}
}
}
+33 -33
View File
@@ -18,6 +18,7 @@ using System.Threading.Tasks;
using BinarySerialization;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using UVtools.Core.Extensions;
using UVtools.Core.Operations;
@@ -359,13 +360,10 @@ namespace UVtools.Core.FileFormats
[FieldOrder(6)] public uint Unknown3 { get; set; }
[FieldOrder(7)] public uint Unknown4 { get; set; }
public Mat Decode(byte[] rawImageData)
public unsafe Mat Decode(byte[] rawImageData)
{
var image = new Mat(new Size((int) ResolutionX, (int) ResolutionY), DepthType.Cv8U, 3);
var span = image.GetPixelSpan<byte>();
//var image = EmguExtensions.CreateMat(out var bytes, new Size((int) ResolutionX, (int) ResolutionY), 3);
//var image = new MatBytes(new Size((int)ResolutionX, (int)ResolutionY), 3);
//var bytes = image.Bytes;
var span = image.GetBytePointer();
int pixel = 0;
for (int n = 0; n < rawImageData.Length; n++)
@@ -398,13 +396,14 @@ namespace UVtools.Core.FileFormats
return $"{nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(ImageOffset)}: {ImageOffset}, {nameof(ImageLength)}: {ImageLength}, {nameof(Unknown1)}: {Unknown1}, {nameof(Unknown2)}: {Unknown2}, {nameof(Unknown3)}: {Unknown3}, {nameof(Unknown4)}: {Unknown4}";
}
public byte[] Encode(Mat image)
public unsafe byte[] Encode(Mat image)
{
List<byte> rawData = new List<byte>();
ushort color15 = 0;
uint rep = 0;
var span = image.GetPixelSpan<byte>();
var span = image.GetBytePointer();
var imageLength = image.GetLength();
void RleRGB15()
{
@@ -434,7 +433,7 @@ namespace UVtools.Core.FileFormats
}
int pixel = 0;
while (pixel < span.Length)
while (pixel < imageLength)
{
var ncolor15 =
// bgr
@@ -541,10 +540,11 @@ namespace UVtools.Core.FileFormats
return image;
}
public static Mat DecodeCbddlpImage(ChituboxFile parent, uint layerIndex)
public static unsafe Mat DecodeCbddlpImage(ChituboxFile parent, uint layerIndex)
{
var image = new Mat(new Size((int)parent.HeaderSettings.ResolutionX, (int)parent.HeaderSettings.ResolutionY), DepthType.Cv8U, 1);
var span = image.GetPixelSpan<byte>();
var image = EmguExtensions.InitMat(parent.Resolution);
var span = image.GetBytePointer();
var imageLength = image.GetLength();
for (byte bit = 0; bit < parent.AntiAliasing; bit++)
{
@@ -568,12 +568,12 @@ namespace UVtools.Core.FileFormats
n += reps;
if (n == span.Length)
if (n == imageLength)
{
break;
}
if (n > span.Length)
if (n > imageLength)
{
image.Dispose();
throw new FileLoadException("Error image ran off the end");
@@ -581,7 +581,7 @@ namespace UVtools.Core.FileFormats
}
}
for (int i = 0; i < span.Length; i++)
for (int i = 0; i < imageLength; i++)
{
int newC = span[i] * (256 / parent.AntiAliasing);
@@ -598,13 +598,10 @@ namespace UVtools.Core.FileFormats
return image;
}
private Mat DecodeCbtImage(uint layerIndex)
private unsafe Mat DecodeCbtImage(uint layerIndex)
{
//Mat image = new Mat(new Size((int)Parent.HeaderSettings.ResolutionX, (int)Parent.HeaderSettings.ResolutionY), DepthType.Cv8U, 1);
//var bytes = image.GetBytes();
//var image = EmguExtensions.CreateMat(out var bytes, new Size((int)Parent.HeaderSettings.ResolutionX, (int)Parent.HeaderSettings.ResolutionY));
var image = new Mat(new Size((int)Parent.HeaderSettings.ResolutionX, (int)Parent.HeaderSettings.ResolutionY), DepthType.Cv8U, 1);
var span = image.GetPixelSpan<byte>();
var image = EmguExtensions.InitMat(Parent.Resolution);
var span = image.GetBytePointer();
if (Parent.HeaderSettings.EncryptionKey > 0)
{
@@ -616,7 +613,7 @@ namespace UVtools.Core.FileFormats
for (var n = 0; n < EncodedRle.Length; n++)
{
byte code = EncodedRle[n];
uint stride = 1;
int stride = 1;
if ((code & 0x80) == 0x80) // It's a run
{
@@ -631,18 +628,17 @@ namespace UVtools.Core.FileFormats
}
else if ((slen & 0xc0) == 0x80)
{
stride = (uint)(((slen & 0x3f) << 8) + EncodedRle[n + 1]);
stride = ((slen & 0x3f) << 8) + EncodedRle[n + 1];
n++;
}
else if ((slen & 0xe0) == 0xc0)
{
stride = (uint)(((slen & 0x1f) << 16) + (EncodedRle[n + 1] << 8) + EncodedRle[n + 2]);
stride = ((slen & 0x1f) << 16) + (EncodedRle[n + 1] << 8) + EncodedRle[n + 2];
n += 2;
}
else if ((slen & 0xf0) == 0xe0)
{
stride = (uint)(((slen & 0xf) << 24) + (EncodedRle[n + 1] << 16) + (EncodedRle[n + 2] << 8) + EncodedRle[n + 3]);
stride = ((slen & 0xf) << 24) + (EncodedRle[n + 1] << 16) + (EncodedRle[n + 2] << 8) + EncodedRle[n + 3];
n += 3;
}
else
@@ -662,11 +658,11 @@ namespace UVtools.Core.FileFormats
if (code == 0) // Ignore blacks, spare cycles
{
pixel += (int)stride;
pixel += stride;
continue;
}
while (stride-- > 0)
for (; stride > 0; stride--)
{
span[pixel] = code;
pixel++;
@@ -681,10 +677,11 @@ namespace UVtools.Core.FileFormats
return Parent.IsCbtFile ? EncodeCbtImage(image, layerIndex) : EncodeCbddlpImage(image, aaIndex);
}
public byte[] EncodeCbddlpImage(Mat image, byte bit)
public unsafe byte[] EncodeCbddlpImage(Mat image, byte bit)
{
List<byte> rawData = new List<byte>();
var span = image.GetPixelSpan<byte>();
var span = image.GetBytePointer();
var imageLength = image.GetLength();
bool obit = false;
int rep = 0;
@@ -712,7 +709,7 @@ namespace UVtools.Core.FileFormats
rawData.Add(by);
}
for (int pixel = 0; pixel < span.Length; pixel++)
for (int pixel = 0; pixel < imageLength; pixel++)
{
var nbit = span[pixel] >= threshold;
@@ -743,12 +740,13 @@ namespace UVtools.Core.FileFormats
return EncodedRle;
}
private byte[] EncodeCbtImage(Mat image, uint layerIndex)
private unsafe byte[] EncodeCbtImage(Mat image, uint layerIndex)
{
List<byte> rawData = new List<byte>();
byte color = byte.MaxValue >> 1;
uint stride = 0;
var span = image.GetPixelSpan<byte>();
var span = image.GetBytePointer();
var imageLength = image.GetLength();
void AddRep()
{
@@ -801,7 +799,7 @@ namespace UVtools.Core.FileFormats
}
for (int pixel = 0; pixel < span.Length; pixel++)
for (int pixel = 0; pixel < imageLength; pixel++)
{
var grey7 = (byte) (span[pixel] >> 1);
@@ -1424,6 +1422,7 @@ namespace UVtools.Core.FileFormats
inputFile.Read(layerData.EncodedRle, 0, (int) layerData.DataSize);
progress++;
progress.Token.ThrowIfCancellationRequested();
}
@@ -1434,6 +1433,7 @@ namespace UVtools.Core.FileFormats
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
Parallel.For(0, LayerCount, layerIndex =>
//for (int layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
if (progress.Token.IsCancellationRequested)
{
+18 -15
View File
@@ -97,11 +97,12 @@ namespace UVtools.Core.FileFormats
[FieldLength(nameof(DataSize))]
public byte[] EncodedRle { get; set; }
public byte[] Encode(Mat mat)
public unsafe byte[] Encode(Mat mat)
{
List<byte> rawData = new List<byte>();
List<byte> chunk = new List<byte>();
var spanMat = mat.GetPixelSpan<byte>();
var spanMat = mat.GetBytePointer();
var imageLength = mat.GetLength();
uint span = 0;
byte lc = 0;
@@ -114,7 +115,7 @@ namespace UVtools.Core.FileFormats
rawData.AddRange(chunk.ToArray());
}
for (int i = 0; i < spanMat.Length; i++)
for (int i = 0; i < imageLength; i++)
{
byte c = (byte) (spanMat[i] & 0xf0);
@@ -137,10 +138,11 @@ namespace UVtools.Core.FileFormats
return EncodedRle;
}
public Mat Decode(bool consumeRle = true)
public unsafe Mat Decode(bool consumeRle = true)
{
Mat mat = new Mat(new Size((int)Parent.HeaderSettings.ResolutionX, (int) Parent.HeaderSettings.ResolutionY), DepthType.Cv8U, 1);
var matSpan = mat.GetPixelSpan<byte>();
var mat = EmguExtensions.InitMat(Parent.Resolution);
var matSpan = mat.GetBytePointer();
var imageLength = mat.GetLength();
byte last = 0;
int span = 0;
@@ -158,7 +160,7 @@ namespace UVtools.Core.FileFormats
{
for(; span > 0; span--)
{
if (index >= matSpan.Length)
if (index >= imageLength)
{
throw new FileLoadException($"'{span}' bytes to many");
}
@@ -175,7 +177,7 @@ namespace UVtools.Core.FileFormats
for (; span > 0; span--)
{
if (index >= matSpan.Length)
if (index >= imageLength)
{
throw new FileLoadException($"'{span}' bytes to many");
}
@@ -183,9 +185,9 @@ namespace UVtools.Core.FileFormats
matSpan[index++] = last;
}
if (index != matSpan.Length)
if (index != imageLength)
{
throw new FileLoadException($"Incomplete buffer, expected: {matSpan.Length}, got: {index}");
throw new FileLoadException($"Incomplete buffer, expected: {imageLength}, got: {index}");
}
@@ -332,13 +334,14 @@ namespace UVtools.Core.FileFormats
#region Methods
public byte[] PreviewEncode(Mat mat)
public unsafe byte[] PreviewEncode(Mat mat)
{
byte[] bytes = new byte[mat.Width * mat.Height * 2];
var span = mat.GetPixelSpan<byte>();
var span = mat.GetBytePointer();
var imageLength = mat.GetLength();
int index = 0;
for (int i = 0; i < span.Length; i+=3)
for (int i = 0; i < imageLength; i+=3)
{
byte b = span[i];
byte g = span[i+1];
@@ -407,10 +410,10 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine("-End-");
}
public Mat PreviewDecode(byte []data)
public unsafe Mat PreviewDecode(byte []data)
{
Mat mat = new Mat((int) HeaderSettings.PreviewSizeY, (int)HeaderSettings.PreviewSizeX, DepthType.Cv8U, 3);
var span = mat.GetPixelSpan<byte>();
var span = mat.GetBytePointer();
int spanIndex = 0;
for (int i = 0; i < data.Length; i+=2)
{
+10 -9
View File
@@ -306,11 +306,10 @@ namespace UVtools.Core.FileFormats
[FieldOrder(6)] public uint Unknown3 { get; set; }
[FieldOrder(7)] public uint Unknown4 { get; set; }
public Mat Decode(byte[] rawImageData)
public unsafe Mat Decode(byte[] rawImageData)
{
var image = new Mat(new Size((int)ResolutionX, (int)ResolutionY), DepthType.Cv8U, 3);
var span = image.GetPixelSpan<byte>();
var span = image.GetBytePointer();
int pixel = 0;
for (uint n = 0; n < ImageLength; n++)
@@ -339,10 +338,12 @@ namespace UVtools.Core.FileFormats
return image;
}
public static byte[] Encode(Mat image)
public static unsafe byte[] Encode(Mat image)
{
List<byte> rawData = new List<byte>();
var span = image.GetPixelSpan<byte>();
var span = image.GetBytePointer();
var imageLength = image.GetLength();
ushort color15 = 0;
uint rep = 0;
@@ -373,7 +374,7 @@ namespace UVtools.Core.FileFormats
}
}
for (int pixel = 0; pixel < span.Length; pixel += image.NumberOfChannels)
for (int pixel = 0; pixel < imageLength; pixel += image.NumberOfChannels)
{
var ncolor15 =
(span[pixel] >> 3)
@@ -461,10 +462,10 @@ namespace UVtools.Core.FileFormats
parent.HeaderSettings.LayerOffTime);
}
public Mat Decode(uint layerIndex, bool consumeData = true)
public unsafe Mat Decode(uint layerIndex, bool consumeData = true)
{
var image = new Mat(new Size((int)Parent.ResolutionX, (int)Parent.ResolutionY), DepthType.Cv8U, 1);
var span = image.GetPixelSpan<byte>();
var image = EmguExtensions.InitMat(Parent.Resolution);
var span = image.GetBytePointer();
if (Parent.HeaderSettings.EncryptionKey > 0)
{
+30 -25
View File
@@ -284,10 +284,10 @@ namespace UVtools.Core.FileFormats
Section = new Section(SectionMark, this);
}
public Mat Decode(bool consumeData = true)
public unsafe Mat Decode(bool consumeData = true)
{
Mat image = new Mat(new Size((int) Width, (int) Height), DepthType.Cv8U, 3);
var span = image.GetPixelSpan<byte>();
var span = image.GetBytePointer();
int pixel = 0;
for (uint i = 0; i < Data.Length; i += 2)
@@ -313,9 +313,10 @@ namespace UVtools.Core.FileFormats
return image;
}
public static Preview Encode(Mat image)
public static unsafe Preview Encode(Mat image)
{
var span = image.GetPixelSpan<byte>();
var span = image.GetBytePointer();
var imageLength = image.GetLength();
Preview preview = new Preview
{
@@ -326,7 +327,7 @@ namespace UVtools.Core.FileFormats
};
int i = 0;
for (int pixel = 0; pixel < span.Length; pixel += image.NumberOfChannels)
for (int pixel = 0; pixel < imageLength; pixel += image.NumberOfChannels)
{
// BGR
int b = span[pixel] >> 3;
@@ -424,10 +425,11 @@ namespace UVtools.Core.FileFormats
return EncodedRle;
}
private Mat DecodePWS()
private unsafe Mat DecodePWS()
{
var image = new Mat(new Size((int) Parent.ResolutionX, (int) Parent.ResolutionY), DepthType.Cv8U, 1);
var span = image.GetPixelSpan<byte>();
var image = EmguExtensions.InitMat(Parent.Resolution);
var span = image.GetBytePointer();
var imageLength = image.GetLength();
int index = 0;
for (byte bit = 0; bit < Parent.AntiAliasing; bit++)
@@ -450,13 +452,13 @@ namespace UVtools.Core.FileFormats
pixel += reps;
if (pixel == span.Length)
if (pixel == imageLength)
{
index++;
break;
}
if (pixel > span.Length)
if (pixel > imageLength)
{
image.Dispose();
throw new FileLoadException("Error image ran off the end");
@@ -464,7 +466,7 @@ namespace UVtools.Core.FileFormats
}
}
for (int i = 0; i < span.Length; i++)
for (int i = 0; i < imageLength; i++)
{
int newC = span[i] * (256 / Parent.AntiAliasing);
@@ -479,10 +481,11 @@ namespace UVtools.Core.FileFormats
return image;
}
public byte[] EncodePWS(Mat image)
public unsafe byte[] EncodePWS(Mat image)
{
List<byte> rawData = new List<byte>();
var span = image.GetPixelSpan<byte>();
var span = image.GetBytePointer();
var imageLength = image.GetLength();
bool obit;
int rep;
@@ -516,7 +519,7 @@ namespace UVtools.Core.FileFormats
byte threshold = (byte)(256 / Parent.AntiAliasing * aalevel - 1);
for (int pixel = 0; pixel < span.Length; pixel++)
for (int pixel = 0; pixel < imageLength; pixel++)
{
var nbit = span[pixel] >= threshold;
@@ -547,10 +550,11 @@ namespace UVtools.Core.FileFormats
return rawData.ToArray();
}
private Mat DecodePW0()
private unsafe Mat DecodePW0()
{
var image = new Mat(new Size((int)Parent.ResolutionX, (int)Parent.ResolutionY), DepthType.Cv8U, 1);
var span = image.GetPixelSpan<byte>();
var image = EmguExtensions.InitMat(Parent.Resolution);
var span = image.GetBytePointer();
var imageLength = image.GetLength();
uint n = 0;
for (int index = 0; index < EncodedRle.Length; index++)
@@ -590,32 +594,33 @@ namespace UVtools.Core.FileFormats
n += reps;
if (n == span.Length)
if (n == imageLength)
{
//index++;
break;
}
if (n > span.Length)
if (n > imageLength)
{
image.Dispose();
throw new FileLoadException($"Error image ran off the end: {n - reps}({reps}) of {span.Length}");
throw new FileLoadException($"Error image ran off the end: {n - reps}({reps}) of {imageLength}");
}
}
if (n != span.Length)
if (n != imageLength)
{
image.Dispose();
throw new FileLoadException($"Error image ended short: {n} of {span.Length}");
throw new FileLoadException($"Error image ended short: {n} of {imageLength}");
}
return image;
}
public byte[] EncodePW0(Mat image)
public unsafe byte[] EncodePW0(Mat image)
{
List<byte> rawData = new List<byte>();
var span = image.GetPixelSpan<byte>();
var span = image.GetBytePointer();
var imageLength = image.GetLength();
int lastColor = -1;
int reps = 0;
@@ -654,7 +659,7 @@ namespace UVtools.Core.FileFormats
}
}
for (int i = 0; i < span.Length; i++)
for (int i = 0; i < imageLength; i++)
{
int color = span[i] >> 4;
+28 -5
View File
@@ -877,11 +877,22 @@ namespace UVtools.GUI
{
var type = config.GetType();
tw.WriteLine($"[{type.Name}]");
foreach (var property in type.GetProperties())
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
tw.WriteLine($"{property.Name} = {property.GetValue(config)}");
if (property.Name.Equals("Item")) continue;
var value = property.GetValue(config);
switch (value)
{
case null:
continue;
case IList list:
tw.WriteLine($"{property.Name} = {list.Count}");
break;
default:
tw.WriteLine($"{property.Name} = {value}");
break;
}
}
tw.WriteLine();
}
@@ -910,9 +921,21 @@ namespace UVtools.GUI
{
var type = config.GetType();
sb.AppendLine($"[{type.Name}]");
foreach (var property in type.GetProperties())
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
sb.AppendLine($"{property.Name} = {property.GetValue(config)}");
if (property.Name.Equals("Item")) continue;
var value = property.GetValue(config);
switch (value)
{
case null:
continue;
case IList list:
sb.AppendLine($"{property.Name} = {list.Count}");
break;
default:
sb.AppendLine($"{property.Name} = {value}");
break;
}
}
sb.AppendLine();
+46 -10
View File
@@ -6,9 +6,11 @@
* of this license document, but changing it is not allowed.
*/
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Avalonia;
using Avalonia.Controls;
@@ -178,14 +180,24 @@ namespace UVtools.WPF
{
var type = config.GetType();
tw.WriteLine($"[{type.Name}]");
foreach (var property in type.GetProperties())
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
tw.WriteLine($"{property.Name} = {property.GetValue(config)}");
if (property.Name.Equals("Item")) continue;
var value = property.GetValue(config);
switch (value)
{
case null:
continue;
case IList list:
tw.WriteLine($"{property.Name} = {list.Count}");
break;
default:
tw.WriteLine($"{property.Name} = {value}");
break;
}
}
tw.WriteLine();
}
tw.Close();
}
}
@@ -211,9 +223,21 @@ namespace UVtools.WPF
{
var type = config.GetType();
sb.AppendLine($"[{type.Name}]");
foreach (var property in type.GetProperties())
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
sb.AppendLine($"{property.Name} = {property.GetValue(config)}");
if (property.Name.Equals("Item")) continue;
var value = property.GetValue(config);
switch (value)
{
case null:
continue;
case IList list:
sb.AppendLine($"{property.Name} = {list.Count}");
break;
default:
sb.AppendLine($"{property.Name} = {value}");
break;
}
}
sb.AppendLine();
@@ -225,14 +249,26 @@ namespace UVtools.WPF
public void RefreshProperties()
{
SlicerProperties.Clear();
if (!(SlicerFile.Configs is null))
{
if (SlicerFile.Configs is null) return;
foreach (var config in SlicerFile.Configs)
{
var type = config.GetType();
foreach (var property in type.GetProperties())
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
SlicerProperties.Add(new SlicerProperty(property.Name, property.GetValue(config, null)?.ToString(), type.Name));
if (property.Name.Equals("Item")) continue;
var value = property.GetValue(config);
switch (value)
{
case null:
continue;
case IList list:
SlicerProperties.Add(new SlicerProperty(property.Name, list.Count.ToString(),
config.GetType().Name));
break;
default:
SlicerProperties.Add(
new SlicerProperty(property.Name, value.ToString(), config.GetType().Name));
break;
}
}
}