mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
111 changed files with 1798 additions and 1743 deletions
@ -0,0 +1,446 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Provides extensions methods for the <see cref="Matrix4x4"/> struct
|
||||
|
/// </summary>
|
||||
|
public static class MatrixFilters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating Achromatomaly (Color desensitivity) color blindness
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 AchromatomalyFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = .618F, |
||||
|
M12 = .163F, |
||||
|
M13 = .163F, |
||||
|
M21 = .320F, |
||||
|
M22 = .775F, |
||||
|
M23 = .320F, |
||||
|
M31 = .062F, |
||||
|
M32 = .062F, |
||||
|
M33 = .516F, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating Achromatopsia (Monochrome) color blindness.
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 AchromatopsiaFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = .299F, |
||||
|
M12 = .299F, |
||||
|
M13 = .299F, |
||||
|
M21 = .587F, |
||||
|
M22 = .587F, |
||||
|
M23 = .587F, |
||||
|
M31 = .114F, |
||||
|
M32 = .114F, |
||||
|
M33 = .114F, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating Deuteranomaly (Green-Weak) color blindness.
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 DeuteranomalyFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = 0.8F, |
||||
|
M12 = 0.258F, |
||||
|
M21 = 0.2F, |
||||
|
M22 = 0.742F, |
||||
|
M23 = 0.142F, |
||||
|
M33 = 0.858F, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating Deuteranopia (Green-Blind) color blindness.
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 DeuteranopiaFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = 0.625F, |
||||
|
M12 = 0.7F, |
||||
|
M21 = 0.375F, |
||||
|
M22 = 0.3F, |
||||
|
M23 = 0.3F, |
||||
|
M33 = 0.7F, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating Protanomaly (Red-Weak) color blindness.
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 ProtanomalyFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = 0.817F, |
||||
|
M12 = 0.333F, |
||||
|
M21 = 0.183F, |
||||
|
M22 = 0.667F, |
||||
|
M23 = 0.125F, |
||||
|
M33 = 0.875F, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating Protanopia (Red-Blind) color blindness.
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 ProtanopiaFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = 0.567F, |
||||
|
M12 = 0.558F, |
||||
|
M21 = 0.433F, |
||||
|
M22 = 0.442F, |
||||
|
M23 = 0.242F, |
||||
|
M33 = 0.758F, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating Tritanomaly (Blue-Weak) color blindness.
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 TritanomalyFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = 0.967F, |
||||
|
M21 = 0.33F, |
||||
|
M22 = 0.733F, |
||||
|
M23 = 0.183F, |
||||
|
M32 = 0.267F, |
||||
|
M33 = 0.817F, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating Tritanopia (Blue-Blind) color blindness.
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 TritanopiaFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = 0.95F, |
||||
|
M21 = 0.05F, |
||||
|
M22 = 0.433F, |
||||
|
M23 = 0.475F, |
||||
|
M32 = 0.567F, |
||||
|
M33 = 0.525F, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets an approximated black and white filter
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 BlackWhiteFilter { get; } = new Matrix4x4() |
||||
|
{ |
||||
|
M11 = 1.5F, |
||||
|
M12 = 1.5F, |
||||
|
M13 = 1.5F, |
||||
|
M21 = 1.5F, |
||||
|
M22 = 1.5F, |
||||
|
M23 = 1.5F, |
||||
|
M31 = 1.5F, |
||||
|
M32 = 1.5F, |
||||
|
M33 = 1.5F, |
||||
|
M41 = -1F, |
||||
|
M42 = -1F, |
||||
|
M43 = -1F, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating an old Kodachrome camera effect.
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 KodachromeFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = 0.7297023F, |
||||
|
M22 = 0.6109577F, |
||||
|
M33 = 0.597218F, |
||||
|
M41 = 0.105F, |
||||
|
M42 = 0.145F, |
||||
|
M43 = 0.155F, |
||||
|
M44 = 1 |
||||
|
} |
||||
|
|
||||
|
* CreateSaturateFilter(1.2F) * CreateContrastFilter(1.35F); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating an old Lomograph camera effect.
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 LomographFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = 1.5F, |
||||
|
M22 = 1.45F, |
||||
|
M33 = 1.16F, |
||||
|
M41 = -.1F, |
||||
|
M42 = -.02F, |
||||
|
M43 = -.07F, |
||||
|
M44 = 1 |
||||
|
} |
||||
|
|
||||
|
* CreateSaturateFilter(1.1F) * CreateContrastFilter(1.33F); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a filter recreating an old Polaroid camera effect.
|
||||
|
/// </summary>
|
||||
|
public static Matrix4x4 PolaroidFilter { get; } = new Matrix4x4 |
||||
|
{ |
||||
|
M11 = 1.538F, |
||||
|
M12 = -0.062F, |
||||
|
M13 = -0.262F, |
||||
|
M21 = -0.022F, |
||||
|
M22 = 1.578F, |
||||
|
M23 = -0.022F, |
||||
|
M31 = .216F, |
||||
|
M32 = -.16F, |
||||
|
M33 = 1.5831F, |
||||
|
M41 = 0.02F, |
||||
|
M42 = -0.05F, |
||||
|
M43 = -0.05F, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create a brightness filter matrix using the given amount.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged.
|
||||
|
/// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing brighter results.
|
||||
|
/// </remarks>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
|
||||
|
/// <returns>The <see cref="Matrix4x4"/></returns>
|
||||
|
public static Matrix4x4 CreateBrightnessFilter(float amount) |
||||
|
{ |
||||
|
Guard.MustBeGreaterThanOrEqualTo(amount, 0, nameof(amount)); |
||||
|
|
||||
|
// See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc
|
||||
|
return new Matrix4x4 |
||||
|
{ |
||||
|
M11 = amount, |
||||
|
M22 = amount, |
||||
|
M33 = amount, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create a contrast filter matrix using the given amount.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// A value of 0 will create an image that is completely gray. A value of 1 leaves the input unchanged.
|
||||
|
/// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing results with more contrast.
|
||||
|
/// </remarks>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
|
||||
|
/// <returns>The <see cref="Matrix4x4"/></returns>
|
||||
|
public static Matrix4x4 CreateContrastFilter(float amount) |
||||
|
{ |
||||
|
Guard.MustBeGreaterThanOrEqualTo(amount, 0, nameof(amount)); |
||||
|
|
||||
|
// See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc
|
||||
|
float contrast = (-.5F * amount) + .5F; |
||||
|
|
||||
|
return new Matrix4x4 |
||||
|
{ |
||||
|
M11 = amount, |
||||
|
M22 = amount, |
||||
|
M33 = amount, |
||||
|
M41 = contrast, |
||||
|
M42 = contrast, |
||||
|
M43 = contrast, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create a greyscale filter matrix using the given amount using 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>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be between 0 and 1.</param>
|
||||
|
/// <returns>The <see cref="Matrix4x4"/></returns>
|
||||
|
public static Matrix4x4 CreateGrayscaleBt601Filter(float amount) |
||||
|
{ |
||||
|
Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); |
||||
|
amount = 1F - amount; |
||||
|
|
||||
|
// https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc
|
||||
|
return new Matrix4x4 |
||||
|
{ |
||||
|
M11 = .299F + (.701F * amount), |
||||
|
M12 = .299F - (.299F * amount), |
||||
|
M13 = .299F - (.299F * amount), |
||||
|
M21 = .587F - (.587F * amount), |
||||
|
M22 = .587F + (.413F * amount), |
||||
|
M23 = .587F - (.587F * amount), |
||||
|
M31 = .114F - (.114F * amount), |
||||
|
M32 = .114F - (.114F * amount), |
||||
|
M33 = .114F + (.886F * amount), |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create a greyscale filter matrix using the given amount using the formula as specified by ITU-R Recommendation BT.709.
|
||||
|
/// <see href="https://en.wikipedia.org/wiki/Rec._709#Luma_coefficients"/>
|
||||
|
/// </summary>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be between 0 and 1.</param>
|
||||
|
/// <returns>The <see cref="Matrix4x4"/></returns>
|
||||
|
public static Matrix4x4 CreateGrayscaleBt709Filter(float amount) |
||||
|
{ |
||||
|
Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); |
||||
|
amount = 1F - amount; |
||||
|
|
||||
|
// https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc
|
||||
|
return new Matrix4x4 |
||||
|
{ |
||||
|
M11 = .2126F + (.7874F * amount), |
||||
|
M12 = .2126F - (.2126F * amount), |
||||
|
M13 = .2126F - (.2126F * amount), |
||||
|
M21 = .7152F - (.7152F * amount), |
||||
|
M22 = .7152F + (.2848F * amount), |
||||
|
M23 = .7152F - (.7152F * amount), |
||||
|
M31 = .0722F - (.0722F * amount), |
||||
|
M32 = .0722F - (.0722F * amount), |
||||
|
M33 = .0722F + (.9278F * amount), |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create a hue filter matrix using the given angle in degrees.
|
||||
|
/// </summary>
|
||||
|
/// <param name="degrees">The angle of rotation in degrees.</param>
|
||||
|
/// <returns>The <see cref="Matrix4x4"/></returns>
|
||||
|
public static Matrix4x4 CreateHueFilter(float degrees) |
||||
|
{ |
||||
|
// Wrap the angle round at 360.
|
||||
|
degrees = degrees % 360; |
||||
|
|
||||
|
// Make sure it's not negative.
|
||||
|
while (degrees < 0) |
||||
|
{ |
||||
|
degrees += 360; |
||||
|
} |
||||
|
|
||||
|
float radian = MathFExtensions.DegreeToRadian(degrees); |
||||
|
float cosRadian = MathF.Cos(radian); |
||||
|
float sinRadian = MathF.Sin(radian); |
||||
|
|
||||
|
// The matrix is set up to preserve the luminance of the image.
|
||||
|
// See http://graficaobscura.com/matrix/index.html
|
||||
|
// Number are taken from https://msdn.microsoft.com/en-us/library/jj192162(v=vs.85).aspx
|
||||
|
return new Matrix4x4 |
||||
|
{ |
||||
|
M11 = .213F + (cosRadian * .787F) - (sinRadian * .213F), |
||||
|
M12 = .213F - (cosRadian * .213F) - (sinRadian * 0.143F), |
||||
|
M13 = .213F - (cosRadian * .213F) - (sinRadian * .787F), |
||||
|
M21 = .715F - (cosRadian * .715F) - (sinRadian * .715F), |
||||
|
M22 = .715F + (cosRadian * .285F) + (sinRadian * 0.140F), |
||||
|
M23 = .715F - (cosRadian * .715F) + (sinRadian * .715F), |
||||
|
M31 = .072F - (cosRadian * .072F) + (sinRadian * .928F), |
||||
|
M32 = .072F - (cosRadian * .072F) - (sinRadian * 0.283F), |
||||
|
M33 = .072F + (cosRadian * .928F) + (sinRadian * .072F), |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create an invert filter matrix using the given amount.
|
||||
|
/// </summary>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be between 0 and 1.</param>
|
||||
|
/// <returns>The <see cref="Matrix4x4"/></returns>
|
||||
|
public static Matrix4x4 CreateInvertFilter(float amount) |
||||
|
{ |
||||
|
Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); |
||||
|
|
||||
|
// See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc
|
||||
|
float invert = 1F - (2F * amount); |
||||
|
|
||||
|
return new Matrix4x4 |
||||
|
{ |
||||
|
M11 = invert, |
||||
|
M22 = invert, |
||||
|
M33 = invert, |
||||
|
M41 = amount, |
||||
|
M42 = amount, |
||||
|
M43 = amount, |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create an opacity filter matrix using the given amount.
|
||||
|
/// </summary>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be between 0 and 1.</param>
|
||||
|
/// <returns>The <see cref="Matrix4x4"/></returns>
|
||||
|
public static Matrix4x4 CreateOpacityFilter(float amount) |
||||
|
{ |
||||
|
Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); |
||||
|
|
||||
|
// See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc
|
||||
|
return new Matrix4x4 |
||||
|
{ |
||||
|
M11 = 1, |
||||
|
M22 = 1, |
||||
|
M33 = 1, |
||||
|
M44 = amount |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create a saturation filter matrix using the given amount.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// A value of 0 is completely un-saturated. A value of 1 leaves the input unchanged.
|
||||
|
/// Other values are linear multipliers on the effect. Values of amount over 1 are allowed, providing super-saturated results
|
||||
|
/// </remarks>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
|
||||
|
/// <returns>The <see cref="Matrix4x4"/></returns>
|
||||
|
public static Matrix4x4 CreateSaturateFilter(float amount) |
||||
|
{ |
||||
|
Guard.MustBeGreaterThanOrEqualTo(amount, 0, nameof(amount)); |
||||
|
|
||||
|
// See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc
|
||||
|
return new Matrix4x4 |
||||
|
{ |
||||
|
M11 = .213F + (.787F * amount), |
||||
|
M12 = .213F - (.213F * amount), |
||||
|
M13 = .213F - (.213F * amount), |
||||
|
M21 = .715F - (.715F * amount), |
||||
|
M22 = .715F + (.285F * amount), |
||||
|
M23 = .715F - (.715F * amount), |
||||
|
M31 = 1F - ((.213F + (.787F * amount)) + (.715F - (.715F * amount))), |
||||
|
M32 = 1F - ((.213F - (.213F * amount)) + (.715F + (.285F * amount))), |
||||
|
M33 = 1F - ((.213F - (.213F * amount)) + (.715F - (.715F * amount))), |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create a sepia filter matrix using the given amount.
|
||||
|
/// The formula used matches the svg specification. <see href="http://www.w3.org/TR/filter-effects/#sepiaEquivalent"/>
|
||||
|
/// </summary>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be between 0 and 1.</param>
|
||||
|
/// <returns>The <see cref="Matrix4x4"/></returns>
|
||||
|
public static Matrix4x4 CreateSepiaFilter(float amount) |
||||
|
{ |
||||
|
Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); |
||||
|
amount = 1F - amount; |
||||
|
|
||||
|
// See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc
|
||||
|
return new Matrix4x4 |
||||
|
{ |
||||
|
M11 = .393F + (.607F * amount), |
||||
|
M12 = .349F - (.349F * amount), |
||||
|
M13 = .272F - (.272F * amount), |
||||
|
M21 = .769F - (.769F * amount), |
||||
|
M22 = .686F + (.314F * amount), |
||||
|
M23 = .534F - (.534F * amount), |
||||
|
M31 = .189F - (.189F * amount), |
||||
|
M32 = .168F - (.168F * amount), |
||||
|
M33 = .131F + (.869F * amount), |
||||
|
M44 = 1 |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Processing.Processors; |
||||
|
using SixLabors.Primitives; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Extension methods for the <see cref="Image{TPixel}"/> type.
|
||||
|
/// </summary>
|
||||
|
public static partial class ImageExtensions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Alters the saturation component of the image.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// A value of 0 is completely un-saturated. A value of 1 leaves the input unchanged.
|
||||
|
/// Other values are linear multipliers on the effect. Values of amount over 1 are allowed, providing super-saturated results
|
||||
|
/// </remarks>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
|
||||
|
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
||||
|
public static IImageProcessingContext<TPixel> Saturate<TPixel>(this IImageProcessingContext<TPixel> source, float amount) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
source.ApplyProcessor(new SaturateProcessor<TPixel>(amount)); |
||||
|
return source; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Alters the saturation component of the image.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// A value of 0 is completely un-saturated. A value of 1 leaves the input unchanged.
|
||||
|
/// Other values are linear multipliers on the effect. Values of amount over 1 are allowed, providing super-saturated results
|
||||
|
/// </remarks>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
|
||||
|
/// <param name="rectangle">
|
||||
|
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
|
||||
|
/// </param>
|
||||
|
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
||||
|
public static IImageProcessingContext<TPixel> Saturate<TPixel>(this IImageProcessingContext<TPixel> source, float amount, Rectangle rectangle) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
source.ApplyProcessor(new SaturateProcessor<TPixel>(amount), rectangle); |
||||
|
return source; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,34 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image to their black and white equivalent.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class BlackWhiteProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4() |
|
||||
{ |
|
||||
M11 = 1.5F, |
|
||||
M12 = 1.5F, |
|
||||
M13 = 1.5F, |
|
||||
M21 = 1.5F, |
|
||||
M22 = 1.5F, |
|
||||
M23 = 1.5F, |
|
||||
M31 = 1.5F, |
|
||||
M32 = 1.5F, |
|
||||
M33 = 1.5F, |
|
||||
M41 = -1F, |
|
||||
M42 = -1F, |
|
||||
M43 = -1F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
@ -1,34 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class AchromatomalyProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4 |
|
||||
{ |
|
||||
M11 = .618F, |
|
||||
M12 = .163F, |
|
||||
M13 = .163F, |
|
||||
M21 = .320F, |
|
||||
M22 = .775F, |
|
||||
M23 = .320F, |
|
||||
M31 = .062F, |
|
||||
M32 = .062F, |
|
||||
M33 = .516F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Compand => false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,34 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class AchromatopsiaProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4 |
|
||||
{ |
|
||||
M11 = .299F, |
|
||||
M12 = .299F, |
|
||||
M13 = .299F, |
|
||||
M21 = .587F, |
|
||||
M22 = .587F, |
|
||||
M23 = .587F, |
|
||||
M31 = .114F, |
|
||||
M32 = .114F, |
|
||||
M33 = .114F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Compand => false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,31 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image recreating Protanopia (Red-Weak) color blindness.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class ProtanomalyProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4 |
|
||||
{ |
|
||||
M11 = 0.817F, |
|
||||
M12 = 0.333F, |
|
||||
M21 = 0.183F, |
|
||||
M22 = 0.667F, |
|
||||
M23 = 0.125F, |
|
||||
M33 = 0.875F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Compand => false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,78 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Numerics; |
|
||||
using System.Threading.Tasks; |
|
||||
using SixLabors.ImageSharp.Advanced; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.Primitives; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// The color matrix filter. Inherit from this class to perform operation involving color matrices.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal abstract class ColorMatrixProcessor<TPixel> : ImageProcessor<TPixel>, IColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public abstract Matrix4x4 Matrix { get; } |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public virtual bool Compand { get; set; } = true; |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
|
||||
{ |
|
||||
int startY = sourceRectangle.Y; |
|
||||
int endY = sourceRectangle.Bottom; |
|
||||
int startX = sourceRectangle.X; |
|
||||
int endX = sourceRectangle.Right; |
|
||||
|
|
||||
// Align start/end positions.
|
|
||||
int minX = Math.Max(0, startX); |
|
||||
int maxX = Math.Min(source.Width, endX); |
|
||||
int minY = Math.Max(0, startY); |
|
||||
int maxY = Math.Min(source.Height, endY); |
|
||||
|
|
||||
// Reset offset if necessary.
|
|
||||
if (minX > 0) |
|
||||
{ |
|
||||
startX = 0; |
|
||||
} |
|
||||
|
|
||||
if (minY > 0) |
|
||||
{ |
|
||||
startY = 0; |
|
||||
} |
|
||||
|
|
||||
Matrix4x4 matrix = this.Matrix; |
|
||||
bool compand = this.Compand; |
|
||||
|
|
||||
Parallel.For( |
|
||||
minY, |
|
||||
maxY, |
|
||||
configuration.ParallelOptions, |
|
||||
y => |
|
||||
{ |
|
||||
Span<TPixel> row = source.GetPixelRowSpan(y - startY); |
|
||||
|
|
||||
for (int x = minX; x < maxX; x++) |
|
||||
{ |
|
||||
ref TPixel pixel = ref row[x - startX]; |
|
||||
var vector = pixel.ToVector4(); |
|
||||
|
|
||||
if (compand) |
|
||||
{ |
|
||||
vector = vector.Expand(); |
|
||||
} |
|
||||
|
|
||||
vector = Vector4.Transform(vector, matrix); |
|
||||
pixel.PackFromVector4(compand ? vector.Compress() : vector); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,32 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image to Grayscale 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>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class GrayscaleBt601Processor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4 |
|
||||
{ |
|
||||
M11 = .299F, |
|
||||
M12 = .299F, |
|
||||
M13 = .299F, |
|
||||
M21 = .587F, |
|
||||
M22 = .587F, |
|
||||
M23 = .587F, |
|
||||
M31 = .114F, |
|
||||
M32 = .114F, |
|
||||
M33 = .114F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
@ -1,32 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image to Grayscale applying the formula as specified by ITU-R Recommendation BT.709
|
|
||||
/// <see href="https://en.wikipedia.org/wiki/Rec._709#Luma_coefficients"/>.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class GrayscaleBt709Processor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4 |
|
||||
{ |
|
||||
M11 = .2126F, |
|
||||
M12 = .2126F, |
|
||||
M13 = .2126F, |
|
||||
M21 = .7152F, |
|
||||
M22 = .7152F, |
|
||||
M23 = .7152F, |
|
||||
M31 = .0722F, |
|
||||
M32 = .0722F, |
|
||||
M33 = .0722F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
@ -1,77 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// An <see cref="ImageProcessor{TPixel}"/> to change the hue of an <see cref="Image{TPixel}"/>.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class HueProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="HueProcessor{TPixel}"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="angle">The new brightness of the image. Must be between -100 and 100.</param>
|
|
||||
public HueProcessor(float angle) |
|
||||
{ |
|
||||
// Wrap the angle round at 360.
|
|
||||
angle = angle % 360; |
|
||||
|
|
||||
// Make sure it's not negative.
|
|
||||
while (angle < 0) |
|
||||
{ |
|
||||
angle += 360; |
|
||||
} |
|
||||
|
|
||||
this.Angle = angle; |
|
||||
|
|
||||
float radians = MathFExtensions.DegreeToRadian(angle); |
|
||||
float cosradians = MathF.Cos(radians); |
|
||||
float sinradians = MathF.Sin(radians); |
|
||||
|
|
||||
float lumR = .213F; |
|
||||
float lumG = .715F; |
|
||||
float lumB = .072F; |
|
||||
|
|
||||
float oneMinusLumR = 1 - lumR; |
|
||||
float oneMinusLumG = 1 - lumG; |
|
||||
float oneMinusLumB = 1 - lumB; |
|
||||
|
|
||||
// The matrix is set up to preserve the luminance of the image.
|
|
||||
// See http://graficaobscura.com/matrix/index.html
|
|
||||
// Number are taken from https://msdn.microsoft.com/en-us/library/jj192162(v=vs.85).aspx
|
|
||||
var matrix4X4 = new Matrix4x4 |
|
||||
{ |
|
||||
M11 = lumR + (cosradians * oneMinusLumR) - (sinradians * lumR), |
|
||||
M12 = lumR - (cosradians * lumR) - (sinradians * 0.143F), |
|
||||
M13 = lumR - (cosradians * lumR) - (sinradians * oneMinusLumR), |
|
||||
M21 = lumG - (cosradians * lumG) - (sinradians * lumG), |
|
||||
M22 = lumG + (cosradians * oneMinusLumG) + (sinradians * 0.140F), |
|
||||
M23 = lumG - (cosradians * lumG) + (sinradians * lumG), |
|
||||
M31 = lumB - (cosradians * lumB) + (sinradians * oneMinusLumB), |
|
||||
M32 = lumB - (cosradians * lumB) - (sinradians * 0.283F), |
|
||||
M33 = lumB + (cosradians * oneMinusLumB) + (sinradians * lumB), |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
|
|
||||
this.Matrix = matrix4X4; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the rotation value.
|
|
||||
/// </summary>
|
|
||||
public float Angle { get; } |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix { get; } |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Compand => false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,27 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Encapsulates properties and methods for creating processors that utilize a matrix to
|
|
||||
/// alter the image pixels.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal interface IColorMatrixProcessor<TPixel> : IImageProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Gets the <see cref="Matrix4x4"/> used to alter the image.
|
|
||||
/// </summary>
|
|
||||
Matrix4x4 Matrix { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets or sets a value indicating whether to compress or expand individual pixel color values on processing.
|
|
||||
/// </summary>
|
|
||||
bool Compand { get; set; } |
|
||||
} |
|
||||
} |
|
||||
@ -1,28 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image recreating an old Kodachrome camera effect.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class KodachromeProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4 |
|
||||
{ |
|
||||
M11 = 0.6997023F, |
|
||||
M22 = 0.4609577F, |
|
||||
M33 = 0.397218F, |
|
||||
M41 = 0.005F, |
|
||||
M42 = -0.005F, |
|
||||
M43 = 0.005F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
@ -1,66 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// An <see cref="ImageProcessor{TPixel}"/> to change the saturation of an <see cref="Image{TPixel}"/>.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class SaturationProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="SaturationProcessor{TPixel}"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="saturation">The new saturation of the image. Must be between -100 and 100.</param>
|
|
||||
/// <exception cref="System.ArgumentException">
|
|
||||
/// <paramref name="saturation"/> is less than -100 or is greater than 100.
|
|
||||
/// </exception>
|
|
||||
public SaturationProcessor(int saturation) |
|
||||
{ |
|
||||
this.Amount = saturation; |
|
||||
Guard.MustBeBetweenOrEqualTo(saturation, -100, 100, nameof(saturation)); |
|
||||
float saturationFactor = saturation / 100F; |
|
||||
|
|
||||
// Stop at -1 to prevent inversion.
|
|
||||
saturationFactor++; |
|
||||
|
|
||||
// The matrix is set up to "shear" the color space using the following set of values.
|
|
||||
// Note that each color component has an effective luminance which contributes to the
|
|
||||
// overall brightness of the pixel.
|
|
||||
// See http://graficaobscura.com/matrix/index.html
|
|
||||
float saturationComplement = 1.0f - saturationFactor; |
|
||||
float saturationComplementR = 0.3086f * saturationComplement; |
|
||||
float saturationComplementG = 0.6094f * saturationComplement; |
|
||||
float saturationComplementB = 0.0820f * saturationComplement; |
|
||||
|
|
||||
var matrix4X4 = new Matrix4x4 |
|
||||
{ |
|
||||
M11 = saturationComplementR + saturationFactor, |
|
||||
M12 = saturationComplementR, |
|
||||
M13 = saturationComplementR, |
|
||||
M21 = saturationComplementG, |
|
||||
M22 = saturationComplementG + saturationFactor, |
|
||||
M23 = saturationComplementG, |
|
||||
M31 = saturationComplementB, |
|
||||
M32 = saturationComplementB, |
|
||||
M33 = saturationComplementB + saturationFactor, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
|
|
||||
this.Matrix = matrix4X4; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the amount to apply.
|
|
||||
/// </summary>
|
|
||||
public int Amount { get; } |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix { get; } |
|
||||
} |
|
||||
} |
|
||||
@ -1,35 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image to their sepia equivalent.
|
|
||||
/// The formula used matches the svg specification. <see href="http://www.w3.org/TR/filter-effects/#sepiaEquivalent"/>
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class SepiaProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4 |
|
||||
{ |
|
||||
M11 = .393F, |
|
||||
M12 = .349F, |
|
||||
M13 = .272F, |
|
||||
M21 = .769F, |
|
||||
M22 = .686F, |
|
||||
M23 = .534F, |
|
||||
M31 = .189F, |
|
||||
M32 = .168F, |
|
||||
M33 = .131F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Compand => false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,81 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Numerics; |
|
||||
using System.Threading.Tasks; |
|
||||
using SixLabors.ImageSharp.Advanced; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.Primitives; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// An <see cref="IImageProcessor{TPixel}"/> to change the alpha component of an <see cref="Image{TPixel}"/>.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class AlphaProcessor<TPixel> : ImageProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="AlphaProcessor{TPixel}"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="percent">The percentage to adjust the opacity of the image. Must be between 0 and 1.</param>
|
|
||||
/// <exception cref="System.ArgumentException">
|
|
||||
/// <paramref name="percent"/> is less than 0 or is greater than 1.
|
|
||||
/// </exception>
|
|
||||
public AlphaProcessor(float percent) |
|
||||
{ |
|
||||
Guard.MustBeBetweenOrEqualTo(percent, 0, 1, nameof(percent)); |
|
||||
this.Value = percent; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the alpha value.
|
|
||||
/// </summary>
|
|
||||
public float Value { get; } |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
|
||||
{ |
|
||||
int startY = sourceRectangle.Y; |
|
||||
int endY = sourceRectangle.Bottom; |
|
||||
int startX = sourceRectangle.X; |
|
||||
int endX = sourceRectangle.Right; |
|
||||
|
|
||||
// Align start/end positions.
|
|
||||
int minX = Math.Max(0, startX); |
|
||||
int maxX = Math.Min(source.Width, endX); |
|
||||
int minY = Math.Max(0, startY); |
|
||||
int maxY = Math.Min(source.Height, endY); |
|
||||
|
|
||||
// Reset offset if necessary.
|
|
||||
if (minX > 0) |
|
||||
{ |
|
||||
startX = 0; |
|
||||
} |
|
||||
|
|
||||
if (minY > 0) |
|
||||
{ |
|
||||
startY = 0; |
|
||||
} |
|
||||
|
|
||||
var alphaVector = new Vector4(1, 1, 1, this.Value); |
|
||||
|
|
||||
Parallel.For( |
|
||||
minY, |
|
||||
maxY, |
|
||||
configuration.ParallelOptions, |
|
||||
y => |
|
||||
{ |
|
||||
Span<TPixel> row = source.GetPixelRowSpan(y - startY); |
|
||||
|
|
||||
for (int x = minX; x < maxX; x++) |
|
||||
{ |
|
||||
ref TPixel pixel = ref row[x - startX]; |
|
||||
pixel.PackFromVector4(pixel.ToVector4() * alphaVector); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,87 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Numerics; |
|
||||
using System.Threading.Tasks; |
|
||||
using SixLabors.ImageSharp.Advanced; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.Primitives; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// An <see cref="IImageProcessor{TPixel}"/> to change the brightness of an <see cref="Image{TPixel}"/>.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class BrightnessProcessor<TPixel> : ImageProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="BrightnessProcessor{TPixel}"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="brightness">The new brightness of the image. Must be between -100 and 100.</param>
|
|
||||
/// <exception cref="System.ArgumentException">
|
|
||||
/// <paramref name="brightness"/> is less than -100 or is greater than 100.
|
|
||||
/// </exception>
|
|
||||
public BrightnessProcessor(int brightness) |
|
||||
{ |
|
||||
Guard.MustBeBetweenOrEqualTo(brightness, -100, 100, nameof(brightness)); |
|
||||
this.Value = brightness; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the brightness value.
|
|
||||
/// </summary>
|
|
||||
public int Value { get; } |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
|
||||
{ |
|
||||
float brightness = this.Value / 100F; |
|
||||
|
|
||||
int startY = sourceRectangle.Y; |
|
||||
int endY = sourceRectangle.Bottom; |
|
||||
int startX = sourceRectangle.X; |
|
||||
int endX = sourceRectangle.Right; |
|
||||
|
|
||||
// Align start/end positions.
|
|
||||
int minX = Math.Max(0, startX); |
|
||||
int maxX = Math.Min(source.Width, endX); |
|
||||
int minY = Math.Max(0, startY); |
|
||||
int maxY = Math.Min(source.Height, endY); |
|
||||
|
|
||||
// Reset offset if necessary.
|
|
||||
if (minX > 0) |
|
||||
{ |
|
||||
startX = 0; |
|
||||
} |
|
||||
|
|
||||
if (minY > 0) |
|
||||
{ |
|
||||
startY = 0; |
|
||||
} |
|
||||
|
|
||||
Parallel.For( |
|
||||
minY, |
|
||||
maxY, |
|
||||
configuration.ParallelOptions, |
|
||||
y => |
|
||||
{ |
|
||||
Span<TPixel> row = source.GetPixelRowSpan(y - startY); |
|
||||
|
|
||||
for (int x = minX; x < maxX; x++) |
|
||||
{ |
|
||||
ref TPixel pixel = ref row[x - startX]; |
|
||||
|
|
||||
// TODO: Check this with other formats.
|
|
||||
Vector4 vector = pixel.ToVector4().Expand(); |
|
||||
Vector3 transformed = new Vector3(vector.X, vector.Y, vector.Z) + new Vector3(brightness); |
|
||||
vector = new Vector4(transformed, vector.W); |
|
||||
|
|
||||
pixel.PackFromVector4(vector.Compress()); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,89 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Numerics; |
|
||||
using System.Threading.Tasks; |
|
||||
using SixLabors.ImageSharp.Advanced; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.Primitives; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// An <see cref="IImageProcessor{TPixel}"/> to change the contrast of an <see cref="Image{TPixel}"/>.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class ContrastProcessor<TPixel> : ImageProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="ContrastProcessor{TPixel}"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="contrast">The new contrast of the image. Must be between -100 and 100.</param>
|
|
||||
/// <exception cref="System.ArgumentException">
|
|
||||
/// <paramref name="contrast"/> is less than -100 or is greater than 100.
|
|
||||
/// </exception>
|
|
||||
public ContrastProcessor(int contrast) |
|
||||
{ |
|
||||
Guard.MustBeBetweenOrEqualTo(contrast, -100, 100, nameof(contrast)); |
|
||||
this.Value = contrast; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the contrast value.
|
|
||||
/// </summary>
|
|
||||
public int Value { get; } |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
|
||||
{ |
|
||||
float contrast = (100F + this.Value) / 100F; |
|
||||
|
|
||||
int startY = sourceRectangle.Y; |
|
||||
int endY = sourceRectangle.Bottom; |
|
||||
int startX = sourceRectangle.X; |
|
||||
int endX = sourceRectangle.Right; |
|
||||
var contrastVector = new Vector4(contrast, contrast, contrast, 1); |
|
||||
var shiftVector = new Vector4(.5F, .5F, .5F, 1); |
|
||||
|
|
||||
// Align start/end positions.
|
|
||||
int minX = Math.Max(0, startX); |
|
||||
int maxX = Math.Min(source.Width, endX); |
|
||||
int minY = Math.Max(0, startY); |
|
||||
int maxY = Math.Min(source.Height, endY); |
|
||||
|
|
||||
// Reset offset if necessary.
|
|
||||
if (minX > 0) |
|
||||
{ |
|
||||
startX = 0; |
|
||||
} |
|
||||
|
|
||||
if (minY > 0) |
|
||||
{ |
|
||||
startY = 0; |
|
||||
} |
|
||||
|
|
||||
Parallel.For( |
|
||||
minY, |
|
||||
maxY, |
|
||||
configuration.ParallelOptions, |
|
||||
y => |
|
||||
{ |
|
||||
Span<TPixel> row = source.GetPixelRowSpan(y - startY); |
|
||||
|
|
||||
for (int x = minX; x < maxX; x++) |
|
||||
{ |
|
||||
ref TPixel pixel = ref row[x - startX]; |
|
||||
|
|
||||
Vector4 vector = pixel.ToVector4().Expand(); |
|
||||
vector -= shiftVector; |
|
||||
vector *= contrastVector; |
|
||||
vector += shiftVector; |
|
||||
|
|
||||
pixel.PackFromVector4(vector.Compress()); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,66 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Numerics; |
|
||||
using System.Threading.Tasks; |
|
||||
using SixLabors.ImageSharp.Advanced; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.Primitives; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// An <see cref="IImageProcessor{TPixel}"/> to invert the colors of an <see cref="Image{TPixel}"/>.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class InvertProcessor<TPixel> : ImageProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
|
||||
{ |
|
||||
int startY = sourceRectangle.Y; |
|
||||
int endY = sourceRectangle.Bottom; |
|
||||
int startX = sourceRectangle.X; |
|
||||
int endX = sourceRectangle.Right; |
|
||||
Vector3 inverseVector = Vector3.One; |
|
||||
|
|
||||
// Align start/end positions.
|
|
||||
int minX = Math.Max(0, startX); |
|
||||
int maxX = Math.Min(source.Width, endX); |
|
||||
int minY = Math.Max(0, startY); |
|
||||
int maxY = Math.Min(source.Height, endY); |
|
||||
|
|
||||
// Reset offset if necessary.
|
|
||||
if (minX > 0) |
|
||||
{ |
|
||||
startX = 0; |
|
||||
} |
|
||||
|
|
||||
if (minY > 0) |
|
||||
{ |
|
||||
startY = 0; |
|
||||
} |
|
||||
|
|
||||
Parallel.For( |
|
||||
minY, |
|
||||
maxY, |
|
||||
configuration.ParallelOptions, |
|
||||
y => |
|
||||
{ |
|
||||
Span<TPixel> row = source.GetPixelRowSpan(y - startY); |
|
||||
|
|
||||
for (int x = minX; x < maxX; x++) |
|
||||
{ |
|
||||
ref TPixel pixel = ref row[x - startX]; |
|
||||
|
|
||||
var vector = pixel.ToVector4(); |
|
||||
Vector3 vector3 = inverseVector - new Vector3(vector.X, vector.Y, vector.Z); |
|
||||
|
|
||||
pixel.PackFromVector4(new Vector4(vector3, vector.W)); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,23 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a black and white filter matrix to the image
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class BlackWhiteProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="BlackWhiteProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
public BlackWhiteProcessor() |
||||
|
: base(MatrixFilters.BlackWhiteFilter) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a brightness filter matrix using the given amount.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class BrightnessProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="BrightnessProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged.
|
||||
|
/// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing brighter results.
|
||||
|
/// </remarks>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
|
||||
|
public BrightnessProcessor(float amount) |
||||
|
: base(MatrixFilters.CreateBrightnessFilter(amount)) |
||||
|
{ |
||||
|
this.Amount = amount; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the proportion of the conversion
|
||||
|
/// </summary>
|
||||
|
public float Amount { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class AchromatomalyProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="AchromatomalyProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
public AchromatomalyProcessor() |
||||
|
: base(MatrixFilters.AchromatomalyFilter) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class AchromatopsiaProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="AchromatopsiaProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
public AchromatopsiaProcessor() |
||||
|
: base(MatrixFilters.AchromatopsiaFilter) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Protanomaly (Red-Weak) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class ProtanomalyProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ProtanomalyProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
public ProtanomalyProcessor() |
||||
|
: base(MatrixFilters.ProtanomalyFilter) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a contrast filter matrix using the given amount.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class ContrastProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ContrastProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// A value of 0 will create an image that is completely gray. A value of 1 leaves the input unchanged.
|
||||
|
/// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing results with more contrast.
|
||||
|
/// </remarks>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
|
||||
|
public ContrastProcessor(float amount) |
||||
|
: base(MatrixFilters.CreateContrastFilter(amount)) |
||||
|
{ |
||||
|
this.Amount = amount; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the proportion of the conversion
|
||||
|
/// </summary>
|
||||
|
public float Amount { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
using System.Threading.Tasks; |
||||
|
using SixLabors.ImageSharp.Advanced; |
||||
|
using SixLabors.ImageSharp.Helpers; |
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.Primitives; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Provides methods that accept a <see cref="Matrix4x4"/> matrix to apply freeform filters to images.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class FilterProcessor<TPixel> : ImageProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="FilterProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The matrix used to apply the image filter</param>
|
||||
|
public FilterProcessor(Matrix4x4 matrix) |
||||
|
{ |
||||
|
this.Matrix = matrix; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the <see cref="Matrix4x4"/> used to apply the image filter.
|
||||
|
/// </summary>
|
||||
|
public Matrix4x4 Matrix { get; } |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
||||
|
{ |
||||
|
var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); |
||||
|
int startY = interest.Y; |
||||
|
int endY = interest.Bottom; |
||||
|
int startX = interest.X; |
||||
|
int endX = interest.Right; |
||||
|
Matrix4x4 matrix = this.Matrix; |
||||
|
|
||||
|
Parallel.For( |
||||
|
startY, |
||||
|
endY, |
||||
|
configuration.ParallelOptions, |
||||
|
y => |
||||
|
{ |
||||
|
Span<TPixel> row = source.GetPixelRowSpan(y); |
||||
|
|
||||
|
for (int x = startX; x < endX; x++) |
||||
|
{ |
||||
|
ref TPixel pixel = ref row[x]; |
||||
|
var vector = Vector4.Transform(pixel.ToVector4(), matrix); |
||||
|
pixel.PackFromVector4(vector); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a greyscale filter matrix using the given amount and the formula as specified by ITU-R Recommendation BT.601
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class GrayscaleBt601Processor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="GrayscaleBt601Processor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be between 0 and 1.</param>
|
||||
|
public GrayscaleBt601Processor(float amount) |
||||
|
: base(MatrixFilters.CreateGrayscaleBt601Filter(amount)) |
||||
|
{ |
||||
|
this.Amount = amount; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the proportion of the conversion
|
||||
|
/// </summary>
|
||||
|
public float Amount { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a greyscale filter matrix using the given amount and the formula as specified by ITU-R Recommendation BT.709
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class GrayscaleBt709Processor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="GrayscaleBt709Processor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be between 0 and 1.</param>
|
||||
|
public GrayscaleBt709Processor(float amount) |
||||
|
: base(MatrixFilters.CreateGrayscaleBt709Filter(amount)) |
||||
|
{ |
||||
|
this.Amount = amount; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the proportion of the conversion
|
||||
|
/// </summary>
|
||||
|
public float Amount { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a hue filter matrix using the given angle of rotation in degrees
|
||||
|
/// </summary>
|
||||
|
internal class HueProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="HueProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="degrees">The angle of rotation in degrees</param>
|
||||
|
public HueProcessor(float degrees) |
||||
|
: base(MatrixFilters.CreateHueFilter(degrees)) |
||||
|
{ |
||||
|
this.Degrees = degrees; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the angle of rotation in degrees
|
||||
|
/// </summary>
|
||||
|
public float Degrees { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a filter matrix that inverts the colors of an image
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class InvertProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="InvertProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be between 0 and 1.</param>
|
||||
|
public InvertProcessor(float amount) |
||||
|
: base(MatrixFilters.CreateInvertFilter(amount)) |
||||
|
{ |
||||
|
this.Amount = amount; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the proportion of the conversion
|
||||
|
/// </summary>
|
||||
|
public float Amount { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a filter matrix recreating an old Kodachrome camera effect matrix to the image
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class KodachromeProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="KodachromeProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
public KodachromeProcessor() |
||||
|
: base(MatrixFilters.KodachromeFilter) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies an opacity filter matrix using the given amount.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class OpacityProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="OpacityProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be between 0 and 1.</param>
|
||||
|
public OpacityProcessor(float amount) |
||||
|
: base(MatrixFilters.CreateOpacityFilter(amount)) |
||||
|
{ |
||||
|
this.Amount = amount; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the proportion of the conversion
|
||||
|
/// </summary>
|
||||
|
public float Amount { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a saturation filter matrix using the given amount.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class SaturateProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SaturateProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// A value of 0 is completely un-saturated. A value of 1 leaves the input unchanged.
|
||||
|
/// Other values are linear multipliers on the effect. Values of amount over 1 are allowed, providing super-saturated results
|
||||
|
/// </remarks>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
|
||||
|
public SaturateProcessor(float amount) |
||||
|
: base(MatrixFilters.CreateSaturateFilter(amount)) |
||||
|
{ |
||||
|
this.Amount = amount; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the proportion of the conversion
|
||||
|
/// </summary>
|
||||
|
public float Amount { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a sepia filter matrix using the given amount.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class SepiaProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SepiaProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="amount">The proportion of the conversion. Must be between 0 and 1.</param>
|
||||
|
public SepiaProcessor(float amount) |
||||
|
: base(MatrixFilters.CreateSepiaFilter(amount)) |
||||
|
{ |
||||
|
this.Amount = amount; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the proportion of the conversion
|
||||
|
/// </summary>
|
||||
|
public float Amount { get; } |
||||
|
} |
||||
|
} |
||||
@ -1,31 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Processing.Processors; |
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Effects |
|
||||
{ |
|
||||
public class AlphaTest : BaseImageOperationsExtensionTest |
|
||||
{ |
|
||||
[Fact] |
|
||||
public void Alpha_amount_AlphaProcessorDefaultsSet() |
|
||||
{ |
|
||||
this.operations.Alpha(0.2f); |
|
||||
var processor = this.Verify<AlphaProcessor<Rgba32>>(); |
|
||||
|
|
||||
Assert.Equal(.2f, processor.Value); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Alpha_amount_rect_AlphaProcessorDefaultsSet() |
|
||||
{ |
|
||||
this.operations.Alpha(0.6f, this.rect); |
|
||||
var processor = this.Verify<AlphaProcessor<Rgba32>>(this.rect); |
|
||||
|
|
||||
Assert.Equal(.6f, processor.Value); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,26 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.Processing; |
||||
|
using SixLabors.ImageSharp.Processing.Processors; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Filters |
||||
|
{ |
||||
|
public class FilterTest : BaseImageOperationsExtensionTest |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Filter_CorrectProcessor() |
||||
|
{ |
||||
|
this.operations.Filter(MatrixFilters.AchromatomalyFilter * MatrixFilters.CreateHueFilter(90F)); |
||||
|
FilterProcessor<Rgba32> p = this.Verify<FilterProcessor<Rgba32>>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Filter_rect_CorrectProcessor() |
||||
|
{ |
||||
|
this.operations.Filter(MatrixFilters.AchromatomalyFilter * MatrixFilters.CreateHueFilter(90F), this.rect); |
||||
|
FilterProcessor<Rgba32> p = this.Verify<FilterProcessor<Rgba32>>(this.rect); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.Processing.Processors; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Effects |
||||
|
{ |
||||
|
public class OpacityTest : BaseImageOperationsExtensionTest |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Alpha_amount_AlphaProcessorDefaultsSet() |
||||
|
{ |
||||
|
this.operations.Opacity(0.2f); |
||||
|
OpacityProcessor<Rgba32> processor = this.Verify<OpacityProcessor<Rgba32>>(); |
||||
|
|
||||
|
Assert.Equal(.2f, processor.Amount); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Alpha_amount_rect_AlphaProcessorDefaultsSet() |
||||
|
{ |
||||
|
this.operations.Opacity(0.6f, this.rect); |
||||
|
OpacityProcessor<Rgba32> processor = this.Verify<OpacityProcessor<Rgba32>>(this.rect); |
||||
|
|
||||
|
Assert.Equal(.6f, processor.Amount); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,43 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix |
|
||||
{ |
|
||||
public class BlackWhiteTest : FileTestBase |
|
||||
{ |
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplyBlackWhiteFilter<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.BlackWhite()); |
|
||||
image.DebugSave(provider); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplyBlackWhiteFilterInBox<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.BlackWhite(bounds)); |
|
||||
image.DebugSave(provider); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,57 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Processing; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix |
|
||||
{ |
|
||||
public class ColorBlindnessTest : FileTestBase |
|
||||
{ |
|
||||
public static readonly TheoryData<ColorBlindness> ColorBlindnessFilters |
|
||||
= new TheoryData<ColorBlindness> |
|
||||
{ |
|
||||
ColorBlindness.Achromatomaly, |
|
||||
ColorBlindness.Achromatopsia, |
|
||||
ColorBlindness.Deuteranomaly, |
|
||||
ColorBlindness.Deuteranopia, |
|
||||
ColorBlindness.Protanomaly, |
|
||||
ColorBlindness.Protanopia, |
|
||||
ColorBlindness.Tritanomaly, |
|
||||
ColorBlindness.Tritanopia |
|
||||
}; |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(ColorBlindnessFilters), DefaultPixelType)] |
|
||||
public void ImageShouldApplyColorBlindnessFilter<TPixel>(TestImageProvider<TPixel> provider, ColorBlindness colorBlindness) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.ColorBlindness(colorBlindness)); |
|
||||
image.DebugSave(provider, colorBlindness.ToString()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(ColorBlindnessFilters), DefaultPixelType)] |
|
||||
public void ImageShouldApplyColorBlindnessFilterInBox<TPixel>(TestImageProvider<TPixel> provider, ColorBlindness colorBlindness) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.ColorBlindness(colorBlindness, bounds)); |
|
||||
image.DebugSave(provider, colorBlindness.ToString()); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,63 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.Advanced; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Processing; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix |
|
||||
{ |
|
||||
public class GrayscaleTest : FileTestBase |
|
||||
{ |
|
||||
public static readonly TheoryData<GrayscaleMode> GrayscaleModeTypes |
|
||||
= new TheoryData<GrayscaleMode> |
|
||||
{ |
|
||||
GrayscaleMode.Bt601, |
|
||||
GrayscaleMode.Bt709 |
|
||||
}; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Use test patterns over loaded images to save decode time.
|
|
||||
/// </summary>
|
|
||||
[Theory] |
|
||||
[WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, DefaultPixelType)] |
|
||||
public void ImageShouldApplyGrayscaleFilterAll<TPixel>(TestImageProvider<TPixel> provider, GrayscaleMode value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Grayscale(value)); |
|
||||
var rgb = default(Rgb24); |
|
||||
System.Span<TPixel> span = image.Frames.RootFrame.GetPixelSpan(); |
|
||||
for (int i = 0; i < span.Length; i++) |
|
||||
{ |
|
||||
span[i].ToRgb24(ref rgb); |
|
||||
Assert.Equal(rgb.R, rgb.B); |
|
||||
Assert.Equal(rgb.B, rgb.G); |
|
||||
} |
|
||||
|
|
||||
image.DebugSave(provider, value.ToString()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, DefaultPixelType)] |
|
||||
public void ImageShouldApplyGrayscaleFilterInBox<TPixel>(TestImageProvider<TPixel> provider, GrayscaleMode value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (Image<TPixel> image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); |
|
||||
image.Mutate(x => x.Grayscale(value, bounds)); |
|
||||
image.DebugSave(provider, value.ToString()); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,50 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix |
|
||||
{ |
|
||||
public class HueTest : FileTestBase |
|
||||
{ |
|
||||
public static readonly TheoryData<int> HueValues |
|
||||
= new TheoryData<int> |
|
||||
{ |
|
||||
180, |
|
||||
-180 |
|
||||
}; |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(HueValues), DefaultPixelType)] |
|
||||
public void ImageShouldApplyHueFilter<TPixel>(TestImageProvider<TPixel> provider, int value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Hue(value)); |
|
||||
image.DebugSave(provider, value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(HueValues), DefaultPixelType)] |
|
||||
public void ImageShouldApplyHueFilterInBox<TPixel>(TestImageProvider<TPixel> provider, int value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.Hue(value, bounds)); |
|
||||
image.DebugSave(provider, value); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,43 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix |
|
||||
{ |
|
||||
public class KodachromeTest : FileTestBase |
|
||||
{ |
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplyKodachromeFilter<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Kodachrome()); |
|
||||
image.DebugSave(provider); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplyKodachromeFilterInBox<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.Kodachrome(bounds)); |
|
||||
image.DebugSave(provider); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,43 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix |
|
||||
{ |
|
||||
public class LomographTest : FileTestBase |
|
||||
{ |
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplyLomographFilter<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Lomograph()); |
|
||||
image.DebugSave(provider); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplyLomographFilterInBox<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.Lomograph(bounds)); |
|
||||
image.DebugSave(provider); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,43 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix |
|
||||
{ |
|
||||
public class PolaroidTest : FileTestBase |
|
||||
{ |
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplyPolaroidFilter<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Polaroid()); |
|
||||
image.DebugSave(provider); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplyPolaroidFilterInBox<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.Polaroid(bounds)); |
|
||||
image.DebugSave(provider); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,50 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix |
|
||||
{ |
|
||||
public class SaturationTest : FileTestBase |
|
||||
{ |
|
||||
public static readonly TheoryData<int> SaturationValues |
|
||||
= new TheoryData<int> |
|
||||
{ |
|
||||
50 , |
|
||||
-50 , |
|
||||
}; |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(SaturationValues), DefaultPixelType)] |
|
||||
public void ImageShouldApplySaturationFilter<TPixel>(TestImageProvider<TPixel> provider, int value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Saturation(value)); |
|
||||
image.DebugSave(provider, value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(SaturationValues), DefaultPixelType)] |
|
||||
public void ImageShouldApplySaturationFilterInBox<TPixel>(TestImageProvider<TPixel> provider, int value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.Saturation(value, bounds)); |
|
||||
image.DebugSave(provider, value); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,43 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix |
|
||||
{ |
|
||||
public class SepiaTest : FileTestBase |
|
||||
{ |
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplySepiaFilter<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Sepia()); |
|
||||
image.DebugSave(provider); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplySepiaFilterInBox<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.Sepia(bounds)); |
|
||||
image.DebugSave(provider); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,50 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects |
|
||||
{ |
|
||||
public class AlphaTest : FileTestBase |
|
||||
{ |
|
||||
public static readonly TheoryData<float> AlphaValues |
|
||||
= new TheoryData<float> |
|
||||
{ |
|
||||
20/100F, |
|
||||
80/100F |
|
||||
}; |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(AlphaValues), DefaultPixelType)] |
|
||||
public void ImageShouldApplyAlphaFilter<TPixel>(TestImageProvider<TPixel> provider, float value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Alpha(value)); |
|
||||
image.DebugSave(provider, value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(AlphaValues), DefaultPixelType)] |
|
||||
public void ImageShouldApplyAlphaFilterInBox<TPixel>(TestImageProvider<TPixel> provider, float value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.Alpha(value, bounds)); |
|
||||
image.DebugSave(provider, value); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,50 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects |
|
||||
{ |
|
||||
public class BrightnessTest : FileTestBase |
|
||||
{ |
|
||||
public static readonly TheoryData<int> BrightnessValues |
|
||||
= new TheoryData<int> |
|
||||
{ |
|
||||
50, |
|
||||
-50 |
|
||||
}; |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(BrightnessValues), DefaultPixelType)] |
|
||||
public void ImageShouldApplyBrightnessFilter<TPixel>(TestImageProvider<TPixel> provider, int value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Brightness(value)); |
|
||||
image.DebugSave(provider, value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(BrightnessValues), DefaultPixelType)] |
|
||||
public void ImageShouldApplyBrightnessFilterInBox<TPixel>(TestImageProvider<TPixel> provider, int value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.Brightness(value, bounds)); |
|
||||
image.DebugSave(provider, value); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,50 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects |
|
||||
{ |
|
||||
public class ContrastTest : FileTestBase |
|
||||
{ |
|
||||
public static readonly TheoryData<int> ContrastValues |
|
||||
= new TheoryData<int> |
|
||||
{ |
|
||||
50, |
|
||||
-50 |
|
||||
}; |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(ContrastValues), DefaultPixelType)] |
|
||||
public void ImageShouldApplyContrastFilter<TPixel>(TestImageProvider<TPixel> provider, int value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Contrast(value)); |
|
||||
image.DebugSave(provider, value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), nameof(ContrastValues), DefaultPixelType)] |
|
||||
public void ImageShouldApplyContrastFilterInBox<TPixel>(TestImageProvider<TPixel> provider, int value) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.Contrast(value, bounds)); |
|
||||
image.DebugSave(provider, value); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,43 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|
||||
|
|
||||
using SixLabors.Primitives; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects |
|
||||
{ |
|
||||
public class InvertTest : FileTestBase |
|
||||
{ |
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplyInvertFilter<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> image = provider.GetImage()) |
|
||||
{ |
|
||||
image.Mutate(x => x.Invert()); |
|
||||
image.DebugSave(provider); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
|
||||
public void ImageShouldApplyInvertFilterInBox<TPixel>(TestImageProvider<TPixel> provider) |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
using (Image<TPixel> source = provider.GetImage()) |
|
||||
using (var image = source.Clone()) |
|
||||
{ |
|
||||
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
|
||||
|
|
||||
image.Mutate(x => x.Invert(bounds)); |
|
||||
image.DebugSave(provider); |
|
||||
|
|
||||
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,21 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class BlackWhiteTest |
||||
|
{ |
||||
|
[Theory] |
||||
|
[WithTestPatternImages(48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyBlackWhiteFilter<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(ctx => ctx.BlackWhite()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class BrightnessTest |
||||
|
{ |
||||
|
public static readonly TheoryData<float> BrightnessValues |
||||
|
= new TheoryData<float> |
||||
|
{ |
||||
|
.5F, |
||||
|
1.5F |
||||
|
}; |
||||
|
|
||||
|
[Theory] |
||||
|
[WithTestPatternImages(nameof(BrightnessValues), 48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyBrightnessFilter<TPixel>(TestImageProvider<TPixel> provider, float value) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(ctx => ctx.Brightness(value), value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Processing; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class ColorBlindnessTest |
||||
|
{ |
||||
|
public static readonly TheoryData<ColorBlindness> ColorBlindnessFilters |
||||
|
= new TheoryData<ColorBlindness> |
||||
|
{ |
||||
|
ColorBlindness.Achromatomaly, |
||||
|
ColorBlindness.Achromatopsia, |
||||
|
ColorBlindness.Deuteranomaly, |
||||
|
ColorBlindness.Deuteranopia, |
||||
|
ColorBlindness.Protanomaly, |
||||
|
ColorBlindness.Protanopia, |
||||
|
ColorBlindness.Tritanomaly, |
||||
|
ColorBlindness.Tritanopia |
||||
|
}; |
||||
|
|
||||
|
[Theory] |
||||
|
[WithTestPatternImages(nameof(ColorBlindnessFilters), 48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyColorBlindnessFilter<TPixel>(TestImageProvider<TPixel> provider, ColorBlindness colorBlindness) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.ColorBlindness(colorBlindness), colorBlindness.ToString()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class ContrastTest |
||||
|
{ |
||||
|
public static readonly TheoryData<float> ContrastValues |
||||
|
= new TheoryData<float> |
||||
|
{ |
||||
|
.5F, |
||||
|
1.5F |
||||
|
}; |
||||
|
|
||||
|
[Theory] |
||||
|
[WithTestPatternImages(nameof(ContrastValues), 48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyContrastFilter<TPixel>(TestImageProvider<TPixel> provider, float value) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.Contrast(value), value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,49 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System.Numerics; |
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Processing; |
||||
|
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
||||
|
|
||||
|
using SixLabors.Primitives; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class FilterTest |
||||
|
{ |
||||
|
// Testing the generic FilterProcessor with more than one pixel type intentionally.
|
||||
|
// There is no need to do this with the specialized ones.
|
||||
|
[Theory] |
||||
|
[WithTestPatternImages(48, 48, PixelTypes.Rgba32 | PixelTypes.Bgra32)] |
||||
|
public void ApplyFilter<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
Matrix4x4 m = CreateCombinedTestFilterMatrix(); |
||||
|
|
||||
|
provider.RunValidatingProcessorTest(x => x.Filter(m)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[WithTestPatternImages(48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyFilterInBox<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
Matrix4x4 m = CreateCombinedTestFilterMatrix(); |
||||
|
|
||||
|
provider.RunRectangleConstrainedValidatingProcessorTest((x, b) => x.Filter(m, b)); |
||||
|
} |
||||
|
|
||||
|
private static Matrix4x4 CreateCombinedTestFilterMatrix() |
||||
|
{ |
||||
|
Matrix4x4 brightness = MatrixFilters.CreateBrightnessFilter(0.9F); |
||||
|
Matrix4x4 hue = MatrixFilters.CreateHueFilter(180F); |
||||
|
Matrix4x4 saturation = MatrixFilters.CreateSaturateFilter(1.5F); |
||||
|
Matrix4x4 m = brightness * hue * saturation; |
||||
|
return m; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.Advanced; |
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Processing; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class GrayscaleTest |
||||
|
{ |
||||
|
public static readonly TheoryData<GrayscaleMode> GrayscaleModeTypes |
||||
|
= new TheoryData<GrayscaleMode> |
||||
|
{ |
||||
|
GrayscaleMode.Bt601, |
||||
|
GrayscaleMode.Bt709 |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Use test patterns over loaded images to save decode time.
|
||||
|
/// </summary>
|
||||
|
[Theory] |
||||
|
[WithTestPatternImages(nameof(GrayscaleModeTypes), 48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyGrayscaleFilter<TPixel>(TestImageProvider<TPixel> provider, GrayscaleMode value) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.Grayscale(value), value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class HueTest |
||||
|
{ |
||||
|
public static readonly TheoryData<int> HueValues |
||||
|
= new TheoryData<int> |
||||
|
{ |
||||
|
180, |
||||
|
-180 |
||||
|
}; |
||||
|
|
||||
|
[Theory] |
||||
|
[WithTestPatternImages(nameof(HueValues), 48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyHueFilter<TPixel>(TestImageProvider<TPixel> provider, int value) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.Hue(value), value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class InvertTest |
||||
|
{ |
||||
|
[Theory] |
||||
|
[WithTestPatternImages(48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyInvertFilter<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.Invert()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class KodachromeTest |
||||
|
{ |
||||
|
[Theory] |
||||
|
[WithTestPatternImages(48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyKodachromeFilter<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.Kodachrome()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class LomographTest |
||||
|
{ |
||||
|
[Theory] |
||||
|
[WithTestPatternImages(48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyLomographFilter<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.Lomograph()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class OpacityTest |
||||
|
{ |
||||
|
public static readonly TheoryData<float> AlphaValues |
||||
|
= new TheoryData<float> |
||||
|
{ |
||||
|
20/100F, |
||||
|
80/100F |
||||
|
}; |
||||
|
|
||||
|
[Theory] |
||||
|
[WithTestPatternImages(nameof(AlphaValues), 48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyAlphaFilter<TPixel>(TestImageProvider<TPixel> provider, float value) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.Opacity(value), value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class PolaroidTest |
||||
|
{ |
||||
|
[Theory] |
||||
|
[WithTestPatternImages(48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplyPolaroidFilter<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.Polaroid()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class SaturateTest |
||||
|
{ |
||||
|
public static readonly TheoryData<float> SaturationValues |
||||
|
= new TheoryData<float> |
||||
|
{ |
||||
|
.5F, |
||||
|
1.5F, |
||||
|
}; |
||||
|
|
||||
|
[Theory] |
||||
|
[WithTestPatternImages(nameof(SaturationValues), 48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplySaturationFilter<TPixel>(TestImageProvider<TPixel> provider, float value) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.Saturate(value), value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
[GroupOutput("Filters")] |
||||
|
public class SepiaTest |
||||
|
{ |
||||
|
[Theory] |
||||
|
[WithTestPatternImages(48, 48, PixelTypes.Rgba32)] |
||||
|
public void ApplySepiaFilter<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest(x => x.Sepia()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue