mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: dc91b2297f19411f822db6e460cda7588dba2f98 Former-commit-id: 1edc310dfa1a7293564500e90a1b0b72061edcad Former-commit-id: 7e12412768a1ff6ad545e77a3b7d5d61f9dea3d7af/merge-core
5 changed files with 69 additions and 84 deletions
@ -0,0 +1,56 @@ |
|||||
|
// <copyright file="Saturation.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// An <see cref="IImageProcessor"/> to change the saturation of an <see cref="Image"/>.
|
||||
|
/// </summary>
|
||||
|
public class Saturation : ColorMatrixFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="Saturation"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="saturation">The new saturation of the image. Must be between -100 and 100.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// <paramref name="saturation"/> is less than -100 or is greater than 100.
|
||||
|
/// </exception>
|
||||
|
public Saturation(int 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 colour space using the following set of values.
|
||||
|
// Note that each colour 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; |
||||
|
|
||||
|
Matrix4x4 matrix = new Matrix4x4() |
||||
|
{ |
||||
|
M11 = saturationComplementR + saturationFactor, |
||||
|
M12 = saturationComplementR, |
||||
|
M13 = saturationComplementR, |
||||
|
M21 = saturationComplementG, |
||||
|
M22 = saturationComplementG + saturationFactor, |
||||
|
M23 = saturationComplementG, |
||||
|
M31 = saturationComplementB, |
||||
|
M32 = saturationComplementB, |
||||
|
M33 = saturationComplementB + saturationFactor, |
||||
|
}; |
||||
|
|
||||
|
this.Value = matrix; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,78 +0,0 @@ |
|||||
// <copyright file="Saturation.cs" company="James South">
|
|
||||
// Copyright (c) James South and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace ImageProcessor.Filters |
|
||||
{ |
|
||||
using System; |
|
||||
using System.Numerics; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// An <see cref="IImageProcessor"/> to change the saturation of an <see cref="Image"/>.
|
|
||||
/// </summary>
|
|
||||
public class Saturation : ParallelImageProcessor |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="Saturation"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="saturation">The new saturation of the image. Must be between -100 and 100.</param>
|
|
||||
/// <exception cref="ArgumentException">
|
|
||||
/// <paramref name="saturation"/> is less than -100 or is greater than 100.
|
|
||||
/// </exception>
|
|
||||
public Saturation(int saturation) |
|
||||
{ |
|
||||
Guard.MustBeBetweenOrEqualTo(saturation, -100, 100, nameof(saturation)); |
|
||||
this.Value = saturation; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the saturation value.
|
|
||||
/// </summary>
|
|
||||
public int Value { get; } |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) |
|
||||
{ |
|
||||
float saturation = this.Value / 100f; |
|
||||
int sourceY = sourceRectangle.Y; |
|
||||
int sourceBottom = sourceRectangle.Bottom; |
|
||||
int startX = sourceRectangle.X; |
|
||||
int endX = sourceRectangle.Right; |
|
||||
|
|
||||
Parallel.For( |
|
||||
startY, |
|
||||
endY, |
|
||||
y => |
|
||||
{ |
|
||||
if (y >= sourceY && y < sourceBottom) |
|
||||
{ |
|
||||
for (int x = startX; x < endX; x++) |
|
||||
{ |
|
||||
target[x, y] = AdjustSaturation(source[x, y], saturation); |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Returns a <see cref="Color"/> with the saturation adjusted.
|
|
||||
/// </summary>
|
|
||||
/// <param name="color">The source color.</param>
|
|
||||
/// <param name="saturation">The saturation adjustment factor.</param>
|
|
||||
/// <returns>
|
|
||||
/// The <see cref="Color"/>.
|
|
||||
/// </returns>
|
|
||||
private static Color AdjustSaturation(Color color, float saturation) |
|
||||
{ |
|
||||
//color = PixelOperations.ToLinear(color);
|
|
||||
|
|
||||
// TODO: This can be done with a matrix. But why can I not get conversion to work?
|
|
||||
Hsv hsv = color; |
|
||||
return new Hsv(hsv.H, saturation, hsv.V); |
|
||||
|
|
||||
//return PixelOperations.ToSrgb(newHsv);
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue