19 using System.Threading.Tasks;
52 return BoxBlurSRGB(image, (
int)Math.Round(
this.BoxRadius * scale));
57 IntPtr intermediateData = System.Runtime.InteropServices.Marshal.AllocHGlobal(image.
Width * image.
Height * (image.
HasAlpha ? 4 : 3));
58 IntPtr tbrData = System.Runtime.InteropServices.Marshal.AllocHGlobal(image.
Width * image.
Height * (image.
HasAlpha ? 4 : 3));
61 int width = image.
Width;
64 int pixelSize = image.
HasAlpha ? 4 : 3;
65 int stride = image.
Width * pixelSize;
67 double normFactor = 1.0 / (2 * boxRadius + 1);
71 double size = Math.Sqrt((
double)image.
Width * image.
Height);
79 threads = Math.Min(4, Environment.ProcessorCount);
83 threads = Math.Min(8, Environment.ProcessorCount);
89 byte* intermediate = (
byte*)intermediateData;
90 byte* output = (
byte*)tbrData;
112 double a = input[y * stride + 3] / 255.0;
114 prevR = input[y * stride] * a;
115 prevG = input[y * stride + 1] * a;
116 prevB = input[y * stride + 2] * a;
119 rAcc = prevR * (boxRadius + 1);
120 gAcc = prevG * (boxRadius + 1);
121 bAcc = prevB * (boxRadius + 1);
122 aAcc = a * (boxRadius + 1);
126 for (
int x = 0; x < boxRadius; x++)
128 rX = Math.Min(x, width - 1);
130 a = input[y * stride + rX * 4 + 3] / 255.0;
132 rAcc += input[y * stride + rX * 4] * a;
133 gAcc += input[y * stride + rX * 4 + 1] * a;
134 bAcc += input[y * stride + rX * 4 + 2] * a;
138 rX = Math.Min(boxRadius, width - 1);
141 for (
int x = 0; x < width; x++)
143 rX = Math.Min(x + boxRadius, width - 1);
144 lX = Math.Max(x - boxRadius - 1, 0);
146 a = input[y * stride + rX * 4 + 3] / 255.0;
147 r = input[y * stride + rX * 4] * a;
148 g = input[y * stride + rX * 4 + 1] * a;
149 b = input[y * stride + rX * 4 + 2] * a;
151 prevA = input[y * stride + lX * 4 + 3] / 255.0;
152 prevR = input[y * stride + lX * 4] * prevA;
153 prevG = input[y * stride + lX * 4 + 1] * prevA;
154 prevB = input[y * stride + lX * 4 + 2] * prevA;
163 intermediate[y * stride + x * 4] = (byte)Math.Min(255, Math.Max(0, rAcc / aAcc));
164 intermediate[y * stride + x * 4 + 1] = (byte)Math.Min(255, Math.Max(0, gAcc / aAcc));
165 intermediate[y * stride + x * 4 + 2] = (byte)Math.Min(255, Math.Max(0, bAcc / aAcc));
166 intermediate[y * stride + x * 4 + 3] = (byte)Math.Min(255, Math.Max(0, aAcc * 255 * normFactor));
170 intermediate[y * stride + x * 4] = 0;
171 intermediate[y * stride + x * 4 + 1] = 0;
172 intermediate[y * stride + x * 4 + 2] = 0;
173 intermediate[y * stride + x * 4 + 3] = 0;
194 prevR = input[y * stride];
195 prevG = input[y * stride + 1];
196 prevB = input[y * stride + 2];
198 rAcc = prevR * (boxRadius + 1);
199 gAcc = prevG * (boxRadius + 1);
200 bAcc = prevB * (boxRadius + 1);
204 for (
int x = 0; x < boxRadius; x++)
206 rX = Math.Min(x, width - 1);
208 rAcc += input[y * stride + rX * 3];
209 gAcc += input[y * stride + rX * 3 + 1];
210 bAcc += input[y * stride + rX * 3 + 2];
213 rX = Math.Min(boxRadius, width - 1);
216 for (
int x = 0; x < width; x++)
218 rX = Math.Min(x + boxRadius, width - 1);
219 lX = Math.Max(x - boxRadius - 1, 0);
221 r = input[y * stride + rX * 3];
222 g = input[y * stride + rX * 3 + 1];
223 b = input[y * stride + rX * 3 + 2];
225 prevR = input[y * stride + lX * 3];
226 prevG = input[y * stride + lX * 3 + 1];
227 prevB = input[y * stride + lX * 3 + 2];
233 intermediate[y * stride + x * 3] = (byte)Math.Min(255, Math.Max(0, rAcc * normFactor));
234 intermediate[y * stride + x * 3 + 1] = (byte)Math.Min(255, Math.Max(0, gAcc * normFactor));
235 intermediate[y * stride + x * 3 + 2] = (byte)Math.Min(255, Math.Max(0, bAcc * normFactor));
260 double a = intermediate[x * 4 + 3] / 255.0;
262 prevR = intermediate[x * 4] * a;
263 prevG = intermediate[x * 4 + 1] * a;
264 prevB = intermediate[x * 4 + 2] * a;
267 rAcc = prevR * (boxRadius + 1);
268 gAcc = prevG * (boxRadius + 1);
269 bAcc = prevB * (boxRadius + 1);
270 aAcc = a * (boxRadius + 1);
274 for (
int y = 0; y < boxRadius; y++)
276 rY = Math.Min(y, height - 1);
278 a = intermediate[rY * stride + x * 4 + 3] / 255.0;
280 rAcc += intermediate[rY * stride + x * 4] * a;
281 gAcc += intermediate[rY * stride + x * 4 + 1] * a;
282 bAcc += intermediate[rY * stride + x * 4 + 2] * a;
286 rY = Math.Min(boxRadius, height - 1);
289 for (
int y = 0; y < height; y++)
291 rY = Math.Min(y + boxRadius, height - 1);
292 lY = Math.Max(y - boxRadius - 1, 0);
294 a = intermediate[rY * stride + x * 4 + 3] / 255.0;
295 r = intermediate[rY * stride + x * 4] * a;
296 g = intermediate[rY * stride + x * 4 + 1] * a;
297 b = intermediate[rY * stride + x * 4 + 2] * a;
299 prevA = intermediate[lY * stride + x * 4 + 3] / 255.0;
300 prevR = intermediate[lY * stride + x * 4] * prevA;
301 prevG = intermediate[lY * stride + x * 4 + 1] * prevA;
302 prevB = intermediate[lY * stride + x * 4 + 2] * prevA;
311 output[y * stride + x * 4] = (byte)Math.Min(255, Math.Max(0, rAcc / aAcc));
312 output[y * stride + x * 4 + 1] = (byte)Math.Min(255, Math.Max(0, gAcc / aAcc));
313 output[y * stride + x * 4 + 2] = (byte)Math.Min(255, Math.Max(0, bAcc / aAcc));
314 output[y * stride + x * 4 + 3] = (byte)Math.Min(255, Math.Max(0, aAcc * 255 * normFactor));
318 output[y * stride + x * 4] = 0;
319 output[y * stride + x * 4 + 1] = 0;
320 output[y * stride + x * 4 + 2] = 0;
321 output[y * stride + x * 4 + 3] = 0;
342 prevR = intermediate[x * 3];
343 prevG = intermediate[x * 3 + 1];
344 prevB = intermediate[x * 3 + 2];
346 rAcc = prevR * (boxRadius + 1);
347 gAcc = prevG * (boxRadius + 1);
348 bAcc = prevB * (boxRadius + 1);
352 for (
int y = 0; y < boxRadius; y++)
354 rY = Math.Min(y, height - 1);
356 rAcc += intermediate[rY * stride + x * 3];
357 gAcc += intermediate[rY * stride + x * 3 + 1];
358 bAcc += intermediate[rY * stride + x * 3 + 2];
361 rY = Math.Min(boxRadius, height - 1);
364 for (
int y = 0; y < height; y++)
366 rY = Math.Min(y + boxRadius, height - 1);
367 lY = Math.Max(y - boxRadius - 1, 0);
369 r = intermediate[rY * stride + x * 3];
370 g = intermediate[rY * stride + x * 3 + 1];
371 b = intermediate[rY * stride + x * 3 + 2];
373 prevR = intermediate[lY * stride + x * 3];
374 prevG = intermediate[lY * stride + x * 3 + 1];
375 prevB = intermediate[lY * stride + x * 3 + 2];
381 output[y * stride + x * 3] = (byte)Math.Min(255, Math.Max(0, rAcc * normFactor));
382 output[y * stride + x * 3 + 1] = (byte)Math.Min(255, Math.Max(0, gAcc * normFactor));
383 output[y * stride + x * 3 + 2] = (byte)Math.Min(255, Math.Max(0, bAcc * normFactor));
390 for (
int y = 0; y < height; y++)
395 for (
int x = 0; x < width; x++)
402 ParallelOptions options =
new ParallelOptions() { MaxDegreeOfParallelism = threads };
404 Parallel.For(0, height, options, yLoop);
405 Parallel.For(0, width, options, xLoop);
409 System.Runtime.InteropServices.Marshal.FreeHGlobal(intermediateData);
412 DisposableIntPtr disp =
new DisposableIntPtr(tbrData);