mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-10 02:22:32 +02:00
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.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
x:Class="UVtools.WPF.Controls.Tools.ToolPixelArithmeticControl">
|
||||
|
||||
<Grid RowDefinitions="Auto,10,Auto">
|
||||
<Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto"
|
||||
<Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto, 10, Auto"
|
||||
ColumnDefinitions="Auto,10,Auto,20,Auto,10,Auto,20,Auto,10,Auto">
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
@@ -70,13 +70,59 @@
|
||||
IsChecked="{Binding Operation.WallChamfer}"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0"
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding Operation.IsDiffusionSettingsVisible}"
|
||||
Text="Diffusion:"/>
|
||||
|
||||
<StackPanel Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="9"
|
||||
IsVisible="{Binding Operation.IsDiffusionSettingsVisible}"
|
||||
Spacing="10" Orientation="Horizontal">
|
||||
|
||||
<CheckBox
|
||||
Margin="10,0,0,0"
|
||||
Content="Preserve voids"
|
||||
ToolTip.Tip="Preserve voids (black pixels) when applying diffusion."
|
||||
IsChecked="{Binding Operation.PreserveVoids}"/>
|
||||
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="Noise range:"/>
|
||||
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="Min:"/>
|
||||
|
||||
<NumericUpDown
|
||||
Minimum="-1000"
|
||||
Maximum="1000"
|
||||
Width="80"
|
||||
Value="{Binding Operation.NoiseMinOffset}"
|
||||
ToolTip.Tip="Minimum value of random noise offset."
|
||||
IsEnabled="true"/>
|
||||
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="Max:"/>
|
||||
|
||||
<NumericUpDown
|
||||
Minimum="-1000"
|
||||
Maximum="1000"
|
||||
Width="80"
|
||||
Value="{Binding Operation.NoiseMaxOffset}"
|
||||
ToolTip.Tip="Maximum value of random noise offset."
|
||||
IsEnabled="true"/>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Row="8" Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding Operation.ValueEnabled}"
|
||||
IsEnabled="{Binding Operation.ValueEnabled}"
|
||||
Text="Brightness:"/>
|
||||
|
||||
<StackPanel Grid.Row="6" Grid.Column="2"
|
||||
<StackPanel Grid.Row="8" Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal" Spacing="5"
|
||||
IsVisible="{Binding Operation.ValueEnabled}"
|
||||
@@ -101,28 +147,28 @@
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="4"
|
||||
<TextBlock Grid.Row="8" Grid.Column="4"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
IsVisible="{Binding Operation.ThresholdEnabled}"
|
||||
IsEnabled="{Binding Operation.ThresholdEnabled}"
|
||||
Text="Max.:"/>
|
||||
|
||||
<NumericUpDown Grid.Row="6" Grid.Column="6"
|
||||
<NumericUpDown Grid.Row="8" Grid.Column="6"
|
||||
Minimum="0"
|
||||
Maximum="255"
|
||||
IsVisible="{Binding Operation.ThresholdEnabled}"
|
||||
IsEnabled="{Binding Operation.ThresholdEnabled}"
|
||||
Value="{Binding Operation.ThresholdMaxValue}"/>
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="8"
|
||||
<TextBlock Grid.Row="8" Grid.Column="8"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
IsVisible="{Binding Operation.ThresholdEnabled}"
|
||||
IsEnabled="{Binding Operation.ThresholdEnabled}"
|
||||
Text="Threshold:"/>
|
||||
|
||||
<ComboBox Grid.Row="6" Grid.Column="10"
|
||||
<ComboBox Grid.Row="8" Grid.Column="10"
|
||||
Width="130"
|
||||
IsVisible="{Binding Operation.ThresholdEnabled}"
|
||||
IsEnabled="{Binding Operation.ThresholdEnabled}"
|
||||
@@ -130,11 +176,11 @@
|
||||
SelectedItem="{Binding Operation.ThresholdType, Converter={StaticResource FromValueDescriptionToEnumConverter}}"/>
|
||||
|
||||
|
||||
<TextBlock Grid.Row="8" Grid.Column="0"
|
||||
<TextBlock Grid.Row="10" Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="Presets:"/>
|
||||
|
||||
<StackPanel Grid.Row="8" Grid.Column="2"
|
||||
<StackPanel Grid.Row="10" Grid.Column="2"
|
||||
Grid.ColumnSpan="9"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal" Spacing="5">
|
||||
|
||||
Reference in New Issue
Block a user