4
4
using System . Buffers ;
5
5
using System . Numerics ;
6
6
using System . Runtime . CompilerServices ;
7
+ using System . Runtime . InteropServices ;
7
8
using SixLabors . ImageSharp . Advanced ;
8
9
using SixLabors . ImageSharp . Memory ;
9
10
using SixLabors . ImageSharp . PixelFormats ;
@@ -34,17 +35,25 @@ public OilPaintingProcessor(Configuration configuration, OilPaintingProcessor de
34
35
/// <inheritdoc/>
35
36
protected override void OnFrameApply ( ImageFrame < TPixel > source )
36
37
{
38
+ int levels = Math . Clamp ( this . definition . Levels , 1 , 255 ) ;
37
39
int brushSize = Math . Clamp ( this . definition . BrushSize , 1 , Math . Min ( source . Width , source . Height ) ) ;
38
40
39
41
using Buffer2D < TPixel > targetPixels = this . Configuration . MemoryAllocator . Allocate2D < TPixel > ( source . Size ( ) ) ;
40
42
41
43
source . CopyTo ( targetPixels ) ;
42
44
43
- RowIntervalOperation operation = new ( this . SourceRectangle , targetPixels , source . PixelBuffer , this . Configuration , brushSize >> 1 , this . definition . Levels ) ;
44
- ParallelRowIterator . IterateRowIntervals (
45
+ RowIntervalOperation operation = new ( this . SourceRectangle , targetPixels , source . PixelBuffer , this . Configuration , brushSize >> 1 , levels ) ;
46
+ try
47
+ {
48
+ ParallelRowIterator . IterateRowIntervals (
45
49
this . Configuration ,
46
50
this . SourceRectangle ,
47
51
in operation ) ;
52
+ }
53
+ catch ( Exception ex )
54
+ {
55
+ throw new ImageProcessingException ( "The OilPaintProcessor failed. The most likely reason is that a pixel component was outside of its' allowed range." , ex ) ;
56
+ }
48
57
49
58
Buffer2D < TPixel > . SwapOrCopyContent ( source . PixelBuffer , targetPixels ) ;
50
59
}
@@ -105,18 +114,18 @@ public void Invoke(in RowInterval rows)
105
114
Span < Vector4 > targetRowVector4Span = targetRowBuffer . Memory . Span ;
106
115
Span < Vector4 > targetRowAreaVector4Span = targetRowVector4Span . Slice ( this . bounds . X , this . bounds . Width ) ;
107
116
108
- ref float binsRef = ref bins . GetReference ( ) ;
109
- ref int intensityBinRef = ref Unsafe . As < float , int > ( ref binsRef ) ;
110
- ref float redBinRef = ref Unsafe . Add ( ref binsRef , ( uint ) this . levels ) ;
111
- ref float blueBinRef = ref Unsafe . Add ( ref redBinRef , ( uint ) this . levels ) ;
112
- ref float greenBinRef = ref Unsafe . Add ( ref blueBinRef , ( uint ) this . levels ) ;
117
+ Span < float > binsSpan = bins . GetSpan ( ) ;
118
+ Span < int > intensityBinsSpan = MemoryMarshal . Cast < float , int > ( binsSpan ) ;
119
+ Span < float > redBinSpan = binsSpan [ this . levels .. ] ;
120
+ Span < float > blueBinSpan = redBinSpan [ this . levels .. ] ;
121
+ Span < float > greenBinSpan = blueBinSpan [ this . levels .. ] ;
113
122
114
123
for ( int y = rows . Min ; y < rows . Max ; y ++ )
115
124
{
116
125
Span < TPixel > sourceRowPixelSpan = this . source . DangerousGetRowSpan ( y ) ;
117
126
Span < TPixel > sourceRowAreaPixelSpan = sourceRowPixelSpan . Slice ( this . bounds . X , this . bounds . Width ) ;
118
127
119
- PixelOperations < TPixel > . Instance . ToVector4 ( this . configuration , sourceRowAreaPixelSpan , sourceRowAreaVector4Span ) ;
128
+ PixelOperations < TPixel > . Instance . ToVector4 ( this . configuration , sourceRowAreaPixelSpan , sourceRowAreaVector4Span , PixelConversionModifiers . Scale ) ;
120
129
121
130
for ( int x = this . bounds . X ; x < this . bounds . Right ; x ++ )
122
131
{
@@ -140,29 +149,29 @@ public void Invoke(in RowInterval rows)
140
149
int offsetX = x + fxr ;
141
150
offsetX = Numerics . Clamp ( offsetX , 0 , maxX ) ;
142
151
143
- Vector4 vector = sourceOffsetRow [ offsetX ] . ToVector4 ( ) ;
152
+ Vector4 vector = sourceOffsetRow [ offsetX ] . ToScaledVector4 ( ) ;
144
153
145
154
float sourceRed = vector . X ;
146
155
float sourceBlue = vector . Z ;
147
156
float sourceGreen = vector . Y ;
148
157
149
158
int currentIntensity = ( int ) MathF . Round ( ( sourceBlue + sourceGreen + sourceRed ) / 3F * ( this . levels - 1 ) ) ;
150
159
151
- Unsafe . Add ( ref intensityBinRef , ( uint ) currentIntensity ) ++ ;
152
- Unsafe . Add ( ref redBinRef , ( uint ) currentIntensity ) + = sourceRed ;
153
- Unsafe . Add ( ref blueBinRef , ( uint ) currentIntensity ) + = sourceBlue ;
154
- Unsafe . Add ( ref greenBinRef , ( uint ) currentIntensity ) + = sourceGreen ;
160
+ intensityBinsSpan [ currentIntensity ] ++ ;
161
+ redBinSpan [ currentIntensity ] += sourceRed ;
162
+ blueBinSpan [ currentIntensity ] += sourceBlue ;
163
+ greenBinSpan [ currentIntensity ] += sourceGreen ;
155
164
156
- if ( Unsafe . Add ( ref intensityBinRef , ( uint ) currentIntensity ) > maxIntensity )
165
+ if ( intensityBinsSpan [ currentIntensity ] > maxIntensity )
157
166
{
158
- maxIntensity = Unsafe . Add ( ref intensityBinRef , ( uint ) currentIntensity ) ;
167
+ maxIntensity = intensityBinsSpan [ currentIntensity ] ;
159
168
maxIndex = currentIntensity ;
160
169
}
161
170
}
162
171
163
- float red = MathF . Abs ( Unsafe . Add ( ref redBinRef , ( uint ) maxIndex ) / maxIntensity ) ;
164
- float blue = MathF . Abs ( Unsafe . Add ( ref blueBinRef , ( uint ) maxIndex ) / maxIntensity ) ;
165
- float green = MathF . Abs ( Unsafe . Add ( ref greenBinRef , ( uint ) maxIndex ) / maxIntensity ) ;
172
+ float red = redBinSpan [ maxIndex ] / maxIntensity ;
173
+ float blue = blueBinSpan [ maxIndex ] / maxIntensity ;
174
+ float green = greenBinSpan [ maxIndex ] / maxIntensity ;
166
175
float alpha = sourceRowVector4Span [ x ] . W ;
167
176
168
177
targetRowVector4Span [ x ] = new Vector4 ( red , green , blue , alpha ) ;
@@ -171,7 +180,7 @@ public void Invoke(in RowInterval rows)
171
180
172
181
Span < TPixel > targetRowAreaPixelSpan = this . targetPixels . DangerousGetRowSpan ( y ) . Slice ( this . bounds . X , this . bounds . Width ) ;
173
182
174
- PixelOperations < TPixel > . Instance . FromVector4Destructive ( this . configuration , targetRowAreaVector4Span , targetRowAreaPixelSpan ) ;
183
+ PixelOperations < TPixel > . Instance . FromVector4Destructive ( this . configuration , targetRowAreaVector4Span , targetRowAreaPixelSpan , PixelConversionModifiers . Scale ) ;
175
184
}
176
185
}
177
186
}
0 commit comments