mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: 491e73ef2b4c46b935abbd9d2778a1c09388a6b8 Former-commit-id: 147535c84f3593676be6830ed231e3f11e43d42e Former-commit-id: aaec7537352e24c285afe67248f8be0df97df371af/merge-core
6 changed files with 244 additions and 85 deletions
@ -0,0 +1,99 @@ |
|||
// <copyright file="Convolution2DFilter.cs" company="James South">
|
|||
// Copyright (c) James South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessor.Filters |
|||
{ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
/// <summary>
|
|||
/// Defines a filter that uses a matrix to perform convolution across two dimensions against an image.
|
|||
/// </summary>
|
|||
public abstract class Convolution2DFilter : ParallelImageProcessor |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the horizontal gradient operator.
|
|||
/// </summary>
|
|||
public abstract float[,] KernelX { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the vertical gradient operator.
|
|||
/// </summary>
|
|||
public abstract float[,] KernelY { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) |
|||
{ |
|||
float[,] kernelX = this.KernelX; |
|||
float[,] kernelY = this.KernelY; |
|||
int kernelYLength = kernelY.GetLength(0); |
|||
int kernelXLength = kernelX.GetLength(0); |
|||
int radiusY = kernelYLength >> 1; |
|||
int radiusX = kernelXLength >> 1; |
|||
|
|||
int sourceY = sourceRectangle.Y; |
|||
int sourceBottom = sourceRectangle.Bottom; |
|||
int startX = sourceRectangle.X; |
|||
int endX = sourceRectangle.Right; |
|||
int maxY = sourceBottom - 1; |
|||
int maxX = endX - 1; |
|||
|
|||
Parallel.For( |
|||
startY, |
|||
endY, |
|||
y => |
|||
{ |
|||
if (y >= sourceY && y < sourceBottom) |
|||
{ |
|||
for (int x = startX; x < endX; x++) |
|||
{ |
|||
float rX = 0; |
|||
float gX = 0; |
|||
float bX = 0; |
|||
float rY = 0; |
|||
float gY = 0; |
|||
float bY = 0; |
|||
|
|||
// Apply each matrix multiplier to the color components for each pixel.
|
|||
for (int fy = 0; fy < kernelYLength; fy++) |
|||
{ |
|||
int fyr = fy - radiusY; |
|||
int offsetY = y + fyr; |
|||
|
|||
offsetY = offsetY.Clamp(0, maxY); |
|||
|
|||
for (int fx = 0; fx < kernelXLength; fx++) |
|||
{ |
|||
int fxr = fx - radiusX; |
|||
int offsetX = x + fxr; |
|||
|
|||
offsetX = offsetX.Clamp(0, maxX); |
|||
|
|||
Color currentColor = source[offsetX, offsetY]; |
|||
float r = currentColor.R; |
|||
float g = currentColor.G; |
|||
float b = currentColor.B; |
|||
|
|||
rX += kernelX[fx, fy] * r; |
|||
gX += kernelX[fx, fy] * g; |
|||
bX += kernelX[fx, fy] * b; |
|||
|
|||
rY += kernelY[fy, fx] * r; |
|||
gY += kernelY[fy, fx] * g; |
|||
bY += kernelY[fy, fx] * b; |
|||
} |
|||
} |
|||
|
|||
float red = (float)Math.Sqrt((rX * rX) + (rY * rY)); |
|||
float green = (float)Math.Sqrt((gX * gX) + (gY * gY)); |
|||
float blue = (float)Math.Sqrt((bX * bX) + (bY * bY)); |
|||
|
|||
target[x, y] = new Color(red, green, blue); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1 +1 @@ |
|||
eb00c54ee74016c2b70f81963e7e8f83cb2dd54b |
|||
3f05708641eb3ed085d4689aae4a960eb067fd16 |
|||
@ -0,0 +1 @@ |
|||
1da0ed59ed220f32d72b01e6cbb9c73a7f3b9b35 |
|||
Loading…
Reference in new issue