Skip to content

Commit

Permalink
v4.0.4
Browse files Browse the repository at this point in the history
- **FileFormat Anycubic:**
  - (Fix) Preview marker size and `PropertyFields` for given file version
  - (Fix) Do not cache and reuse layer images if equal on file write, as that is causing "file damage" message (#782, #787)
- **Tools:**
  - **Mask:**
    - (Improvement) Apply the mask with Multiply instead of BitwiseAnd (#747)
  - **Layer and pixel arithmetic**:
    - (Improvement) Use the byte scale value (1/255) for multiply operations
  - **Infill:**
    - (Add) Floor/Ceil thickness (#785)
    - (Fix) Remove the debug blocking window when selecting the honeycomb pattern
- (Upgrade) .NET from 6.0.23 to 6.0.24
  • Loading branch information
sn4k3 committed Nov 9, 2023
1 parent ffdcd89 commit 2caaba8
Show file tree
Hide file tree
Showing 26 changed files with 261 additions and 87 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/devskim.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Run DevSkim scanner
uses: microsoft/DevSkim-Action@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/package-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
timeout-minutes: 15
steps:
- name: 🛒 Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Verify commit exists in origin/master
run: |
Expand Down
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
# Changelog

## /10/2023 - v4.0.3
## 09/11/2023 - v4.0.4

- **FileFormat Anycubic:**
- (Fix) Preview marker size and `PropertyFields` for given file version
- (Fix) Do not cache and reuse layer images if equal on file write, as that is causing "file damage" message (#782, #787)
- **Tools:**
- **Mask:**
- (Improvement) Apply the mask with Multiply instead of BitwiseAnd (#747)
- **Layer and pixel arithmetic**:
- (Improvement) Use the byte scale value (1/255) for multiply operations
- **Infill:**
- (Add) Floor/Ceil thickness (#785)
- (Fix) Remove the debug blocking window when selecting the honeycomb pattern
- (Upgrade) .NET from 6.0.23 to 6.0.24

## 19/10/2023 - v4.0.3

- (Change) macOS: Change from Control to Command key to activate shortcuts from main menu (#766)
- (Upgrade) .NET from 6.0.22 to 6.0.23
Expand Down
3 changes: 2 additions & 1 deletion CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,5 @@
- Kevin Bullmann
- Robert Redden
- Nick Spirov
- Sylvain Chartrand
- Sylvain Chartrand
- Michael Pullen
15 changes: 12 additions & 3 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
- (Change) macOS: Change from Control to Command key to activate shortcuts from main menu (#766)
- (Upgrade) .NET from 6.0.22 to 6.0.23
- (Upgrade) AvaloniaUI from 11.0.4 to 11.0.5
- **FileFormat Anycubic:**
- (Fix) Preview marker size and `PropertyFields` for given file version
- (Fix) Do not cache and reuse layer images if equal on file write, as that is causing "file damage" message (#782, #787)
- **Tools:**
- **Mask:**
- (Improvement) Apply the mask with Multiply instead of BitwiseAnd (#747)
- **Layer and pixel arithmetic**:
- (Improvement) Use the byte scale value (1/255) for multiply operations
- **Infill:**
- (Add) Floor/Ceil thickness (#785)
- (Fix) Remove the debug blocking window when selecting the honeycomb pattern
- (Upgrade) .NET from 6.0.23 to 6.0.24

3 changes: 2 additions & 1 deletion Scripts/010 Editor/PhotonWorkshop.bt
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ if(fileMark.PreviewAddress > 0){
}

typedef struct(int size) {
BYTE layerDataBlock[size] <fgcolor=cBlack, bgcolor=0x00FF00>;
ubyte layerDataBlock[size] <fgcolor=cBlack, bgcolor=0x00FF00>;
} layerRawData;

if(fileMark.Version >= 515 && fileMark.LayerImageColorAddress > 0)
Expand Down Expand Up @@ -298,6 +298,7 @@ if(fileMark.LayerDefinitionAddress > 0){
struct LAYERSDATA{
local uint i;
for( i = 0; i < layerDefinition.LayerCount; i++ ){
FSeek(layers.layerDef[i].DataAddress);
layerRawData lD(layers.layerDef[i].DataLength);
}
} layersData;
Expand Down
4 changes: 2 additions & 2 deletions UVtools.Core/Extensions/DrawingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ namespace UVtools.Core.Extensions;
public static class DrawingExtensions
{
public static Color FactorColor(this Color color, byte pixelColor, byte min = 0, byte max = byte.MaxValue) =>
FactorColor(color, pixelColor / 255f, min, max);
FactorColor(color, pixelColor / 255.0, min, max);

public static Color FactorColor(this Color color, float factor, byte min = 0, byte max = byte.MaxValue)
public static Color FactorColor(this Color color, double factor, byte min = 0, byte max = byte.MaxValue)
{
byte r = (byte)(color.R == 0 ? 0 :
Math.Min(Math.Max(min, color.R * factor), max));
Expand Down
7 changes: 7 additions & 0 deletions UVtools.Core/Extensions/EmguExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ public static class EmguExtensions

public static readonly Point AnchorCenter = new (-1, -1);
public static readonly Mat Kernel3x3Rectangle = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), AnchorCenter);

/// <summary>
/// Gets the scale relation for 0-255 byte value.<br/>
/// Constant for: 1/255.0 = 0.00392156862745098039
/// </summary>
/// <remarks>Last three digits will drop (...039)</remarks>
public const double ByteScale = 1 / 255.0;
#endregion

#region Initializers methods
Expand Down
16 changes: 9 additions & 7 deletions UVtools.Core/FileFormats/PhotonWorkshopFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ public override string ToString()
public class Preview : AnycubicNamedTable
{
protected override string DefaultTableName => "PREVIEW";
protected override bool IncludeBaseTableLength => true;

/// <summary>
/// Gets the image width, in pixels.
Expand Down Expand Up @@ -568,7 +569,7 @@ public class Machine : AnycubicNamedTable
[FieldOrder(0)][FieldLength(96)][SerializeAs(SerializedType.TerminatedString)] public string MachineName { get; set; } = null!;
[FieldOrder(1)][FieldLength(16)][SerializeAs(SerializedType.TerminatedString)] public string LayerImageFormat { get; set; } = "pw0img";
[FieldOrder(2)] public uint MaxAntialiasingLevel { get; set; } = 16;
[FieldOrder(3)] public uint PropertyFields { get; set; } = 7;
[FieldOrder(3)] public uint PropertyFields { get; set; } = 1;
[FieldOrder(4)] public float DisplayWidth { get; set; }
[FieldOrder(5)] public float DisplayHeight { get; set; }
[FieldOrder(6)] public float MachineZ { get; set; }
Expand Down Expand Up @@ -1935,7 +1936,8 @@ protected override void EncodeInternally(OperationProgress progress)
MachineSettings.PropertyFields = Version switch
{
>= VERSION_518 => 15,
_ => 7
>= VERSION_517 => 7,
_ => 1
};

HeaderSettings.PixelSizeUm = PixelSizeMicronsMax;
Expand Down Expand Up @@ -2018,7 +2020,7 @@ protected override void EncodeInternally(OperationProgress progress)
FileMarkSettings.ExtraAddress = FileMarkSettings.LayerImageAddress;
}

var layersHash = new Dictionary<string, LayerDef>();
//var layersHash = new Dictionary<string, LayerDef>();

foreach (var batch in BatchLayersIndexes())
{
Expand All @@ -2040,24 +2042,24 @@ protected override void EncodeInternally(OperationProgress progress)

var layerDef = LayersDefinition.Layers[layerIndex];

var hash = CryptExtensions.ComputeSHA1Hash(layerDef.EncodedRle);
/*var hash = CryptExtensions.ComputeSHA1Hash(layerDef.EncodedRle);
if (layersHash.TryGetValue(hash, out var layerDataHash))
{
layerDef.DataAddress = layerDataHash.DataAddress;
layerDef.DataLength = layerDataHash.DataLength;
}
else
{
{*/
layerDef.DataAddress = (uint)outputFile.Position;
SubLayersDefinition[layerIndex].SetFrom(layerDef);


layersHash.Add(hash, layerDef);
//layersHash.Add(hash, layerDef);

outputFile.WriteBytes(layerDef.EncodedRle);
layerDef.EncodedRle = null!;
}
//}
}
}

Expand Down
2 changes: 1 addition & 1 deletion UVtools.Core/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ public static void SwapVariables<T>(ref T var1, ref T var2)
(var1, var2) = (var2, var1);
}

public static float BrightnessToPercent(byte brightness, byte roundPlates = 2) => (float)Math.Round(brightness * 100 / 255f, roundPlates);
public static float BrightnessToPercent(byte brightness, byte roundPlates = 2) => (float)Math.Round(brightness * 100 / 255.0, roundPlates);
}
101 changes: 80 additions & 21 deletions UVtools.Core/Operations/OperationInfill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@
using System.Threading.Tasks;
using UVtools.Core.Extensions;
using UVtools.Core.FileFormats;
using UVtools.Core.Layers;

namespace UVtools.Core.Operations;


public sealed class OperationInfill : Operation
public sealed class OperationInfill : Operation, IEquatable<OperationInfill>
{
#region Members
private InfillAlgorithm _infillType = InfillAlgorithm.CubicCrossAlternating;
private decimal _floorCeilThickness = 3.0m;
private ushort _wallThickness = 64;
private ushort _infillThickness = 45;
private ushort _infillSpacing = 300;
Expand Down Expand Up @@ -87,6 +89,12 @@ public InfillAlgorithm InfillType
set => RaiseAndSetIfChanged(ref _infillType, value);
}

public decimal FloorCeilThickness
{
get => _floorCeilThickness;
set => RaiseAndSetIfChanged(ref _floorCeilThickness, value);
}

public ushort WallThickness
{
get => _wallThickness;
Expand Down Expand Up @@ -119,7 +127,7 @@ public bool ReinforceInfill

public override string ToString()
{
var result = $"[{_infillType}] [Wall: {_wallThickness}px] [B: {_infillBrightness}px] [T: {_infillThickness}px] [S: {_infillSpacing}px] [R: {_reinforceInfill}]" + LayerRangeString;
var result = $"[{_infillType}] [Floor/Ceil: {_floorCeilThickness}mm] [Wall: {_wallThickness}px] [B: {_infillBrightness}px] [T: {_infillThickness}px] [S: {_infillSpacing}px] [R: {_reinforceInfill}]" + LayerRangeString;
if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
return result;
}
Expand All @@ -136,9 +144,11 @@ public OperationInfill(FileFormat slicerFile) : base(slicerFile) { }

#region Equality

private bool Equals(OperationInfill other)
public bool Equals(OperationInfill? other)
{
return _infillType == other._infillType && _wallThickness == other._wallThickness && _infillThickness == other._infillThickness && _infillSpacing == other._infillSpacing && _infillBrightness == other._infillBrightness && _reinforceInfill == other._reinforceInfill;
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return _infillType == other._infillType && _floorCeilThickness == other._floorCeilThickness && _wallThickness == other._wallThickness && _infillThickness == other._infillThickness && _infillSpacing == other._infillSpacing && _infillBrightness == other._infillBrightness && _reinforceInfill == other._reinforceInfill;
}

public override bool Equals(object? obj)
Expand All @@ -148,7 +158,17 @@ public override bool Equals(object? obj)

public override int GetHashCode()
{
return HashCode.Combine((int) _infillType, _wallThickness, _infillThickness, _infillSpacing, _infillBrightness, _reinforceInfill);
return HashCode.Combine((int)_infillType, _floorCeilThickness, _wallThickness, _infillThickness, _infillSpacing, _infillBrightness, _reinforceInfill);
}

public static bool operator ==(OperationInfill? left, OperationInfill? right)
{
return Equals(left, right);
}

public static bool operator !=(OperationInfill? left, OperationInfill? right)
{
return !Equals(left, right);
}

#endregion
Expand All @@ -161,19 +181,21 @@ protected override bool ExecuteInternally(OperationProgress progress)
if (_infillType == InfillAlgorithm.Honeycomb)
{
mask = GetHoneycombMask(GetRoiSizeOrVolumeSize());
CvInvoke.Imshow("Honeycomb", mask);
CvInvoke.WaitKey();
//CvInvoke.Imshow("Honeycomb", mask);
//CvInvoke.WaitKey();
}
else if (_infillType == InfillAlgorithm.Concentric)
{
mask = GetConcentricMask(GetRoiSizeOrVolumeSize());
}

var clonedLayers = SlicerFile.CloneLayers();

Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
{
progress.PauseIfRequested();
using var mat = SlicerFile[layerIndex].LayerMat;
Execute(mat, layerIndex, mask!);
Execute(mat, layerIndex, mask!, clonedLayers);
SlicerFile[layerIndex].LayerMat = mat;

progress.LockAndIncrement();
Expand All @@ -184,17 +206,18 @@ protected override bool ExecuteInternally(OperationProgress progress)

public override bool Execute(Mat mat, params object[]? arguments)
{
if (arguments is null || arguments.Length < 1) return false;
if (arguments is null || arguments.Length < 3) return false;

var kernel = EmguExtensions.Kernel3x3Rectangle;
var infillColor = new MCvScalar(_infillBrightness);
uint index = Convert.ToUInt32(arguments[0]);
uint layerIndex = index - LayerIndexStart;
var infillColor = new MCvScalar(_infillBrightness);
var clonedLayers = (Layer[])arguments[2];

Mat? patternMask = null;
using Mat erode = new ();
using Mat diff = new ();
var target = GetRoiOrVolumeBounds(mat);
using var erode = new Mat();
using var diff = new Mat();
using var target = GetRoiOrVolumeBounds(mat);
using var mask = GetMask(mat);
bool disposeTargetMask = true;

Expand Down Expand Up @@ -331,8 +354,7 @@ or InfillAlgorithm.CubicCrossAlternating
}


CvInvoke.Repeat(infillPattern, target.Rows / infillPattern.Rows + 1,
target.Cols / infillPattern.Cols + 1, matPattern);
CvInvoke.Repeat(infillPattern, target.Rows / infillPattern.Rows + 1, target.Cols / infillPattern.Cols + 1, matPattern);
patternMask = matPattern.Roi(target);
disposeTargetMask = true;
}
Expand Down Expand Up @@ -466,18 +488,55 @@ or InfillAlgorithm.CubicCrossAlternating
disposeTargetMask = true;
}

using var surfaceMat = target.Clone();

decimal heightAccumulator = (decimal)SlicerFile[index].LayerHeight;
if (_floorCeilThickness > heightAccumulator)
{
for (int floorLayerIndex = (int)(index - 1); heightAccumulator <= _floorCeilThickness && floorLayerIndex >= 0; floorLayerIndex--)
{
using var floorMat = clonedLayers[floorLayerIndex].LayerMat;
using var floorMatRoi = GetRoiOrVolumeBounds(floorMat);

CvInvoke.BitwiseAnd(surfaceMat, floorMatRoi, surfaceMat);

heightAccumulator += (decimal)SlicerFile[floorLayerIndex + 1].PositionZ - (decimal)SlicerFile[floorLayerIndex].PositionZ;
}

if (heightAccumulator <= _floorCeilThickness) return true;

heightAccumulator = (decimal)SlicerFile[index].LayerHeight;
for (var ceilLayerIndex = index + 1; heightAccumulator <= _floorCeilThickness && ceilLayerIndex <= SlicerFile.LastLayerIndex; ceilLayerIndex++)
{
using var ceilMat = clonedLayers[ceilLayerIndex].LayerMat;
using var ceilMatRoi = GetRoiOrVolumeBounds(ceilMat);

CvInvoke.BitwiseAnd(surfaceMat, ceilMatRoi, surfaceMat);

heightAccumulator += (decimal)SlicerFile[ceilLayerIndex].PositionZ - (decimal)SlicerFile[ceilLayerIndex - 1].PositionZ;
}

if (heightAccumulator <= _floorCeilThickness) return true;
}


//patternMask.Save("D:\\pattern.png");
CvInvoke.Erode(target, erode, kernel, EmguExtensions.AnchorCenter, WallThickness, BorderType.Reflect101,
default);
CvInvoke.Subtract(target, erode, diff);
CvInvoke.Erode(target, erode, kernel, EmguExtensions.AnchorCenter, WallThickness, BorderType.Reflect101, default);

CvInvoke.BitwiseAnd(erode, surfaceMat, erode, mask);
patternMask!.CopyTo(target, erode);
//target.SetTo(EmguExtensions.BlackColor, erode);
//erode.CopyTo(target);
//CvInvoke.BitwiseOr(target, patternMask, target, erode);


CvInvoke.BitwiseAnd(erode, patternMask, target, mask);
CvInvoke.Add(target, diff, target, mask);
//CvInvoke.Subtract(target, erode, diff);
//CvInvoke.BitwiseAnd(erode, patternMask, target, mask);
//CvInvoke.Add(target, diff, target, mask);

if (disposeTargetMask)
{
patternMask!.Dispose();
patternMask.Dispose();
}

return true;
Expand Down
Loading

0 comments on commit 2caaba8

Please sign in to comment.