33
44using System . Buffers ;
55using System . Numerics ;
6- using SixLabors . ImageSharp . Memory ;
76
87namespace SixLabors . ImageSharp . PixelFormats ;
98
@@ -52,16 +51,53 @@ public void Blend<TPixelSrc>(
5251 Guard . MustBeBetweenOrEqualTo ( amount , 0 , 1 , nameof ( amount ) ) ;
5352
5453 using IMemoryOwner < Vector4 > buffer = configuration . MemoryAllocator . Allocate < Vector4 > ( maxLength * 3 ) ;
55- Span < Vector4 > destinationVectors = buffer . Slice ( 0 , maxLength ) ;
56- Span < Vector4 > backgroundVectors = buffer . Slice ( maxLength , maxLength ) ;
57- Span < Vector4 > sourceVectors = buffer . Slice ( maxLength * 2 , maxLength ) ;
54+ this . Blend (
55+ configuration ,
56+ destination ,
57+ background ,
58+ source ,
59+ amount ,
60+ buffer . Memory . Span [ ..( maxLength * 3 ) ] ) ;
61+ }
62+
63+ /// <summary>
64+ /// Blends 2 rows together using caller-provided temporary vector scratch.
65+ /// </summary>
66+ /// <typeparam name="TPixelSrc">the pixel format of the source span</typeparam>
67+ /// <param name="configuration"><see cref="Configuration"/> to use internally</param>
68+ /// <param name="destination">the destination span</param>
69+ /// <param name="background">the background span</param>
70+ /// <param name="source">the source span</param>
71+ /// <param name="amount">
72+ /// A value between 0 and 1 indicating the weight of the second source vector.
73+ /// At amount = 0, "background" is returned, at amount = 1, "source" is returned.
74+ /// </param>
75+ /// <param name="workingBuffer">Reusable temporary vector scratch with capacity for at least 3 rows.</param>
76+ public void Blend < TPixelSrc > (
77+ Configuration configuration ,
78+ Span < TPixel > destination ,
79+ ReadOnlySpan < TPixel > background ,
80+ ReadOnlySpan < TPixelSrc > source ,
81+ float amount ,
82+ Span < Vector4 > workingBuffer )
83+ where TPixelSrc : unmanaged, IPixel < TPixelSrc >
84+ {
85+ int maxLength = destination . Length ;
86+ Guard . MustBeGreaterThanOrEqualTo ( background . Length , maxLength , nameof ( background . Length ) ) ;
87+ Guard . MustBeGreaterThanOrEqualTo ( source . Length , maxLength , nameof ( source . Length ) ) ;
88+ Guard . MustBeBetweenOrEqualTo ( amount , 0 , 1 , nameof ( amount ) ) ;
89+ Guard . MustBeGreaterThanOrEqualTo ( workingBuffer . Length , maxLength * 3 , nameof ( workingBuffer . Length ) ) ;
90+
91+ Span < Vector4 > destinationVectors = workingBuffer [ ..maxLength ] ;
92+ Span < Vector4 > backgroundVectors = workingBuffer . Slice ( maxLength , maxLength ) ;
93+ Span < Vector4 > sourceVectors = workingBuffer . Slice ( maxLength * 2 , maxLength ) ;
5894
5995 PixelOperations < TPixel > . Instance . ToVector4 ( configuration , background [ ..maxLength ] , backgroundVectors , PixelConversionModifiers . Scale ) ;
6096 PixelOperations < TPixelSrc > . Instance . ToVector4 ( configuration , source [ ..maxLength ] , sourceVectors , PixelConversionModifiers . Scale ) ;
6197
6298 this . BlendFunction ( destinationVectors , backgroundVectors , sourceVectors , amount ) ;
6399
64- PixelOperations < TPixel > . Instance . FromVector4Destructive ( configuration , destinationVectors [ .. maxLength ] , destination , PixelConversionModifiers . Scale ) ;
100+ PixelOperations < TPixel > . Instance . FromVector4Destructive ( configuration , destinationVectors , destination , PixelConversionModifiers . Scale ) ;
65101 }
66102
67103 /// <summary>
@@ -87,14 +123,48 @@ public void Blend(
87123 Guard . MustBeBetweenOrEqualTo ( amount , 0 , 1 , nameof ( amount ) ) ;
88124
89125 using IMemoryOwner < Vector4 > buffer = configuration . MemoryAllocator . Allocate < Vector4 > ( maxLength * 2 ) ;
90- Span < Vector4 > destinationVectors = buffer . Slice ( 0 , maxLength ) ;
91- Span < Vector4 > backgroundVectors = buffer . Slice ( maxLength , maxLength ) ;
126+ this . Blend (
127+ configuration ,
128+ destination ,
129+ background ,
130+ source ,
131+ amount ,
132+ buffer . Memory . Span [ ..( maxLength * 2 ) ] ) ;
133+ }
134+
135+ /// <summary>
136+ /// Blends a row against a constant source color using caller-provided temporary vector scratch.
137+ /// </summary>
138+ /// <param name="configuration"><see cref="Configuration"/> to use internally</param>
139+ /// <param name="destination">the destination span</param>
140+ /// <param name="background">the background span</param>
141+ /// <param name="source">the source color</param>
142+ /// <param name="amount">
143+ /// A value between 0 and 1 indicating the weight of the second source vector.
144+ /// At amount = 0, "background" is returned, at amount = 1, "source" is returned.
145+ /// </param>
146+ /// <param name="workingBuffer">Reusable temporary vector scratch with capacity for at least 2 rows.</param>
147+ public void Blend (
148+ Configuration configuration ,
149+ Span < TPixel > destination ,
150+ ReadOnlySpan < TPixel > background ,
151+ TPixel source ,
152+ float amount ,
153+ Span < Vector4 > workingBuffer )
154+ {
155+ int maxLength = destination . Length ;
156+ Guard . MustBeGreaterThanOrEqualTo ( background . Length , maxLength , nameof ( background . Length ) ) ;
157+ Guard . MustBeBetweenOrEqualTo ( amount , 0 , 1 , nameof ( amount ) ) ;
158+ Guard . MustBeGreaterThanOrEqualTo ( workingBuffer . Length , maxLength * 2 , nameof ( workingBuffer . Length ) ) ;
159+
160+ Span < Vector4 > destinationVectors = workingBuffer [ ..maxLength ] ;
161+ Span < Vector4 > backgroundVectors = workingBuffer . Slice ( maxLength , maxLength ) ;
92162
93163 PixelOperations < TPixel > . Instance . ToVector4 ( configuration , background [ ..maxLength ] , backgroundVectors , PixelConversionModifiers . Scale ) ;
94164
95165 this . BlendFunction ( destinationVectors , backgroundVectors , source . ToScaledVector4 ( ) , amount ) ;
96166
97- PixelOperations < TPixel > . Instance . FromVector4Destructive ( configuration , destinationVectors [ .. maxLength ] , destination , PixelConversionModifiers . Scale ) ;
167+ PixelOperations < TPixel > . Instance . FromVector4Destructive ( configuration , destinationVectors , destination , PixelConversionModifiers . Scale ) ;
98168 }
99169
100170 /// <summary>
@@ -116,6 +186,27 @@ public void Blend(
116186 ReadOnlySpan < float > amount )
117187 => this . Blend < TPixel > ( configuration , destination , background , source , amount ) ;
118188
189+ /// <summary>
190+ /// Blends 2 rows together using caller-provided temporary vector scratch.
191+ /// </summary>
192+ /// <param name="configuration"><see cref="Configuration"/> to use internally</param>
193+ /// <param name="destination">the destination span</param>
194+ /// <param name="background">the background span</param>
195+ /// <param name="source">the source span</param>
196+ /// <param name="amount">
197+ /// A span with values between 0 and 1 indicating the weight of the second source vector.
198+ /// At amount = 0, "background" is returned, at amount = 1, "source" is returned.
199+ /// </param>
200+ /// <param name="workingBuffer">Reusable temporary vector scratch with capacity for at least 3 rows.</param>
201+ public void Blend (
202+ Configuration configuration ,
203+ Span < TPixel > destination ,
204+ ReadOnlySpan < TPixel > background ,
205+ ReadOnlySpan < TPixel > source ,
206+ ReadOnlySpan < float > amount ,
207+ Span < Vector4 > workingBuffer )
208+ => this . Blend < TPixel > ( configuration , destination , background , source , amount , workingBuffer ) ;
209+
119210 /// <summary>
120211 /// Blends 2 rows together
121212 /// </summary>
@@ -142,20 +233,89 @@ public void Blend<TPixelSrc>(
142233 Guard . MustBeGreaterThanOrEqualTo ( amount . Length , maxLength , nameof ( amount . Length ) ) ;
143234
144235 using IMemoryOwner < Vector4 > buffer = configuration . MemoryAllocator . Allocate < Vector4 > ( maxLength * 3 ) ;
145- Span < Vector4 > destinationVectors = buffer . Slice ( 0 , maxLength ) ;
146- Span < Vector4 > backgroundVectors = buffer . Slice ( maxLength , maxLength ) ;
147- Span < Vector4 > sourceVectors = buffer . Slice ( maxLength * 2 , maxLength ) ;
236+ this . Blend (
237+ configuration ,
238+ destination ,
239+ background ,
240+ source ,
241+ amount ,
242+ buffer . Memory . Span [ ..( maxLength * 3 ) ] ) ;
243+ }
244+
245+ /// <summary>
246+ /// Blends a row against a constant source color.
247+ /// </summary>
248+ /// <param name="configuration"><see cref="Configuration"/> to use internally</param>
249+ /// <param name="destination">the destination span</param>
250+ /// <param name="background">the background span</param>
251+ /// <param name="source">the source color</param>
252+ /// <param name="amount">
253+ /// A span with values between 0 and 1 indicating the weight of the second source vector.
254+ /// At amount = 0, "background" is returned, at amount = 1, "source" is returned.
255+ /// </param>
256+ public void Blend (
257+ Configuration configuration ,
258+ Span < TPixel > destination ,
259+ ReadOnlySpan < TPixel > background ,
260+ TPixel source ,
261+ ReadOnlySpan < float > amount )
262+ {
263+ int maxLength = destination . Length ;
264+ Guard . MustBeGreaterThanOrEqualTo ( background . Length , maxLength , nameof ( background . Length ) ) ;
265+ Guard . MustBeGreaterThanOrEqualTo ( amount . Length , maxLength , nameof ( amount . Length ) ) ;
266+
267+ using IMemoryOwner < Vector4 > buffer = configuration . MemoryAllocator . Allocate < Vector4 > ( maxLength * 2 ) ;
268+ this . Blend (
269+ configuration ,
270+ destination ,
271+ background ,
272+ source ,
273+ amount ,
274+ buffer . Memory . Span [ ..( maxLength * 2 ) ] ) ;
275+ }
276+
277+ /// <summary>
278+ /// Blends 2 rows together using caller-provided temporary vector scratch.
279+ /// </summary>
280+ /// <typeparam name="TPixelSrc">the pixel format of the source span</typeparam>
281+ /// <param name="configuration"><see cref="Configuration"/> to use internally</param>
282+ /// <param name="destination">the destination span</param>
283+ /// <param name="background">the background span</param>
284+ /// <param name="source">the source span</param>
285+ /// <param name="amount">
286+ /// A span with values between 0 and 1 indicating the weight of the second source vector.
287+ /// At amount = 0, "background" is returned, at amount = 1, "source" is returned.
288+ /// </param>
289+ /// <param name="workingBuffer">Reusable temporary vector scratch with capacity for at least 3 rows.</param>
290+ public void Blend < TPixelSrc > (
291+ Configuration configuration ,
292+ Span < TPixel > destination ,
293+ ReadOnlySpan < TPixel > background ,
294+ ReadOnlySpan < TPixelSrc > source ,
295+ ReadOnlySpan < float > amount ,
296+ Span < Vector4 > workingBuffer )
297+ where TPixelSrc : unmanaged, IPixel < TPixelSrc >
298+ {
299+ int maxLength = destination . Length ;
300+ Guard . MustBeGreaterThanOrEqualTo ( background . Length , maxLength , nameof ( background . Length ) ) ;
301+ Guard . MustBeGreaterThanOrEqualTo ( source . Length , maxLength , nameof ( source . Length ) ) ;
302+ Guard . MustBeGreaterThanOrEqualTo ( amount . Length , maxLength , nameof ( amount . Length ) ) ;
303+ Guard . MustBeGreaterThanOrEqualTo ( workingBuffer . Length , maxLength * 3 , nameof ( workingBuffer . Length ) ) ;
304+
305+ Span < Vector4 > destinationVectors = workingBuffer [ ..maxLength ] ;
306+ Span < Vector4 > backgroundVectors = workingBuffer . Slice ( maxLength , maxLength ) ;
307+ Span < Vector4 > sourceVectors = workingBuffer . Slice ( maxLength * 2 , maxLength ) ;
148308
149309 PixelOperations < TPixel > . Instance . ToVector4 ( configuration , background [ ..maxLength ] , backgroundVectors , PixelConversionModifiers . Scale ) ;
150310 PixelOperations < TPixelSrc > . Instance . ToVector4 ( configuration , source [ ..maxLength ] , sourceVectors , PixelConversionModifiers . Scale ) ;
151311
152312 this . BlendFunction ( destinationVectors , backgroundVectors , sourceVectors , amount ) ;
153313
154- PixelOperations < TPixel > . Instance . FromVector4Destructive ( configuration , destinationVectors [ .. maxLength ] , destination , PixelConversionModifiers . Scale ) ;
314+ PixelOperations < TPixel > . Instance . FromVector4Destructive ( configuration , destinationVectors , destination , PixelConversionModifiers . Scale ) ;
155315 }
156316
157317 /// <summary>
158- /// Blends a row against a constant source color.
318+ /// Blends a row against a constant source color using caller-provided temporary vector scratch .
159319 /// </summary>
160320 /// <param name="configuration"><see cref="Configuration"/> to use internally</param>
161321 /// <param name="destination">the destination span</param>
@@ -165,26 +325,28 @@ public void Blend<TPixelSrc>(
165325 /// A span with values between 0 and 1 indicating the weight of the second source vector.
166326 /// At amount = 0, "background" is returned, at amount = 1, "source" is returned.
167327 /// </param>
328+ /// <param name="workingBuffer">Reusable temporary vector scratch with capacity for at least 2 rows.</param>
168329 public void Blend (
169330 Configuration configuration ,
170331 Span < TPixel > destination ,
171332 ReadOnlySpan < TPixel > background ,
172333 TPixel source ,
173- ReadOnlySpan < float > amount )
334+ ReadOnlySpan < float > amount ,
335+ Span < Vector4 > workingBuffer )
174336 {
175337 int maxLength = destination . Length ;
176338 Guard . MustBeGreaterThanOrEqualTo ( background . Length , maxLength , nameof ( background . Length ) ) ;
177339 Guard . MustBeGreaterThanOrEqualTo ( amount . Length , maxLength , nameof ( amount . Length ) ) ;
340+ Guard . MustBeGreaterThanOrEqualTo ( workingBuffer . Length , maxLength * 2 , nameof ( workingBuffer . Length ) ) ;
178341
179- using IMemoryOwner < Vector4 > buffer = configuration . MemoryAllocator . Allocate < Vector4 > ( maxLength * 2 ) ;
180- Span < Vector4 > destinationVectors = buffer . Slice ( 0 , maxLength ) ;
181- Span < Vector4 > backgroundVectors = buffer . Slice ( maxLength , maxLength ) ;
342+ Span < Vector4 > destinationVectors = workingBuffer [ ..maxLength ] ;
343+ Span < Vector4 > backgroundVectors = workingBuffer . Slice ( maxLength , maxLength ) ;
182344
183345 PixelOperations < TPixel > . Instance . ToVector4 ( configuration , background [ ..maxLength ] , backgroundVectors , PixelConversionModifiers . Scale ) ;
184346
185347 this . BlendFunction ( destinationVectors , backgroundVectors , source . ToScaledVector4 ( ) , amount ) ;
186348
187- PixelOperations < TPixel > . Instance . FromVector4Destructive ( configuration , destinationVectors [ .. maxLength ] , destination , PixelConversionModifiers . Scale ) ;
349+ PixelOperations < TPixel > . Instance . FromVector4Destructive ( configuration , destinationVectors , destination , PixelConversionModifiers . Scale ) ;
188350 }
189351
190352 /// <summary>
0 commit comments