Browse Source

Begin convert to Matrix4x4

Former-commit-id: 4db3d124f9e5beccc91978920d9807aac8fa3ae5
Former-commit-id: b22c9fa18696752af28beebb7fb05959fdaa91c7
Former-commit-id: 6b120402ba51cdf065c2ee1e1134e501cb27ce1c
pull/17/head
James Jackson-South 10 years ago
parent
commit
ee22c04e7a
  1. 29
      src/ImageProcessor/Filters/ColorMatrix/GreyscaleBt601.cs
  2. 29
      src/ImageProcessor/Filters/ColorMatrix/GreyscaleBt709.cs
  3. 33
      src/ImageProcessor/Filters/ColorMatrix/Lomograph.cs
  4. 77
      src/ImageProcessor/Filters/ColorMatrix/MatrixFilter.cs
  5. 28
      src/ImageProcessor/Filters/ColorMatrix/Sepia.cs
  6. 1
      src/ImageProcessor/ImageProcessor.csproj
  7. 6
      tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
  8. 18
      tests/ImageProcessor.Tests/Processors/ProcessorTestBase.cs

29
src/ImageProcessor/Filters/ColorMatrix/GreyscaleBt601.cs

@ -5,30 +5,35 @@
namespace ImageProcessor.Filters
{
using System.Numerics;
/// <summary>
/// Converts the colors of the image to greyscale applying the formula as specified by
/// ITU-R Recommendation BT.601 <see href="https://en.wikipedia.org/wiki/Luma_%28video%29#Rec._601_luma_versus_Rec._709_luma_coefficients"/>.
/// </summary>
public class GreyscaleBt601 : ColorMatrixFilter
public class GreyscaleBt601 : MatrixFilter
{
/// <summary>
/// The inversion matrix.
/// The greyscale matrix.
/// </summary>
private static readonly ColorMatrix Matrix = new ColorMatrix(
new[]
{
new float[] { 0.299f, 0.299f, 0.299f, 0, 0 },
new float[] { 0.587f, 0.587f, 0.587f, 0, 0 },
new float[] { 0.114f, 0.114f, 0.114f, 0, 0 },
new float[] { 0, 0, 0, 1, 0 },
new float[] { 0, 0, 0, 0, 1 }
});
private static readonly Matrix4x4 Matrix = new Matrix4x4()
{
M11 = .299f,
M12 = .299f,
M13 = .299f,
M21 = .587f,
M22 = .587f,
M23 = .587f,
M31 = .114f,
M32 = .114f,
M33 = .114f
};
/// <summary>
/// Initializes a new instance of the <see cref="GreyscaleBt601"/> class.
/// </summary>
public GreyscaleBt601()
: base(Matrix, true)
: base(Matrix)
{
}
}

29
src/ImageProcessor/Filters/ColorMatrix/GreyscaleBt709.cs

@ -5,30 +5,35 @@
namespace ImageProcessor.Filters
{
using System.Numerics;
/// <summary>
/// Converts the colors of the image to greyscale applying the formula as specified by
/// ITU-R Recommendation BT.709 <see href="https://en.wikipedia.org/wiki/Rec._709#Luma_coefficients"/>.
/// </summary>
public class GreyscaleBt709 : ColorMatrixFilter
public class GreyscaleBt709 : MatrixFilter
{
/// <summary>
/// The inversion matrix.
/// The greyscale matrix.
/// </summary>
private static readonly ColorMatrix Matrix = new ColorMatrix(
new[]
{
new float[] { 0.2126f, 0.2126f, 0.2126f, 0, 0 },
new float[] { 0.7152f, 0.7152f, 0.7152f, 0, 0 },
new float[] { 0.0722f, 0.0722f, 0.0722f, 0, 0 },
new float[] { 0, 0, 0, 1, 0 },
new float[] { 0, 0, 0, 0, 1 }
});
private static readonly Matrix4x4 Matrix = new Matrix4x4()
{
M11 = .2126f,
M12 = .2126f,
M13 = .2126f,
M21 = .7152f,
M22 = .7152f,
M23 = .7152f,
M31 = .0722f,
M32 = .0722f,
M33 = .0722f
};
/// <summary>
/// Initializes a new instance of the <see cref="GreyscaleBt709"/> class.
/// </summary>
public GreyscaleBt709()
: base(Matrix, true)
: base(Matrix)
{
}
}

33
src/ImageProcessor/Filters/ColorMatrix/Lomograph.cs

@ -5,30 +5,41 @@
namespace ImageProcessor.Filters
{
using System.Numerics;
/// <summary>
/// Converts the colors of the image recreating an old Lomograph effect.
/// </summary>
public class Lomograph : ColorMatrixFilter
public class Lomograph : MatrixFilter
{
/// <summary>
/// The Lomograph matrix. Purely artistic in composition.
/// TODO: Calculate a matrix that works in the linear color space.
/// </summary>
private static readonly ColorMatrix Matrix = new ColorMatrix(
new[]
{
new[] { 1.50f, 0, 0, 0, 0 },
new[] { 0, 1.45f, 0, 0, 0 },
new[] { 0, 0, 1.09f, 0, 0 },
new float[] { 0, 0, 0, 1, 0 },
new[] { -0.10f, 0.05f, -0.08f, 0, 1 }
});
private static readonly Matrix4x4 Matrix = new Matrix4x4()
{
M11 = 1.5f,
M22 = 1.45f,
M33 = 1.09f,
M41 = -.1f,
M42 = .0f,
M43 = -.08f
};
//private static readonly ColorMatrix Matrix = new ColorMatrix(
// new[]
// {
// new[] { 1.50f, 0, 0, 0, 0 },
// new[] { 0, 1.45f, 0, 0, 0 },
// new[] { 0, 0, 1.09f, 0, 0 },
// new float[] { 0, 0, 0, 1, 0 },
// new[] { -0.10f, 0.05f, -0.08f, 0, 1 }
// });
/// <summary>
/// Initializes a new instance of the <see cref="Lomograph"/> class.
/// </summary>
public Lomograph()
: base(Matrix, false)
: base(Matrix)
{
}
}

77
src/ImageProcessor/Filters/ColorMatrix/MatrixFilter.cs

@ -0,0 +1,77 @@
// <copyright file="ColorMatrixFilter.cs" company="James South">
// Copyright (c) James South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageProcessor.Filters
{
using System.Numerics;
using System.Threading.Tasks;
/// <summary>
/// The color matrix filter.
/// </summary>
public class MatrixFilter : ParallelImageProcessor
{
/// <summary>
/// Initializes a new instance of the <see cref="MatrixFilter"/> class.
/// </summary>
/// <param name="matrix">The <see cref="Matrix4x4"/> to apply.</param>
public MatrixFilter(Matrix4x4 matrix)
{
this.Value = matrix;
}
/// <summary>
/// Gets the matrix value.
/// </summary>
public Matrix4x4 Value { get; }
/// <inheritdoc/>
protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
int sourceY = sourceRectangle.Y;
int sourceBottom = sourceRectangle.Bottom;
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
Matrix4x4 matrix = this.Value;
Parallel.For(
startY,
endY,
y =>
{
if (y >= sourceY && y < sourceBottom)
{
for (int x = startX; x < endX; x++)
{
target[x, y] = ApplyMatrix(source[x, y], matrix);
}
}
});
}
/// <summary>
/// Applies the color matrix against the given color.
/// </summary>
/// <param name="color">The source color.</param>
/// <param name="matrix">The matrix.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
private static Color ApplyMatrix(Color color, Matrix4x4 matrix)
{
color = PixelOperations.ToLinear(color);
float sr = color.R;
float sg = color.G;
float sb = color.B;
color.R = (sr * matrix.M11) + (sg * matrix.M21) + (sb * matrix.M31) + matrix.M41;
color.G = (sr * matrix.M12) + (sg * matrix.M22) + (sb * matrix.M32) + matrix.M42;
color.B = (sr * matrix.M13) + (sg * matrix.M23) + (sb * matrix.M33) + matrix.M43;
return PixelOperations.ToSrgb(color);
}
}
}

28
src/ImageProcessor/Filters/ColorMatrix/Sepia.cs

@ -5,30 +5,34 @@
namespace ImageProcessor.Filters
{
using System.Numerics;
/// <summary>
/// Converts the colors of the image to their sepia equivalent recreating an old photo effect.
/// </summary>
public class Sepia : ColorMatrixFilter
public class Sepia : MatrixFilter
{
/// <summary>
/// The sepia matrix.
/// TODO: Calculate a matrix that works in the linear color space.
/// </summary>
private static readonly ColorMatrix Matrix = new ColorMatrix(
new[]
{
new[] { .393f, .349f, .272f, 0, 0 },
new[] { .769f, .686f, .534f, 0, 0 },
new[] { .189f, .168f, .131f, 0, 0 },
new float[] { 0, 0, 0, 1, 0 },
new float[] { 0, 0, 0, 0, 1 }
});
private static readonly Matrix4x4 Matrix = new Matrix4x4()
{
M11 = .393f,
M12 = .349f,
M13 = .272f,
M21 = .769f,
M22 = .686f,
M23 = .534f,
M31 = .189f,
M32 = .168f,
M33 = .131f
};
/// <summary>
/// Initializes a new instance of the <see cref="Sepia"/> class.
/// </summary>
public Sepia()
: base(Matrix, false)
: base(Matrix)
{
}
}

1
src/ImageProcessor/ImageProcessor.csproj

@ -48,6 +48,7 @@
<Compile Include="Common\Extensions\EnumerableExtensions.cs" />
<Compile Include="Common\Helpers\ImageMaths.cs" />
<Compile Include="Common\Helpers\PixelOperations.cs" />
<Compile Include="Filters\ColorMatrix\MatrixFilter.cs" />
<Compile Include="Filters\Saturation.cs" />
<Compile Include="Filters\ColorMatrix\GreyscaleMode.cs" />
<Compile Include="Filters\Brightness.cs" />

6
tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs

@ -16,13 +16,13 @@ namespace ImageProcessor.Tests
//{ "Brightness--50", new Brightness(-50) },
//{ "Contrast-50", new Contrast(50) },
//{ "Contrast--50", new Contrast(-50) },
{ "Saturation-100", new Saturation(100) },
{ "Saturation--0", new Saturation(0) },
//{ "Saturation-100", new Saturation(100) },
//{ "Saturation--0", new Saturation(0) },
//{ "Alpha--50", new Alpha(50) },
//{ "Invert", new Invert() },
//{ "Sepia", new Sepia() },
//{ "BlackWhite", new BlackWhite() },
//{ "Lomograph", new Lomograph() },
{ "Lomograph", new Lomograph() },
//{ "Polaroid", new Polaroid() },
//{ "GreyscaleBt709", new GreyscaleBt709() },
//{ "GreyscaleBt601", new GreyscaleBt601() },

18
tests/ImageProcessor.Tests/Processors/ProcessorTestBase.cs

@ -19,16 +19,16 @@ namespace ImageProcessor.Tests
/// </summary>
public static readonly List<string> Files = new List<string>
{
"../../TestImages/Formats/Jpg/Backdrop.jpg",
//"../../TestImages/Formats/Jpg/Backdrop.jpg",
"../../TestImages/Formats/Jpg/Calliphora.jpg",
"../../TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg",
"../../TestImages/Formats/Jpg/greyscale.jpg",
"../../TestImages/Formats/Bmp/Car.bmp",
"../../TestImages/Formats/Png/cmyk.png",
"../../TestImages/Formats/Png/gamma-1.0-or-2.2.png",
"../../TestImages/Formats/Png/splash.png",
"../../TestImages/Formats/Gif/leaf.gif",
"../../TestImages/Formats/Gif/rings.gif",
//"../../TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg",
//"../../TestImages/Formats/Jpg/greyscale.jpg",
//"../../TestImages/Formats/Bmp/Car.bmp",
//"../../TestImages/Formats/Png/cmyk.png",
//"../../TestImages/Formats/Png/gamma-1.0-or-2.2.png",
//"../../TestImages/Formats/Png/splash.png",
//"../../TestImages/Formats/Gif/leaf.gif",
//"../../TestImages/Formats/Gif/rings.gif",
//"../../TestImages/Formats/Gif/ani2.gif",
//"../../TestImages/Formats/Gif/giphy.gif"
};

Loading…
Cancel
Save