From eb590c36576ca5b16d6721f51fee16b4f50ea202 Mon Sep 17 00:00:00 2001 From: Finn Neuik Date: Mon, 27 Sep 2021 19:25:48 +0100 Subject: [PATCH] Switched to uniform noise offset, added ui. Added switch to random offset as it smooths the diffusion service by leveraging grey values. Added UI, preserves void option duplicates the "model only" option but is significantly faster as it avoid the calculation for void voxels. Incorporated crypto random and using spans for array access based on PR feedback. --- .../Operations/OperationPixelArithmetic.cs | 62 ++++++++++++------ .../Tools/ToolPixelArithmeticControl.axaml | 64 ++++++++++++++++--- 2 files changed, 97 insertions(+), 29 deletions(-) diff --git a/UVtools.Core/Operations/OperationPixelArithmetic.cs b/UVtools.Core/Operations/OperationPixelArithmetic.cs index 83da85b..3f473f4 100644 --- a/UVtools.Core/Operations/OperationPixelArithmetic.cs +++ b/UVtools.Core/Operations/OperationPixelArithmetic.cs @@ -10,7 +10,7 @@ using System; using System.ComponentModel; using System.Diagnostics; using System.Drawing; -using System.Runtime.InteropServices; +using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using System.Xml.Serialization; @@ -58,7 +58,10 @@ namespace UVtools.Core.Operations private byte _patternGenBrightness = 128; private byte _patternGenInfillThickness = 10; private byte _patternGenInfillSpacing = 20; - + private bool _preserveVoids = true; + private int _minNoiseOffset = -128; + private int _maxNoiseOffset = 128; + #endregion @@ -97,7 +100,7 @@ namespace UVtools.Core.Operations KeepRegion, [Description("Discard Region: in the selected ROI or masks")] DiscardRegion, - [Description("Corrode: randomly remove pixels, adds microtexture and diffuses layer lines (WIP)")] + [Description("Corrode: diffuse pixels using uniform random noise")] Corrode } @@ -166,6 +169,10 @@ namespace UVtools.Core.Operations { sb.AppendLine("Can't divide by 0."); } + else if (_operator == PixelArithmeticOperators.Corrode && _minNoiseOffset >= _maxNoiseOffset) + { + sb.AppendLine("Minimum noise offset must be less than the maximum offset."); + } if (_applyMethod is PixelArithmeticApplyMethod.ModelWalls //or PixelArithmeticApplyMethod.ModelWallsMinimum && ( @@ -255,6 +262,7 @@ namespace UVtools.Core.Operations RaisePropertyChanged(nameof(IsUsePatternVisible)); RaisePropertyChanged(nameof(ThresholdEnabled)); RaisePropertyChanged(nameof(IsApplyMethodEnabled)); + RaisePropertyChanged(nameof(IsDiffusionSettingsVisible)); } } @@ -301,6 +309,27 @@ namespace UVtools.Core.Operations set => RaiseAndSetIfChanged(ref _wallChamfer, value); } + + public bool IsDiffusionSettingsVisible => _operator is PixelArithmeticOperators.Corrode; + + public bool PreserveVoids + { + get => _preserveVoids; + set => RaiseAndSetIfChanged(ref _preserveVoids, value); + } + + public int NoiseMinOffset + { + get => _minNoiseOffset; + set => RaiseAndSetIfChanged(ref _minNoiseOffset, value); + } + + public int NoiseMaxOffset + { + get => _maxNoiseOffset; + set => RaiseAndSetIfChanged(ref _maxNoiseOffset, value); + } + public byte Value { get => _value; @@ -653,28 +682,18 @@ namespace UVtools.Core.Operations break; case PixelArithmeticOperators.Corrode: { - byte[,] originalData = (byte[,])target.GetData(); // don't need for now, but needed for more subtle noise effects - byte[,] targetData = (byte[,])target.GetData(); + var pixels = target.GetDataByteSpan(); - var zeroMatEntry = new byte[] { 0 }; // add value to ui (or maybe replace by a dimming option) - var noiseThreshold = 280; // add value to ui, values > 255 delete white and increases corrosion intensity - - var rand = new Random(); - for (int i = original.Rows - 1; i >= 0; i--) + for (int i = pixels.Length - 1; i >= 0; i--) { - for (int j = original.Cols - 1; j >= 0; j--) + if (!_preserveVoids || pixels[i] > 0) { - if (originalData[i, j] > 0 - && rand.Next(noiseThreshold) >= originalData[i, j]) - { - // target.SetByte(i, j, 0); not sure why this form (also when reading) isn't working - // so using direct byte copy to array instead, seems equivalent - - Marshal.Copy(zeroMatEntry, 0, target.DataPointer + (i * target.Cols + j) * target.ElementSize, 1); - } + pixels[i] = (byte) Math.Clamp(RandomNumberGenerator.GetInt32(_minNoiseOffset, _maxNoiseOffset) + pixels[i], byte.MinValue, byte.MaxValue); } } + if (_applyMethod != PixelArithmeticApplyMethod.All) ApplyMask(originalRoi, target, applyMask); + break; } default: @@ -1190,7 +1209,7 @@ namespace UVtools.Core.Operations protected bool Equals(OperationPixelArithmetic other) { - return _operator == other._operator && _applyMethod == other._applyMethod && _wallThicknessStart == other._wallThicknessStart && _wallThicknessEnd == other._wallThicknessEnd && _wallChamfer == other._wallChamfer && _value == other._value && _usePattern == other._usePattern && _thresholdType == other._thresholdType && _thresholdMaxValue == other._thresholdMaxValue && _patternAlternatePerLayersNumber == other._patternAlternatePerLayersNumber && _patternInvert == other._patternInvert && _patternText == other._patternText && _patternTextAlternate == other._patternTextAlternate && _patternGenMinBrightness == other._patternGenMinBrightness && _patternGenBrightness == other._patternGenBrightness && _patternGenInfillThickness == other._patternGenInfillThickness && _patternGenInfillSpacing == other._patternGenInfillSpacing; + return _operator == other._operator && _applyMethod == other._applyMethod && _wallThicknessStart == other._wallThicknessStart && _wallThicknessEnd == other._wallThicknessEnd && _wallChamfer == other._wallChamfer && _value == other._value && _usePattern == other._usePattern && _thresholdType == other._thresholdType && _thresholdMaxValue == other._thresholdMaxValue && _patternAlternatePerLayersNumber == other._patternAlternatePerLayersNumber && _patternInvert == other._patternInvert && _patternText == other._patternText && _patternTextAlternate == other._patternTextAlternate && _patternGenMinBrightness == other._patternGenMinBrightness && _patternGenBrightness == other._patternGenBrightness && _patternGenInfillThickness == other._patternGenInfillThickness && _patternGenInfillSpacing == other._patternGenInfillSpacing && _preserveVoids == other._preserveVoids && _minNoiseOffset == other._minNoiseOffset && _maxNoiseOffset == other._maxNoiseOffset; } public override bool Equals(object obj) @@ -1221,6 +1240,9 @@ namespace UVtools.Core.Operations hashCode.Add(_patternGenBrightness); hashCode.Add(_patternGenInfillThickness); hashCode.Add(_patternGenInfillSpacing); + hashCode.Add(_preserveVoids); + hashCode.Add(_minNoiseOffset); + hashCode.Add(_maxNoiseOffset); return hashCode.ToHashCode(); } diff --git a/UVtools.WPF/Controls/Tools/ToolPixelArithmeticControl.axaml b/UVtools.WPF/Controls/Tools/ToolPixelArithmeticControl.axaml index 9b0f8e2..a45bb08 100644 --- a/UVtools.WPF/Controls/Tools/ToolPixelArithmeticControl.axaml +++ b/UVtools.WPF/Controls/Tools/ToolPixelArithmeticControl.axaml @@ -6,7 +6,7 @@ x:Class="UVtools.WPF.Controls.Tools.ToolPixelArithmeticControl"> - - + + + + + + + + + + + + + + + + + + - - - - - - -