mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
893 changed files with 24369 additions and 29328 deletions
@ -1 +1 @@ |
|||
Subproject commit 353b9afe32a8000410312d17263407cd7bb82d19 |
|||
Subproject commit 1dbfb576c83507645265c79e03369b66cdc0379f |
|||
@ -1,7 +1,4 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<RuleSet Name="ImageSharp" ToolsVersion="17.0"> |
|||
<Include Path="..\shared-infrastructure\sixlabors.ruleset" Action="Default" /> |
|||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers"> |
|||
<Rule Id="SA1011" Action="None" /> |
|||
</Rules> |
|||
</RuleSet> |
|||
@ -1,240 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp; |
|||
|
|||
/// <content>
|
|||
/// Contains constructors and implicit conversion methods.
|
|||
/// </content>
|
|||
public readonly partial struct Color |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Rgba64"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Rgba64 pixel) |
|||
{ |
|||
this.data = pixel; |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Rgb48"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Rgb48 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel.R, pixel.G, pixel.B, ushort.MaxValue); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="La32"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(La32 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel.L, pixel.L, pixel.L, pixel.A); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="L16"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(L16 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel.PackedValue, pixel.PackedValue, pixel.PackedValue, ushort.MaxValue); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Rgba32"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Rgba32 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Argb32"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Argb32 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Bgra32"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Bgra32 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Abgr32"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Abgr32 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Rgb24"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Rgb24 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Bgr24"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Bgr24 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The <see cref="Vector4"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Vector4 vector) |
|||
{ |
|||
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One); |
|||
this.boxedHighPrecisionPixel = new RgbaVector(vector.X, vector.Y, vector.Z, vector.W); |
|||
this.data = default; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Color"/> to <see cref="Vector4"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The <see cref="Color"/>.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static explicit operator Vector4(Color color) => color.ToScaledVector4(); |
|||
|
|||
/// <summary>
|
|||
/// Converts an <see cref="Vector4"/> to <see cref="Color"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Vector4"/>.</param>
|
|||
/// <returns>The <see cref="Color"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static explicit operator Color(Vector4 source) => new(source); |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Rgba32 ToRgba32() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToRgba32(); |
|||
} |
|||
|
|||
Rgba32 value = default; |
|||
this.boxedHighPrecisionPixel.ToRgba32(ref value); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Bgra32 ToBgra32() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToBgra32(); |
|||
} |
|||
|
|||
Bgra32 value = default; |
|||
value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4()); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Argb32 ToArgb32() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToArgb32(); |
|||
} |
|||
|
|||
Argb32 value = default; |
|||
value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4()); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Abgr32 ToAbgr32() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToAbgr32(); |
|||
} |
|||
|
|||
Abgr32 value = default; |
|||
value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4()); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Rgb24 ToRgb24() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToRgb24(); |
|||
} |
|||
|
|||
Rgb24 value = default; |
|||
value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4()); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Bgr24 ToBgr24() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToBgr24(); |
|||
} |
|||
|
|||
Bgr24 value = default; |
|||
value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4()); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Vector4 ToScaledVector4() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToScaledVector4(); |
|||
} |
|||
|
|||
return this.boxedHighPrecisionPixel.ToScaledVector4(); |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Enumerate the possible sources of the white point used in chromatic adaptation.
|
|||
/// </summary>
|
|||
public enum ChromaticAdaptionWhitePointSource |
|||
{ |
|||
/// <summary>
|
|||
/// The white point of the source color space.
|
|||
/// </summary>
|
|||
WhitePoint, |
|||
|
|||
/// <summary>
|
|||
/// The white point of the source working space.
|
|||
/// </summary>
|
|||
RgbWorkingSpace |
|||
} |
|||
@ -0,0 +1,178 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Represents a CIE L*a*b* 1976 color.
|
|||
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space"/>
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public readonly struct CieLab : IProfileConnectingSpace<CieLab, CieXyz> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLab"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="a">The a (green - magenta) component.</param>
|
|||
/// <param name="b">The b (blue - yellow) component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLab(float l, float a, float b) |
|||
{ |
|||
// Not clamping as documentation about this space only indicates "usual" ranges
|
|||
this.L = l; |
|||
this.A = a; |
|||
this.B = b; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLab"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, a, b components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLab(Vector3 vector) |
|||
: this() |
|||
{ |
|||
this.L = vector.X; |
|||
this.A = vector.Y; |
|||
this.B = vector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension.
|
|||
/// <remarks>A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
|
|||
/// </summary>
|
|||
public float L { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the a color component.
|
|||
/// <remarks>A value usually ranging from -100 to 100. Negative is green, positive magenta.</remarks>
|
|||
/// </summary>
|
|||
public float A { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the b color component.
|
|||
/// <remarks>A value usually ranging from -100 to 100. Negative is blue, positive is yellow</remarks>
|
|||
/// </summary>
|
|||
public float B { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLab"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLab"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLab"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(CieLab left, CieLab right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLab"/> objects for inequality
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLab"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLab"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(CieLab left, CieLab right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static CieLab FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source) |
|||
{ |
|||
// Conversion algorithm described here:
|
|||
// http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
|
|||
CieXyz whitePoint = options.TargetWhitePoint; |
|||
float wx = whitePoint.X, wy = whitePoint.Y, wz = whitePoint.Z; |
|||
|
|||
float xr = source.X / wx, yr = source.Y / wy, zr = source.Z / wz; |
|||
|
|||
const float inv116 = 1 / 116F; |
|||
|
|||
float fx = xr > CieConstants.Epsilon ? MathF.Pow(xr, 0.3333333F) : ((CieConstants.Kappa * xr) + 16F) * inv116; |
|||
float fy = yr > CieConstants.Epsilon ? MathF.Pow(yr, 0.3333333F) : ((CieConstants.Kappa * yr) + 16F) * inv116; |
|||
float fz = zr > CieConstants.Epsilon ? MathF.Pow(zr, 0.3333333F) : ((CieConstants.Kappa * zr) + 16F) * inv116; |
|||
|
|||
float l = (116F * fy) - 16F; |
|||
float a = 500F * (fx - fy); |
|||
float b = 200F * (fy - fz); |
|||
|
|||
return new CieLab(l, a, b); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<CieXyz> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
|
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
CieXyz xyz = source[i]; |
|||
destination[i] = FromProfileConnectingSpace(options, in xyz); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyz ToProfileConnectingSpace(ColorConversionOptions options) |
|||
{ |
|||
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html
|
|||
float l = this.L, a = this.A, b = this.B; |
|||
float fy = (l + 16) / 116F; |
|||
float fx = (a / 500F) + fy; |
|||
float fz = fy - (b / 200F); |
|||
|
|||
float fx3 = Numerics.Pow3(fx); |
|||
float fz3 = Numerics.Pow3(fz); |
|||
|
|||
float xr = fx3 > CieConstants.Epsilon ? fx3 : ((116F * fx) - 16F) / CieConstants.Kappa; |
|||
float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? Numerics.Pow3((l + 16F) / 116F) : l / CieConstants.Kappa; |
|||
float zr = fz3 > CieConstants.Epsilon ? fz3 : ((116F * fz) - 16F) / CieConstants.Kappa; |
|||
|
|||
CieXyz whitePoint = options.WhitePoint; |
|||
Vector3 wxyz = new(whitePoint.X, whitePoint.Y, whitePoint.Z); |
|||
Vector3 xyzr = new(xr, yr, zr); |
|||
|
|||
return new(xyzr * wxyz); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<CieLab> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
|
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
CieLab lab = source[i]; |
|||
destination[i] = lab.ToProfileConnectingSpace(options); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource() |
|||
=> ChromaticAdaptionWhitePointSource.WhitePoint; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => HashCode.Combine(this.L, this.A, this.B); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() => FormattableString.Invariant($"CieLab({this.L:#0.##}, {this.A:#0.##}, {this.B:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) => obj is CieLab other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(CieLab other) |
|||
=> this.AsVector3Unsafe() == other.AsVector3Unsafe(); |
|||
|
|||
private Vector3 AsVector3Unsafe() => Unsafe.As<CieLab, Vector3>(ref Unsafe.AsRef(in this)); |
|||
} |
|||
@ -0,0 +1,167 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Represents the CIE L*C*h°, cylindrical form of the CIE L*u*v* 1976 color.
|
|||
/// <see href="https://en.wikipedia.org/wiki/CIELAB_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC"/>
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public readonly struct CieLchuv : IColorProfile<CieLchuv, CieXyz> |
|||
{ |
|||
private static readonly Vector3 Min = new(0, -200, 0); |
|||
private static readonly Vector3 Max = new(100, 200, 360); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLchuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="c">The chroma, relative saturation.</param>
|
|||
/// <param name="h">The hue in degrees.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLchuv(float l, float c, float h) |
|||
: this(new Vector3(l, c, h)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLchuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, c, h components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLchuv(Vector3 vector) |
|||
: this() |
|||
{ |
|||
vector = Vector3.Clamp(vector, Min, Max); |
|||
this.L = vector.X; |
|||
this.C = vector.Y; |
|||
this.H = vector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension.
|
|||
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
|
|||
/// </summary>
|
|||
public float L { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the a chroma component.
|
|||
/// <remarks>A value ranging from 0 to 200.</remarks>
|
|||
/// </summary>
|
|||
public float C { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the h° hue component in degrees.
|
|||
/// <remarks>A value ranging from 0 to 360.</remarks>
|
|||
/// </summary>
|
|||
public float H { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLchuv"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLchuv"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLchuv"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(CieLchuv left, CieLchuv right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLchuv"/> objects for inequality
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLchuv"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLchuv"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(CieLchuv left, CieLchuv right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public static CieLchuv FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source) |
|||
{ |
|||
CieLuv luv = CieLuv.FromProfileConnectingSpace(options, source); |
|||
|
|||
// Conversion algorithm described here:
|
|||
// https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29
|
|||
float l = luv.L, u = luv.U, v = luv.V; |
|||
float c = MathF.Sqrt((u * u) + (v * v)); |
|||
float hRadians = MathF.Atan2(v, u); |
|||
float hDegrees = GeometryUtilities.RadianToDegree(hRadians); |
|||
|
|||
// Wrap the angle round at 360.
|
|||
hDegrees %= 360; |
|||
|
|||
// Make sure it's not negative.
|
|||
while (hDegrees < 0) |
|||
{ |
|||
hDegrees += 360; |
|||
} |
|||
|
|||
return new CieLchuv(l, c, hDegrees); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<CieXyz> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
CieXyz xyz = source[i]; |
|||
destination[i] = FromProfileConnectingSpace(options, in xyz); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public CieXyz ToProfileConnectingSpace(ColorConversionOptions options) |
|||
{ |
|||
// Conversion algorithm described here:
|
|||
// https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29
|
|||
float l = this.L, c = this.C, hDegrees = this.H; |
|||
float hRadians = GeometryUtilities.DegreeToRadian(hDegrees); |
|||
|
|||
float u = c * MathF.Cos(hRadians); |
|||
float v = c * MathF.Sin(hRadians); |
|||
|
|||
CieLuv luv = new(l, u, v); |
|||
return luv.ToProfileConnectingSpace(options); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<CieLchuv> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
CieLchuv lch = source[i]; |
|||
destination[i] = lch.ToProfileConnectingSpace(options); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource() |
|||
=> ChromaticAdaptionWhitePointSource.WhitePoint; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
=> HashCode.Combine(this.L, this.C, this.H); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
=> FormattableString.Invariant($"CieLchuv({this.L:#0.##}, {this.C:#0.##}, {this.H:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) |
|||
=> obj is CieLchuv other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(CieLchuv other) |
|||
=> this.AsVector3Unsafe() == other.AsVector3Unsafe(); |
|||
|
|||
private Vector3 AsVector3Unsafe() => Unsafe.As<CieLchuv, Vector3>(ref Unsafe.AsRef(in this)); |
|||
} |
|||
@ -0,0 +1,221 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// The CIE 1976 (L*, u*, v*) color space, commonly known by its abbreviation CIELUV, is a color space adopted by the International
|
|||
/// Commission on Illumination (CIE) in 1976, as a simple-to-compute transformation of the 1931 CIE XYZ color space, but which
|
|||
/// attempted perceptual uniformity
|
|||
/// <see href="https://en.wikipedia.org/wiki/CIELUV"/>
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public readonly struct CieLuv : IColorProfile<CieLuv, CieXyz> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="u">The blue-yellow chromaticity coordinate of the given white point.</param>
|
|||
/// <param name="v">The red-green chromaticity coordinate of the given white point.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLuv(float l, float u, float v) |
|||
{ |
|||
// Not clamping as documentation about this space only indicates "usual" ranges
|
|||
this.L = l; |
|||
this.U = u; |
|||
this.V = v; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, u, v components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLuv(Vector3 vector) |
|||
: this() |
|||
{ |
|||
this.L = vector.X; |
|||
this.U = vector.Y; |
|||
this.V = vector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension
|
|||
/// <remarks>A value usually ranging between 0 and 100.</remarks>
|
|||
/// </summary>
|
|||
public float L { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the blue-yellow chromaticity coordinate of the given white point.
|
|||
/// <remarks>A value usually ranging between -100 and 100.</remarks>
|
|||
/// </summary>
|
|||
public float U { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the red-green chromaticity coordinate of the given white point.
|
|||
/// <remarks>A value usually ranging between -100 and 100.</remarks>
|
|||
/// </summary>
|
|||
public float V { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLuv"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLuv"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLuv"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(CieLuv left, CieLuv right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLuv"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLuv"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLuv"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(CieLuv left, CieLuv right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public static CieLuv FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source) |
|||
{ |
|||
// Use doubles here for accuracy.
|
|||
// Conversion algorithm described here:
|
|||
// http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Luv.html
|
|||
CieXyz whitePoint = options.TargetWhitePoint; |
|||
|
|||
double yr = source.Y / whitePoint.Y; |
|||
|
|||
double den = source.X + (15 * source.Y) + (3 * source.Z); |
|||
double up = den > 0 ? ComputeU(in source) : 0; |
|||
double vp = den > 0 ? ComputeV(in source) : 0; |
|||
double upr = ComputeU(in whitePoint); |
|||
double vpr = ComputeV(in whitePoint); |
|||
|
|||
const double e = 1 / 3d; |
|||
double l = yr > CieConstants.Epsilon |
|||
? ((116 * Math.Pow(yr, e)) - 16d) |
|||
: (CieConstants.Kappa * yr); |
|||
|
|||
if (double.IsNaN(l) || l == -0d) |
|||
{ |
|||
l = 0; |
|||
} |
|||
|
|||
double u = 13 * l * (up - upr); |
|||
double v = 13 * l * (vp - vpr); |
|||
|
|||
if (double.IsNaN(u) || u == -0d) |
|||
{ |
|||
u = 0; |
|||
} |
|||
|
|||
if (double.IsNaN(v) || v == -0d) |
|||
{ |
|||
v = 0; |
|||
} |
|||
|
|||
return new CieLuv((float)l, (float)u, (float)v); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<CieXyz> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
CieXyz xyz = source[i]; |
|||
destination[i] = FromProfileConnectingSpace(options, in xyz); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public CieXyz ToProfileConnectingSpace(ColorConversionOptions options) |
|||
{ |
|||
// Use doubles here for accuracy.
|
|||
// Conversion algorithm described here:
|
|||
// http://www.brucelindbloom.com/index.html?Eqn_Luv_to_XYZ.html
|
|||
CieXyz whitePoint = options.WhitePoint; |
|||
|
|||
double l = this.L, u = this.U, v = this.V; |
|||
|
|||
double u0 = ComputeU(in whitePoint); |
|||
double v0 = ComputeV(in whitePoint); |
|||
|
|||
double y = l > CieConstants.Kappa * CieConstants.Epsilon |
|||
? Numerics.Pow3((l + 16) / 116d) |
|||
: l / CieConstants.Kappa; |
|||
|
|||
double a = ((52 * l / (u + (13 * l * u0))) - 1) / 3; |
|||
double b = -5 * y; |
|||
const double c = -1 / 3d; |
|||
double d = y * ((39 * l / (v + (13 * l * v0))) - 5); |
|||
|
|||
double x = (d - b) / (a - c); |
|||
double z = (x * a) + b; |
|||
|
|||
if (double.IsNaN(x) || x == -0d) |
|||
{ |
|||
x = 0; |
|||
} |
|||
|
|||
if (double.IsNaN(y) || y == -0d) |
|||
{ |
|||
y = 0; |
|||
} |
|||
|
|||
if (double.IsNaN(z) || z == -0d) |
|||
{ |
|||
z = 0; |
|||
} |
|||
|
|||
return new CieXyz((float)x, (float)y, (float)z); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<CieLuv> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
CieLuv luv = source[i]; |
|||
destination[i] = luv.ToProfileConnectingSpace(options); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource() |
|||
=> ChromaticAdaptionWhitePointSource.WhitePoint; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => HashCode.Combine(this.L, this.U, this.V); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() => FormattableString.Invariant($"CieLuv({this.L:#0.##}, {this.U:#0.##}, {this.V:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) => obj is CieLuv other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(CieLuv other) |
|||
=> this.AsVector3Unsafe() == other.AsVector3Unsafe(); |
|||
|
|||
private Vector3 AsVector3Unsafe() => Unsafe.As<CieLuv, Vector3>(ref Unsafe.AsRef(in this)); |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static double ComputeU(in CieXyz source) |
|||
=> (4 * source.X) / (source.X + (15 * source.Y) + (3 * source.Z)); |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static double ComputeV(in CieXyz source) |
|||
=> (9 * source.Y) / (source.X + (15 * source.Y) + (3 * source.Z)); |
|||
} |
|||
@ -0,0 +1,165 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Represents an CMYK (cyan, magenta, yellow, keyline) color.
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public readonly struct Cmyk : IColorProfile<Cmyk, Rgb> |
|||
{ |
|||
private static readonly Vector4 Min = Vector4.Zero; |
|||
private static readonly Vector4 Max = Vector4.One; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Cmyk"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="c">The cyan component.</param>
|
|||
/// <param name="m">The magenta component.</param>
|
|||
/// <param name="y">The yellow component.</param>
|
|||
/// <param name="k">The keyline black component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Cmyk(float c, float m, float y, float k) |
|||
: this(new Vector4(c, m, y, k)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Cmyk"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the c, m, y, k components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Cmyk(Vector4 vector) |
|||
{ |
|||
vector = Numerics.Clamp(vector, Min, Max); |
|||
this.C = vector.X; |
|||
this.M = vector.Y; |
|||
this.Y = vector.Z; |
|||
this.K = vector.W; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the cyan color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float C { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the magenta color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float M { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the yellow color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float Y { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the keyline black color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float K { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Cmyk"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Cmyk"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Cmyk"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(Cmyk left, Cmyk right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Cmyk"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Cmyk"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Cmyk"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(Cmyk left, Cmyk right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public static Cmyk FromProfileConnectingSpace(ColorConversionOptions options, in Rgb source) |
|||
{ |
|||
// To CMY
|
|||
Vector3 cmy = Vector3.One - source.ToScaledVector3(); |
|||
|
|||
// To CMYK
|
|||
Vector3 k = new(MathF.Min(cmy.X, MathF.Min(cmy.Y, cmy.Z))); |
|||
|
|||
if (MathF.Abs(k.X - 1F) < Constants.Epsilon) |
|||
{ |
|||
return new Cmyk(0, 0, 0, 1F); |
|||
} |
|||
|
|||
cmy = (cmy - k) / (Vector3.One - k); |
|||
|
|||
return new Cmyk(cmy.X, cmy.Y, cmy.Z, k.X); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<Rgb> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
|
|||
// TODO: We can optimize this by using SIMD
|
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
Rgb rgb = source[i]; |
|||
destination[i] = FromProfileConnectingSpace(options, in rgb); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public Rgb ToProfileConnectingSpace(ColorConversionOptions options) |
|||
{ |
|||
Vector3 rgb = (Vector3.One - new Vector3(this.C, this.M, this.Y)) * (Vector3.One - new Vector3(this.K)); |
|||
return Rgb.FromScaledVector3(rgb); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<Cmyk> source, Span<Rgb> destination) |
|||
{ |
|||
// TODO: We can possibly optimize this by using SIMD
|
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
Cmyk cmyk = source[i]; |
|||
destination[i] = cmyk.ToProfileConnectingSpace(options); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource() |
|||
=> ChromaticAdaptionWhitePointSource.RgbWorkingSpace; |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override int GetHashCode() |
|||
=> HashCode.Combine(this.C, this.M, this.Y, this.K); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
=> FormattableString.Invariant($"Cmyk({this.C:#0.##}, {this.M:#0.##}, {this.Y:#0.##}, {this.K:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) |
|||
=> obj is Cmyk other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Cmyk other) |
|||
=> this.AsVector4Unsafe() == other.AsVector4Unsafe(); |
|||
|
|||
private Vector4 AsVector4Unsafe() => Unsafe.As<Cmyk, Vector4>(ref Unsafe.AsRef(in this)); |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using SixLabors.ImageSharp.ColorProfiles.WorkingSpaces; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Provides options for color profile conversion.
|
|||
/// </summary>
|
|||
public class ColorConversionOptions |
|||
{ |
|||
private Matrix4x4 adaptationMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ColorConversionOptions"/> class.
|
|||
/// </summary>
|
|||
public ColorConversionOptions() => this.AdaptationMatrix = KnownChromaticAdaptationMatrices.Bradford; |
|||
|
|||
/// <summary>
|
|||
/// Gets the memory allocator.
|
|||
/// </summary>
|
|||
public MemoryAllocator MemoryAllocator { get; init; } = MemoryAllocator.Default; |
|||
|
|||
/// <summary>
|
|||
/// Gets the source white point used for chromatic adaptation in conversions from/to XYZ color space.
|
|||
/// </summary>
|
|||
public CieXyz WhitePoint { get; init; } = KnownIlluminants.D50; |
|||
|
|||
/// <summary>
|
|||
/// Gets the destination white point used for chromatic adaptation in conversions from/to XYZ color space.
|
|||
/// </summary>
|
|||
public CieXyz TargetWhitePoint { get; init; } = KnownIlluminants.D50; |
|||
|
|||
/// <summary>
|
|||
/// Gets the source working space used for companding in conversions from/to XYZ color space.
|
|||
/// </summary>
|
|||
public RgbWorkingSpace RgbWorkingSpace { get; init; } = KnownRgbWorkingSpaces.SRgb; |
|||
|
|||
/// <summary>
|
|||
/// Gets the destination working space used for companding in conversions from/to XYZ color space.
|
|||
/// </summary>
|
|||
public RgbWorkingSpace TargetRgbWorkingSpace { get; init; } = KnownRgbWorkingSpaces.SRgb; |
|||
|
|||
/// <summary>
|
|||
/// Gets the transformation matrix used in conversion to perform chromatic adaptation.
|
|||
/// <see cref="KnownChromaticAdaptationMatrices"/> for further information. Default is Bradford.
|
|||
/// </summary>
|
|||
public Matrix4x4 AdaptationMatrix |
|||
{ |
|||
get => this.adaptationMatrix; |
|||
init |
|||
{ |
|||
this.adaptationMatrix = value; |
|||
Matrix4x4.Invert(value, out Matrix4x4 inverted); |
|||
this.InverseAdaptationMatrix = inverted; |
|||
} |
|||
} |
|||
|
|||
internal Matrix4x4 InverseAdaptationMatrix { get; private set; } |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Allows the conversion of color profiles.
|
|||
/// </summary>
|
|||
public class ColorProfileConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ColorProfileConverter"/> class.
|
|||
/// </summary>
|
|||
public ColorProfileConverter() |
|||
: this(new()) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ColorProfileConverter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="options">The color profile conversion options.</param>
|
|||
public ColorProfileConverter(ColorConversionOptions options) |
|||
=> this.Options = options; |
|||
|
|||
/// <summary>
|
|||
/// Gets the color profile conversion options.
|
|||
/// </summary>
|
|||
public ColorConversionOptions Options { get; } |
|||
|
|||
internal (CieXyz From, CieXyz To) GetChromaticAdaptionWhitePoints<TFrom, TTo>() |
|||
where TFrom : struct, IColorProfile |
|||
where TTo : struct, IColorProfile |
|||
{ |
|||
CieXyz sourceWhitePoint = TFrom.GetChromaticAdaptionWhitePointSource() == ChromaticAdaptionWhitePointSource.WhitePoint |
|||
? this.Options.WhitePoint |
|||
: this.Options.RgbWorkingSpace.WhitePoint; |
|||
|
|||
CieXyz targetWhitePoint = TTo.GetChromaticAdaptionWhitePointSource() == ChromaticAdaptionWhitePointSource.WhitePoint |
|||
? this.Options.TargetWhitePoint |
|||
: this.Options.TargetRgbWorkingSpace.WhitePoint; |
|||
|
|||
return (sourceWhitePoint, targetWhitePoint); |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
internal static class ColorProfileConverterExtensionsCieLabCieLab |
|||
{ |
|||
public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in TFrom source) |
|||
where TFrom : struct, IColorProfile<TFrom, CieLab> |
|||
where TTo : struct, IColorProfile<TTo, CieLab> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS
|
|||
CieLab pcsFromA = source.ToProfileConnectingSpace(options); |
|||
CieXyz pcsFromB = pcsFromA.ToProfileConnectingSpace(options); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
pcsFromB = VonKriesChromaticAdaptation.Transform(in pcsFromB, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS
|
|||
CieLab pcsTo = CieLab.FromProfileConnectingSpace(options, in pcsFromB); |
|||
|
|||
// Convert to output from PCS
|
|||
return TTo.FromProfileConnectingSpace(options, in pcsTo); |
|||
} |
|||
|
|||
public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, ReadOnlySpan<TFrom> source, Span<TTo> destination) |
|||
where TFrom : struct, IColorProfile<TFrom, CieLab> |
|||
where TTo : struct, IColorProfile<TTo, CieLab> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS.
|
|||
using IMemoryOwner<CieLab> pcsFromToOwner = options.MemoryAllocator.Allocate<CieLab>(source.Length); |
|||
Span<CieLab> pcsFromTo = pcsFromToOwner.GetSpan(); |
|||
TFrom.ToProfileConnectionSpace(options, source, pcsFromTo); |
|||
|
|||
using IMemoryOwner<CieXyz> pcsFromOwner = options.MemoryAllocator.Allocate<CieXyz>(source.Length); |
|||
Span<CieXyz> pcsFrom = pcsFromOwner.GetSpan(); |
|||
CieLab.ToProfileConnectionSpace(options, pcsFromTo, pcsFrom); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
VonKriesChromaticAdaptation.Transform(pcsFrom, pcsFrom, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS.
|
|||
CieLab.FromProfileConnectionSpace(options, pcsFrom, pcsFromTo); |
|||
|
|||
// Convert to output from PCS
|
|||
TTo.FromProfileConnectionSpace(options, pcsFromTo, destination); |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
internal static class ColorProfileConverterExtensionsCieLabCieXyz |
|||
{ |
|||
public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in TFrom source) |
|||
where TFrom : struct, IColorProfile<TFrom, CieLab> |
|||
where TTo : struct, IColorProfile<TTo, CieXyz> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS
|
|||
CieLab pcsFrom = source.ToProfileConnectingSpace(options); |
|||
|
|||
// Convert between PCS
|
|||
CieXyz pcsTo = pcsFrom.ToProfileConnectingSpace(options); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
pcsTo = VonKriesChromaticAdaptation.Transform(in pcsTo, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert to output from PCS
|
|||
return TTo.FromProfileConnectingSpace(options, in pcsTo); |
|||
} |
|||
|
|||
public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, ReadOnlySpan<TFrom> source, Span<TTo> destination) |
|||
where TFrom : struct, IColorProfile<TFrom, CieLab> |
|||
where TTo : struct, IColorProfile<TTo, CieXyz> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS.
|
|||
using IMemoryOwner<CieLab> pcsFromOwner = options.MemoryAllocator.Allocate<CieLab>(source.Length); |
|||
Span<CieLab> pcsFrom = pcsFromOwner.GetSpan(); |
|||
TFrom.ToProfileConnectionSpace(options, source, pcsFrom); |
|||
|
|||
// Convert between PCS.
|
|||
using IMemoryOwner<CieXyz> pcsToOwner = options.MemoryAllocator.Allocate<CieXyz>(source.Length); |
|||
Span<CieXyz> pcsTo = pcsToOwner.GetSpan(); |
|||
CieLab.ToProfileConnectionSpace(options, pcsFrom, pcsTo); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
VonKriesChromaticAdaptation.Transform(pcsTo, pcsTo, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert to output from PCS
|
|||
TTo.FromProfileConnectionSpace(options, pcsTo, destination); |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
internal static class ColorProfileConverterExtensionsCieLabRgb |
|||
{ |
|||
public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in TFrom source) |
|||
where TFrom : struct, IColorProfile<TFrom, CieLab> |
|||
where TTo : struct, IColorProfile<TTo, Rgb> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS
|
|||
CieLab pcsFromA = source.ToProfileConnectingSpace(options); |
|||
CieXyz pcsFromB = pcsFromA.ToProfileConnectingSpace(options); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
pcsFromB = VonKriesChromaticAdaptation.Transform(in pcsFromB, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS
|
|||
Rgb pcsTo = Rgb.FromProfileConnectingSpace(options, in pcsFromB); |
|||
|
|||
// Convert to output from PCS
|
|||
return TTo.FromProfileConnectingSpace(options, in pcsTo); |
|||
} |
|||
|
|||
public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, ReadOnlySpan<TFrom> source, Span<TTo> destination) |
|||
where TFrom : struct, IColorProfile<TFrom, CieLab> |
|||
where TTo : struct, IColorProfile<TTo, Rgb> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS.
|
|||
using IMemoryOwner<CieLab> pcsFromAOwner = options.MemoryAllocator.Allocate<CieLab>(source.Length); |
|||
Span<CieLab> pcsFromA = pcsFromAOwner.GetSpan(); |
|||
TFrom.ToProfileConnectionSpace(options, source, pcsFromA); |
|||
|
|||
using IMemoryOwner<CieXyz> pcsFromBOwner = options.MemoryAllocator.Allocate<CieXyz>(source.Length); |
|||
Span<CieXyz> pcsFromB = pcsFromBOwner.GetSpan(); |
|||
CieLab.ToProfileConnectionSpace(options, pcsFromA, pcsFromB); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
VonKriesChromaticAdaptation.Transform(pcsFromB, pcsFromB, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS.
|
|||
using IMemoryOwner<Rgb> pcsToOwner = options.MemoryAllocator.Allocate<Rgb>(source.Length); |
|||
Span<Rgb> pcsTo = pcsToOwner.GetSpan(); |
|||
Rgb.FromProfileConnectionSpace(options, pcsFromB, pcsTo); |
|||
|
|||
// Convert to output from PCS
|
|||
TTo.FromProfileConnectionSpace(options, pcsTo, destination); |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
internal static class ColorProfileConverterExtensionsCieXyzCieLab |
|||
{ |
|||
public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in TFrom source) |
|||
where TFrom : struct, IColorProfile<TFrom, CieXyz> |
|||
where TTo : struct, IColorProfile<TTo, CieLab> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS
|
|||
CieXyz pcsFrom = source.ToProfileConnectingSpace(options); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
pcsFrom = VonKriesChromaticAdaptation.Transform(in pcsFrom, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS
|
|||
CieLab pcsTo = CieLab.FromProfileConnectingSpace(options, in pcsFrom); |
|||
|
|||
// Convert to output from PCS
|
|||
return TTo.FromProfileConnectingSpace(options, in pcsTo); |
|||
} |
|||
|
|||
public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, ReadOnlySpan<TFrom> source, Span<TTo> destination) |
|||
where TFrom : struct, IColorProfile<TFrom, CieXyz> |
|||
where TTo : struct, IColorProfile<TTo, CieLab> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS.
|
|||
using IMemoryOwner<CieXyz> pcsFromOwner = options.MemoryAllocator.Allocate<CieXyz>(source.Length); |
|||
Span<CieXyz> pcsFrom = pcsFromOwner.GetSpan(); |
|||
TFrom.ToProfileConnectionSpace(options, source, pcsFrom); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
VonKriesChromaticAdaptation.Transform(pcsFrom, pcsFrom, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS.
|
|||
using IMemoryOwner<CieLab> pcsToOwner = options.MemoryAllocator.Allocate<CieLab>(source.Length); |
|||
Span<CieLab> pcsTo = pcsToOwner.GetSpan(); |
|||
CieLab.FromProfileConnectionSpace(options, pcsFrom, pcsTo); |
|||
|
|||
// Convert to output from PCS
|
|||
TTo.FromProfileConnectionSpace(options, pcsTo, destination); |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
internal static class ColorProfileConverterExtensionsCieXyzCieXyz |
|||
{ |
|||
public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in TFrom source) |
|||
where TFrom : struct, IColorProfile<TFrom, CieXyz> |
|||
where TTo : struct, IColorProfile<TTo, CieXyz> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS
|
|||
CieXyz pcsFrom = source.ToProfileConnectingSpace(options); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
pcsFrom = VonKriesChromaticAdaptation.Transform(in pcsFrom, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert to output from PCS
|
|||
return TTo.FromProfileConnectingSpace(options, in pcsFrom); |
|||
} |
|||
|
|||
public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, ReadOnlySpan<TFrom> source, Span<TTo> destination) |
|||
where TFrom : struct, IColorProfile<TFrom, CieXyz> |
|||
where TTo : struct, IColorProfile<TTo, CieXyz> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS.
|
|||
using IMemoryOwner<CieXyz> pcsFromOwner = options.MemoryAllocator.Allocate<CieXyz>(source.Length); |
|||
Span<CieXyz> pcsFrom = pcsFromOwner.GetSpan(); |
|||
TFrom.ToProfileConnectionSpace(options, source, pcsFrom); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
VonKriesChromaticAdaptation.Transform(pcsFrom, pcsFrom, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert to output from PCS
|
|||
TTo.FromProfileConnectionSpace(options, pcsFrom, destination); |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
internal static class ColorProfileConverterExtensionsCieXyzRgb |
|||
{ |
|||
public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in TFrom source) |
|||
where TFrom : struct, IColorProfile<TFrom, CieXyz> |
|||
where TTo : struct, IColorProfile<TTo, Rgb> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS
|
|||
CieXyz pcsFrom = source.ToProfileConnectingSpace(options); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
pcsFrom = VonKriesChromaticAdaptation.Transform(in pcsFrom, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS
|
|||
Rgb pcsTo = Rgb.FromProfileConnectingSpace(options, in pcsFrom); |
|||
|
|||
// Convert to output from PCS
|
|||
return TTo.FromProfileConnectingSpace(options, in pcsTo); |
|||
} |
|||
|
|||
public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, ReadOnlySpan<TFrom> source, Span<TTo> destination) |
|||
where TFrom : struct, IColorProfile<TFrom, CieXyz> |
|||
where TTo : struct, IColorProfile<TTo, Rgb> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS.
|
|||
using IMemoryOwner<CieXyz> pcsFromOwner = options.MemoryAllocator.Allocate<CieXyz>(source.Length); |
|||
Span<CieXyz> pcsFrom = pcsFromOwner.GetSpan(); |
|||
TFrom.ToProfileConnectionSpace(options, source, pcsFrom); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
VonKriesChromaticAdaptation.Transform(pcsFrom, pcsFrom, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS.
|
|||
using IMemoryOwner<Rgb> pcsToOwner = options.MemoryAllocator.Allocate<Rgb>(source.Length); |
|||
Span<Rgb> pcsTo = pcsToOwner.GetSpan(); |
|||
Rgb.FromProfileConnectionSpace(options, pcsFrom, pcsTo); |
|||
|
|||
// Convert to output from PCS
|
|||
TTo.FromProfileConnectionSpace(options, pcsTo, destination); |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
internal static class ColorProfileConverterExtensionsRgbCieLab |
|||
{ |
|||
public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in TFrom source) |
|||
where TFrom : struct, IColorProfile<TFrom, Rgb> |
|||
where TTo : struct, IColorProfile<TTo, CieLab> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS
|
|||
Rgb pcsFromA = source.ToProfileConnectingSpace(options); |
|||
CieXyz pcsFromB = pcsFromA.ToProfileConnectingSpace(options); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
pcsFromB = VonKriesChromaticAdaptation.Transform(in pcsFromB, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS
|
|||
CieLab pcsTo = CieLab.FromProfileConnectingSpace(options, in pcsFromB); |
|||
|
|||
// Convert to output from PCS
|
|||
return TTo.FromProfileConnectingSpace(options, in pcsTo); |
|||
} |
|||
|
|||
public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, ReadOnlySpan<TFrom> source, Span<TTo> destination) |
|||
where TFrom : struct, IColorProfile<TFrom, Rgb> |
|||
where TTo : struct, IColorProfile<TTo, CieLab> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS.
|
|||
using IMemoryOwner<Rgb> pcsFromAOwner = options.MemoryAllocator.Allocate<Rgb>(source.Length); |
|||
Span<Rgb> pcsFromA = pcsFromAOwner.GetSpan(); |
|||
TFrom.ToProfileConnectionSpace(options, source, pcsFromA); |
|||
|
|||
using IMemoryOwner<CieXyz> pcsFromBOwner = options.MemoryAllocator.Allocate<CieXyz>(source.Length); |
|||
Span<CieXyz> pcsFromB = pcsFromBOwner.GetSpan(); |
|||
Rgb.ToProfileConnectionSpace(options, pcsFromA, pcsFromB); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
VonKriesChromaticAdaptation.Transform(pcsFromB, pcsFromB, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS.
|
|||
using IMemoryOwner<CieLab> pcsToOwner = options.MemoryAllocator.Allocate<CieLab>(source.Length); |
|||
Span<CieLab> pcsTo = pcsToOwner.GetSpan(); |
|||
CieLab.FromProfileConnectionSpace(options, pcsFromB, pcsTo); |
|||
|
|||
// Convert to output from PCS
|
|||
TTo.FromProfileConnectionSpace(options, pcsTo, destination); |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
internal static class ColorProfileConverterExtensionsRgbCieXyz |
|||
{ |
|||
public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in TFrom source) |
|||
where TFrom : struct, IColorProfile<TFrom, Rgb> |
|||
where TTo : struct, IColorProfile<TTo, CieXyz> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS
|
|||
Rgb pcsFrom = source.ToProfileConnectingSpace(options); |
|||
|
|||
// Convert between PCS
|
|||
CieXyz pcsTo = pcsFrom.ToProfileConnectingSpace(options); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
pcsTo = VonKriesChromaticAdaptation.Transform(in pcsTo, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert to output from PCS
|
|||
return TTo.FromProfileConnectingSpace(options, in pcsTo); |
|||
} |
|||
|
|||
public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, ReadOnlySpan<TFrom> source, Span<TTo> destination) |
|||
where TFrom : struct, IColorProfile<TFrom, Rgb> |
|||
where TTo : struct, IColorProfile<TTo, CieXyz> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS.
|
|||
using IMemoryOwner<Rgb> pcsFromOwner = options.MemoryAllocator.Allocate<Rgb>(source.Length); |
|||
Span<Rgb> pcsFrom = pcsFromOwner.GetSpan(); |
|||
TFrom.ToProfileConnectionSpace(options, source, pcsFrom); |
|||
|
|||
// Convert between PCS.
|
|||
using IMemoryOwner<CieXyz> pcsToOwner = options.MemoryAllocator.Allocate<CieXyz>(source.Length); |
|||
Span<CieXyz> pcsTo = pcsToOwner.GetSpan(); |
|||
Rgb.ToProfileConnectionSpace(options, pcsFrom, pcsTo); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
VonKriesChromaticAdaptation.Transform(pcsTo, pcsTo, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert to output from PCS
|
|||
TTo.FromProfileConnectionSpace(options, pcsTo, destination); |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
internal static class ColorProfileConverterExtensionsRgbRgb |
|||
{ |
|||
public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in TFrom source) |
|||
where TFrom : struct, IColorProfile<TFrom, Rgb> |
|||
where TTo : struct, IColorProfile<TTo, Rgb> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS
|
|||
Rgb pcsFromA = source.ToProfileConnectingSpace(options); |
|||
CieXyz pcsFromB = pcsFromA.ToProfileConnectingSpace(options); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
pcsFromB = VonKriesChromaticAdaptation.Transform(in pcsFromB, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS
|
|||
Rgb pcsTo = Rgb.FromProfileConnectingSpace(options, in pcsFromB); |
|||
|
|||
// Convert to output from PCS
|
|||
return TTo.FromProfileConnectingSpace(options, in pcsTo); |
|||
} |
|||
|
|||
public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, ReadOnlySpan<TFrom> source, Span<TTo> destination) |
|||
where TFrom : struct, IColorProfile<TFrom, Rgb> |
|||
where TTo : struct, IColorProfile<TTo, Rgb> |
|||
{ |
|||
ColorConversionOptions options = converter.Options; |
|||
|
|||
// Convert to input PCS.
|
|||
using IMemoryOwner<Rgb> pcsFromToOwner = options.MemoryAllocator.Allocate<Rgb>(source.Length); |
|||
Span<Rgb> pcsFromTo = pcsFromToOwner.GetSpan(); |
|||
TFrom.ToProfileConnectionSpace(options, source, pcsFromTo); |
|||
|
|||
using IMemoryOwner<CieXyz> pcsFromOwner = options.MemoryAllocator.Allocate<CieXyz>(source.Length); |
|||
Span<CieXyz> pcsFrom = pcsFromOwner.GetSpan(); |
|||
Rgb.ToProfileConnectionSpace(options, pcsFromTo, pcsFrom); |
|||
|
|||
// Adapt to target white point
|
|||
(CieXyz From, CieXyz To) whitePoints = converter.GetChromaticAdaptionWhitePoints<TFrom, TTo>(); |
|||
VonKriesChromaticAdaptation.Transform(pcsFrom, pcsFrom, whitePoints, options.AdaptationMatrix); |
|||
|
|||
// Convert between PCS.
|
|||
Rgb.FromProfileConnectionSpace(options, pcsFrom, pcsFromTo); |
|||
|
|||
// Convert to output from PCS
|
|||
TTo.FromProfileConnectionSpace(options, pcsFromTo, destination); |
|||
} |
|||
} |
|||
@ -0,0 +1,182 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Collections.Concurrent; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using System.Runtime.Intrinsics; |
|||
using System.Runtime.Intrinsics.X86; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Companding utilities that allow the accelerated compression-expansion of color channels.
|
|||
/// </summary>
|
|||
public static class CompandingUtilities |
|||
{ |
|||
private const int Length = Scale + 2; // 256kb @ 16bit precision.
|
|||
private const int Scale = (1 << 16) - 1; |
|||
private static readonly ConcurrentDictionary<(Type, double), float[]> CompressLookupTables = new(); |
|||
private static readonly ConcurrentDictionary<(Type, double), float[]> ExpandLookupTables = new(); |
|||
|
|||
/// <summary>
|
|||
/// Lazily creates and stores a companding compression lookup table using the given function and modifier.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of companding function.</typeparam>
|
|||
/// <param name="compandingFunction">The companding function.</param>
|
|||
/// <param name="modifier">A modifier to pass to the function.</param>
|
|||
/// <returns>The <see cref="float"/> array.</returns>
|
|||
public static float[] GetCompressLookupTable<T>(Func<double, double, double> compandingFunction, double modifier = 0) |
|||
=> CompressLookupTables.GetOrAdd((typeof(T), modifier), args => CreateLookupTableImpl(compandingFunction, args.Item2)); |
|||
|
|||
/// <summary>
|
|||
/// Lazily creates and stores a companding expanding lookup table using the given function and modifier.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of companding function.</typeparam>
|
|||
/// <param name="compandingFunction">The companding function.</param>
|
|||
/// <param name="modifier">A modifier to pass to the function.</param>
|
|||
/// <returns>The <see cref="float"/> array.</returns>
|
|||
public static float[] GetExpandLookupTable<T>(Func<double, double, double> compandingFunction, double modifier = 0) |
|||
=> ExpandLookupTables.GetOrAdd((typeof(T), modifier), args => CreateLookupTableImpl(compandingFunction, args.Item2)); |
|||
|
|||
/// <summary>
|
|||
/// Creates a companding lookup table using the given function.
|
|||
/// </summary>
|
|||
/// <param name="compandingFunction">The companding function.</param>
|
|||
/// <param name="modifier">A modifier to pass to the function.</param>
|
|||
/// <returns>The <see cref="float"/> array.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static float[] CreateLookupTableImpl(Func<double, double, double> compandingFunction, double modifier = 0) |
|||
{ |
|||
float[] result = new float[Length]; |
|||
|
|||
for (int i = 0; i < result.Length; i++) |
|||
{ |
|||
double d = (double)i / Scale; |
|||
d = compandingFunction(d, modifier); |
|||
result[i] = (float)d; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the companding operation on the given vectors using the given table.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
/// <param name="table">The lookup table.</param>
|
|||
public static void Compand(Span<Vector4> vectors, float[] table) |
|||
{ |
|||
DebugGuard.MustBeGreaterThanOrEqualTo(table.Length, Length, nameof(table)); |
|||
|
|||
if (Avx2.IsSupported && vectors.Length >= 2) |
|||
{ |
|||
CompandAvx2(vectors, table); |
|||
|
|||
if (Numerics.Modulo2(vectors.Length) != 0) |
|||
{ |
|||
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
|
|||
ref Vector4 last = ref MemoryMarshal.GetReference(vectors[^1..]); |
|||
last = Compand(last, table); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
CompandScalar(vectors, table); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the companding operation on the given vector using the given table.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <param name="table">The lookup table.</param>
|
|||
/// <returns>The <see cref="Vector4"/></returns>
|
|||
public static Vector4 Compand(Vector4 vector, float[] table) |
|||
{ |
|||
DebugGuard.MustBeGreaterThanOrEqualTo(table.Length, Length, nameof(table)); |
|||
|
|||
Vector4 zero = Vector4.Zero; |
|||
Vector4 scale = new(Scale); |
|||
|
|||
Vector4 multiplied = Numerics.Clamp(vector * Scale, zero, scale); |
|||
|
|||
float f0 = multiplied.X; |
|||
float f1 = multiplied.Y; |
|||
float f2 = multiplied.Z; |
|||
|
|||
uint i0 = (uint)f0; |
|||
uint i1 = (uint)f1; |
|||
uint i2 = (uint)f2; |
|||
|
|||
// Alpha is already a linear representation of opacity so we do not want to convert it.
|
|||
vector.X = Numerics.Lerp(table[i0], table[i0 + 1], f0 - (int)i0); |
|||
vector.Y = Numerics.Lerp(table[i1], table[i1 + 1], f1 - (int)i1); |
|||
vector.Z = Numerics.Lerp(table[i2], table[i2 + 1], f2 - (int)i2); |
|||
|
|||
return vector; |
|||
} |
|||
|
|||
private static unsafe void CompandAvx2(Span<Vector4> vectors, float[] table) |
|||
{ |
|||
fixed (float* tablePointer = &MemoryMarshal.GetArrayDataReference(table)) |
|||
{ |
|||
Vector256<float> scale = Vector256.Create((float)Scale); |
|||
Vector256<float> zero = Vector256<float>.Zero; |
|||
Vector256<int> offset = Vector256.Create(1); |
|||
|
|||
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
|
|||
ref Vector256<float> vectorsBase = ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors)); |
|||
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (uint)vectors.Length / 2u); |
|||
|
|||
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|||
{ |
|||
Vector256<float> multiplied = Avx.Multiply(scale, vectorsBase); |
|||
multiplied = Avx.Min(Avx.Max(zero, multiplied), scale); |
|||
|
|||
Vector256<int> truncated = Avx.ConvertToVector256Int32WithTruncation(multiplied); |
|||
Vector256<float> truncatedF = Avx.ConvertToVector256Single(truncated); |
|||
|
|||
Vector256<float> low = Avx2.GatherVector256(tablePointer, truncated, sizeof(float)); |
|||
Vector256<float> high = Avx2.GatherVector256(tablePointer, Avx2.Add(truncated, offset), sizeof(float)); |
|||
|
|||
// Alpha is already a linear representation of opacity so we do not want to convert it.
|
|||
Vector256<float> companded = Numerics.Lerp(low, high, Avx.Subtract(multiplied, truncatedF)); |
|||
vectorsBase = Avx.Blend(companded, vectorsBase, Numerics.BlendAlphaControl); |
|||
vectorsBase = ref Unsafe.Add(ref vectorsBase, 1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private static unsafe void CompandScalar(Span<Vector4> vectors, float[] table) |
|||
{ |
|||
fixed (float* tablePointer = &MemoryMarshal.GetArrayDataReference(table)) |
|||
{ |
|||
Vector4 zero = Vector4.Zero; |
|||
Vector4 scale = new(Scale); |
|||
ref Vector4 vectorsBase = ref MemoryMarshal.GetReference(vectors); |
|||
ref Vector4 vectorsLast = ref Unsafe.Add(ref vectorsBase, (uint)vectors.Length); |
|||
|
|||
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|||
{ |
|||
Vector4 multiplied = Numerics.Clamp(vectorsBase * Scale, zero, scale); |
|||
|
|||
float f0 = multiplied.X; |
|||
float f1 = multiplied.Y; |
|||
float f2 = multiplied.Z; |
|||
|
|||
uint i0 = (uint)f0; |
|||
uint i1 = (uint)f1; |
|||
uint i2 = (uint)f2; |
|||
|
|||
// Alpha is already a linear representation of opacity so we do not want to convert it.
|
|||
vectorsBase.X = Numerics.Lerp(tablePointer[i0], tablePointer[i0 + 1], f0 - (int)i0); |
|||
vectorsBase.Y = Numerics.Lerp(tablePointer[i1], tablePointer[i1 + 1], f1 - (int)i1); |
|||
vectorsBase.Z = Numerics.Lerp(tablePointer[i2], tablePointer[i2 + 1], f2 - (int)i2); |
|||
|
|||
vectorsBase = ref Unsafe.Add(ref vectorsBase, 1); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Implements gamma companding.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
|
|||
/// </remarks>
|
|||
public static class GammaCompanding |
|||
{ |
|||
private static Func<double, double, double> CompressFunction => (d, m) => Math.Pow(d, 1 / m); |
|||
|
|||
private static Func<double, double, double> ExpandFunction => Math.Pow; |
|||
|
|||
/// <summary>
|
|||
/// Compresses the linear vectors to their nonlinear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
/// <param name="gamma">The gamma value.</param>
|
|||
public static void Compress(Span<Vector4> vectors, double gamma) |
|||
=> CompandingUtilities.Compand(vectors, CompandingUtilities.GetCompressLookupTable<GammaCompandingKey>(CompressFunction, gamma)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the nonlinear vectors to their linear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
/// <param name="gamma">The gamma value.</param>
|
|||
public static void Expand(Span<Vector4> vectors, double gamma) |
|||
=> CompandingUtilities.Compand(vectors, CompandingUtilities.GetExpandLookupTable<GammaCompandingKey>(ExpandFunction, gamma)); |
|||
|
|||
/// <summary>
|
|||
/// Compresses the linear vector to its nonlinear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <param name="gamma">The gamma value.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Compress(Vector4 vector, double gamma) |
|||
=> CompandingUtilities.Compand(vector, CompandingUtilities.GetCompressLookupTable<GammaCompandingKey>(CompressFunction, gamma)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the nonlinear vector to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <param name="gamma">The gamma value.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Expand(Vector4 vector, double gamma) |
|||
=> CompandingUtilities.Compand(vector, CompandingUtilities.GetExpandLookupTable<GammaCompandingKey>(ExpandFunction, gamma)); |
|||
|
|||
private class GammaCompandingKey; |
|||
} |
|||
@ -0,0 +1,71 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Implements L* companding.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// For more info see:
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
|
|||
/// </remarks>
|
|||
public static class LCompanding |
|||
{ |
|||
private static Func<double, double, double> CompressFunction |
|||
=> (d, _) => |
|||
{ |
|||
if (d <= CieConstants.Epsilon) |
|||
{ |
|||
return (d * CieConstants.Kappa) / 100; |
|||
} |
|||
|
|||
return (1.16 * Math.Pow(d, 0.3333333)) - 0.16; |
|||
}; |
|||
|
|||
private static Func<double, double, double> ExpandFunction |
|||
=> (d, _) => |
|||
{ |
|||
if (d <= 0.08) |
|||
{ |
|||
return (100 * d) / CieConstants.Kappa; |
|||
} |
|||
|
|||
return Numerics.Pow3(((float)(d + 0.16f)) / 1.16f); |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// Compresses the linear vectors to their nonlinear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
public static void Compress(Span<Vector4> vectors) |
|||
=> CompandingUtilities.Compand(vectors, CompandingUtilities.GetCompressLookupTable<LCompandingKey>(CompressFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the nonlinear vectors to their linear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
public static void Expand(Span<Vector4> vectors) |
|||
=> CompandingUtilities.Compand(vectors, CompandingUtilities.GetExpandLookupTable<LCompandingKey>(ExpandFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Compresses the linear vector to its nonlinear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Compress(Vector4 vector) |
|||
=> CompandingUtilities.Compand(vector, CompandingUtilities.GetCompressLookupTable<LCompandingKey>(CompressFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the nonlinear vector to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Expand(Vector4 vector) |
|||
=> CompandingUtilities.Compand(vector, CompandingUtilities.GetExpandLookupTable<LCompandingKey>(ExpandFunction)); |
|||
|
|||
private class LCompandingKey; |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Implements Rec. 2020 companding function.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <see href="http://en.wikipedia.org/wiki/Rec._2020"/>
|
|||
/// </remarks>
|
|||
public static class Rec2020Companding |
|||
{ |
|||
private const double Alpha = 1.09929682680944; |
|||
private const double AlphaMinusOne = Alpha - 1; |
|||
private const double Beta = 0.018053968510807; |
|||
private const double InverseBeta = Beta * 4.5; |
|||
private const double Epsilon = 1 / 0.45; |
|||
|
|||
private static Func<double, double, double> CompressFunction |
|||
=> (d, _) => |
|||
{ |
|||
if (d < Beta) |
|||
{ |
|||
return 4.5 * d; |
|||
} |
|||
|
|||
return (Alpha * Math.Pow(d, 0.45)) - AlphaMinusOne; |
|||
}; |
|||
|
|||
private static Func<double, double, double> ExpandFunction |
|||
=> (d, _) => |
|||
{ |
|||
if (d < InverseBeta) |
|||
{ |
|||
return d / 4.5; |
|||
} |
|||
|
|||
return Math.Pow((d + AlphaMinusOne) / Alpha, Epsilon); |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// Compresses the linear vectors to their nonlinear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
public static void Compress(Span<Vector4> vectors) |
|||
=> CompandingUtilities.Compand(vectors, CompandingUtilities.GetCompressLookupTable<Rec2020CompandingKey>(CompressFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the nonlinear vectors to their linear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
public static void Expand(Span<Vector4> vectors) |
|||
=> CompandingUtilities.Compand(vectors, CompandingUtilities.GetExpandLookupTable<Rec2020CompandingKey>(ExpandFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Compresses the linear vector to its nonlinear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Compress(Vector4 vector) |
|||
=> CompandingUtilities.Compand(vector, CompandingUtilities.GetCompressLookupTable<Rec2020CompandingKey>(CompressFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the nonlinear vector to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Expand(Vector4 vector) |
|||
=> CompandingUtilities.Compand(vector, CompandingUtilities.GetExpandLookupTable<Rec2020CompandingKey>(ExpandFunction)); |
|||
|
|||
private class Rec2020CompandingKey; |
|||
} |
|||
@ -0,0 +1,71 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Implements the Rec. 709 companding function.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// http://en.wikipedia.org/wiki/Rec._709
|
|||
/// </remarks>
|
|||
public static class Rec709Companding |
|||
{ |
|||
private const double Epsilon = 1 / 0.45; |
|||
|
|||
private static Func<double, double, double> CompressFunction |
|||
=> (d, _) => |
|||
{ |
|||
if (d < 0.018) |
|||
{ |
|||
return 4.5 * d; |
|||
} |
|||
|
|||
return (1.099 * Math.Pow(d, 0.45)) - 0.099; |
|||
}; |
|||
|
|||
private static Func<double, double, double> ExpandFunction |
|||
=> (d, _) => |
|||
{ |
|||
if (d < 0.081) |
|||
{ |
|||
return d / 4.5; |
|||
} |
|||
|
|||
return Math.Pow((d + 0.099) / 1.099, Epsilon); |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// Compresses the linear vectors to their nonlinear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
public static void Compress(Span<Vector4> vectors) |
|||
=> CompandingUtilities.Compand(vectors, CompandingUtilities.GetCompressLookupTable<Rec2020CompandingKey>(CompressFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the nonlinear vectors to their linear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
public static void Expand(Span<Vector4> vectors) |
|||
=> CompandingUtilities.Compand(vectors, CompandingUtilities.GetExpandLookupTable<Rec2020CompandingKey>(ExpandFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Compresses the linear vector to its nonlinear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Compress(Vector4 vector) |
|||
=> CompandingUtilities.Compand(vector, CompandingUtilities.GetCompressLookupTable<Rec2020CompandingKey>(CompressFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the nonlinear vector to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Expand(Vector4 vector) |
|||
=> CompandingUtilities.Compand(vector, CompandingUtilities.GetExpandLookupTable<Rec2020CompandingKey>(ExpandFunction)); |
|||
|
|||
private class Rec2020CompandingKey; |
|||
} |
|||
@ -0,0 +1,71 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Implements sRGB companding.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// For more info see:
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
|
|||
/// </remarks>
|
|||
public static class SRgbCompanding |
|||
{ |
|||
private static Func<double, double, double> CompressFunction |
|||
=> (d, _) => |
|||
{ |
|||
if (d <= (0.04045 / 12.92)) |
|||
{ |
|||
return d * 12.92; |
|||
} |
|||
|
|||
return (1.055 * Math.Pow(d, 1.0 / 2.4)) - 0.055; |
|||
}; |
|||
|
|||
private static Func<double, double, double> ExpandFunction |
|||
=> (d, _) => |
|||
{ |
|||
if (d <= 0.04045) |
|||
{ |
|||
return d / 12.92; |
|||
} |
|||
|
|||
return Math.Pow((d + 0.055) / 1.055, 2.4); |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// Compresses the linear vectors to their nonlinear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
public static void Compress(Span<Vector4> vectors) |
|||
=> CompandingUtilities.Compand(vectors, CompandingUtilities.GetCompressLookupTable<SRgbCompandingKey>(CompressFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the nonlinear vectors to their linear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
public static void Expand(Span<Vector4> vectors) |
|||
=> CompandingUtilities.Compand(vectors, CompandingUtilities.GetExpandLookupTable<SRgbCompandingKey>(ExpandFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Compresses the linear vector to its nonlinear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Compress(Vector4 vector) |
|||
=> CompandingUtilities.Compand(vector, CompandingUtilities.GetCompressLookupTable<SRgbCompandingKey>(CompressFunction)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the nonlinear vector to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Expand(Vector4 vector) |
|||
=> CompandingUtilities.Compand(vector, CompandingUtilities.GetExpandLookupTable<SRgbCompandingKey>(ExpandFunction)); |
|||
|
|||
private class SRgbCompandingKey; |
|||
} |
|||
@ -0,0 +1,245 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Represents a Hsl (hue, saturation, lightness) color.
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public readonly struct Hsl : IColorProfile<Hsl, Rgb> |
|||
{ |
|||
private static readonly Vector3 Min = Vector3.Zero; |
|||
private static readonly Vector3 Max = new(360, 1, 1); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Hsl"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="h">The h hue component.</param>
|
|||
/// <param name="s">The s saturation component.</param>
|
|||
/// <param name="l">The l value (lightness) component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Hsl(float h, float s, float l) |
|||
: this(new Vector3(h, s, l)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Hsl"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the h, s, l components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Hsl(Vector3 vector) |
|||
{ |
|||
vector = Vector3.Clamp(vector, Min, Max); |
|||
this.H = vector.X; |
|||
this.S = vector.Y; |
|||
this.L = vector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the hue component.
|
|||
/// <remarks>A value ranging between 0 and 360.</remarks>
|
|||
/// </summary>
|
|||
public float H { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the saturation component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float S { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float L { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Hsl"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Hsl"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">The <see cref="Hsl"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(Hsl left, Hsl right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Hsl"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Hsl"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Hsl"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(Hsl left, Hsl right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public static Hsl FromProfileConnectingSpace(ColorConversionOptions options, in Rgb source) |
|||
{ |
|||
float r = source.R; |
|||
float g = source.G; |
|||
float b = source.B; |
|||
|
|||
float max = MathF.Max(r, MathF.Max(g, b)); |
|||
float min = MathF.Min(r, MathF.Min(g, b)); |
|||
float chroma = max - min; |
|||
float h = 0F; |
|||
float s = 0F; |
|||
float l = (max + min) / 2F; |
|||
|
|||
if (MathF.Abs(chroma) < Constants.Epsilon) |
|||
{ |
|||
return new Hsl(0F, s, l); |
|||
} |
|||
|
|||
if (MathF.Abs(r - max) < Constants.Epsilon) |
|||
{ |
|||
h = (g - b) / chroma; |
|||
} |
|||
else if (MathF.Abs(g - max) < Constants.Epsilon) |
|||
{ |
|||
h = 2F + ((b - r) / chroma); |
|||
} |
|||
else if (MathF.Abs(b - max) < Constants.Epsilon) |
|||
{ |
|||
h = 4F + ((r - g) / chroma); |
|||
} |
|||
|
|||
h *= 60F; |
|||
if (h < -Constants.Epsilon) |
|||
{ |
|||
h += 360F; |
|||
} |
|||
|
|||
if (l <= .5F) |
|||
{ |
|||
s = chroma / (max + min); |
|||
} |
|||
else |
|||
{ |
|||
s = chroma / (2F - max - min); |
|||
} |
|||
|
|||
return new Hsl(h, s, l); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<Rgb> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
Rgb rgb = source[i]; |
|||
destination[i] = FromProfileConnectingSpace(options, in rgb); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public Rgb ToProfileConnectingSpace(ColorConversionOptions options) |
|||
{ |
|||
float rangedH = this.H / 360F; |
|||
float r = 0; |
|||
float g = 0; |
|||
float b = 0; |
|||
float s = this.S; |
|||
float l = this.L; |
|||
|
|||
if (MathF.Abs(l) > Constants.Epsilon) |
|||
{ |
|||
if (MathF.Abs(s) < Constants.Epsilon) |
|||
{ |
|||
r = g = b = l; |
|||
} |
|||
else |
|||
{ |
|||
float temp2 = (l < .5F) ? l * (1F + s) : l + s - (l * s); |
|||
float temp1 = (2F * l) - temp2; |
|||
|
|||
r = GetColorComponent(temp1, temp2, rangedH + 0.3333333F); |
|||
g = GetColorComponent(temp1, temp2, rangedH); |
|||
b = GetColorComponent(temp1, temp2, rangedH - 0.3333333F); |
|||
} |
|||
} |
|||
|
|||
return new Rgb(r, g, b); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<Hsl> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
Hsl hsl = source[i]; |
|||
destination[i] = hsl.ToProfileConnectingSpace(options); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource() |
|||
=> ChromaticAdaptionWhitePointSource.RgbWorkingSpace; |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override int GetHashCode() => HashCode.Combine(this.H, this.S, this.L); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() => FormattableString.Invariant($"Hsl({this.H:#0.##}, {this.S:#0.##}, {this.L:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) => obj is Hsl other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Hsl other) |
|||
=> this.AsVector3Unsafe() == other.AsVector3Unsafe(); |
|||
|
|||
private Vector3 AsVector3Unsafe() => Unsafe.As<Hsl, Vector3>(ref Unsafe.AsRef(in this)); |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static float GetColorComponent(float first, float second, float third) |
|||
{ |
|||
third = MoveIntoRange(third); |
|||
if (third < 0.1666667F) |
|||
{ |
|||
return first + ((second - first) * 6F * third); |
|||
} |
|||
|
|||
if (third < .5F) |
|||
{ |
|||
return second; |
|||
} |
|||
|
|||
if (third < 0.6666667F) |
|||
{ |
|||
return first + ((second - first) * (0.6666667F - third) * 6F); |
|||
} |
|||
|
|||
return first; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static float MoveIntoRange(float value) |
|||
{ |
|||
if (value < 0F) |
|||
{ |
|||
value++; |
|||
} |
|||
else if (value > 1F) |
|||
{ |
|||
value--; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
} |
|||
@ -0,0 +1,231 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Represents a HSV (hue, saturation, value) color. Also known as HSB (hue, saturation, brightness).
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public readonly struct Hsv : IColorProfile<Hsv, Rgb> |
|||
{ |
|||
private static readonly Vector3 Min = Vector3.Zero; |
|||
private static readonly Vector3 Max = new(360, 1, 1); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Hsv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="h">The h hue component.</param>
|
|||
/// <param name="s">The s saturation component.</param>
|
|||
/// <param name="v">The v value (brightness) component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Hsv(float h, float s, float v) |
|||
: this(new Vector3(h, s, v)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Hsv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the h, s, v components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Hsv(Vector3 vector) |
|||
{ |
|||
vector = Vector3.Clamp(vector, Min, Max); |
|||
this.H = vector.X; |
|||
this.S = vector.Y; |
|||
this.V = vector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the hue component.
|
|||
/// <remarks>A value ranging between 0 and 360.</remarks>
|
|||
/// </summary>
|
|||
public float H { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the saturation component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float S { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the value (brightness) component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float V { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Hsv"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Hsv"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Hsv"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(Hsv left, Hsv right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Hsv"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Hsv"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Hsv"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(Hsv left, Hsv right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public static Hsv FromProfileConnectingSpace(ColorConversionOptions options, in Rgb source) |
|||
{ |
|||
float r = source.R; |
|||
float g = source.G; |
|||
float b = source.B; |
|||
|
|||
float max = MathF.Max(r, MathF.Max(g, b)); |
|||
float min = MathF.Min(r, MathF.Min(g, b)); |
|||
float chroma = max - min; |
|||
float h = 0; |
|||
float s = 0; |
|||
float v = max; |
|||
|
|||
if (MathF.Abs(chroma) < Constants.Epsilon) |
|||
{ |
|||
return new Hsv(0, s, v); |
|||
} |
|||
|
|||
if (MathF.Abs(r - max) < Constants.Epsilon) |
|||
{ |
|||
h = (g - b) / chroma; |
|||
} |
|||
else if (MathF.Abs(g - max) < Constants.Epsilon) |
|||
{ |
|||
h = 2 + ((b - r) / chroma); |
|||
} |
|||
else if (MathF.Abs(b - max) < Constants.Epsilon) |
|||
{ |
|||
h = 4 + ((r - g) / chroma); |
|||
} |
|||
|
|||
h *= 60F; |
|||
if (h < -Constants.Epsilon) |
|||
{ |
|||
h += 360F; |
|||
} |
|||
|
|||
s = chroma / v; |
|||
|
|||
return new Hsv(h, s, v); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<Rgb> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
Rgb rgb = source[i]; |
|||
destination[i] = FromProfileConnectingSpace(options, in rgb); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public Rgb ToProfileConnectingSpace(ColorConversionOptions options) |
|||
{ |
|||
float s = this.S; |
|||
float v = this.V; |
|||
|
|||
if (MathF.Abs(s) < Constants.Epsilon) |
|||
{ |
|||
return new Rgb(v, v, v); |
|||
} |
|||
|
|||
float h = (MathF.Abs(this.H - 360) < Constants.Epsilon) ? 0 : this.H / 60; |
|||
int i = (int)Math.Truncate(h); |
|||
float f = h - i; |
|||
|
|||
float p = v * (1F - s); |
|||
float q = v * (1F - (s * f)); |
|||
float t = v * (1F - (s * (1F - f))); |
|||
|
|||
float r, g, b; |
|||
switch (i) |
|||
{ |
|||
case 0: |
|||
r = v; |
|||
g = t; |
|||
b = p; |
|||
break; |
|||
|
|||
case 1: |
|||
r = q; |
|||
g = v; |
|||
b = p; |
|||
break; |
|||
|
|||
case 2: |
|||
r = p; |
|||
g = v; |
|||
b = t; |
|||
break; |
|||
|
|||
case 3: |
|||
r = p; |
|||
g = q; |
|||
b = v; |
|||
break; |
|||
|
|||
case 4: |
|||
r = t; |
|||
g = p; |
|||
b = v; |
|||
break; |
|||
|
|||
default: |
|||
r = v; |
|||
g = p; |
|||
b = q; |
|||
break; |
|||
} |
|||
|
|||
return new Rgb(r, g, b); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<Hsv> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
Hsv hsv = source[i]; |
|||
destination[i] = hsv.ToProfileConnectingSpace(options); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource() |
|||
=> ChromaticAdaptionWhitePointSource.RgbWorkingSpace; |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override int GetHashCode() => HashCode.Combine(this.H, this.S, this.V); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() => FormattableString.Invariant($"Hsv({this.H:#0.##}, {this.S:#0.##}, {this.V:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) => obj is Hsv other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Hsv other) |
|||
=> this.AsVector3Unsafe() == other.AsVector3Unsafe(); |
|||
|
|||
private Vector3 AsVector3Unsafe() => Unsafe.As<Hsv, Vector3>(ref Unsafe.AsRef(in this)); |
|||
} |
|||
@ -0,0 +1,200 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Represents an Hunter LAB color.
|
|||
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space"/>.
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public readonly struct HunterLab : IColorProfile<HunterLab, CieXyz> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="HunterLab"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="a">The a (green - magenta) component.</param>
|
|||
/// <param name="b">The b (blue - yellow) component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public HunterLab(float l, float a, float b) |
|||
{ |
|||
this.L = l; |
|||
this.A = a; |
|||
this.B = b; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="HunterLab"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l a b components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public HunterLab(Vector3 vector) |
|||
{ |
|||
// Not clamping as documentation about this space only indicates "usual" ranges
|
|||
this.L = vector.X; |
|||
this.A = vector.Y; |
|||
this.B = vector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension.
|
|||
/// <remarks>A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
|
|||
/// </summary>
|
|||
public float L { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the a color component.
|
|||
/// <remarks>A value usually ranging from -100 to 100. Negative is green, positive magenta.</remarks>
|
|||
/// </summary>
|
|||
public float A { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the b color component.
|
|||
/// <remarks>A value usually ranging from -100 to 100. Negative is blue, positive is yellow</remarks>
|
|||
/// </summary>
|
|||
public float B { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="HunterLab"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="HunterLab"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="HunterLab"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(HunterLab left, HunterLab right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="HunterLab"/> objects for inequality
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="HunterLab"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="HunterLab"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(HunterLab left, HunterLab right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public static HunterLab FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source) |
|||
{ |
|||
// Conversion algorithm described here:
|
|||
// http://en.wikipedia.org/wiki/Lab_color_space#Hunter_Lab
|
|||
CieXyz whitePoint = options.TargetWhitePoint; |
|||
float x = source.X, y = source.Y, z = source.Z; |
|||
float xn = whitePoint.X, yn = whitePoint.Y, zn = whitePoint.Z; |
|||
|
|||
float ka = ComputeKa(in whitePoint); |
|||
float kb = ComputeKb(in whitePoint); |
|||
|
|||
float yByYn = y / yn; |
|||
float sqrtYbyYn = MathF.Sqrt(yByYn); |
|||
float l = 100 * sqrtYbyYn; |
|||
float a = ka * (((x / xn) - yByYn) / sqrtYbyYn); |
|||
float b = kb * ((yByYn - (z / zn)) / sqrtYbyYn); |
|||
|
|||
if (float.IsNaN(a)) |
|||
{ |
|||
a = 0; |
|||
} |
|||
|
|||
if (float.IsNaN(b)) |
|||
{ |
|||
b = 0; |
|||
} |
|||
|
|||
return new HunterLab(l, a, b); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<CieXyz> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
CieXyz xyz = source[i]; |
|||
destination[i] = FromProfileConnectingSpace(options, in xyz); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public CieXyz ToProfileConnectingSpace(ColorConversionOptions options) |
|||
{ |
|||
// Conversion algorithm described here:
|
|||
// http://en.wikipedia.org/wiki/Lab_color_space#Hunter_Lab
|
|||
CieXyz whitePoint = options.WhitePoint; |
|||
float l = this.L, a = this.A, b = this.B; |
|||
float xn = whitePoint.X, yn = whitePoint.Y, zn = whitePoint.Z; |
|||
|
|||
float ka = ComputeKa(in whitePoint); |
|||
float kb = ComputeKb(in whitePoint); |
|||
|
|||
float pow = Numerics.Pow2(l / 100F); |
|||
float sqrtPow = MathF.Sqrt(pow); |
|||
float y = pow * yn; |
|||
|
|||
float x = (((a / ka) * sqrtPow) + pow) * xn; |
|||
float z = (((b / kb) * sqrtPow) - pow) * (-zn); |
|||
|
|||
return new CieXyz(x, y, z); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<HunterLab> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
HunterLab lab = source[i]; |
|||
destination[i] = lab.ToProfileConnectingSpace(options); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource() |
|||
=> ChromaticAdaptionWhitePointSource.WhitePoint; |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override int GetHashCode() => HashCode.Combine(this.L, this.A, this.B); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() => FormattableString.Invariant($"HunterLab({this.L:#0.##}, {this.A:#0.##}, {this.B:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) => obj is HunterLab other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(HunterLab other) |
|||
=> this.AsVector3Unsafe() == other.AsVector3Unsafe(); |
|||
|
|||
private Vector3 AsVector3Unsafe() => Unsafe.As<HunterLab, Vector3>(ref Unsafe.AsRef(in this)); |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static float ComputeKa(in CieXyz whitePoint) |
|||
{ |
|||
if (whitePoint.Equals(KnownIlluminants.C)) |
|||
{ |
|||
return 175F; |
|||
} |
|||
|
|||
return 100F * (175F / 198.04F) * (whitePoint.X + whitePoint.Y); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static float ComputeKb(in CieXyz whitePoint) |
|||
{ |
|||
if (whitePoint == KnownIlluminants.C) |
|||
{ |
|||
return 70F; |
|||
} |
|||
|
|||
return 100F * (70F / 218.11F) * (whitePoint.Y + whitePoint.Z); |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Defines the contract for all color profiles.
|
|||
/// </summary>
|
|||
public interface IColorProfile |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the chromatic adaption white point source.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="ChromaticAdaptionWhitePointSource"/>.</returns>
|
|||
public static abstract ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Defines the contract for all color profiles.
|
|||
/// </summary>
|
|||
/// <typeparam name="TSelf">The type of color profile.</typeparam>
|
|||
/// <typeparam name="TProfileSpace">The type of color profile connecting space.</typeparam>
|
|||
public interface IColorProfile<TSelf, TProfileSpace> : IColorProfile, IEquatable<TSelf> |
|||
where TSelf : IColorProfile<TSelf, TProfileSpace> |
|||
where TProfileSpace : struct, IProfileConnectingSpace |
|||
{ |
|||
#pragma warning disable CA1000 // Do not declare static members on generic types
|
|||
/// <summary>
|
|||
/// Converts the color from the profile connection space.
|
|||
/// </summary>
|
|||
/// <param name="options">The color profile conversion options.</param>
|
|||
/// <param name="source">The color profile connecting space.</param>
|
|||
/// <returns>The <typeparamref name="TSelf"/>.</returns>
|
|||
public static abstract TSelf FromProfileConnectingSpace(ColorConversionOptions options, in TProfileSpace source); |
|||
|
|||
/// <summary>
|
|||
/// Converts the span of colors from the profile connection space.
|
|||
/// </summary>
|
|||
/// <param name="options">The color profile conversion options.</param>
|
|||
/// <param name="source">The color profile span to convert from.</param>
|
|||
/// <param name="destination">The color span to write the results to.</param>
|
|||
public static abstract void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<TProfileSpace> source, Span<TSelf> destination); |
|||
|
|||
/// <summary>
|
|||
/// Converts the color to the profile connection space.
|
|||
/// </summary>
|
|||
/// <param name="options">The color profile conversion options.</param>
|
|||
/// <returns>The <typeparamref name="TProfileSpace"/>.</returns>
|
|||
public TProfileSpace ToProfileConnectingSpace(ColorConversionOptions options); |
|||
|
|||
/// <summary>
|
|||
/// Converts the span of colors to the profile connection space.
|
|||
/// </summary>
|
|||
/// <param name="options">The color profile conversion options.</param>
|
|||
/// <param name="source">The color span to convert from.</param>
|
|||
/// <param name="destination">The color profile span to write the results to.</param>
|
|||
public static abstract void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<TSelf> source, Span<TProfileSpace> destination); |
|||
#pragma warning restore CA1000 // Do not declare static members on generic types
|
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Defines the contract for all color profile connection spaces.
|
|||
/// </summary>
|
|||
public interface IProfileConnectingSpace; |
|||
|
|||
/// <summary>
|
|||
/// Defines the contract for all color profile connection spaces.
|
|||
/// </summary>
|
|||
/// <typeparam name="TSelf">The type of color profile.</typeparam>
|
|||
/// <typeparam name="TProfileSpace">The type of color profile connecting space.</typeparam>
|
|||
public interface IProfileConnectingSpace<TSelf, TProfileSpace> : IColorProfile<TSelf, TProfileSpace>, IProfileConnectingSpace |
|||
where TSelf : struct, IColorProfile<TSelf, TProfileSpace>, IProfileConnectingSpace |
|||
where TProfileSpace : struct, IProfileConnectingSpace; |
|||
@ -0,0 +1,71 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// The well known standard illuminants.
|
|||
/// Standard illuminants provide a basis for comparing images or colors recorded under different lighting
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Coefficients taken from: http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
|
|||
/// <br />
|
|||
/// Descriptions taken from: http://en.wikipedia.org/wiki/Standard_illuminant
|
|||
/// </remarks>
|
|||
public static class KnownIlluminants |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the Incandescent / Tungsten illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz A { get; } = new(1.09850F, 1F, 0.35585F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the Direct sunlight at noon (obsoleteF) illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz B { get; } = new(0.99072F, 1F, 0.85223F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the Average / North sky Daylight (obsoleteF) illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz C { get; } = new(0.98074F, 1F, 1.18232F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the Horizon Light. ICC profile PCS illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz D50 { get; } = new(0.96422F, 1F, 0.82521F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the Mid-morning / Mid-afternoon Daylight illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz D55 { get; } = new(0.95682F, 1F, 0.92149F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the Noon Daylight: TelevisionF, sRGB color space illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz D65 { get; } = new(0.95047F, 1F, 1.08883F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the North sky Daylight illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz D75 { get; } = new(0.94972F, 1F, 1.22638F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the Equal energy illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz E { get; } = new(1F, 1F, 1F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the Cool White Fluorescent illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz F2 { get; } = new(0.99186F, 1F, 0.67393F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the D65 simulatorF, Daylight simulator illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz F7 { get; } = new(0.95041F, 1F, 1.08747F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the Philips TL84F, Ultralume 40 illuminant.
|
|||
/// </summary>
|
|||
public static CieXyz F11 { get; } = new(1.00962F, 1F, 0.64350F); |
|||
} |
|||
@ -0,0 +1,113 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.ColorProfiles.Companding; |
|||
using SixLabors.ImageSharp.ColorProfiles.WorkingSpaces; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Chromaticity coordinates based on: <see href="http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html"/>
|
|||
/// </summary>
|
|||
public static class KnownRgbWorkingSpaces |
|||
{ |
|||
/// <summary>
|
|||
/// sRgb working space.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Uses proper companding function, according to:
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_Rgb_to_XYZ.html"/>
|
|||
/// </remarks>
|
|||
public static readonly RgbWorkingSpace SRgb = new SRgbWorkingSpace(KnownIlluminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); |
|||
|
|||
/// <summary>
|
|||
/// Simplified sRgb working space (uses <see cref="GammaCompanding">gamma companding</see> instead of <see cref="SRgbCompanding"/>).
|
|||
/// See also <see cref="SRgb"/>.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace SRgbSimplified = new GammaWorkingSpace(2.2F, KnownIlluminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); |
|||
|
|||
/// <summary>
|
|||
/// Rec. 709 (ITU-R Recommendation BT.709) working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace Rec709 = new Rec709WorkingSpace(KnownIlluminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.64F, 0.33F), new CieXyChromaticityCoordinates(0.30F, 0.60F), new CieXyChromaticityCoordinates(0.15F, 0.06F))); |
|||
|
|||
/// <summary>
|
|||
/// Rec. 2020 (ITU-R Recommendation BT.2020F) working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace Rec2020 = new Rec2020WorkingSpace(KnownIlluminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.708F, 0.292F), new CieXyChromaticityCoordinates(0.170F, 0.797F), new CieXyChromaticityCoordinates(0.131F, 0.046F))); |
|||
|
|||
/// <summary>
|
|||
/// ECI Rgb v2 working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace ECIRgbv2 = new LWorkingSpace(KnownIlluminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); |
|||
|
|||
/// <summary>
|
|||
/// Adobe Rgb (1998) working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace AdobeRgb1998 = new GammaWorkingSpace(2.2F, KnownIlluminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); |
|||
|
|||
/// <summary>
|
|||
/// Apple sRgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace ApplesRgb = new GammaWorkingSpace(1.8F, KnownIlluminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6250F, 0.3400F), new CieXyChromaticityCoordinates(0.2800F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); |
|||
|
|||
/// <summary>
|
|||
/// Best Rgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace BestRgb = new GammaWorkingSpace(2.2F, KnownIlluminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.2150F, 0.7750F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); |
|||
|
|||
/// <summary>
|
|||
/// Beta Rgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace BetaRgb = new GammaWorkingSpace(2.2F, KnownIlluminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6888F, 0.3112F), new CieXyChromaticityCoordinates(0.1986F, 0.7551F), new CieXyChromaticityCoordinates(0.1265F, 0.0352F))); |
|||
|
|||
/// <summary>
|
|||
/// Bruce Rgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace BruceRgb = new GammaWorkingSpace(2.2F, KnownIlluminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2800F, 0.6500F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); |
|||
|
|||
/// <summary>
|
|||
/// CIE Rgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace CIERgb = new GammaWorkingSpace(2.2F, KnownIlluminants.E, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.2740F, 0.7170F), new CieXyChromaticityCoordinates(0.1670F, 0.0090F))); |
|||
|
|||
/// <summary>
|
|||
/// ColorMatch Rgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace ColorMatchRgb = new GammaWorkingSpace(1.8F, KnownIlluminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.2950F, 0.6050F), new CieXyChromaticityCoordinates(0.1500F, 0.0750F))); |
|||
|
|||
/// <summary>
|
|||
/// Don Rgb 4 working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace DonRgb4 = new GammaWorkingSpace(2.2F, KnownIlluminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6960F, 0.3000F), new CieXyChromaticityCoordinates(0.2150F, 0.7650F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); |
|||
|
|||
/// <summary>
|
|||
/// Ekta Space PS5 working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace EktaSpacePS5 = new GammaWorkingSpace(2.2F, KnownIlluminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6950F, 0.3050F), new CieXyChromaticityCoordinates(0.2600F, 0.7000F), new CieXyChromaticityCoordinates(0.1100F, 0.0050F))); |
|||
|
|||
/// <summary>
|
|||
/// NTSC Rgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace NTSCRgb = new GammaWorkingSpace(2.2F, KnownIlluminants.C, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); |
|||
|
|||
/// <summary>
|
|||
/// PAL/SECAM Rgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace PALSECAMRgb = new GammaWorkingSpace(2.2F, KnownIlluminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2900F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); |
|||
|
|||
/// <summary>
|
|||
/// ProPhoto Rgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace ProPhotoRgb = new GammaWorkingSpace(1.8F, KnownIlluminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.1596F, 0.8404F), new CieXyChromaticityCoordinates(0.0366F, 0.0001F))); |
|||
|
|||
/// <summary>
|
|||
/// SMPTE-C Rgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace SMPTECRgb = new GammaWorkingSpace(2.2F, KnownIlluminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.3100F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); |
|||
|
|||
/// <summary>
|
|||
/// Wide Gamut Rgb working space.
|
|||
/// </summary>
|
|||
public static readonly RgbWorkingSpace WideGamutRgb = new GammaWorkingSpace(2.2F, KnownIlluminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F))); |
|||
} |
|||
@ -0,0 +1,269 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.ColorProfiles.WorkingSpaces; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Represents an RGB (red, green, blue) color profile.
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public readonly struct Rgb : IProfileConnectingSpace<Rgb, CieXyz> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgb"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component usually ranging between 0 and 1.</param>
|
|||
/// <param name="g">The green component usually ranging between 0 and 1.</param>
|
|||
/// <param name="b">The blue component usually ranging between 0 and 1.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb(float r, float g, float b) |
|||
{ |
|||
// Not clamping as this space can exceed "usual" ranges
|
|||
this.R = r; |
|||
this.G = g; |
|||
this.B = b; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgb"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="source">The vector representing the r, g, b components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb(Vector3 source) |
|||
{ |
|||
this.R = source.X; |
|||
this.G = source.Y; |
|||
this.B = source.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the red component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float R { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the green component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float G { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the blue component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float B { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rgb"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Rgb"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Rgb"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(Rgb left, Rgb right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rgb"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Rgb"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Rgb"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(Rgb left, Rgb right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public static Rgb FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source) |
|||
{ |
|||
// Convert to linear rgb then compress.
|
|||
Rgb linear = new(Vector3.Transform(source.ToVector3(), GetCieXyzToRgbMatrix(options.TargetRgbWorkingSpace))); |
|||
return FromScaledVector4(options.TargetRgbWorkingSpace.Compress(linear.ToScaledVector4())); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<CieXyz> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
|
|||
Matrix4x4 matrix = GetCieXyzToRgbMatrix(options.TargetRgbWorkingSpace); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
// Convert to linear rgb then compress.
|
|||
Rgb linear = new(Vector3.Transform(source[i].ToVector3(), matrix)); |
|||
Vector4 nonlinear = options.TargetRgbWorkingSpace.Compress(linear.ToScaledVector4()); |
|||
destination[i] = FromScaledVector4(nonlinear); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public CieXyz ToProfileConnectingSpace(ColorConversionOptions options) |
|||
{ |
|||
// First expand to linear rgb
|
|||
Rgb linear = FromScaledVector4(options.RgbWorkingSpace.Expand(this.ToScaledVector4())); |
|||
|
|||
// Then convert to xyz
|
|||
return new CieXyz(Vector3.Transform(linear.ToScaledVector3(), GetRgbToCieXyzMatrix(options.RgbWorkingSpace))); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<Rgb> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
|
|||
Matrix4x4 matrix = GetRgbToCieXyzMatrix(options.RgbWorkingSpace); |
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
Rgb rgb = source[i]; |
|||
|
|||
// First expand to linear rgb
|
|||
Rgb linear = FromScaledVector4(options.RgbWorkingSpace.Expand(rgb.ToScaledVector4())); |
|||
|
|||
// Then convert to xyz
|
|||
destination[i] = new CieXyz(Vector3.Transform(linear.ToScaledVector3(), matrix)); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource() => ChromaticAdaptionWhitePointSource.RgbWorkingSpace; |
|||
|
|||
/// <summary>
|
|||
/// Initializes the color instance from a generic scaled <see cref="Vector3"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The vector to load the color from.</param>
|
|||
/// <returns>The <see cref="Rgb"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rgb FromScaledVector3(Vector3 source) => new(Vector3.Clamp(source, Vector3.Zero, Vector3.One)); |
|||
|
|||
/// <summary>
|
|||
/// Initializes the color instance from a generic scaled <see cref="Vector4"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The vector to load the color from.</param>
|
|||
/// <returns>The <see cref="Rgb"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rgb FromScaledVector4(Vector4 source) |
|||
{ |
|||
source = Vector4.Clamp(source, Vector4.Zero, Vector4.One); |
|||
return new(source.X, source.Y, source.Z); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes the color instance for a source clamped between <value>0</value> and <value>1</value>
|
|||
/// </summary>
|
|||
/// <param name="source">The source to load the color from.</param>
|
|||
/// <returns>The <see cref="Rgb"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rgb Clamp(Rgb source) => new(Vector3.Clamp(new(source.R, source.G, source.B), Vector3.Zero, Vector3.One)); |
|||
|
|||
/// <summary>
|
|||
/// Expands the color into a generic ("scaled") <see cref="Vector3"/> representation
|
|||
/// with values scaled and usually clamped between <value>0</value> and <value>1</value>.
|
|||
/// The vector components are typically expanded in least to greatest significance order.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Vector3"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Vector3 ToScaledVector3() => Clamp(this).ToVector3(); |
|||
|
|||
/// <summary>
|
|||
/// Expands the color into a generic <see cref="Vector3"/> representation.
|
|||
/// The vector components are typically expanded in least to greatest significance order.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Vector3"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Vector3 ToVector3() => new(this.R, this.G, this.B); |
|||
|
|||
/// <summary>
|
|||
/// Expands the color into a generic ("scaled") <see cref="Vector4"/> representation
|
|||
/// with values scaled and usually clamped between <value>0</value> and <value>1</value>.
|
|||
/// The vector components are typically expanded in least to greatest significance order.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Vector4 ToScaledVector4() => new(this.ToScaledVector3(), 1f); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() => FormattableString.Invariant($"Rgb({this.R:#0.##}, {this.G:#0.##}, {this.B:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) => obj is Rgb other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Rgb other) |
|||
=> this.AsVector3Unsafe() == other.AsVector3Unsafe(); |
|||
|
|||
private Vector3 AsVector3Unsafe() => Unsafe.As<Rgb, Vector3>(ref Unsafe.AsRef(in this)); |
|||
|
|||
private static Matrix4x4 GetCieXyzToRgbMatrix(RgbWorkingSpace workingSpace) |
|||
{ |
|||
Matrix4x4 matrix = GetRgbToCieXyzMatrix(workingSpace); |
|||
Matrix4x4.Invert(matrix, out Matrix4x4 inverseMatrix); |
|||
return inverseMatrix; |
|||
} |
|||
|
|||
private static Matrix4x4 GetRgbToCieXyzMatrix(RgbWorkingSpace workingSpace) |
|||
{ |
|||
DebugGuard.NotNull(workingSpace, nameof(workingSpace)); |
|||
RgbPrimariesChromaticityCoordinates chromaticity = workingSpace.ChromaticityCoordinates; |
|||
|
|||
float xr = chromaticity.R.X; |
|||
float xg = chromaticity.G.X; |
|||
float xb = chromaticity.B.X; |
|||
float yr = chromaticity.R.Y; |
|||
float yg = chromaticity.G.Y; |
|||
float yb = chromaticity.B.Y; |
|||
|
|||
float mXr = xr / yr; |
|||
float mZr = (1 - xr - yr) / yr; |
|||
|
|||
float mXg = xg / yg; |
|||
float mZg = (1 - xg - yg) / yg; |
|||
|
|||
float mXb = xb / yb; |
|||
float mZb = (1 - xb - yb) / yb; |
|||
|
|||
Matrix4x4 xyzMatrix = new() |
|||
{ |
|||
M11 = mXr, |
|||
M21 = mXg, |
|||
M31 = mXb, |
|||
M12 = 1F, |
|||
M22 = 1F, |
|||
M32 = 1F, |
|||
M13 = mZr, |
|||
M23 = mZg, |
|||
M33 = mZb, |
|||
M44 = 1F |
|||
}; |
|||
|
|||
Matrix4x4.Invert(xyzMatrix, out Matrix4x4 inverseXyzMatrix); |
|||
|
|||
Vector3 vector = Vector3.Transform(workingSpace.WhitePoint.ToVector3(), inverseXyzMatrix); |
|||
|
|||
// Use transposed Rows/Columns
|
|||
return new Matrix4x4 |
|||
{ |
|||
M11 = vector.X * mXr, |
|||
M21 = vector.Y * mXg, |
|||
M31 = vector.Z * mXb, |
|||
M12 = vector.X, |
|||
M22 = vector.Y, |
|||
M32 = vector.Z, |
|||
M13 = vector.X * mZr, |
|||
M23 = vector.Y * mZg, |
|||
M33 = vector.Z * mZb, |
|||
M44 = 1F |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
/// <summary>
|
|||
/// Implementation of the Von Kries chromatic adaptation model.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Transformation described here:
|
|||
/// http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
|
|||
/// </remarks>
|
|||
public static class VonKriesChromaticAdaptation |
|||
{ |
|||
/// <summary>
|
|||
/// Performs a linear transformation of a source color in to the destination color.
|
|||
/// </summary>
|
|||
/// <remarks>Doesn't crop the resulting color space coordinates (e.g. allows negative values for XYZ coordinates).</remarks>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <param name="whitePoints">The conversion white points.</param>
|
|||
/// <param name="matrix">The chromatic adaptation matrix.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public static CieXyz Transform(in CieXyz source, (CieXyz From, CieXyz To) whitePoints, Matrix4x4 matrix) |
|||
{ |
|||
CieXyz from = whitePoints.From; |
|||
CieXyz to = whitePoints.To; |
|||
|
|||
if (from.Equals(to)) |
|||
{ |
|||
return new(source.X, source.Y, source.Z); |
|||
} |
|||
|
|||
Vector3 sourceColorLms = Vector3.Transform(source.ToVector3(), matrix); |
|||
Vector3 sourceWhitePointLms = Vector3.Transform(from.ToVector3(), matrix); |
|||
Vector3 targetWhitePointLms = Vector3.Transform(to.ToVector3(), matrix); |
|||
|
|||
Vector3 vector = targetWhitePointLms / sourceWhitePointLms; |
|||
Vector3 targetColorLms = Vector3.Multiply(vector, sourceColorLms); |
|||
|
|||
Matrix4x4.Invert(matrix, out Matrix4x4 inverseMatrix); |
|||
return new CieXyz(Vector3.Transform(targetColorLms, inverseMatrix)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs a bulk linear transformation of a source color in to the destination color.
|
|||
/// </summary>
|
|||
/// <remarks>Doesn't crop the resulting color space coordinates (e. g. allows negative values for XYZ coordinates).</remarks>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
/// <param name="whitePoints">The conversion white points.</param>
|
|||
/// <param name="matrix">The chromatic adaptation matrix.</param>
|
|||
public static void Transform( |
|||
ReadOnlySpan<CieXyz> source, |
|||
Span<CieXyz> destination, |
|||
(CieXyz From, CieXyz To) whitePoints, |
|||
Matrix4x4 matrix) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
CieXyz from = whitePoints.From; |
|||
CieXyz to = whitePoints.To; |
|||
|
|||
if (from.Equals(to)) |
|||
{ |
|||
source.CopyTo(destination[..count]); |
|||
return; |
|||
} |
|||
|
|||
Matrix4x4.Invert(matrix, out Matrix4x4 inverseMatrix); |
|||
|
|||
ref CieXyz sourceBase = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destinationBase = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
Vector3 sourceWhitePointLms = Vector3.Transform(from.ToVector3(), matrix); |
|||
Vector3 targetWhitePointLms = Vector3.Transform(to.ToVector3(), matrix); |
|||
|
|||
Vector3 vector = targetWhitePointLms / sourceWhitePointLms; |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceBase, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destinationBase, i); |
|||
|
|||
Vector3 sourceColorLms = Vector3.Transform(sp.ToVector3(), matrix); |
|||
|
|||
Vector3 targetColorLms = Vector3.Multiply(vector, sourceColorLms); |
|||
dp = new CieXyz(Vector3.Transform(targetColorLms, inverseMatrix)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,135 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Represents a CIE L*a*b* 1976 color.
|
|||
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space"/>
|
|||
/// </summary>
|
|||
public readonly struct CieLab : IEquatable<CieLab> |
|||
{ |
|||
/// <summary>
|
|||
/// D50 standard illuminant.
|
|||
/// Used when reference white is not specified explicitly.
|
|||
/// </summary>
|
|||
public static readonly CieXyz DefaultWhitePoint = Illuminants.D50; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLab"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="a">The a (green - magenta) component.</param>
|
|||
/// <param name="b">The b (blue - yellow) component.</param>
|
|||
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLab(float l, float a, float b) |
|||
: this(l, a, b, DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLab"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="a">The a (green - magenta) component.</param>
|
|||
/// <param name="b">The b (blue - yellow) component.</param>
|
|||
/// <param name="whitePoint">The reference white point. <see cref="Illuminants"/></param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLab(float l, float a, float b, CieXyz whitePoint) |
|||
: this(new Vector3(l, a, b), whitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLab"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, a, b components.</param>
|
|||
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLab(Vector3 vector) |
|||
: this(vector, DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLab"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, a, b components.</param>
|
|||
/// <param name="whitePoint">The reference white point. <see cref="Illuminants"/></param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLab(Vector3 vector, CieXyz whitePoint) |
|||
: this() |
|||
{ |
|||
// Not clamping as documentation about this space only indicates "usual" ranges
|
|||
this.L = vector.X; |
|||
this.A = vector.Y; |
|||
this.B = vector.Z; |
|||
this.WhitePoint = whitePoint; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension.
|
|||
/// <remarks>A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
|
|||
/// </summary>
|
|||
public readonly float L { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the a color component.
|
|||
/// <remarks>A value usually ranging from -100 to 100. Negative is green, positive magenta.</remarks>
|
|||
/// </summary>
|
|||
public readonly float A { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the b color component.
|
|||
/// <remarks>A value usually ranging from -100 to 100. Negative is blue, positive is yellow</remarks>
|
|||
/// </summary>
|
|||
public readonly float B { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the reference white point of this color
|
|||
/// </summary>
|
|||
public readonly CieXyz WhitePoint { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLab"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLab"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLab"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static bool operator ==(CieLab left, CieLab right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLab"/> objects for inequality
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLab"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLab"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static bool operator !=(CieLab left, CieLab right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => HashCode.Combine(this.L, this.A, this.B, this.WhitePoint); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() => FormattableString.Invariant($"CieLab({this.L:#0.##}, {this.A:#0.##}, {this.B:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) => obj is CieLab other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public bool Equals(CieLab other) => |
|||
this.L.Equals(other.L) |
|||
&& this.A.Equals(other.A) |
|||
&& this.B.Equals(other.B) |
|||
&& this.WhitePoint.Equals(other.WhitePoint); |
|||
} |
|||
@ -1,156 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Represents the CIE L*C*h°, cylindrical form of the CIE L*u*v* 1976 color.
|
|||
/// <see href="https://en.wikipedia.org/wiki/CIELAB_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC"/>
|
|||
/// </summary>
|
|||
public readonly struct CieLchuv : IEquatable<CieLchuv> |
|||
{ |
|||
private static readonly Vector3 Min = new(0, -200, 0); |
|||
private static readonly Vector3 Max = new(100, 200, 360); |
|||
|
|||
/// <summary>
|
|||
/// D50 standard illuminant.
|
|||
/// Used when reference white is not specified explicitly.
|
|||
/// </summary>
|
|||
public static readonly CieXyz DefaultWhitePoint = Illuminants.D65; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLchuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="c">The chroma, relative saturation.</param>
|
|||
/// <param name="h">The hue in degrees.</param>
|
|||
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLchuv(float l, float c, float h) |
|||
: this(l, c, h, DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLchuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="c">The chroma, relative saturation.</param>
|
|||
/// <param name="h">The hue in degrees.</param>
|
|||
/// <param name="whitePoint">The reference white point. <see cref="Illuminants"/></param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLchuv(float l, float c, float h, CieXyz whitePoint) |
|||
: this(new Vector3(l, c, h), whitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLchuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, c, h components.</param>
|
|||
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLchuv(Vector3 vector) |
|||
: this(vector, DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLchuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, c, h components.</param>
|
|||
/// <param name="whitePoint">The reference white point. <see cref="Illuminants"/></param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLchuv(Vector3 vector, CieXyz whitePoint) |
|||
: this() |
|||
{ |
|||
vector = Vector3.Clamp(vector, Min, Max); |
|||
this.L = vector.X; |
|||
this.C = vector.Y; |
|||
this.H = vector.Z; |
|||
this.WhitePoint = whitePoint; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension.
|
|||
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
|
|||
/// </summary>
|
|||
public readonly float L { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the a chroma component.
|
|||
/// <remarks>A value ranging from 0 to 200.</remarks>
|
|||
/// </summary>
|
|||
public readonly float C { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the h° hue component in degrees.
|
|||
/// <remarks>A value ranging from 0 to 360.</remarks>
|
|||
/// </summary>
|
|||
public readonly float H { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the reference white point of this color
|
|||
/// </summary>
|
|||
public readonly CieXyz WhitePoint { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLchuv"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLchuv"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLchuv"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(CieLchuv left, CieLchuv right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLchuv"/> objects for inequality
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLchuv"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLchuv"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(CieLchuv left, CieLchuv right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => HashCode.Combine(this.L, this.C, this.H, this.WhitePoint); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() => FormattableString.Invariant($"CieLchuv({this.L:#0.##}, {this.C:#0.##}, {this.H:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) => obj is CieLchuv other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public bool Equals(CieLchuv other) |
|||
=> this.L.Equals(other.L) |
|||
&& this.C.Equals(other.C) |
|||
&& this.H.Equals(other.H) |
|||
&& this.WhitePoint.Equals(other.WhitePoint); |
|||
|
|||
/// <summary>
|
|||
/// Computes the saturation of the color (chroma normalized by lightness)
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// A value ranging from 0 to 100.
|
|||
/// </remarks>
|
|||
/// <returns>The <see cref="float"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public float Saturation() |
|||
{ |
|||
float result = 100 * (this.C / this.L); |
|||
|
|||
if (float.IsNaN(result)) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
@ -1,136 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// The CIE 1976 (L*, u*, v*) color space, commonly known by its abbreviation CIELUV, is a color space adopted by the International
|
|||
/// Commission on Illumination (CIE) in 1976, as a simple-to-compute transformation of the 1931 CIE XYZ color space, but which
|
|||
/// attempted perceptual uniformity
|
|||
/// <see href="https://en.wikipedia.org/wiki/CIELUV"/>
|
|||
/// </summary>
|
|||
public readonly struct CieLuv : IEquatable<CieLuv> |
|||
{ |
|||
/// <summary>
|
|||
/// D65 standard illuminant.
|
|||
/// Used when reference white is not specified explicitly.
|
|||
/// </summary>
|
|||
public static readonly CieXyz DefaultWhitePoint = Illuminants.D65; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="u">The blue-yellow chromaticity coordinate of the given whitepoint.</param>
|
|||
/// <param name="v">The red-green chromaticity coordinate of the given whitepoint.</param>
|
|||
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLuv(float l, float u, float v) |
|||
: this(l, u, v, DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="u">The blue-yellow chromaticity coordinate of the given whitepoint.</param>
|
|||
/// <param name="v">The red-green chromaticity coordinate of the given whitepoint.</param>
|
|||
/// <param name="whitePoint">The reference white point. <see cref="Illuminants"/></param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLuv(float l, float u, float v, CieXyz whitePoint) |
|||
: this(new Vector3(l, u, v), whitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, u, v components.</param>
|
|||
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLuv(Vector3 vector) |
|||
: this(vector, DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLuv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, u, v components.</param>
|
|||
/// <param name="whitePoint">The reference white point. <see cref="Illuminants"/></param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLuv(Vector3 vector, CieXyz whitePoint) |
|||
{ |
|||
// Not clamping as documentation about this space only indicates "usual" ranges
|
|||
this.L = vector.X; |
|||
this.U = vector.Y; |
|||
this.V = vector.Z; |
|||
this.WhitePoint = whitePoint; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension
|
|||
/// <remarks>A value usually ranging between 0 and 100.</remarks>
|
|||
/// </summary>
|
|||
public readonly float L { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the blue-yellow chromaticity coordinate of the given whitepoint.
|
|||
/// <remarks>A value usually ranging between -100 and 100.</remarks>
|
|||
/// </summary>
|
|||
public readonly float U { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the red-green chromaticity coordinate of the given whitepoint.
|
|||
/// <remarks>A value usually ranging between -100 and 100.</remarks>
|
|||
/// </summary>
|
|||
public readonly float V { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the reference white point of this color
|
|||
/// </summary>
|
|||
public readonly CieXyz WhitePoint { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLuv"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLuv"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLuv"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static bool operator ==(CieLuv left, CieLuv right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLuv"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="CieLuv"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="CieLuv"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static bool operator !=(CieLuv left, CieLuv right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => HashCode.Combine(this.L, this.U, this.V, this.WhitePoint); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() => FormattableString.Invariant($"CieLuv({this.L:#0.##}, {this.U:#0.##}, {this.V:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) => obj is CieLuv other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public bool Equals(CieLuv other) |
|||
=> this.L.Equals(other.L) |
|||
&& this.U.Equals(other.U) |
|||
&& this.V.Equals(other.V) |
|||
&& this.WhitePoint.Equals(other.WhitePoint); |
|||
} |
|||
@ -1,107 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Represents an CMYK (cyan, magenta, yellow, keyline) color.
|
|||
/// </summary>
|
|||
public readonly struct Cmyk : IEquatable<Cmyk> |
|||
{ |
|||
private static readonly Vector4 Min = Vector4.Zero; |
|||
private static readonly Vector4 Max = Vector4.One; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Cmyk"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="c">The cyan component.</param>
|
|||
/// <param name="m">The magenta component.</param>
|
|||
/// <param name="y">The yellow component.</param>
|
|||
/// <param name="k">The keyline black component.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Cmyk(float c, float m, float y, float k) |
|||
: this(new Vector4(c, m, y, k)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Cmyk"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the c, m, y, k components.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Cmyk(Vector4 vector) |
|||
{ |
|||
vector = Numerics.Clamp(vector, Min, Max); |
|||
this.C = vector.X; |
|||
this.M = vector.Y; |
|||
this.Y = vector.Z; |
|||
this.K = vector.W; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the cyan color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public readonly float C { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the magenta color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public readonly float M { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the yellow color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public readonly float Y { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the keyline black color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public readonly float K { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Cmyk"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Cmyk"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Cmyk"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static bool operator ==(Cmyk left, Cmyk right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Cmyk"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Cmyk"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Cmyk"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static bool operator !=(Cmyk left, Cmyk right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public override int GetHashCode() => HashCode.Combine(this.C, this.M, this.Y, this.K); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() => FormattableString.Invariant($"Cmyk({this.C:#0.##}, {this.M:#0.##}, {this.Y:#0.##}, {this.K:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object? obj) => obj is Cmyk other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public bool Equals(Cmyk other) |
|||
=> this.C.Equals(other.C) |
|||
&& this.M.Equals(other.M) |
|||
&& this.Y.Equals(other.Y) |
|||
&& this.K.Equals(other.K); |
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Implements gamma companding.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
|
|||
/// </remarks>
|
|||
public static class GammaCompanding |
|||
{ |
|||
/// <summary>
|
|||
/// Expands a companded channel to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <param name="gamma">The gamma value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Expand(float channel, float gamma) => MathF.Pow(channel, gamma); |
|||
|
|||
/// <summary>
|
|||
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <param name="gamma">The gamma value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Compress(float channel, float gamma) => MathF.Pow(channel, 1 / gamma); |
|||
} |
|||
@ -1,36 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Implements L* companding.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// For more info see:
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
|
|||
/// </remarks>
|
|||
public static class LCompanding |
|||
{ |
|||
/// <summary>
|
|||
/// Expands a companded channel to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Expand(float channel) |
|||
=> channel <= 0.08F ? (100F * channel) / CieConstants.Kappa : Numerics.Pow3((channel + 0.16F) / 1.16F); |
|||
|
|||
/// <summary>
|
|||
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value</param>
|
|||
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Compress(float channel) |
|||
=> channel <= CieConstants.Epsilon ? (channel * CieConstants.Kappa) / 100F : (1.16F * MathF.Pow(channel, 0.3333333F)) - 0.16F; |
|||
} |
|||
@ -1,39 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Implements Rec. 2020 companding function.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <see href="http://en.wikipedia.org/wiki/Rec._2020"/>
|
|||
/// </remarks>
|
|||
public static class Rec2020Companding |
|||
{ |
|||
private const float Alpha = 1.09929682680944F; |
|||
private const float AlphaMinusOne = Alpha - 1F; |
|||
private const float Beta = 0.018053968510807F; |
|||
private const float InverseBeta = Beta * 4.5F; |
|||
private const float Epsilon = 1 / 0.45F; |
|||
|
|||
/// <summary>
|
|||
/// Expands a companded channel to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Expand(float channel) |
|||
=> channel < InverseBeta ? channel / 4.5F : MathF.Pow((channel + AlphaMinusOne) / Alpha, Epsilon); |
|||
|
|||
/// <summary>
|
|||
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Compress(float channel) |
|||
=> channel < Beta ? 4.5F * channel : (Alpha * MathF.Pow(channel, 0.45F)) - AlphaMinusOne; |
|||
} |
|||
@ -1,35 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Implements the Rec. 709 companding function.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// http://en.wikipedia.org/wiki/Rec._709
|
|||
/// </remarks>
|
|||
public static class Rec709Companding |
|||
{ |
|||
private const float Epsilon = 1 / 0.45F; |
|||
|
|||
/// <summary>
|
|||
/// Expands a companded channel to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Expand(float channel) |
|||
=> channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, Epsilon); |
|||
|
|||
/// <summary>
|
|||
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Compress(float channel) |
|||
=> channel < 0.018F ? 4.5F * channel : (1.099F * MathF.Pow(channel, 0.45F)) - 0.099F; |
|||
} |
|||
@ -1,230 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using System.Runtime.Intrinsics; |
|||
using System.Runtime.Intrinsics.X86; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Companding; |
|||
|
|||
/// <summary>
|
|||
/// Implements sRGB companding.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// For more info see:
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
|
|||
/// </remarks>
|
|||
public static class SRgbCompanding |
|||
{ |
|||
private const int Length = Scale + 2; // 256kb @ 16bit precision.
|
|||
private const int Scale = (1 << 16) - 1; |
|||
|
|||
private static readonly Lazy<float[]> LazyCompressTable = new( |
|||
() => |
|||
{ |
|||
float[] result = new float[Length]; |
|||
|
|||
for (int i = 0; i < result.Length; i++) |
|||
{ |
|||
double d = (double)i / Scale; |
|||
if (d <= (0.04045 / 12.92)) |
|||
{ |
|||
d *= 12.92; |
|||
} |
|||
else |
|||
{ |
|||
d = (1.055 * Math.Pow(d, 1.0 / 2.4)) - 0.055; |
|||
} |
|||
|
|||
result[i] = (float)d; |
|||
} |
|||
|
|||
return result; |
|||
}, |
|||
true); |
|||
|
|||
private static readonly Lazy<float[]> LazyExpandTable = new( |
|||
() => |
|||
{ |
|||
float[] result = new float[Length]; |
|||
|
|||
for (int i = 0; i < result.Length; i++) |
|||
{ |
|||
double d = (double)i / Scale; |
|||
if (d <= 0.04045) |
|||
{ |
|||
d /= 12.92; |
|||
} |
|||
else |
|||
{ |
|||
d = Math.Pow((d + 0.055) / 1.055, 2.4); |
|||
} |
|||
|
|||
result[i] = (float)d; |
|||
} |
|||
|
|||
return result; |
|||
}, |
|||
true); |
|||
|
|||
private static float[] ExpandTable => LazyExpandTable.Value; |
|||
|
|||
private static float[] CompressTable => LazyCompressTable.Value; |
|||
|
|||
/// <summary>
|
|||
/// Expands the companded vectors to their linear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Expand(Span<Vector4> vectors) |
|||
{ |
|||
if (Avx2.IsSupported && vectors.Length >= 2) |
|||
{ |
|||
CompandAvx2(vectors, ExpandTable); |
|||
|
|||
if (Numerics.Modulo2(vectors.Length) != 0) |
|||
{ |
|||
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
|
|||
Expand(ref MemoryMarshal.GetReference(vectors[^1..])); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
CompandScalar(vectors, ExpandTable); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compresses the uncompanded vectors to their nonlinear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static unsafe void Compress(Span<Vector4> vectors) |
|||
{ |
|||
if (Avx2.IsSupported && vectors.Length >= 2) |
|||
{ |
|||
CompandAvx2(vectors, CompressTable); |
|||
|
|||
if (Numerics.Modulo2(vectors.Length) != 0) |
|||
{ |
|||
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
|
|||
Compress(ref MemoryMarshal.GetReference(vectors[^1..])); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
CompandScalar(vectors, CompressTable); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands a companded vector to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Expand(ref Vector4 vector) |
|||
{ |
|||
// Alpha is already a linear representation of opacity so we do not want to convert it.
|
|||
vector.X = Expand(vector.X); |
|||
vector.Y = Expand(vector.Y); |
|||
vector.Z = Expand(vector.Z); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compresses an uncompanded vector (linear) to its nonlinear equivalent.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Compress(ref Vector4 vector) |
|||
{ |
|||
// Alpha is already a linear representation of opacity so we do not want to convert it.
|
|||
vector.X = Compress(vector.X); |
|||
vector.Y = Compress(vector.Y); |
|||
vector.Z = Compress(vector.Z); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands a companded channel to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Expand(float channel) |
|||
=> channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F); |
|||
|
|||
/// <summary>
|
|||
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Compress(float channel) |
|||
=> channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static unsafe void CompandAvx2(Span<Vector4> vectors, float[] table) |
|||
{ |
|||
fixed (float* tablePointer = &MemoryMarshal.GetArrayDataReference(table)) |
|||
{ |
|||
var scale = Vector256.Create((float)Scale); |
|||
Vector256<float> zero = Vector256<float>.Zero; |
|||
var offset = Vector256.Create(1); |
|||
|
|||
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
|
|||
ref Vector256<float> vectorsBase = ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors)); |
|||
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (uint)vectors.Length / 2u); |
|||
|
|||
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|||
{ |
|||
Vector256<float> multiplied = Avx.Multiply(scale, vectorsBase); |
|||
multiplied = Avx.Min(Avx.Max(zero, multiplied), scale); |
|||
|
|||
Vector256<int> truncated = Avx.ConvertToVector256Int32WithTruncation(multiplied); |
|||
Vector256<float> truncatedF = Avx.ConvertToVector256Single(truncated); |
|||
|
|||
Vector256<float> low = Avx2.GatherVector256(tablePointer, truncated, sizeof(float)); |
|||
Vector256<float> high = Avx2.GatherVector256(tablePointer, Avx2.Add(truncated, offset), sizeof(float)); |
|||
|
|||
// Alpha is already a linear representation of opacity so we do not want to convert it.
|
|||
Vector256<float> companded = Numerics.Lerp(low, high, Avx.Subtract(multiplied, truncatedF)); |
|||
vectorsBase = Avx.Blend(companded, vectorsBase, Numerics.BlendAlphaControl); |
|||
vectorsBase = ref Unsafe.Add(ref vectorsBase, 1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static unsafe void CompandScalar(Span<Vector4> vectors, float[] table) |
|||
{ |
|||
fixed (float* tablePointer = &MemoryMarshal.GetArrayDataReference(table)) |
|||
{ |
|||
Vector4 zero = Vector4.Zero; |
|||
var scale = new Vector4(Scale); |
|||
ref Vector4 vectorsBase = ref MemoryMarshal.GetReference(vectors); |
|||
ref Vector4 vectorsLast = ref Unsafe.Add(ref vectorsBase, (uint)vectors.Length); |
|||
|
|||
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|||
{ |
|||
Vector4 multiplied = Numerics.Clamp(vectorsBase * Scale, zero, scale); |
|||
|
|||
float f0 = multiplied.X; |
|||
float f1 = multiplied.Y; |
|||
float f2 = multiplied.Z; |
|||
|
|||
uint i0 = (uint)f0; |
|||
uint i1 = (uint)f1; |
|||
uint i2 = (uint)f2; |
|||
|
|||
// Alpha is already a linear representation of opacity so we do not want to convert it.
|
|||
vectorsBase.X = Numerics.Lerp(tablePointer[i0], tablePointer[i0 + 1], f0 - (int)i0); |
|||
vectorsBase.Y = Numerics.Lerp(tablePointer[i1], tablePointer[i1 + 1], f1 - (int)i1); |
|||
vectorsBase.Z = Numerics.Lerp(tablePointer[i2], tablePointer[i2 + 1], f2 - (int)i2); |
|||
|
|||
vectorsBase = ref Unsafe.Add(ref vectorsBase, 1); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,159 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Performs chromatic adaptation on the various color spaces.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs chromatic adaptation of given <see cref="CieXyz"/> color.
|
|||
/// Target white point is <see cref="ColorSpaceConverterOptions.WhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <param name="sourceWhitePoint">The source white point.</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieXyz Adapt(in CieXyz color, in CieXyz sourceWhitePoint) => this.Adapt(color, sourceWhitePoint, this.whitePoint); |
|||
|
|||
/// <summary>
|
|||
/// Performs chromatic adaptation of given <see cref="CieXyz"/> color.
|
|||
/// Target white point is <see cref="ColorSpaceConverterOptions.WhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <param name="sourceWhitePoint">The source white point.</param>
|
|||
/// <param name="targetWhitePoint">The target white point.</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieXyz Adapt(in CieXyz color, in CieXyz sourceWhitePoint, in CieXyz targetWhitePoint) |
|||
{ |
|||
if (!this.performChromaticAdaptation || sourceWhitePoint.Equals(targetWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
// We know that chromaticAdaption is not null because performChromaticAdaption is checked
|
|||
return this.chromaticAdaptation!.Transform(color, sourceWhitePoint, targetWhitePoint); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adapts <see cref="CieLab"/> color from the source white point to white point set in <see cref="ColorSpaceConverterOptions.TargetLabWhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieLab Adapt(in CieLab color) |
|||
{ |
|||
if (!this.performChromaticAdaptation || color.WhitePoint.Equals(this.targetLabWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adapts <see cref="CieLch"/> color from the source white point to white point set in <see cref="ColorSpaceConverterOptions.TargetLabWhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieLch Adapt(in CieLch color) |
|||
{ |
|||
if (!this.performChromaticAdaptation || color.WhitePoint.Equals(this.targetLabWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
var labColor = this.ToCieLab(color); |
|||
return this.ToCieLch(labColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adapts <see cref="CieLchuv"/> color from the source white point to white point set in <see cref="ColorSpaceConverterOptions.TargetLabWhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieLchuv Adapt(in CieLchuv color) |
|||
{ |
|||
if (!this.performChromaticAdaptation || color.WhitePoint.Equals(this.targetLabWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
var luvColor = this.ToCieLuv(color); |
|||
return this.ToCieLchuv(luvColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adapts <see cref="CieLuv"/> color from the source white point to white point set in <see cref="ColorSpaceConverterOptions.TargetLuvWhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieLuv Adapt(in CieLuv color) |
|||
{ |
|||
if (!this.performChromaticAdaptation || color.WhitePoint.Equals(this.targetLuvWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adapts <see cref="HunterLab"/> color from the source white point to white point set in <see cref="ColorSpaceConverterOptions.TargetHunterLabWhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public HunterLab Adapt(in HunterLab color) |
|||
{ |
|||
if (!this.performChromaticAdaptation || color.WhitePoint.Equals(this.targetHunterLabWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adapts a <see cref="LinearRgb"/> color from the source working space to working space set in <see cref="ColorSpaceConverterOptions.TargetRgbWorkingSpace"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public LinearRgb Adapt(in LinearRgb color) |
|||
{ |
|||
if (!this.performChromaticAdaptation || color.WorkingSpace.Equals(this.targetRgbWorkingSpace)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
// Conversion to XYZ
|
|||
LinearRgbToCieXyzConverter converterToXYZ = GetLinearRgbToCieXyzConverter(color.WorkingSpace); |
|||
CieXyz unadapted = converterToXYZ.Convert(color); |
|||
|
|||
// Adaptation
|
|||
// We know that chromaticAdaption is not null because performChromaticAdaption is checked
|
|||
CieXyz adapted = this.chromaticAdaptation!.Transform(unadapted, color.WorkingSpace.WhitePoint, this.targetRgbWorkingSpace.WhitePoint); |
|||
|
|||
// Conversion back to RGB
|
|||
return this.cieXyzToLinearRgbConverter.Convert(adapted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adapts an <see cref="Rgb"/> color from the source working space to working space set in <see cref="ColorSpaceConverterOptions.TargetRgbWorkingSpace"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public Rgb Adapt(in Rgb color) |
|||
{ |
|||
if (!this.performChromaticAdaptation) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
var linearInput = ToLinearRgb(color); |
|||
LinearRgb linearOutput = this.Adapt(linearInput); |
|||
return ToRgb(linearOutput); |
|||
} |
|||
} |
|||
@ -1,441 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieLab"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in CieLch color) |
|||
{ |
|||
// Conversion (preserving white point)
|
|||
CieLab unadapted = CieLchToCieLabConverter.Convert(color); |
|||
|
|||
return this.Adapt(unadapted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in CieLchuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in CieLuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in CieXyy color) |
|||
{ |
|||
CieXyz xyzColor = ToCieXyz(color); |
|||
|
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="CieLab"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in CieXyz color) |
|||
{ |
|||
CieXyz adapted = this.Adapt(color, this.whitePoint, this.targetLabWhitePoint); |
|||
|
|||
return this.cieXyzToCieLabConverter.Convert(adapted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="CieLab"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="CieLab"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in Cmyk color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Cmyk> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in Hsl color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsl> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in Hsv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsv> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in HunterLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in Lms color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in LinearRgb color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<LinearRgb> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in Rgb color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Rgb> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="CieLab"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLab ToCieLab(in YCbCr color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<CieLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLab(sp); |
|||
} |
|||
} |
|||
} |
|||
@ -1,441 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieLch"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="CieLch"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in CieLab color) |
|||
{ |
|||
CieLab adapted = this.Adapt(color); |
|||
|
|||
return CieLabToCieLchConverter.Convert(adapted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in CieLchuv color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in CieLuv color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in CieXyy color) |
|||
{ |
|||
var xyzColor = ToCieXyz(color); |
|||
|
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="CieLch"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in CieXyz color) |
|||
{ |
|||
var labColor = this.ToCieLab(color); |
|||
|
|||
return this.ToCieLch(labColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in Cmyk color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Cmyk> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in Hsl color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsl> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in Hsv color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsv> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in HunterLab color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in LinearRgb color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<LinearRgb> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in Lms color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in Rgb color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Rgb> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLch"/></returns>
|
|||
public CieLch ToCieLch(in YCbCr color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<CieLch> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLch destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLch dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLch(sp); |
|||
} |
|||
} |
|||
} |
|||
@ -1,441 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieLchuv"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="CieLchuv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in CieLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in CieLch color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in CieLuv color) |
|||
{ |
|||
CieLuv adapted = this.Adapt(color); |
|||
|
|||
return CieLuvToCieLchuvConverter.Convert(adapted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in CieXyy color) |
|||
{ |
|||
CieXyz xyzColor = ToCieXyz(color); |
|||
|
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in CieXyz color) |
|||
{ |
|||
CieLuv luvColor = this.ToCieLuv(color); |
|||
|
|||
return this.ToCieLchuv(luvColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in Cmyk color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Cmyk> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in Hsl color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="CieLchuv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsl> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in Hsv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsv> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in HunterLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in LinearRgb color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<LinearRgb> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in Lms color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in Rgb color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Rgb> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLchuv"/></returns>
|
|||
public CieLchuv ToCieLchuv(in YCbCr color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="CieLchuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<CieLchuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLchuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLchuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLchuv(sp); |
|||
} |
|||
} |
|||
} |
|||
@ -1,435 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieLuv"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in CieLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in CieLch color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLab"/></returns>
|
|||
public CieLuv ToCieLuv(in CieLchuv color) |
|||
{ |
|||
// Conversion (preserving white point)
|
|||
CieLuv unadapted = CieLchuvToCieLuvConverter.Convert(color); |
|||
|
|||
// Adaptation
|
|||
return this.Adapt(unadapted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in CieXyy color) |
|||
{ |
|||
CieXyz xyzColor = ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in CieXyz color) |
|||
{ |
|||
// Adaptation
|
|||
CieXyz adapted = this.Adapt(color, this.whitePoint, this.targetLuvWhitePoint); |
|||
|
|||
// Conversion
|
|||
return this.cieXyzToCieLuvConverter.Convert(adapted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in Cmyk color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Cmyk> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="CieLuv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in Hsl color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsl> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in Hsv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsv> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in HunterLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in Lms color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in LinearRgb color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<LinearRgb> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in Rgb color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Rgb> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieLuv"/></returns>
|
|||
public CieLuv ToCieLuv(in YCbCr color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<CieLuv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieLuv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieLuv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieLuv(sp); |
|||
} |
|||
} |
|||
} |
|||
@ -1,437 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieXyy"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in CieLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in CieLch color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in CieLchuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in CieLuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public static CieXyy ToCieXyy(in CieXyz color) => CieXyzAndCieXyyConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<CieXyz> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in Cmyk color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Cmyk> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(Hsl color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsl> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in Hsv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsv> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in HunterLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in LinearRgb color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<LinearRgb> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in Lms color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in Rgb color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Rgb> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyy"/></returns>
|
|||
public CieXyy ToCieXyy(in YCbCr color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="CieXyy"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<CieXyy> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyy destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyy dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyy(sp); |
|||
} |
|||
} |
|||
} |
|||
@ -1,458 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Collections.Concurrent; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieXyz"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
private static readonly ConcurrentDictionary<RgbWorkingSpace, LinearRgbToCieXyzConverter> ConverterCache = new(); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in CieLab color) |
|||
{ |
|||
// Conversion
|
|||
CieXyz unadapted = CieLabToCieXyzConverter.Convert(color); |
|||
|
|||
// Adaptation
|
|||
return this.Adapt(unadapted, color.WhitePoint); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in CieLch color) |
|||
{ |
|||
// Conversion to Lab
|
|||
CieLab labColor = CieLchToCieLabConverter.Convert(color); |
|||
|
|||
// Conversion to XYZ (incl. adaptation)
|
|||
return this.ToCieXyz(labColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in CieLchuv color) |
|||
{ |
|||
// Conversion to Luv
|
|||
CieLuv luvColor = CieLchuvToCieLuvConverter.Convert(color); |
|||
|
|||
// Conversion to XYZ (incl. adaptation)
|
|||
return this.ToCieXyz(luvColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="CieXyz"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in CieLuv color) |
|||
{ |
|||
// Conversion
|
|||
CieXyz unadapted = CieLuvToCieXyzConverter.Convert(color); |
|||
|
|||
// Adaptation
|
|||
return this.Adapt(unadapted, color.WhitePoint); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public static CieXyz ToCieXyz(in CieXyy color) |
|||
|
|||
// Conversion
|
|||
=> CieXyzAndCieXyyConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<CieXyy> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in Cmyk color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return this.ToCieXyz(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Cmyk> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in Hsl color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return this.ToCieXyz(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<Hsl> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in Hsv color) |
|||
{ |
|||
// Conversion
|
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return this.ToCieXyz(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsv> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in HunterLab color) |
|||
{ |
|||
CieXyz unadapted = HunterLabToCieXyzConverter.Convert(color); |
|||
|
|||
return this.Adapt(unadapted, color.WhitePoint); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in LinearRgb color) |
|||
{ |
|||
// Conversion
|
|||
LinearRgbToCieXyzConverter converter = GetLinearRgbToCieXyzConverter(color.WorkingSpace); |
|||
CieXyz unadapted = converter.Convert(color); |
|||
|
|||
return this.Adapt(unadapted, color.WorkingSpace.WhitePoint); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<LinearRgb> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in Lms color) |
|||
=> this.cieXyzAndLmsConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="CieXyz"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in Rgb color) |
|||
{ |
|||
// Conversion
|
|||
LinearRgb linear = RgbToLinearRgbConverter.Convert(color); |
|||
return this.ToCieXyz(linear); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="CieXyz"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Rgb> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="CieXyz"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
public CieXyz ToCieXyz(in YCbCr color) |
|||
{ |
|||
Rgb rgb = this.ToRgb(color); |
|||
|
|||
return this.ToCieXyz(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="CieXyz"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<CieXyz> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref CieXyz destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref CieXyz dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCieXyz(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the correct converter for the given rgb working space.
|
|||
/// </summary>
|
|||
/// <param name="workingSpace">The source working space</param>
|
|||
/// <returns>The <see cref="LinearRgbToCieXyzConverter"/></returns>
|
|||
private static LinearRgbToCieXyzConverter GetLinearRgbToCieXyzConverter(RgbWorkingSpace workingSpace) |
|||
=> ConverterCache.GetOrAdd(workingSpace, (key) => new LinearRgbToCieXyzConverter(key)); |
|||
} |
|||
@ -1,437 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="Cmyk"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public Cmyk ToCmyk(in CieLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public Cmyk ToCmyk(in CieLch color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="Cmyk"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public Cmyk ToCmyk(in CieLchuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="Cmyk"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="Cmyk"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public Cmyk ToCmyk(in CieLuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="Cmyk"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public Cmyk ToCmyk(in CieXyy color) |
|||
{ |
|||
CieXyz xyzColor = ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public Cmyk ToCmyk(in CieXyz color) |
|||
{ |
|||
Rgb rgb = this.ToRgb(color); |
|||
|
|||
return CmykAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="Cmyk"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public static Cmyk ToCmyk(in Hsl color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return CmykAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Hsl> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public static Cmyk ToCmyk(in Hsv color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return CmykAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Hsv> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public Cmyk ToCmyk(in HunterLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public static Cmyk ToCmyk(in LinearRgb color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return CmykAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<LinearRgb> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public Cmyk ToCmyk(in Lms color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors,</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public static Cmyk ToCmyk(in Rgb color) => CmykAndRgbConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="Cmyk"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Rgb> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToCmyk(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Cmyk"/></returns>
|
|||
public Cmyk ToCmyk(in YCbCr color) |
|||
{ |
|||
Rgb rgb = this.ToRgb(color); |
|||
|
|||
return CmykAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<Cmyk> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Cmyk destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Cmyk dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToCmyk(sp); |
|||
} |
|||
} |
|||
} |
|||
@ -1,437 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="Hsl"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public Hsl ToHsl(in CieLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public Hsl ToHsl(in CieLch color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public Hsl ToHsl(in CieLchuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public Hsl ToHsl(in CieLuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public Hsl ToHsl(in CieXyy color) |
|||
{ |
|||
CieXyz xyzColor = ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="Hsl"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="Hsl"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public Hsl ToHsl(in CieXyz color) |
|||
{ |
|||
Rgb rgb = this.ToRgb(color); |
|||
|
|||
return HslAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="Hsl"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="Hsl"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public static Hsl ToHsl(in Cmyk color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return HslAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="Hsl"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Cmyk> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="Hsl"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public static Hsl ToHsl(in Hsv color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return HslAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="Hsl"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Hsv> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public Hsl ToHsl(in HunterLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public static Hsl ToHsl(in LinearRgb color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return HslAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<LinearRgb> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public Hsl ToHsl(Lms color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="Hsl"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public static Hsl ToHsl(in Rgb color) => HslAndRgbConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Rgb> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToHsl(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsl"/></returns>
|
|||
public Hsl ToHsl(in YCbCr color) |
|||
{ |
|||
Rgb rgb = this.ToRgb(color); |
|||
|
|||
return HslAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<Hsl> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsl destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsl dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsl(sp); |
|||
} |
|||
} |
|||
} |
|||
@ -1,437 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="Hsv"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public Hsv ToHsv(in CieLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public Hsv ToHsv(in CieLch color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public Hsv ToHsv(in CieLchuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public Hsv ToHsv(in CieLuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public Hsv ToHsv(in CieXyy color) |
|||
{ |
|||
CieXyz xyzColor = ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public Hsv ToHsv(in CieXyz color) |
|||
{ |
|||
Rgb rgb = this.ToRgb(color); |
|||
|
|||
return HsvAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public static Hsv ToHsv(in Cmyk color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return HsvAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Cmyk> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public static Hsv ToHsv(in Hsl color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return HsvAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public static void Convert(ReadOnlySpan<Hsl> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public Hsv ToHsv(in HunterLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public static Hsv ToHsv(in LinearRgb color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return HsvAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<LinearRgb> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public Hsv ToHsv(Lms color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public static Hsv ToHsv(in Rgb color) => HsvAndRgbConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Rgb> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToHsv(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Hsv"/></returns>
|
|||
public Hsv ToHsv(in YCbCr color) |
|||
{ |
|||
Rgb rgb = this.ToRgb(color); |
|||
|
|||
return HsvAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="Hsv"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<Hsv> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Hsv destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Hsv dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHsv(sp); |
|||
} |
|||
} |
|||
} |
|||
@ -1,430 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="HunterLab"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Cmyk> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<Hsl> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsv> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="HunterLab"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<LinearRgb> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Rgb> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<HunterLab> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref HunterLab destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref HunterLab dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToHunterLab(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in CieLab color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in CieLch color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in CieLchuv color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in CieLuv color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in CieXyy color) |
|||
{ |
|||
var xyzColor = ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in CieXyz color) |
|||
{ |
|||
CieXyz adapted = this.Adapt(color, this.whitePoint, this.targetHunterLabWhitePoint); |
|||
|
|||
return this.cieXyzToHunterLabConverter.Convert(adapted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in Cmyk color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in Hsl color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in Hsv color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in LinearRgb color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in Lms color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="HunterLab"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in Rgb color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="HunterLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="HunterLab"/></returns>
|
|||
public HunterLab ToHunterLab(in YCbCr color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
} |
|||
@ -1,429 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="LinearRgb"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public static void Convert(ReadOnlySpan<Cmyk> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public static void Convert(ReadOnlySpan<Hsl> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public static void Convert(ReadOnlySpan<Hsv> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Rgb> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<LinearRgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref LinearRgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLinearRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public LinearRgb ToLinearRgb(in CieLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToLinearRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public LinearRgb ToLinearRgb(in CieLch color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToLinearRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public LinearRgb ToLinearRgb(in CieLchuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToLinearRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public LinearRgb ToLinearRgb(in CieLuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToLinearRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="LinearRgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public LinearRgb ToLinearRgb(in CieXyy color) |
|||
{ |
|||
CieXyz xyzColor = ToCieXyz(color); |
|||
return this.ToLinearRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public LinearRgb ToLinearRgb(in CieXyz color) |
|||
{ |
|||
// Adaptation
|
|||
CieXyz adapted = this.Adapt(color, this.whitePoint, this.targetRgbWorkingSpace.WhitePoint); |
|||
|
|||
// Conversion
|
|||
return this.cieXyzToLinearRgbConverter.Convert(adapted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public static LinearRgb ToLinearRgb(in Cmyk color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
return ToLinearRgb(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public static LinearRgb ToLinearRgb(in Hsl color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
return ToLinearRgb(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public static LinearRgb ToLinearRgb(in Hsv color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
return ToLinearRgb(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public LinearRgb ToLinearRgb(in HunterLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToLinearRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public LinearRgb ToLinearRgb(in Lms color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToLinearRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="LinearRgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public static LinearRgb ToLinearRgb(in Rgb color) |
|||
=> RgbToLinearRgbConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="LinearRgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="LinearRgb"/></returns>
|
|||
public LinearRgb ToLinearRgb(in YCbCr color) |
|||
{ |
|||
Rgb rgb = this.ToRgb(color); |
|||
return ToLinearRgb(rgb); |
|||
} |
|||
} |
|||
@ -1,425 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="Lms"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Cmyk> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsl> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Hsv> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<LinearRgb> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Rgb> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<Lms> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Lms destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Lms dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToLms(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in CieLab color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in CieLch color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in CieLchuv color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in CieLuv color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in CieXyy color) |
|||
{ |
|||
var xyzColor = ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in CieXyz color) => this.cieXyzAndLmsConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in Cmyk color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in Hsl color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in Hsv color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in HunterLab color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in LinearRgb color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in Rgb color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="Lms"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Lms"/></returns>
|
|||
public Lms ToLms(in YCbCr color) |
|||
{ |
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
} |
|||
@ -1,419 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="Rgb"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLchuv"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLchuv> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLchuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLchuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Cmyk> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Hsv> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Hsl> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<LinearRgb> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="YCbCr"/> into <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<YCbCr> source, Span<Rgb> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref YCbCr sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref Rgb destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref YCbCr sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToRgb(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public Rgb ToRgb(in CieLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public Rgb ToRgb(in CieLch color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public Rgb ToRgb(in CieLchuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public Rgb ToRgb(in CieLuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public Rgb ToRgb(in CieXyy color) |
|||
{ |
|||
CieXyz xyzColor = ToCieXyz(color); |
|||
return this.ToRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public Rgb ToRgb(in CieXyz color) |
|||
{ |
|||
// Conversion
|
|||
LinearRgb linear = this.ToLinearRgb(color); |
|||
|
|||
// Compand
|
|||
return ToRgb(linear); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public static Rgb ToRgb(in Cmyk color) => CmykAndRgbConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public static Rgb ToRgb(in Hsv color) => HsvAndRgbConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public static Rgb ToRgb(in Hsl color) => HslAndRgbConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public Rgb ToRgb(in HunterLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public static Rgb ToRgb(in LinearRgb color) => LinearRgbToRgbConverter.Convert(color); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public Rgb ToRgb(in Lms color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToRgb(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="YCbCr"/> into a <see cref="Rgb"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="Rgb"/></returns>
|
|||
public Rgb ToRgb(in YCbCr color) |
|||
{ |
|||
// Conversion
|
|||
Rgb rgb = YCbCrAndRgbConverter.Convert(color); |
|||
|
|||
// Adaptation
|
|||
return this.Adapt(rgb); |
|||
} |
|||
} |
|||
@ -1,404 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="YCbCr"/>.
|
|||
/// </content>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieLab> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLch"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors.</param>
|
|||
/// <param name="destination">The span to the destination colors.</param>
|
|||
public void Convert(ReadOnlySpan<CieLch> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLch sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLch sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieLuv"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieLuv> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieLuv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieLuv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="YCbCr"/>
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyy> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyy sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<CieXyz> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref CieXyz sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Cmyk"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Cmyk> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Cmyk sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsl"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Hsl> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsl sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Hsv"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Hsv> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Hsv sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="HunterLab"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<HunterLab> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref HunterLab sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref HunterLab sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="LinearRgb"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<LinearRgb> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref LinearRgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public void Convert(ReadOnlySpan<Lms> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Lms sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Lms sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = this.ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The span to the source colors</param>
|
|||
/// <param name="destination">The span to the destination colors</param>
|
|||
public static void Convert(ReadOnlySpan<Rgb> source, Span<YCbCr> destination) |
|||
{ |
|||
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); |
|||
int count = source.Length; |
|||
|
|||
ref Rgb sourceRef = ref MemoryMarshal.GetReference(source); |
|||
ref YCbCr destRef = ref MemoryMarshal.GetReference(destination); |
|||
|
|||
for (nuint i = 0; i < (uint)count; i++) |
|||
{ |
|||
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref YCbCr dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = ToYCbCr(sp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLab"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public YCbCr ToYCbCr(in CieLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToYCbCr(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLch"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public YCbCr ToYCbCr(in CieLch color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToYCbCr(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLuv"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public YCbCr ToYCbCr(in CieLuv color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToYCbCr(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyy"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public YCbCr ToYCbCr(in CieXyy color) |
|||
{ |
|||
CieXyz xyzColor = ToCieXyz(color); |
|||
|
|||
return this.ToYCbCr(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieXyz"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public YCbCr ToYCbCr(in CieXyz color) |
|||
{ |
|||
Rgb rgb = this.ToRgb(color); |
|||
|
|||
return YCbCrAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Cmyk"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public static YCbCr ToYCbCr(in Cmyk color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return YCbCrAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsl"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public static YCbCr ToYCbCr(in Hsl color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return YCbCrAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Hsv"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public static YCbCr ToYCbCr(in Hsv color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return YCbCrAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="HunterLab"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public YCbCr ToYCbCr(in HunterLab color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToYCbCr(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="LinearRgb"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public static YCbCr ToYCbCr(in LinearRgb color) |
|||
{ |
|||
Rgb rgb = ToRgb(color); |
|||
|
|||
return YCbCrAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Lms"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public YCbCr ToYCbCr(in Lms color) |
|||
{ |
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToYCbCr(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Rgb"/> into a <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public static YCbCr ToYCbCr(in Rgb color) => YCbCrAndRgbConverter.Convert(color); |
|||
} |
|||
@ -1,59 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Provides methods to allow the conversion of color values between different color spaces.
|
|||
/// </summary>
|
|||
public partial class ColorSpaceConverter |
|||
{ |
|||
// Options.
|
|||
private static readonly ColorSpaceConverterOptions DefaultOptions = new(); |
|||
private readonly Matrix4x4 lmsAdaptationMatrix; |
|||
private readonly CieXyz whitePoint; |
|||
private readonly CieXyz targetLuvWhitePoint; |
|||
private readonly CieXyz targetLabWhitePoint; |
|||
private readonly CieXyz targetHunterLabWhitePoint; |
|||
private readonly RgbWorkingSpace targetRgbWorkingSpace; |
|||
private readonly IChromaticAdaptation? chromaticAdaptation; |
|||
private readonly bool performChromaticAdaptation; |
|||
private readonly CieXyzAndLmsConverter cieXyzAndLmsConverter; |
|||
private readonly CieXyzToCieLabConverter cieXyzToCieLabConverter; |
|||
private readonly CieXyzToCieLuvConverter cieXyzToCieLuvConverter; |
|||
private readonly CieXyzToHunterLabConverter cieXyzToHunterLabConverter; |
|||
private readonly CieXyzToLinearRgbConverter cieXyzToLinearRgbConverter; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ColorSpaceConverter"/> class.
|
|||
/// </summary>
|
|||
public ColorSpaceConverter() |
|||
: this(DefaultOptions) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ColorSpaceConverter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="options">The configuration options.</param>
|
|||
public ColorSpaceConverter(ColorSpaceConverterOptions options) |
|||
{ |
|||
Guard.NotNull(options, nameof(options)); |
|||
this.whitePoint = options.WhitePoint; |
|||
this.targetLuvWhitePoint = options.TargetLuvWhitePoint; |
|||
this.targetLabWhitePoint = options.TargetLabWhitePoint; |
|||
this.targetHunterLabWhitePoint = options.TargetHunterLabWhitePoint; |
|||
this.targetRgbWorkingSpace = options.TargetRgbWorkingSpace; |
|||
this.chromaticAdaptation = options.ChromaticAdaptation; |
|||
this.performChromaticAdaptation = this.chromaticAdaptation != null; |
|||
this.lmsAdaptationMatrix = options.LmsAdaptationMatrix; |
|||
|
|||
this.cieXyzAndLmsConverter = new CieXyzAndLmsConverter(this.lmsAdaptationMatrix); |
|||
this.cieXyzToCieLabConverter = new CieXyzToCieLabConverter(this.targetLabWhitePoint); |
|||
this.cieXyzToCieLuvConverter = new CieXyzToCieLuvConverter(this.targetLuvWhitePoint); |
|||
this.cieXyzToHunterLabConverter = new CieXyzToHunterLabConverter(this.targetHunterLabWhitePoint); |
|||
this.cieXyzToLinearRgbConverter = new CieXyzToLinearRgbConverter(this.targetRgbWorkingSpace); |
|||
} |
|||
} |
|||
@ -1,53 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Configuration options for the <see cref="ColorSpaceConverter"/> class.
|
|||
/// </summary>
|
|||
public class ColorSpaceConverterOptions |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the white point used for chromatic adaptation in conversions from/to XYZ color space.
|
|||
/// When <value>default</value>, no adaptation will be performed.
|
|||
/// Defaults to: <see cref="CieLuv.DefaultWhitePoint"/>.
|
|||
/// </summary>
|
|||
public CieXyz WhitePoint { get; set; } = CieLuv.DefaultWhitePoint; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the white point used *when creating* Luv/LChuv colors. (Luv/LChuv colors on the input already contain the white point information)
|
|||
/// Defaults to: <see cref="CieLuv.DefaultWhitePoint"/>.
|
|||
/// </summary>
|
|||
public CieXyz TargetLuvWhitePoint { get; set; } = CieLuv.DefaultWhitePoint; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the white point used *when creating* Lab/LChab colors. (Lab/LChab colors on the input already contain the white point information)
|
|||
/// Defaults to: <see cref="CieLab.DefaultWhitePoint"/>.
|
|||
/// </summary>
|
|||
public CieXyz TargetLabWhitePoint { get; set; } = CieLab.DefaultWhitePoint; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the white point used *when creating* HunterLab colors. (HunterLab colors on the input already contain the white point information)
|
|||
/// Defaults to: <see cref="HunterLab.DefaultWhitePoint"/>.
|
|||
/// </summary>
|
|||
public CieXyz TargetHunterLabWhitePoint { get; set; } = HunterLab.DefaultWhitePoint; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the target working space used *when creating* RGB colors. (RGB colors on the input already contain the working space information)
|
|||
/// Defaults to: <see cref="Rgb.DefaultWorkingSpace"/>.
|
|||
/// </summary>
|
|||
public RgbWorkingSpace TargetRgbWorkingSpace { get; set; } = Rgb.DefaultWorkingSpace; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the chromatic adaptation method used. When <value>null</value>, no adaptation will be performed.
|
|||
/// </summary>
|
|||
public IChromaticAdaptation? ChromaticAdaptation { get; set; } = new VonKriesChromaticAdaptation(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets transformation matrix used in conversion to and from <see cref="Lms"/>.
|
|||
/// </summary>
|
|||
public Matrix4x4 LmsAdaptationMatrix { get; set; } = CieXyzAndLmsConverter.DefaultTransformationMatrix; |
|||
} |
|||
@ -1,31 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLch"/> to <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
internal static class CieLchToCieLabConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieLch"/> input to an instance of <see cref="CieLab"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static CieLab Convert(in CieLch input) |
|||
{ |
|||
// Conversion algorithm described here:
|
|||
// https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC
|
|||
float l = input.L, c = input.C, hDegrees = input.H; |
|||
float hRadians = GeometryUtilities.DegreeToRadian(hDegrees); |
|||
|
|||
float a = c * MathF.Cos(hRadians); |
|||
float b = c * MathF.Sin(hRadians); |
|||
|
|||
return new CieLab(l, a, b, input.WhitePoint); |
|||
} |
|||
} |
|||
@ -1,39 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLab"/> to <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
internal static class CieLabToCieLchConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieLab"/> input to an instance of <see cref="CieLch"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static CieLch Convert(in CieLab input) |
|||
{ |
|||
// Conversion algorithm described here:
|
|||
// https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC
|
|||
float l = input.L, a = input.A, b = input.B; |
|||
float c = MathF.Sqrt((a * a) + (b * b)); |
|||
float hRadians = MathF.Atan2(b, a); |
|||
float hDegrees = GeometryUtilities.RadianToDegree(hRadians); |
|||
|
|||
// Wrap the angle round at 360.
|
|||
hDegrees %= 360; |
|||
|
|||
// Make sure it's not negative.
|
|||
while (hDegrees < 0) |
|||
{ |
|||
hDegrees += 360; |
|||
} |
|||
|
|||
return new CieLch(l, c, hDegrees, input.WhitePoint); |
|||
} |
|||
} |
|||
@ -1,43 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLab"/> to <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
internal static class CieLabToCieXyzConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieLab"/> input to an instance of <see cref="CieXyz"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static CieXyz Convert(in CieLab input) |
|||
{ |
|||
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html
|
|||
float l = input.L, a = input.A, b = input.B; |
|||
float fy = (l + 16) / 116F; |
|||
float fx = (a / 500F) + fy; |
|||
float fz = fy - (b / 200F); |
|||
|
|||
float fx3 = Numerics.Pow3(fx); |
|||
float fz3 = Numerics.Pow3(fz); |
|||
|
|||
float xr = fx3 > CieConstants.Epsilon ? fx3 : ((116F * fx) - 16F) / CieConstants.Kappa; |
|||
float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? Numerics.Pow3((l + 16F) / 116F) : l / CieConstants.Kappa; |
|||
float zr = fz3 > CieConstants.Epsilon ? fz3 : ((116F * fz) - 16F) / CieConstants.Kappa; |
|||
|
|||
Vector3 wxyz = new(input.WhitePoint.X, input.WhitePoint.Y, input.WhitePoint.Z); |
|||
|
|||
// Avoids XYZ coordinates out range (restricted by 0 and XYZ reference white)
|
|||
Vector3 xyzr = Vector3.Clamp(new Vector3(xr, yr, zr), Vector3.Zero, Vector3.One); |
|||
|
|||
Vector3 xyz = xyzr * wxyz; |
|||
return new CieXyz(xyz); |
|||
} |
|||
} |
|||
@ -1,31 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLch"/> to <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
internal static class CieLchuvToCieLuvConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieLchuv"/> input to an instance of <see cref="CieLuv"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static CieLuv Convert(in CieLchuv input) |
|||
{ |
|||
// Conversion algorithm described here:
|
|||
// https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29
|
|||
float l = input.L, c = input.C, hDegrees = input.H; |
|||
float hRadians = GeometryUtilities.DegreeToRadian(hDegrees); |
|||
|
|||
float u = c * MathF.Cos(hRadians); |
|||
float v = c * MathF.Sin(hRadians); |
|||
|
|||
return new CieLuv(l, u, v, input.WhitePoint); |
|||
} |
|||
} |
|||
@ -1,39 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLab"/> to <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
internal static class CieLuvToCieLchuvConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieLuv"/> input to an instance of <see cref="CieLchuv"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static CieLchuv Convert(in CieLuv input) |
|||
{ |
|||
// Conversion algorithm described here:
|
|||
// https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29
|
|||
float l = input.L, a = input.U, b = input.V; |
|||
float c = MathF.Sqrt((a * a) + (b * b)); |
|||
float hRadians = MathF.Atan2(b, a); |
|||
float hDegrees = GeometryUtilities.RadianToDegree(hRadians); |
|||
|
|||
// Wrap the angle round at 360.
|
|||
hDegrees %= 360; |
|||
|
|||
// Make sure it's not negative.
|
|||
while (hDegrees < 0) |
|||
{ |
|||
hDegrees += 360; |
|||
} |
|||
|
|||
return new CieLchuv(l, c, hDegrees, input.WhitePoint); |
|||
} |
|||
} |
|||
@ -1,73 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLuv"/> to <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
internal static class CieLuvToCieXyzConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieLuv"/> input to an instance of <see cref="CieXyz"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
public static CieXyz Convert(in CieLuv input) |
|||
{ |
|||
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Luv_to_XYZ.html
|
|||
float l = input.L, u = input.U, v = input.V; |
|||
|
|||
float u0 = ComputeU0(input.WhitePoint); |
|||
float v0 = ComputeV0(input.WhitePoint); |
|||
|
|||
float y = l > CieConstants.Kappa * CieConstants.Epsilon |
|||
? Numerics.Pow3((l + 16) / 116) |
|||
: l / CieConstants.Kappa; |
|||
|
|||
float a = ((52 * l / (u + (13 * l * u0))) - 1) / 3; |
|||
float b = -5 * y; |
|||
const float c = -0.3333333F; |
|||
float d = y * ((39 * l / (v + (13 * l * v0))) - 5); |
|||
|
|||
float x = (d - b) / (a - c); |
|||
float z = (x * a) + b; |
|||
|
|||
if (float.IsNaN(x) || x < 0) |
|||
{ |
|||
x = 0; |
|||
} |
|||
|
|||
if (float.IsNaN(y) || y < 0) |
|||
{ |
|||
y = 0; |
|||
} |
|||
|
|||
if (float.IsNaN(z) || z < 0) |
|||
{ |
|||
z = 0; |
|||
} |
|||
|
|||
return new CieXyz(x, y, z); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Calculates the blue-yellow chromacity based on the given whitepoint.
|
|||
/// </summary>
|
|||
/// <param name="input">The whitepoint</param>
|
|||
/// <returns>The <see cref="float"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
private static float ComputeU0(in CieXyz input) |
|||
=> (4 * input.X) / (input.X + (15 * input.Y) + (3 * input.Z)); |
|||
|
|||
/// <summary>
|
|||
/// Calculates the red-green chromacity based on the given whitepoint.
|
|||
/// </summary>
|
|||
/// <param name="input">The whitepoint</param>
|
|||
/// <returns>The <see cref="float"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
private static float ComputeV0(in CieXyz input) |
|||
=> (9 * input.Y) / (input.X + (15 * input.Y) + (3 * input.Z)); |
|||
} |
|||
@ -1,52 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between CIE XYZ and CIE xyY.
|
|||
/// <see href="http://www.brucelindbloom.com/"/> for formulas.
|
|||
/// </summary>
|
|||
internal static class CieXyzAndCieXyyConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieXyz"/> input to an instance of <see cref="CieXyy"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static CieXyy Convert(in CieXyz input) |
|||
{ |
|||
float x = input.X / (input.X + input.Y + input.Z); |
|||
float y = input.Y / (input.X + input.Y + input.Z); |
|||
|
|||
if (float.IsNaN(x) || float.IsNaN(y)) |
|||
{ |
|||
return new CieXyy(0, 0, input.Y); |
|||
} |
|||
|
|||
return new CieXyy(x, y, input.Y); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieXyy"/> input to an instance of <see cref="CieXyz"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static CieXyz Convert(in CieXyy input) |
|||
{ |
|||
if (MathF.Abs(input.Y) < Constants.Epsilon) |
|||
{ |
|||
return new CieXyz(0, 0, input.Yl); |
|||
} |
|||
|
|||
float x = (input.X * input.Yl) / input.Y; |
|||
float y = input.Yl; |
|||
float z = ((1 - input.X - input.Y) * y) / input.Y; |
|||
|
|||
return new CieXyz(x, y, z); |
|||
} |
|||
} |
|||
@ -1,44 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// The base class for converting between <see cref="HunterLab"/> and <see cref="CieXyz"/> color spaces.
|
|||
/// </summary>
|
|||
internal abstract class CieXyzAndHunterLabConverterBase |
|||
{ |
|||
/// <summary>
|
|||
/// Returns the Ka coefficient that depends upon the whitepoint illuminant.
|
|||
/// </summary>
|
|||
/// <param name="whitePoint">The whitepoint</param>
|
|||
/// <returns>The <see cref="float"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float ComputeKa(CieXyz whitePoint) |
|||
{ |
|||
if (whitePoint.Equals(Illuminants.C)) |
|||
{ |
|||
return 175F; |
|||
} |
|||
|
|||
return 100F * (175F / 198.04F) * (whitePoint.X + whitePoint.Y); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the Kb coefficient that depends upon the whitepoint illuminant.
|
|||
/// </summary>
|
|||
/// <param name="whitePoint">The whitepoint</param>
|
|||
/// <returns>The <see cref="float"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float ComputeKb(CieXyz whitePoint) |
|||
{ |
|||
if (whitePoint == Illuminants.C) |
|||
{ |
|||
return 70F; |
|||
} |
|||
|
|||
return 100F * (70F / 218.11F) * (whitePoint.Y + whitePoint.Z); |
|||
} |
|||
} |
|||
@ -1,69 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between <see cref="CieXyz"/> and <see cref="Lms"/>
|
|||
/// </summary>
|
|||
internal sealed class CieXyzAndLmsConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Default transformation matrix used, when no other is set. (Bradford)
|
|||
/// <see cref="LmsAdaptationMatrix"/>
|
|||
/// </summary>
|
|||
public static readonly Matrix4x4 DefaultTransformationMatrix = LmsAdaptationMatrix.Bradford; |
|||
|
|||
private Matrix4x4 inverseTransformationMatrix; |
|||
private Matrix4x4 transformationMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzAndLmsConverter"/> class.
|
|||
/// </summary>
|
|||
public CieXyzAndLmsConverter() |
|||
: this(DefaultTransformationMatrix) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzAndLmsConverter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="transformationMatrix">
|
|||
/// Definition of the cone response domain (see <see cref="LmsAdaptationMatrix"/>),
|
|||
/// if not set <see cref="DefaultTransformationMatrix"/> will be used.
|
|||
/// </param>
|
|||
public CieXyzAndLmsConverter(Matrix4x4 transformationMatrix) |
|||
{ |
|||
this.transformationMatrix = transformationMatrix; |
|||
Matrix4x4.Invert(this.transformationMatrix, out this.inverseTransformationMatrix); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieXyz"/> input to an instance of <see cref="Lms"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Lms Convert(in CieXyz input) |
|||
{ |
|||
Vector3 vector = Vector3.Transform(input.ToVector3(), this.transformationMatrix); |
|||
|
|||
return new Lms(vector); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="Lms"/> input to an instance of <see cref="CieXyz"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieXyz Convert(in Lms input) |
|||
{ |
|||
Vector3 vector = Vector3.Transform(input.ToVector3(), this.inverseTransformationMatrix); |
|||
|
|||
return new CieXyz(vector); |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieXyz"/> to <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
internal sealed class CieXyzToCieLabConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToCieLabConverter"/> class.
|
|||
/// </summary>
|
|||
public CieXyzToCieLabConverter() |
|||
: this(CieLab.DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToCieLabConverter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="labWhitePoint">The target reference lab white point</param>
|
|||
public CieXyzToCieLabConverter(CieXyz labWhitePoint) => this.LabWhitePoint = labWhitePoint; |
|||
|
|||
/// <summary>
|
|||
/// Gets the target reference whitepoint. When not set, <see cref="CieLab.DefaultWhitePoint"/> is used.
|
|||
/// </summary>
|
|||
public CieXyz LabWhitePoint { get; } |
|||
|
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieXyz"/> input to an instance of <see cref="CieLab"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public CieLab Convert(in CieXyz input) |
|||
{ |
|||
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
|
|||
float wx = this.LabWhitePoint.X, wy = this.LabWhitePoint.Y, wz = this.LabWhitePoint.Z; |
|||
|
|||
float xr = input.X / wx, yr = input.Y / wy, zr = input.Z / wz; |
|||
|
|||
const float inv116 = 1 / 116F; |
|||
|
|||
float fx = xr > CieConstants.Epsilon ? MathF.Pow(xr, 0.3333333F) : ((CieConstants.Kappa * xr) + 16F) * inv116; |
|||
float fy = yr > CieConstants.Epsilon ? MathF.Pow(yr, 0.3333333F) : ((CieConstants.Kappa * yr) + 16F) * inv116; |
|||
float fz = zr > CieConstants.Epsilon ? MathF.Pow(zr, 0.3333333F) : ((CieConstants.Kappa * zr) + 16F) * inv116; |
|||
|
|||
float l = (116F * fy) - 16F; |
|||
float a = 500F * (fx - fy); |
|||
float b = 200F * (fy - fz); |
|||
|
|||
return new CieLab(l, a, b, this.LabWhitePoint); |
|||
} |
|||
} |
|||
@ -1,86 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieXyz"/> to <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
internal sealed class CieXyzToCieLuvConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToCieLuvConverter"/> class.
|
|||
/// </summary>
|
|||
public CieXyzToCieLuvConverter() |
|||
: this(CieLuv.DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToCieLuvConverter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="luvWhitePoint">The target reference luv white point</param>
|
|||
public CieXyzToCieLuvConverter(CieXyz luvWhitePoint) => this.LuvWhitePoint = luvWhitePoint; |
|||
|
|||
/// <summary>
|
|||
/// Gets the target reference whitepoint. When not set, <see cref="CieLuv.DefaultWhitePoint"/> is used.
|
|||
/// </summary>
|
|||
public CieXyz LuvWhitePoint { get; } |
|||
|
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieXyz"/> input to an instance of <see cref="CieLuv"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
public CieLuv Convert(in CieXyz input) |
|||
{ |
|||
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Luv.html
|
|||
float yr = input.Y / this.LuvWhitePoint.Y; |
|||
float up = ComputeUp(input); |
|||
float vp = ComputeVp(input); |
|||
float upr = ComputeUp(this.LuvWhitePoint); |
|||
float vpr = ComputeVp(this.LuvWhitePoint); |
|||
|
|||
float l = yr > CieConstants.Epsilon ? ((116 * MathF.Pow(yr, 0.3333333F)) - 16F) : (CieConstants.Kappa * yr); |
|||
|
|||
if (float.IsNaN(l) || l < 0) |
|||
{ |
|||
l = 0; |
|||
} |
|||
|
|||
float u = 13 * l * (up - upr); |
|||
float v = 13 * l * (vp - vpr); |
|||
|
|||
if (float.IsNaN(u)) |
|||
{ |
|||
u = 0; |
|||
} |
|||
|
|||
if (float.IsNaN(v)) |
|||
{ |
|||
v = 0; |
|||
} |
|||
|
|||
return new CieLuv(l, u, v, this.LuvWhitePoint); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Calculates the blue-yellow chromacity based on the given whitepoint.
|
|||
/// </summary>
|
|||
/// <param name="input">The whitepoint</param>
|
|||
/// <returns>The <see cref="float"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static float ComputeUp(in CieXyz input) |
|||
=> (4 * input.X) / (input.X + (15 * input.Y) + (3 * input.Z)); |
|||
|
|||
/// <summary>
|
|||
/// Calculates the red-green chromacity based on the given whitepoint.
|
|||
/// </summary>
|
|||
/// <param name="input">The whitepoint</param>
|
|||
/// <returns>The <see cref="float"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
private static float ComputeVp(in CieXyz input) |
|||
=> (9 * input.Y) / (input.X + (15 * input.Y) + (3 * input.Z)); |
|||
} |
|||
@ -1,65 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between <see cref="CieXyz"/> and <see cref="HunterLab"/>
|
|||
/// </summary>
|
|||
internal sealed class CieXyzToHunterLabConverter : CieXyzAndHunterLabConverterBase |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToHunterLabConverter"/> class.
|
|||
/// </summary>
|
|||
public CieXyzToHunterLabConverter() |
|||
: this(HunterLab.DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToHunterLabConverter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="labWhitePoint">The hunter Lab white point.</param>
|
|||
public CieXyzToHunterLabConverter(CieXyz labWhitePoint) => this.HunterLabWhitePoint = labWhitePoint; |
|||
|
|||
/// <summary>
|
|||
/// Gets the target reference white. When not set, <see cref="HunterLab.DefaultWhitePoint"/> is used.
|
|||
/// </summary>
|
|||
public CieXyz HunterLabWhitePoint { get; } |
|||
|
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieXyz"/> input to an instance of <see cref="HunterLab"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public HunterLab Convert(in CieXyz input) |
|||
{ |
|||
// Conversion algorithm described here: http://en.wikipedia.org/wiki/Lab_color_space#Hunter_Lab
|
|||
float x = input.X, y = input.Y, z = input.Z; |
|||
float xn = this.HunterLabWhitePoint.X, yn = this.HunterLabWhitePoint.Y, zn = this.HunterLabWhitePoint.Z; |
|||
|
|||
float ka = ComputeKa(this.HunterLabWhitePoint); |
|||
float kb = ComputeKb(this.HunterLabWhitePoint); |
|||
|
|||
float yByYn = y / yn; |
|||
float sqrtYbyYn = MathF.Sqrt(yByYn); |
|||
float l = 100 * sqrtYbyYn; |
|||
float a = ka * (((x / xn) - yByYn) / sqrtYbyYn); |
|||
float b = kb * ((yByYn - (z / zn)) / sqrtYbyYn); |
|||
|
|||
if (float.IsNaN(a)) |
|||
{ |
|||
a = 0; |
|||
} |
|||
|
|||
if (float.IsNaN(b)) |
|||
{ |
|||
b = 0; |
|||
} |
|||
|
|||
return new HunterLab(l, a, b, this.HunterLabWhitePoint); |
|||
} |
|||
} |
|||
@ -1,55 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between <see cref="CieXyz"/> and <see cref="LinearRgb"/>
|
|||
/// </summary>
|
|||
internal sealed class CieXyzToLinearRgbConverter : LinearRgbAndCieXyzConverterBase |
|||
{ |
|||
private readonly Matrix4x4 conversionMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToLinearRgbConverter"/> class.
|
|||
/// </summary>
|
|||
public CieXyzToLinearRgbConverter() |
|||
: this(Rgb.DefaultWorkingSpace) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToLinearRgbConverter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="workingSpace">The target working space.</param>
|
|||
public CieXyzToLinearRgbConverter(RgbWorkingSpace workingSpace) |
|||
{ |
|||
this.TargetWorkingSpace = workingSpace; |
|||
|
|||
// Gets the inverted Rgb -> Xyz matrix
|
|||
Matrix4x4.Invert(GetRgbToCieXyzMatrix(workingSpace), out Matrix4x4 inverted); |
|||
|
|||
this.conversionMatrix = inverted; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the target working space.
|
|||
/// </summary>
|
|||
public RgbWorkingSpace TargetWorkingSpace { get; } |
|||
|
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="CieXyz"/> input to an instance of <see cref="LinearRgb"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public LinearRgb Convert(in CieXyz input) |
|||
{ |
|||
var vector = Vector3.Transform(input.ToVector3(), this.conversionMatrix); |
|||
|
|||
return new LinearRgb(vector, this.TargetWorkingSpace); |
|||
} |
|||
} |
|||
@ -1,49 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between <see cref="Cmyk"/> and <see cref="Rgb"/>.
|
|||
/// </summary>
|
|||
internal static class CmykAndRgbConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="Cmyk"/> input to an instance of <see cref="Rgb"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Rgb Convert(in Cmyk input) |
|||
{ |
|||
Vector3 rgb = (Vector3.One - new Vector3(input.C, input.M, input.Y)) * (Vector3.One - new Vector3(input.K)); |
|||
return new Rgb(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="Rgb"/> input to an instance of <see cref="Cmyk"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Cmyk Convert(in Rgb input) |
|||
{ |
|||
// To CMY
|
|||
Vector3 cmy = Vector3.One - input.ToVector3(); |
|||
|
|||
// To CMYK
|
|||
Vector3 k = new(MathF.Min(cmy.X, MathF.Min(cmy.Y, cmy.Z))); |
|||
|
|||
if (MathF.Abs(k.X - 1F) < Constants.Epsilon) |
|||
{ |
|||
return new Cmyk(0, 0, 0, 1F); |
|||
} |
|||
|
|||
cmy = (cmy - k) / (Vector3.One - k); |
|||
|
|||
return new Cmyk(cmy.X, cmy.Y, cmy.Z, k.X); |
|||
} |
|||
} |
|||
@ -1,158 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between HSL and Rgb
|
|||
/// See <see href="http://www.poynton.com/PDFs/coloureq.pdf"/> for formulas.
|
|||
/// </summary>
|
|||
internal static class HslAndRgbConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="Hsl"/> input to an instance of <see cref="Rgb"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Rgb Convert(in Hsl input) |
|||
{ |
|||
float rangedH = input.H / 360F; |
|||
float r = 0; |
|||
float g = 0; |
|||
float b = 0; |
|||
float s = input.S; |
|||
float l = input.L; |
|||
|
|||
if (MathF.Abs(l) > Constants.Epsilon) |
|||
{ |
|||
if (MathF.Abs(s) < Constants.Epsilon) |
|||
{ |
|||
r = g = b = l; |
|||
} |
|||
else |
|||
{ |
|||
float temp2 = (l < .5F) ? l * (1F + s) : l + s - (l * s); |
|||
float temp1 = (2F * l) - temp2; |
|||
|
|||
r = GetColorComponent(temp1, temp2, rangedH + 0.3333333F); |
|||
g = GetColorComponent(temp1, temp2, rangedH); |
|||
b = GetColorComponent(temp1, temp2, rangedH - 0.3333333F); |
|||
} |
|||
} |
|||
|
|||
return new Rgb(r, g, b); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs the conversion from the <see cref="Rgb"/> input to an instance of <see cref="Hsl"/> type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Hsl Convert(in Rgb input) |
|||
{ |
|||
float r = input.R; |
|||
float g = input.G; |
|||
float b = input.B; |
|||
|
|||
float max = MathF.Max(r, MathF.Max(g, b)); |
|||
float min = MathF.Min(r, MathF.Min(g, b)); |
|||
float chroma = max - min; |
|||
float h = 0F; |
|||
float s = 0F; |
|||
float l = (max + min) / 2F; |
|||
|
|||
if (MathF.Abs(chroma) < Constants.Epsilon) |
|||
{ |
|||
return new Hsl(0F, s, l); |
|||
} |
|||
|
|||
if (MathF.Abs(r - max) < Constants.Epsilon) |
|||
{ |
|||
h = (g - b) / chroma; |
|||
} |
|||
else if (MathF.Abs(g - max) < Constants.Epsilon) |
|||
{ |
|||
h = 2F + ((b - r) / chroma); |
|||
} |
|||
else if (MathF.Abs(b - max) < Constants.Epsilon) |
|||
{ |
|||
h = 4F + ((r - g) / chroma); |
|||
} |
|||
|
|||
h *= 60F; |
|||
if (h < 0F) |
|||
{ |
|||
h += 360F; |
|||
} |
|||
|
|||
if (l <= .5F) |
|||
{ |
|||
s = chroma / (max + min); |
|||
} |
|||
else |
|||
{ |
|||
s = chroma / (2F - max - min); |
|||
} |
|||
|
|||
return new Hsl(h, s, l); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the color component from the given values.
|
|||
/// </summary>
|
|||
/// <param name="first">The first value.</param>
|
|||
/// <param name="second">The second value.</param>
|
|||
/// <param name="third">The third value.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
private static float GetColorComponent(float first, float second, float third) |
|||
{ |
|||
third = MoveIntoRange(third); |
|||
if (third < 0.1666667F) |
|||
{ |
|||
return first + ((second - first) * 6F * third); |
|||
} |
|||
|
|||
if (third < .5F) |
|||
{ |
|||
return second; |
|||
} |
|||
|
|||
if (third < 0.6666667F) |
|||
{ |
|||
return first + ((second - first) * (0.6666667F - third) * 6F); |
|||
} |
|||
|
|||
return first; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Moves the specific value within the acceptable range for
|
|||
/// conversion.
|
|||
/// <remarks>Used for converting <see cref="Hsl"/> colors to this type.</remarks>
|
|||
/// </summary>
|
|||
/// <param name="value">The value to shift.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
private static float MoveIntoRange(float value) |
|||
{ |
|||
if (value < 0F) |
|||
{ |
|||
value++; |
|||
} |
|||
else if (value > 1F) |
|||
{ |
|||
value--; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue