|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
@ -0,0 +1,183 @@ |
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
// <copyright file="OilPaintingFilter.cs" company="James South">
|
|||
// Copyright (c) James South.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
// <summary>
|
|||
// The oil painting filter.
|
|||
// </summary>
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters.Artistic |
|||
{ |
|||
using System; |
|||
using System.Drawing; |
|||
|
|||
using ImageProcessor.Common.Extensions; |
|||
|
|||
/// <summary>
|
|||
/// The oil painting filter.
|
|||
/// </summary>
|
|||
public class OilPaintingFilter |
|||
{ |
|||
/// <summary>
|
|||
/// The levels.
|
|||
/// </summary>
|
|||
private int levels; |
|||
|
|||
/// <summary>
|
|||
/// The brush size.
|
|||
/// </summary>
|
|||
private int brushSize; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="OilPaintingFilter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="levels">
|
|||
/// The number of levels.
|
|||
/// </param>
|
|||
/// <param name="brushSize">
|
|||
/// The brush size.
|
|||
/// </param>
|
|||
public OilPaintingFilter(int levels, int brushSize) |
|||
{ |
|||
this.levels = levels; |
|||
this.brushSize = brushSize; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the number of levels.
|
|||
/// </summary>
|
|||
public int Levels |
|||
{ |
|||
get |
|||
{ |
|||
return this.levels; |
|||
} |
|||
|
|||
set |
|||
{ |
|||
if (value > 0) |
|||
{ |
|||
this.levels = value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the brush size.
|
|||
/// </summary>
|
|||
public int BrushSize |
|||
{ |
|||
get |
|||
{ |
|||
return this.brushSize; |
|||
} |
|||
|
|||
set |
|||
{ |
|||
if (value > 0) |
|||
{ |
|||
this.brushSize = value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Applies the filter. TODO: Make this class implement an interface?
|
|||
/// </summary>
|
|||
/// <param name="source">
|
|||
/// The source.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The <see cref="Bitmap"/>.
|
|||
/// </returns>
|
|||
public Bitmap ApplyFilter(Bitmap source) |
|||
{ |
|||
int width = source.Width; |
|||
int height = source.Height; |
|||
|
|||
int radius = this.brushSize >> 1; |
|||
|
|||
Bitmap destination = new Bitmap(width, height); |
|||
using (FastBitmap sourceBitmap = new FastBitmap(source)) |
|||
{ |
|||
using (FastBitmap destinationBitmap = new FastBitmap(destination)) |
|||
{ |
|||
for (int y = 0; y < height; y++) |
|||
{ |
|||
for (int x = 0; x < width; x++) |
|||
{ |
|||
int maxIntensity = 0; |
|||
int maxIndex = 0; |
|||
int[] intensityBin = new int[this.levels]; |
|||
int[] blueBin = new int[this.levels]; |
|||
int[] greenBin = new int[this.levels]; |
|||
int[] redBin = new int[this.levels]; |
|||
|
|||
for (int i = 0; i <= radius; i++) |
|||
{ |
|||
int ir = i - radius; |
|||
int offsetY = y + ir; |
|||
|
|||
// Skip the current row
|
|||
if (offsetY < 0) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
// Outwith the current bounds so break.
|
|||
if (offsetY >= height) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
for (int fx = 0; fx <= radius; fx++) |
|||
{ |
|||
int jr = fx - radius; |
|||
int offsetX = x + jr; |
|||
|
|||
// Skip the column
|
|||
if (offsetX < 0) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (offsetX < width) |
|||
{ |
|||
Color color = sourceBitmap.GetPixel(offsetX, offsetY); |
|||
|
|||
byte sourceBlue = color.B; |
|||
byte sourceGreen = color.G; |
|||
byte sourceRed = color.R; |
|||
|
|||
int currentIntensity = (int)Math.Round(((sourceBlue + sourceGreen + sourceRed) / 3.0 * (this.levels - 1)) / 255.0); |
|||
|
|||
intensityBin[currentIntensity] += 1; |
|||
blueBin[currentIntensity] += sourceBlue; |
|||
greenBin[currentIntensity] += sourceGreen; |
|||
redBin[currentIntensity] += sourceRed; |
|||
|
|||
if (intensityBin[currentIntensity] > maxIntensity) |
|||
{ |
|||
maxIntensity = intensityBin[currentIntensity]; |
|||
maxIndex = currentIntensity; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
byte blue = Math.Abs(blueBin[maxIndex] / maxIntensity).ToByte(); |
|||
byte green = Math.Abs(greenBin[maxIndex] / maxIntensity).ToByte(); |
|||
byte red = Math.Abs(redBin[maxIndex] / maxIntensity).ToByte(); |
|||
|
|||
destinationBitmap.SetPixel(x, y, Color.FromArgb(red, green, blue)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return destination; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
// <copyright file="IEdgeFilter.cs" company="James South">
|
|||
// Copyright (c) James South.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
// <summary>
|
|||
// Describes properties for creating 2 dimension edge detection filters.
|
|||
// </summary>
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters.EdgeDetection |
|||
{ |
|||
/// <summary>
|
|||
/// Describes properties for creating 2 dimension edge detection filters.
|
|||
/// </summary>
|
|||
public interface I2DEdgeFilter : IEdgeFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the vertical gradient operator.
|
|||
/// </summary>
|
|||
double[,] VerticalGradientOperator { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
// <copyright file="Laplacian3x3Filter.cs" company="James South">
|
|||
// Copyright (c) James South.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
// <summary>
|
|||
// The Laplacian 3 x 3 operator filter.
|
|||
// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator" />
|
|||
// </summary>
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters.EdgeDetection |
|||
{ |
|||
/// <summary>
|
|||
/// The Laplacian 3 x 3 operator filter.
|
|||
/// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator"/>
|
|||
/// </summary>
|
|||
public class Laplacian3X3Filter : IEdgeFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the horizontal gradient operator.
|
|||
/// </summary>
|
|||
public double[,] HorizontalGradientOperator |
|||
{ |
|||
get |
|||
{ |
|||
return new double[,] |
|||
{ |
|||
{ -1, -1, -1 }, |
|||
{ -1, 8, -1 }, |
|||
{ -1, -1, -1 } |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
// <copyright file="Laplacian5X5Filter.cs" company="James South">
|
|||
// Copyright (c) James South.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
// <summary>
|
|||
// The Laplacian 5 x 5 operator filter.
|
|||
// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator" />
|
|||
// </summary>
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters.EdgeDetection |
|||
{ |
|||
/// <summary>
|
|||
/// The Laplacian 5 x 5 operator filter.
|
|||
/// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator"/>
|
|||
/// </summary>
|
|||
public class Laplacian5X5Filter : IEdgeFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the horizontal gradient operator.
|
|||
/// </summary>
|
|||
public double[,] HorizontalGradientOperator |
|||
{ |
|||
get |
|||
{ |
|||
return new double[,] |
|||
{ |
|||
{ -1, -1, -1, -1, -1 }, |
|||
{ -1, -1, -1, -1, -1 }, |
|||
{ -1, -1, 24, -1, -1 }, |
|||
{ -1, -1, -1, -1, -1 }, |
|||
{ -1, -1, -1, -1, -1 } |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
// <copyright file="LaplacianOfGaussianFilter.cs" company="James South">
|
|||
// Copyright (c) James South.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
// <summary>
|
|||
// The Laplacian of Gaussian operator filter.
|
|||
// <see href="http://fourier.eng.hmc.edu/e161/lectures/gradient/node9.html" />
|
|||
// </summary>
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters.EdgeDetection |
|||
{ |
|||
/// <summary>
|
|||
/// The Laplacian of Gaussian operator filter.
|
|||
/// <see href="http://fourier.eng.hmc.edu/e161/lectures/gradient/node9.html"/>
|
|||
/// </summary>
|
|||
public class LaplacianOfGaussianFilter : IEdgeFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the horizontal gradient operator.
|
|||
/// </summary>
|
|||
public double[,] HorizontalGradientOperator |
|||
{ |
|||
get |
|||
{ |
|||
return new double[,] |
|||
{ |
|||
{ 0, 0, -1, 0, 0 }, |
|||
{ 0, -1, -2, -1, 0 }, |
|||
{ -1, -2, 16, -2, -1 }, |
|||
{ 0, -1, -2, -1, 0 }, |
|||
{ 0, 0, -1, 0, 0 } |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||