/
MedianSketchGpuEffect.cs
103 lines (83 loc) · 3.74 KB
/
MedianSketchGpuEffect.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using PaintDotNet;
using PaintDotNet.Direct2D1;
using PaintDotNet.Direct2D1.Effects;
using PaintDotNet.Effects;
using PaintDotNet.Effects.Gpu;
using PaintDotNet.IndirectUI;
using PaintDotNet.PropertySystem;
using System;
using System.Collections.Generic;
namespace MedianSketch;
internal sealed partial class MedianSketchGpuEffect
: PropertyBasedGpuImageEffect
{
public MedianSketchGpuEffect()
: base(
"Median Sketch",
SubmenuNames.Artistic,
GpuImageEffectOptions.Create() with
{
IsConfigurable = true
})
{
}
private enum PropertyNames
{
Radius,
Percentile,
Iterations
}
protected override PropertyCollection OnCreatePropertyCollection()
{
List<Property> props = new List<Property>();
props.Add(new DoubleProperty(PropertyNames.Radius, 25, 0, MedianApproximationEffect.MaxRadius));
props.Add(new Int32Property(PropertyNames.Percentile, 50, 0, 100));
props.Add(new Int32Property(PropertyNames.Iterations, 3, 1, 20));
return new PropertyCollection(props);
}
protected override ControlInfo OnCreateConfigUI(PropertyCollection props)
{
ControlInfo configUI = CreateDefaultConfigUI(props);
configUI.SetPropertyControlValue(PropertyNames.Radius, ControlInfoPropertyNames.DisplayName, "Radius");
configUI.SetPropertyControlValue(PropertyNames.Radius, ControlInfoPropertyNames.ShowHeaderLine, false);
configUI.SetPropertyControlValue(PropertyNames.Percentile, ControlInfoPropertyNames.DisplayName, "Percentile");
configUI.SetPropertyControlValue(PropertyNames.Percentile, ControlInfoPropertyNames.ShowHeaderLine, false);
configUI.SetPropertyControlValue(PropertyNames.Iterations, ControlInfoPropertyNames.DisplayName, "Iterations");
configUI.SetPropertyControlValue(PropertyNames.Iterations, ControlInfoPropertyNames.ShowHeaderLine, false);
return configUI;
}
protected override void OnInitializeRenderInfo(IGpuImageEffectRenderInfo renderInfo)
{
renderInfo.InputAlphaMode = GpuEffectAlphaMode.Straight;
renderInfo.OutputAlphaMode = GpuEffectAlphaMode.Straight;
base.OnInitializeRenderInfo(renderInfo);
}
private MedianApproximationEffect? medianEffect;
protected override void OnInvalidateDeviceResources()
{
DisposableUtil.Free(ref this.medianEffect);
base.OnInvalidateDeviceResources();
}
protected override IDeviceImage OnCreateOutput(IDeviceContext deviceContext)
{
this.medianEffect = new MedianApproximationEffect(deviceContext);
this.medianEffect.Properties.Input.Set(this.Environment.SourceImage);
this.medianEffect.Properties.SampleCountPercent.SetValue(0.01f);
this.medianEffect.Properties.EdgeMode.SetValue(BorderEdgeMode2.Mirror);
return this.medianEffect;
}
protected override InspectTokenAction OnInspectTokenChanges(PropertyBasedEffectConfigToken oldToken, PropertyBasedEffectConfigToken newToken)
{
return InspectTokenAction.UpdateOutput;
}
protected override unsafe void OnUpdateOutput(IDeviceContext deviceContext)
{
double radius = this.Token!.GetProperty<DoubleProperty>(PropertyNames.Radius)!.Value;
int percentile = this.Token!.GetProperty<Int32Property>(PropertyNames.Percentile)!.Value;
int iterations = this.Token!.GetProperty<Int32Property>(PropertyNames.Iterations)!.Value;
this.medianEffect!.Properties.Radius.SetValue((float)radius);
this.medianEffect!.Properties.Percentile.SetValue(percentile / 100.0f);
this.medianEffect!.Properties.Iterations.SetValue(iterations);
base.OnUpdateOutput(deviceContext);
}
}