mirror of https://github.com/SixLabors/ImageSharp
297 changed files with 28690 additions and 2351 deletions
@ -1,129 +1,129 @@ |
|||
// <copyright file="DrawImage.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using Drawing.Processors; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Image{TPixel}"/> type.
|
|||
/// </summary>
|
|||
public static partial class ImageExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="size">The size to draw the blended image.</param>
|
|||
/// <param name="location">The location to draw the blended image.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> DrawImage<TPixel>(this Image<TPixel> source, Image<TPixel> image, Size size, Point location, GraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
if (size == default(Size)) |
|||
{ |
|||
size = new Size(image.Width, image.Height); |
|||
} |
|||
|
|||
if (location == default(Point)) |
|||
{ |
|||
location = Point.Empty; |
|||
} |
|||
|
|||
source.ApplyProcessor(new DrawImageProcessor<TPixel>(image, size, location, options), source.Bounds); |
|||
return source; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Blend<TPixel>(this Image<TPixel> source, Image<TPixel> image, float percent) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
GraphicsOptions options = GraphicsOptions.Default; |
|||
options.BlendPercentage = percent; |
|||
return DrawImage(source, image, default(Size), default(Point), options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="blender">The blending mode.</param>
|
|||
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Blend<TPixel>(this Image<TPixel> source, Image<TPixel> image, PixelBlenderMode blender, float percent) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
GraphicsOptions options = GraphicsOptions.Default; |
|||
options.BlendPercentage = percent; |
|||
options.BlenderMode = blender; |
|||
return DrawImage(source, image, default(Size), default(Point), options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="options">The options, including the blending type and belnding amount.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Blend<TPixel>(this Image<TPixel> source, Image<TPixel> image, GraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return DrawImage(source, image, default(Size), default(Point), options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
|
|||
/// <param name="size">The size to draw the blended image.</param>
|
|||
/// <param name="location">The location to draw the blended image.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> DrawImage<TPixel>(this Image<TPixel> source, Image<TPixel> image, float percent, Size size, Point location) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
GraphicsOptions options = GraphicsOptions.Default; |
|||
options.BlendPercentage = percent; |
|||
return source.DrawImage(image, size, location, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="blender">The type of bending to apply.</param>
|
|||
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
|
|||
/// <param name="size">The size to draw the blended image.</param>
|
|||
/// <param name="location">The location to draw the blended image.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> DrawImage<TPixel>(this Image<TPixel> source, Image<TPixel> image, PixelBlenderMode blender, float percent, Size size, Point location) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
GraphicsOptions options = GraphicsOptions.Default; |
|||
options.BlenderMode = blender; |
|||
options.BlendPercentage = percent; |
|||
return source.DrawImage(image, size, location, options); |
|||
} |
|||
} |
|||
// <copyright file="DrawImage.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using Drawing.Processors; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Image{TPixel}"/> type.
|
|||
/// </summary>
|
|||
public static partial class ImageExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="size">The size to draw the blended image.</param>
|
|||
/// <param name="location">The location to draw the blended image.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> DrawImage<TPixel>(this Image<TPixel> source, Image<TPixel> image, Size size, Point location, GraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
if (size == default(Size)) |
|||
{ |
|||
size = new Size(image.Width, image.Height); |
|||
} |
|||
|
|||
if (location == default(Point)) |
|||
{ |
|||
location = Point.Empty; |
|||
} |
|||
|
|||
source.ApplyProcessor(new DrawImageProcessor<TPixel>(image, size, location, options), source.Bounds); |
|||
return source; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Blend<TPixel>(this Image<TPixel> source, Image<TPixel> image, float percent) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
GraphicsOptions options = GraphicsOptions.Default; |
|||
options.BlendPercentage = percent; |
|||
return DrawImage(source, image, default(Size), default(Point), options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="blender">The blending mode.</param>
|
|||
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Blend<TPixel>(this Image<TPixel> source, Image<TPixel> image, PixelBlenderMode blender, float percent) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
GraphicsOptions options = GraphicsOptions.Default; |
|||
options.BlendPercentage = percent; |
|||
options.BlenderMode = blender; |
|||
return DrawImage(source, image, default(Size), default(Point), options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="options">The options, including the blending type and belnding amount.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Blend<TPixel>(this Image<TPixel> source, Image<TPixel> image, GraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return DrawImage(source, image, default(Size), default(Point), options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
|
|||
/// <param name="size">The size to draw the blended image.</param>
|
|||
/// <param name="location">The location to draw the blended image.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> DrawImage<TPixel>(this Image<TPixel> source, Image<TPixel> image, float percent, Size size, Point location) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
GraphicsOptions options = GraphicsOptions.Default; |
|||
options.BlendPercentage = percent; |
|||
return source.DrawImage(image, size, location, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the given image together with the current one by blending their pixels.
|
|||
/// </summary>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="blender">The type of bending to apply.</param>
|
|||
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
|
|||
/// <param name="size">The size to draw the blended image.</param>
|
|||
/// <param name="location">The location to draw the blended image.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> DrawImage<TPixel>(this Image<TPixel> source, Image<TPixel> image, PixelBlenderMode blender, float percent, Size size, Point location) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
GraphicsOptions options = GraphicsOptions.Default; |
|||
options.BlenderMode = blender; |
|||
options.BlendPercentage = percent; |
|||
return source.DrawImage(image, size, location, options); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,247 @@ |
|||
// <copyright file="CieLch.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents the CIE L*C*h°, cylindrical form of the CIE L*a*b* 1976 color.
|
|||
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC"/>
|
|||
/// </summary>
|
|||
internal struct CieLch : IColorVector, IEquatable<CieLch>, IAlmostEquatable<CieLch, float> |
|||
{ |
|||
/// <summary>
|
|||
/// D50 standard illuminant.
|
|||
/// Used when reference white is not specified explicitly.
|
|||
/// </summary>
|
|||
public static readonly CieXyz DefaultWhitePoint = Illuminants.D50; |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="CieLch"/> that has L, C, H values set to zero.
|
|||
/// </summary>
|
|||
public static readonly CieLch Empty = default(CieLch); |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private readonly Vector3 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLch"/> 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(MethodImplOptions.AggressiveInlining)] |
|||
public CieLch(float l, float c, float h) |
|||
: this(new Vector3(l, c, h), DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLch"/> 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(MethodImplOptions.AggressiveInlining)] |
|||
public CieLch(float l, float c, float h, CieXyz whitePoint) |
|||
: this(new Vector3(l, c, h), whitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLch"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, c, h components.</param>
|
|||
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLch(Vector3 vector) |
|||
: this(vector, DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLch"/> 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(MethodImplOptions.AggressiveInlining)] |
|||
public CieLch(Vector3 vector, CieXyz whitePoint) |
|||
: this() |
|||
{ |
|||
this.backingVector = vector; |
|||
this.WhitePoint = whitePoint; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the reference white point of this color
|
|||
/// </summary>
|
|||
public CieXyz WhitePoint |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension.
|
|||
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
|
|||
/// </summary>
|
|||
public float L |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.X; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the a chroma component.
|
|||
/// <remarks>A value ranging from 0 to 100.</remarks>
|
|||
/// </summary>
|
|||
public float C |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the h° hue component in degrees.
|
|||
/// <remarks>A value ranging from 0 to 360.</remarks>
|
|||
/// </summary>
|
|||
public float H |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="CieLch"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector3 Vector |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLch"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="CieLch"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="CieLch"/> 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 ==(CieLch left, CieLch right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLch"/> objects for inequality
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="CieLch"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="CieLch"/> 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 !=(CieLch left, CieLch right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = this.WhitePoint.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.backingVector.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "CieLch [Empty]"; |
|||
} |
|||
|
|||
return $"CieLch [ L={this.L:#0.##}, C={this.C:#0.##}, H={this.H:#0.##}]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is CieLch) |
|||
{ |
|||
return this.Equals((CieLch)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(CieLch other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector) |
|||
&& this.WhitePoint.Equals(other.WhitePoint); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool AlmostEquals(CieLch other, float precision) |
|||
{ |
|||
var result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return this.WhitePoint.Equals(other.WhitePoint) |
|||
&& result.X <= precision |
|||
&& result.Y <= precision |
|||
&& result.Z <= precision; |
|||
} |
|||
|
|||
/// <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(MethodImplOptions.AggressiveInlining)] |
|||
public float Saturation() |
|||
{ |
|||
float result = 100 * (this.C / this.L); |
|||
|
|||
if (float.IsNaN(result)) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,247 @@ |
|||
// <copyright file="CieLchuv.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents the CIE L*C*h°, cylindrical form of the CIE L*u*v* 1976 color.
|
|||
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CieLchuv_or_CIEHLC"/>
|
|||
/// </summary>
|
|||
internal struct CieLchuv : IColorVector, IEquatable<CieLchuv>, IAlmostEquatable<CieLchuv, float> |
|||
{ |
|||
/// <summary>
|
|||
/// D50 standard illuminant.
|
|||
/// Used when reference white is not specified explicitly.
|
|||
/// </summary>
|
|||
public static readonly CieXyz DefaultWhitePoint = Illuminants.D65; |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="CieLchuv"/> that has L, C, H values set to zero.
|
|||
/// </summary>
|
|||
public static readonly CieLchuv Empty = default(CieLchuv); |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private readonly Vector3 backingVector; |
|||
|
|||
/// <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(MethodImplOptions.AggressiveInlining)] |
|||
public CieLchuv(float l, float c, float h) |
|||
: this(new Vector3(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(MethodImplOptions.AggressiveInlining)] |
|||
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(MethodImplOptions.AggressiveInlining)] |
|||
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(MethodImplOptions.AggressiveInlining)] |
|||
public CieLchuv(Vector3 vector, CieXyz whitePoint) |
|||
: this() |
|||
{ |
|||
this.backingVector = vector; |
|||
this.WhitePoint = whitePoint; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the reference white point of this color
|
|||
/// </summary>
|
|||
public CieXyz WhitePoint |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension.
|
|||
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
|
|||
/// </summary>
|
|||
public float L |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.X; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the a chroma component.
|
|||
/// <remarks>A value ranging from 0 to 100.</remarks>
|
|||
/// </summary>
|
|||
public float C |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the h° hue component in degrees.
|
|||
/// <remarks>A value ranging from 0 to 360.</remarks>
|
|||
/// </summary>
|
|||
public float H |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="CieLchuv"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector3 Vector |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector; |
|||
} |
|||
|
|||
/// <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>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(CieLchuv left, CieLchuv right) |
|||
{ |
|||
return 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>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(CieLchuv left, CieLchuv right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = this.WhitePoint.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.backingVector.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "CieLchuv [Empty]"; |
|||
} |
|||
|
|||
return $"CieLchuv [ L={this.L:#0.##}, C={this.C:#0.##}, H={this.H:#0.##}]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is CieLchuv) |
|||
{ |
|||
return this.Equals((CieLchuv)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(CieLchuv other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector) |
|||
&& this.WhitePoint.Equals(other.WhitePoint); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool AlmostEquals(CieLchuv other, float precision) |
|||
{ |
|||
var result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return this.WhitePoint.Equals(other.WhitePoint) |
|||
&& result.X <= precision |
|||
&& result.Y <= precision |
|||
&& result.Z <= precision; |
|||
} |
|||
|
|||
/// <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(MethodImplOptions.AggressiveInlining)] |
|||
public float Saturation() |
|||
{ |
|||
float result = 100 * (this.C / this.L); |
|||
|
|||
if (float.IsNaN(result)) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,229 @@ |
|||
// <copyright file="CieLuv.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <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>
|
|||
internal struct CieLuv : IColorVector, IEquatable<CieLuv>, IAlmostEquatable<CieLuv, float> |
|||
{ |
|||
/// <summary>
|
|||
/// D65 standard illuminant.
|
|||
/// Used when reference white is not specified explicitly.
|
|||
/// </summary>
|
|||
public static readonly CieXyz DefaultWhitePoint = Illuminants.D65; |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="CieLuv"/> that has L, U, and V values set to zero.
|
|||
/// </summary>
|
|||
public static readonly CieLuv Empty = default(CieLuv); |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private readonly Vector3 backingVector; |
|||
|
|||
/// <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(MethodImplOptions.AggressiveInlining)] |
|||
public CieLuv(float l, float u, float v) |
|||
: this(new Vector3(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(MethodImplOptions.AggressiveInlining)] |
|||
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(MethodImplOptions.AggressiveInlining)] |
|||
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(MethodImplOptions.AggressiveInlining)] |
|||
public CieLuv(Vector3 vector, CieXyz whitePoint) |
|||
: this() |
|||
{ |
|||
this.backingVector = vector; |
|||
this.WhitePoint = whitePoint; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the reference white point of this color
|
|||
/// </summary>
|
|||
public CieXyz WhitePoint |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension
|
|||
/// <remarks>A value usually ranging between 0 and 100.</remarks>
|
|||
/// </summary>
|
|||
public float L |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.X; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the blue-yellow chromaticity coordinate of the given whitepoint.
|
|||
/// <remarks>A value usually ranging between -100 and 100.</remarks>
|
|||
/// </summary>
|
|||
public float U |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the red-green chromaticity coordinate of the given whitepoint.
|
|||
/// <remarks>A value usually ranging between -100 and 100.</remarks>
|
|||
/// </summary>
|
|||
public float V |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="CieLuv"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector3 Vector |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector; |
|||
} |
|||
|
|||
/// <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) |
|||
{ |
|||
return 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) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = this.WhitePoint.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.backingVector.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "CieLuv [ Empty ]"; |
|||
} |
|||
|
|||
return $"CieLuv [ L={this.L:#0.##}, U={this.U:#0.##}, V={this.V:#0.##} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is CieLuv) |
|||
{ |
|||
return this.Equals((CieLuv)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(CieLuv other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector) |
|||
&& this.WhitePoint.Equals(other.WhitePoint); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool AlmostEquals(CieLuv other, float precision) |
|||
{ |
|||
var result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return this.WhitePoint.Equals(other.WhitePoint) |
|||
&& result.X <= precision |
|||
&& result.Y <= precision |
|||
&& result.Z <= precision; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,161 @@ |
|||
// <copyright file="CieXyChromaticityCoordinates.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents the coordinates of CIEXY chromaticity space
|
|||
/// </summary>
|
|||
internal struct CieXyChromaticityCoordinates : IEquatable<CieXyChromaticityCoordinates>, IAlmostEquatable<CieXyChromaticityCoordinates, float> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="CieXyChromaticityCoordinates"/> that has X, Y values set to zero.
|
|||
/// </summary>
|
|||
public static readonly CieXyChromaticityCoordinates Empty = default(CieXyChromaticityCoordinates); |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private readonly Vector2 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyChromaticityCoordinates"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">Chromaticity coordinate x (usually from 0 to 1)</param>
|
|||
/// <param name="y">Chromaticity coordinate y (usually from 0 to 1)</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyChromaticityCoordinates(float x, float y) |
|||
: this(new Vector2(x, y)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyChromaticityCoordinates"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the XY Chromaticity coordinates</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyChromaticityCoordinates(Vector2 vector) |
|||
{ |
|||
this.backingVector = vector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the chromaticity X-coordinate.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Ranges usually from 0 to 1.
|
|||
/// </remarks>
|
|||
public float X |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.X; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the chromaticity Y-coordinate
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Ranges usually from 0 to 1.
|
|||
/// </remarks>
|
|||
public float Y |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="CieXyChromaticityCoordinates"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieXyChromaticityCoordinates"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="CieXyChromaticityCoordinates"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="CieXyChromaticityCoordinates"/> 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 ==(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieXyChromaticityCoordinates"/> objects for inequality
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="CieXyChromaticityCoordinates"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="CieXyChromaticityCoordinates"/> 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 !=(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.backingVector.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "CieXyChromaticityCoordinates [Empty]"; |
|||
} |
|||
|
|||
return $"CieXyChromaticityCoordinates [ X={this.X:#0.##}, Y={this.Y:#0.##}]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is CieXyChromaticityCoordinates) |
|||
{ |
|||
return this.Equals((CieXyChromaticityCoordinates)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(CieXyChromaticityCoordinates other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool AlmostEquals(CieXyChromaticityCoordinates other, float precision) |
|||
{ |
|||
var result = Vector2.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return result.X <= precision |
|||
&& result.Y <= precision; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,179 @@ |
|||
// <copyright file="CieXyy.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents an CIE xyY 1931 color
|
|||
/// <see href="https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space"/>
|
|||
/// </summary>
|
|||
internal struct CieXyy : IColorVector, IEquatable<CieXyy>, IAlmostEquatable<CieXyy, float> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="CieXyy"/> that has X, Y, and Y values set to zero.
|
|||
/// </summary>
|
|||
public static readonly CieXyy Empty = default(CieXyy); |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private readonly Vector3 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyy"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The x chroma component.</param>
|
|||
/// <param name="y">The y chroma component.</param>
|
|||
/// <param name="yl">The y luminance component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyy(float x, float y, float yl) |
|||
: this(new Vector3(x, y, yl)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyy"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the x, y, Y components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyy(Vector3 vector) |
|||
: this() |
|||
{ |
|||
// Not clamping as documentation about this space seems to indicate "usual" ranges
|
|||
this.backingVector = vector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the X chrominance component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float X |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.X; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the Y chrominance component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float Y |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the Y luminance component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float Yl |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="CieXyy"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector3 Vector |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieXyy"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="CieXyy"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="CieXyy"/> 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 ==(CieXyy left, CieXyy right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieXyy"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="CieXyy"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="CieXyy"/> 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 !=(CieXyy left, CieXyy right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.backingVector.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "CieXyy [ Empty ]"; |
|||
} |
|||
|
|||
return $"CieXyy [ X={this.X:#0.##}, Y={this.Y:#0.##}, Yl={this.Yl:#0.##} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is CieXyy) |
|||
{ |
|||
return this.Equals((CieXyy)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(CieXyy other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool AlmostEquals(CieXyy other, float precision) |
|||
{ |
|||
var result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return result.X <= precision |
|||
&& result.Y <= precision |
|||
&& result.Z <= precision; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// <copyright file="CieConstants.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
/// <summary>
|
|||
/// Constants use for Cie conversion calculations
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html"/>
|
|||
/// </summary>
|
|||
internal static class CieConstants |
|||
{ |
|||
/// <summary>
|
|||
/// 216F / 24389F
|
|||
/// </summary>
|
|||
public const float Epsilon = 0.008856452F; |
|||
|
|||
/// <summary>
|
|||
/// 24389F / 27F
|
|||
/// </summary>
|
|||
public const float Kappa = 903.2963F; |
|||
} |
|||
} |
|||
@ -0,0 +1,198 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using System; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Rgb; |
|||
|
|||
/// <content>
|
|||
/// Performs chromatic adaptation on the various color spaces.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// Performs chromatic adaptation of given <see cref="CieXyz"/> color.
|
|||
/// Target white point is <see cref="WhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <param name="sourceWhitePoint">The white point to adapt for</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieXyz Adapt(CieXyz color, CieXyz sourceWhitePoint) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
Guard.NotNull(sourceWhitePoint, nameof(sourceWhitePoint)); |
|||
|
|||
if (!this.IsChromaticAdaptationPerformed) |
|||
{ |
|||
throw new InvalidOperationException("Cannot perform chromatic adaptation, provide a chromatic adaptation method and white point."); |
|||
} |
|||
|
|||
return this.ChromaticAdaptation.Transform(color, sourceWhitePoint, this.WhitePoint); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adapts <see cref="CieLab"/> color from the source white point to white point set in <see cref="TargetLabWhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieLab Adapt(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
if (!this.IsChromaticAdaptationPerformed) |
|||
{ |
|||
throw new InvalidOperationException("Cannot perform chromatic adaptation, provide a chromatic adaptation method and white point."); |
|||
} |
|||
|
|||
if (color.WhitePoint.Equals(this.TargetLabWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
CieXyz 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="TargetLabWhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieLch Adapt(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
if (!this.IsChromaticAdaptationPerformed) |
|||
{ |
|||
throw new InvalidOperationException("Cannot perform chromatic adaptation, provide a chromatic adaptation method and white point."); |
|||
} |
|||
|
|||
if (color.WhitePoint.Equals(this.TargetLabWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
CieLab 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="TargetLabWhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieLchuv Adapt(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
if (!this.IsChromaticAdaptationPerformed) |
|||
{ |
|||
throw new InvalidOperationException("Cannot perform chromatic adaptation, provide a chromatic adaptation method and white point."); |
|||
} |
|||
|
|||
if (color.WhitePoint.Equals(this.TargetLabWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
CieLuv 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="TargetLuvWhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public CieLuv Adapt(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
if (!this.IsChromaticAdaptationPerformed) |
|||
{ |
|||
throw new InvalidOperationException("Cannot perform chromatic adaptation, provide a chromatic adaptation method and white point."); |
|||
} |
|||
|
|||
if (color.WhitePoint.Equals(this.TargetLuvWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
CieXyz 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="TargetHunterLabWhitePoint"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public HunterLab Adapt(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
if (!this.IsChromaticAdaptationPerformed) |
|||
{ |
|||
throw new InvalidOperationException("Cannot perform chromatic adaptation, provide a chromatic adaptation method and white point."); |
|||
} |
|||
|
|||
if (color.WhitePoint.Equals(this.TargetHunterLabWhitePoint)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
CieXyz 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="TargetRgbWorkingSpace"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public LinearRgb Adapt(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
if (!this.IsChromaticAdaptationPerformed) |
|||
{ |
|||
throw new InvalidOperationException("Cannot perform chromatic adaptation, provide a chromatic adaptation method and white point."); |
|||
} |
|||
|
|||
if (color.WorkingSpace.Equals(this.TargetRgbWorkingSpace)) |
|||
{ |
|||
return color; |
|||
} |
|||
|
|||
// Conversion to XYZ
|
|||
LinearRgbToCieXyzConverter converterToXYZ = this.GetLinearRgbToCieXyzConverter(color.WorkingSpace); |
|||
CieXyz unadapted = converterToXYZ.Convert(color); |
|||
|
|||
// Adaptation
|
|||
CieXyz adapted = this.ChromaticAdaptation.Transform(unadapted, color.WorkingSpace.WhitePoint, this.TargetRgbWorkingSpace.WhitePoint); |
|||
|
|||
// Conversion back to RGB
|
|||
CieXyzToLinearRgbConverter converterToRGB = this.GetCieXyxToLinearRgbConverter(this.TargetRgbWorkingSpace); |
|||
return converterToRGB.Convert(adapted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adapts an <see cref="Rgb"/> color from the source working space to working space set in <see cref="TargetRgbWorkingSpace"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The color to adapt</param>
|
|||
/// <returns>The adapted color</returns>
|
|||
public Rgb Adapt(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
LinearRgb linearInput = this.ToLinearRgb(color); |
|||
LinearRgb linearOutput = this.Adapt(linearInput); |
|||
return this.ToRgb(linearOutput); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,205 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.CieLab; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.CieLch; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieLab"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// The converter for converting between CieLch to CieLab.
|
|||
/// </summary>
|
|||
private static readonly CieLchToCieLabConverter CieLchToCieLabConverter = new CieLchToCieLabConverter(); |
|||
|
|||
/// <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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion (perserving white point)
|
|||
CieLab unadapted = CieLchToCieLabConverter.Convert(color); |
|||
|
|||
if (!this.IsChromaticAdaptationPerformed) |
|||
{ |
|||
return unadapted; |
|||
} |
|||
|
|||
// Adaptation
|
|||
return this.Adapt(unadapted); |
|||
} |
|||
|
|||
/// <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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Adaptation
|
|||
CieXyz adapted = !this.WhitePoint.Equals(this.TargetLabWhitePoint) && this.IsChromaticAdaptationPerformed |
|||
? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetLabWhitePoint) |
|||
: color; |
|||
|
|||
// Conversion
|
|||
CieXyzToCieLabConverter converter = new CieXyzToCieLabConverter(this.TargetLabWhitePoint); |
|||
return converter.Convert(adapted); |
|||
} |
|||
|
|||
/// <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(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <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(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <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(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <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(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <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(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
|
|||
/// <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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLab(xyzColor); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,192 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.CieLch; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieLch"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// The converter for converting between CieLab to CieLch.
|
|||
/// </summary>
|
|||
private static readonly CieLabToCieLchConverter CieLabToCieLchConverter = new CieLabToCieLchConverter(); |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Adaptation
|
|||
CieLab adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color; |
|||
|
|||
// Conversion
|
|||
return CieLabToCieLchConverter.Convert(adapted); |
|||
} |
|||
|
|||
/// <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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieLab labColor = this.ToCieLab(color); |
|||
return this.ToCieLch(labColor); |
|||
} |
|||
|
|||
/// <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(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <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(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <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(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <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(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <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(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
|
|||
/// <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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLch(xyzColor); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,192 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuv; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieLchuv"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// The converter for converting between CieLab to CieLchuv.
|
|||
/// </summary>
|
|||
private static readonly CieLuvToCieLchuvConverter CieLuvToCieLchuvConverter = new CieLuvToCieLchuvConverter(); |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Adaptation
|
|||
CieLuv adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color; |
|||
|
|||
// Conversion
|
|||
return CieLuvToCieLchuvConverter.Convert(adapted); |
|||
} |
|||
|
|||
/// <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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieLab labColor = this.ToCieLab(color); |
|||
return this.ToCieLchuv(labColor); |
|||
} |
|||
|
|||
/// <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(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
CieXyz xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLchuv(xyzColor); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,202 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuv; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.CieLuv; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieLuv"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
private static readonly CieLchuvToCieLuvConverter CieLchuvToCieLuvConverter = new CieLchuvToCieLuvConverter(); |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion (perserving white point)
|
|||
CieLuv unadapted = CieLchuvToCieLuvConverter.Convert(color); |
|||
|
|||
if (!this.IsChromaticAdaptationPerformed) |
|||
{ |
|||
return unadapted; |
|||
} |
|||
|
|||
// Adaptation
|
|||
return this.Adapt(unadapted); |
|||
} |
|||
|
|||
/// <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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Adaptation
|
|||
CieXyz adapted = !this.WhitePoint.Equals(this.TargetLabWhitePoint) && this.IsChromaticAdaptationPerformed |
|||
? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetLabWhitePoint) |
|||
: color; |
|||
|
|||
// Conversion
|
|||
var converter = new CieXyzToCieLuvConverter(this.TargetLuvWhitePoint); |
|||
return converter.Convert(adapted); |
|||
} |
|||
|
|||
/// <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(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
|
|||
/// <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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToCieLuv(xyzColor); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,197 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.CieXyy; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieXyy"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
private static readonly CieXyzAndCieXyyConverter CieXyzAndCieXyyConverter = new CieXyzAndCieXyyConverter(); |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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 CieXyy ToCieXyy(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
return CieXyzAndCieXyyConverter.Convert(color); |
|||
} |
|||
|
|||
/// <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(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
|
|||
/// <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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCieXyy(xyzColor); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,253 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.CieLab; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.CieLuv; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.HunterLab; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Rgb; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="CieXyz"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
private static readonly CieLabToCieXyzConverter CieLabToCieXyzConverter = new CieLabToCieXyzConverter(); |
|||
|
|||
private static readonly CieLuvToCieXyzConverter CieLuvToCieXyzConverter = new CieLuvToCieXyzConverter(); |
|||
|
|||
private static readonly HunterLabToCieXyzConverter HunterLabToCieXyzConverter = new HunterLabToCieXyzConverter(); |
|||
|
|||
private LinearRgbToCieXyzConverter linearRgbToCieXyzConverter; |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
CieXyz unadapted = CieLabToCieXyzConverter.Convert(color); |
|||
|
|||
// Adaptation
|
|||
CieXyz adapted = color.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed |
|||
? unadapted |
|||
: this.Adapt(unadapted, color.WhitePoint); |
|||
|
|||
return adapted; |
|||
} |
|||
|
|||
/// <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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion to Lab
|
|||
CieLab labColor = CieLchToCieLabConverter.Convert(color); |
|||
|
|||
// Conversion to XYZ (incl. adaptation)
|
|||
return this.ToCieXyz(labColor); |
|||
} |
|||
|
|||
/// <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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion to Luv
|
|||
CieLuv luvColor = CieLchuvToCieLuvConverter.Convert(color); |
|||
|
|||
// Conversion to XYZ (incl. adaptation)
|
|||
return this.ToCieXyz(luvColor); |
|||
} |
|||
|
|||
/// <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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
CieXyz unadapted = CieLuvToCieXyzConverter.Convert(color); |
|||
|
|||
// Adaptation
|
|||
CieXyz adapted = color.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed |
|||
? unadapted |
|||
: this.Adapt(unadapted, color.WhitePoint); |
|||
|
|||
return adapted; |
|||
} |
|||
|
|||
/// <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 CieXyz ToCieXyz(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
return CieXyzAndCieXyyConverter.Convert(color); |
|||
} |
|||
|
|||
/// <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(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return this.ToCieXyz(rgb); |
|||
} |
|||
|
|||
/// <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(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return this.ToCieXyz(rgb); |
|||
} |
|||
|
|||
/// <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(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return this.ToCieXyz(rgb); |
|||
} |
|||
|
|||
/// <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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
CieXyz unadapted = HunterLabToCieXyzConverter.Convert(color); |
|||
|
|||
// Adaptation
|
|||
CieXyz adapted = color.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed |
|||
? unadapted |
|||
: this.Adapt(unadapted, color.WhitePoint); |
|||
|
|||
return adapted; |
|||
} |
|||
|
|||
/// <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(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
LinearRgbToCieXyzConverter converter = this.GetLinearRgbToCieXyzConverter(color.WorkingSpace); |
|||
CieXyz unadapted = converter.Convert(color); |
|||
|
|||
// Adaptation
|
|||
return color.WorkingSpace.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed |
|||
? unadapted |
|||
: this.Adapt(unadapted, color.WorkingSpace.WhitePoint); |
|||
} |
|||
|
|||
/// <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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
return this.cachedCieXyzAndLmsConverter.Convert(color); |
|||
} |
|||
|
|||
/// <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(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
LinearRgb linear = RgbToLinearRgbConverter.Convert(color); |
|||
return this.ToCieXyz(linear); |
|||
} |
|||
|
|||
/// <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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return this.ToCieXyz(rgb); |
|||
} |
|||
|
|||
/// <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 LinearRgbToCieXyzConverter GetLinearRgbToCieXyzConverter(IRgbWorkingSpace workingSpace) |
|||
{ |
|||
if (this.linearRgbToCieXyzConverter != null && this.linearRgbToCieXyzConverter.SourceWorkingSpace.Equals(workingSpace)) |
|||
{ |
|||
return this.linearRgbToCieXyzConverter; |
|||
} |
|||
|
|||
return this.linearRgbToCieXyzConverter = new LinearRgbToCieXyzConverter(workingSpace); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,198 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Cmyk; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="Cmyk"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
private static readonly CmykAndRgbConverter CmykAndRgbConverter = new CmykAndRgbConverter(); |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return CmykAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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 Cmyk ToCmyk(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return CmykAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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 Cmyk ToCmyk(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return CmykAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <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 Cmyk ToCmyk(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return CmykAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToCmyk(xyzColor); |
|||
} |
|||
|
|||
/// <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 Cmyk ToCmyk(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
return CmykAndRgbConverter.Convert(color); |
|||
} |
|||
|
|||
/// <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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return CmykAndRgbConverter.Convert(rgb); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,198 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Hsl; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="Hsl"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
private static readonly HslAndRgbConverter HslAndRgbConverter = new HslAndRgbConverter(); |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return HslAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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 Hsl ToHsl(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return HslAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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 Hsl ToHsl(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return HslAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <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 Hsl ToHsl(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return HslAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsl(xyzColor); |
|||
} |
|||
|
|||
/// <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 Hsl ToHsl(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
return HslAndRgbConverter.Convert(color); |
|||
} |
|||
|
|||
/// <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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return HslAndRgbConverter.Convert(rgb); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,198 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Hsv; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="Hsv"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
private static readonly HsvAndRgbConverter HsvAndRgbConverter = new HsvAndRgbConverter(); |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return HsvAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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 Hsv ToHsv(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return HsvAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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 Hsv ToHsv(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return HsvAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <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 Hsv ToHsv(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return HsvAndRgbConverter.Convert(rgb); |
|||
} |
|||
|
|||
/// <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) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToHsv(xyzColor); |
|||
} |
|||
|
|||
/// <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 Hsv ToHsv(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
return HsvAndRgbConverter.Convert(color); |
|||
} |
|||
|
|||
/// <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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
|
|||
return HsvAndRgbConverter.Convert(rgb); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,189 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.HunterLab; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="HunterLab"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Adaptation
|
|||
CieXyz adapted = !this.WhitePoint.Equals(this.TargetHunterLabWhitePoint) && this.IsChromaticAdaptationPerformed |
|||
? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetHunterLabWhitePoint) |
|||
: color; |
|||
|
|||
// Conversion
|
|||
return new CieXyzToHunterLabConverter(this.TargetHunterLabWhitePoint).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(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToHunterLab(xyzColor); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,209 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Rgb; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="LinearRgb"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
private static readonly RgbToLinearRgbConverter RgbToLinearRgbConverter = new RgbToLinearRgbConverter(); |
|||
|
|||
private CieXyzToLinearRgbConverter cieXyzToLinearRgbConverter; |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Adaptation
|
|||
CieXyz adapted = this.TargetRgbWorkingSpace.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed |
|||
? color |
|||
: this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetRgbWorkingSpace.WhitePoint); |
|||
|
|||
// Conversion
|
|||
CieXyzToLinearRgbConverter xyzConverter = this.GetCieXyxToLinearRgbConverter(this.TargetRgbWorkingSpace); |
|||
return xyzConverter.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 LinearRgb ToLinearRgb(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
return this.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 LinearRgb ToLinearRgb(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
return this.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 LinearRgb ToLinearRgb(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
return this.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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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 LinearRgb ToLinearRgb(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
return 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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.ToRgb(color); |
|||
return this.ToLinearRgb(rgb); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the correct converter for the given rgb working space.
|
|||
/// </summary>
|
|||
/// <param name="workingSpace">The target working space</param>
|
|||
/// <returns>The <see cref="CieXyzToLinearRgbConverter"/></returns>
|
|||
private CieXyzToLinearRgbConverter GetCieXyxToLinearRgbConverter(IRgbWorkingSpace workingSpace) |
|||
{ |
|||
if (this.cieXyzToLinearRgbConverter != null && this.cieXyzToLinearRgbConverter.TargetWorkingSpace.Equals(workingSpace)) |
|||
{ |
|||
return this.cieXyzToLinearRgbConverter; |
|||
} |
|||
|
|||
return this.cieXyzToLinearRgbConverter = new CieXyzToLinearRgbConverter(workingSpace); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,184 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="Lms"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
return this.cachedCieXyzAndLmsConverter.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(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
return this.ToLms(xyzColor); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,193 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Rgb; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="Rgb"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
private static readonly LinearRgbToRgbConverter LinearRgbToRgbConverter = new LinearRgbToRgbConverter(); |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
var linear = this.ToLinearRgb(color); |
|||
|
|||
// Compand
|
|||
return this.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 Rgb ToRgb(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
return 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 Rgb ToRgb(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
return 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 Rgb ToRgb(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
return 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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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 Rgb ToRgb(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
return 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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(YCbCr color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
// Conversion
|
|||
Rgb rgb = YCbCrAndRgbConverter.Convert(color); |
|||
|
|||
// Adaptation
|
|||
// TODO: Check this!
|
|||
return rgb.WorkingSpace.Equals(this.TargetRgbWorkingSpace) ? rgb : this.Adapt(rgb); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,198 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.YCbCr; |
|||
|
|||
/// <content>
|
|||
/// Allows conversion to <see cref="YCbCr"/>.
|
|||
/// </content>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
private static readonly YCbCrAndRgbConverter YCbCrAndRgbConverter = new YCbCrAndRgbConverter(); |
|||
|
|||
/// <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(CieLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieLch color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.ToCieXyz(color); |
|||
|
|||
return this.ToYCbCr(xyzColor); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="CieLchuv"/> into a <see cref="YCbCr"/>
|
|||
/// </summary>
|
|||
/// <param name="color">The color to convert.</param>
|
|||
/// <returns>The <see cref="YCbCr"/></returns>
|
|||
public YCbCr ToYCbCr(CieLchuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieLuv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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(CieXyy color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var xyzColor = this.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(CieXyz color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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 YCbCr ToYCbCr(Cmyk color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.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 YCbCr ToYCbCr(Hsl color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.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 YCbCr ToYCbCr(Hsv color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.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(HunterLab color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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 YCbCr ToYCbCr(LinearRgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var rgb = this.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(Lms color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
var 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 YCbCr ToYCbCr(Rgb color) |
|||
{ |
|||
Guard.NotNull(color, nameof(color)); |
|||
|
|||
return YCbCrAndRgbConverter.Convert(color); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,104 @@ |
|||
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Lms; |
|||
|
|||
/// <summary>
|
|||
/// Converts between color spaces ensuring that the color is adapted using chromatic adaptation.
|
|||
/// </summary>
|
|||
internal partial class ColorSpaceConverter |
|||
{ |
|||
/// <summary>
|
|||
/// The default whitepoint used for converting to CieLab
|
|||
/// </summary>
|
|||
public static readonly CieXyz DefaultWhitePoint = Illuminants.D65; |
|||
|
|||
private Matrix4x4 transformationMatrix; |
|||
|
|||
private CieXyzAndLmsConverter cachedCieXyzAndLmsConverter; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ColorSpaceConverter"/> class.
|
|||
/// </summary>
|
|||
public ColorSpaceConverter() |
|||
{ |
|||
// Note the order here this is important.
|
|||
this.WhitePoint = DefaultWhitePoint; |
|||
this.LmsAdaptationMatrix = CieXyzAndLmsConverter.DefaultTransformationMatrix; |
|||
this.ChromaticAdaptation = new VonKriesChromaticAdaptation(this.cachedCieXyzAndLmsConverter); |
|||
this.TargetLuvWhitePoint = CieLuv.DefaultWhitePoint; |
|||
this.TargetLabWhitePoint = CieLab.DefaultWhitePoint; |
|||
this.TargetHunterLabWhitePoint = HunterLab.DefaultWhitePoint; |
|||
this.TargetRgbWorkingSpace = Rgb.DefaultWorkingSpace; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the white point used for chromatic adaptation in conversions from/to XYZ color space.
|
|||
/// When null, no adaptation will be performed.
|
|||
/// </summary>
|
|||
public CieXyz WhitePoint { get; set; } |
|||
|
|||
/// <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; } |
|||
|
|||
/// <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; } |
|||
|
|||
/// <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; } |
|||
|
|||
/// <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 IRgbWorkingSpace TargetRgbWorkingSpace { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the chromatic adaptation method used. When null, no adaptation will be performed.
|
|||
/// </summary>
|
|||
public IChromaticAdaptation ChromaticAdaptation { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets transformation matrix used in conversion to <see cref="Lms"/>,
|
|||
/// also used in the default Von Kries Chromatic Adaptation method.
|
|||
/// </summary>
|
|||
public Matrix4x4 LmsAdaptationMatrix |
|||
{ |
|||
get => this.transformationMatrix; |
|||
|
|||
set |
|||
{ |
|||
this.transformationMatrix = value; |
|||
if (this.cachedCieXyzAndLmsConverter == null) |
|||
{ |
|||
this.cachedCieXyzAndLmsConverter = new CieXyzAndLmsConverter(value); |
|||
} |
|||
else |
|||
{ |
|||
this.cachedCieXyzAndLmsConverter.TransformationMatrix = value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether chromatic adaptation has been performed.
|
|||
/// </summary>
|
|||
private bool IsChromaticAdaptationPerformed => this.ChromaticAdaptation != null; |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// <copyright file="IChromaticAdaptation.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Chromatic adaptation.
|
|||
/// A linear transformation of a source color (XS, YS, ZS) into a destination color (XD, YD, ZD) by a linear transformation [M]
|
|||
/// which is dependent on the source reference white (XWS, YWS, ZWS) and the destination reference white (XWD, YWD, ZWD).
|
|||
/// </summary>
|
|||
internal interface IChromaticAdaptation |
|||
{ |
|||
/// <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="sourceColor">The source color.</param>
|
|||
/// <param name="sourceWhitePoint">The source white point.</param>
|
|||
/// <param name="targetWhitePoint">The target white point.</param>
|
|||
/// <returns>The <see cref="CieXyz"/></returns>
|
|||
CieXyz Transform(CieXyz sourceColor, CieXyz sourceWhitePoint, CieXyz targetWhitePoint); |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
// <copyright file="IColorConversion.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
/// <summary>
|
|||
/// Converts color between two color spaces.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The input color type.</typeparam>
|
|||
/// <typeparam name="TResult">The result color type.</typeparam>
|
|||
internal interface IColorConversion<in T, out TResult> |
|||
{ |
|||
/// <summary>
|
|||
/// Performs the conversion from the input to an instance of the output type.
|
|||
/// </summary>
|
|||
/// <param name="input">The input color instance.</param>
|
|||
/// <returns>The converted result</returns>
|
|||
TResult Convert(T input); |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
// <copyright file="CieLabToCieXyzConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.CieLab |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLab"/> to <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
internal class CieLabToCieXyzConverter : IColorConversion<CieLab, CieXyz> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyz Convert(CieLab input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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 = MathF.Pow(fx, 3F); |
|||
float fz3 = MathF.Pow(fz, 3F); |
|||
|
|||
float xr = fx3 > CieConstants.Epsilon ? fx3 : ((116F * fx) - 16F) / CieConstants.Kappa; |
|||
float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? MathF.Pow((l + 16F) / 116F, 3F) : l / CieConstants.Kappa; |
|||
float zr = fz3 > CieConstants.Epsilon ? fz3 : ((116F * fz) - 16F) / CieConstants.Kappa; |
|||
|
|||
float wx = input.WhitePoint.X, wy = input.WhitePoint.Y, wz = input.WhitePoint.Z; |
|||
|
|||
// Avoids XYZ coordinates out range (restricted by 0 and XYZ reference white)
|
|||
xr = xr.Clamp(0, 1F); |
|||
yr = yr.Clamp(0, 1F); |
|||
zr = zr.Clamp(0, 1F); |
|||
|
|||
float x = xr * wx; |
|||
float y = yr * wy; |
|||
float z = zr * wz; |
|||
|
|||
return new CieXyz(x, y, z); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
// <copyright file="CieXyzToCieLabConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.CieLab |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieXyz"/> to <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
internal class CieXyzToCieLabConverter : IColorConversion<CieXyz, CieLab> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToCieLabConverter"/> class.
|
|||
/// </summary>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
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>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
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 |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLab Convert(CieXyz input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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; |
|||
|
|||
float fx = xr > CieConstants.Epsilon ? MathF.Pow(xr, 0.3333333F) : ((CieConstants.Kappa * xr) + 16F) / 116F; |
|||
float fy = yr > CieConstants.Epsilon ? MathF.Pow(yr, 0.3333333F) : ((CieConstants.Kappa * yr) + 16F) / 116F; |
|||
float fz = zr > CieConstants.Epsilon ? MathF.Pow(zr, 0.3333333F) : ((CieConstants.Kappa * zr) + 16F) / 116F; |
|||
|
|||
float l = (116F * fy) - 16F; |
|||
float a = 500F * (fx - fy); |
|||
float b = 200F * (fy - fz); |
|||
|
|||
return new CieLab(l, a, b, this.LabWhitePoint); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
// <copyright file="CieLchToCieLabConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.CieLch |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLch"/> to <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
internal class CieLchToCieLabConverter : IColorConversion<CieLch, CieLab> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLab Convert(CieLch input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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 = MathF.DegreeToRadian(hDegrees); |
|||
|
|||
float a = c * MathF.Cos(hRadians); |
|||
float b = c * MathF.Sin(hRadians); |
|||
|
|||
return new CieLab(l, a, b, input.WhitePoint); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <copyright file="CieLabToCieLchConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.CieLch |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLab"/> to <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
internal class CieLabToCieLchConverter : IColorConversion<CieLab, CieLch> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLch Convert(CieLab input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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 = MathF.RadianToDegree(hRadians); |
|||
|
|||
// Wrap the angle round at 360.
|
|||
hDegrees = hDegrees % 360; |
|||
|
|||
// Make sure it's not negative.
|
|||
while (hDegrees < 0) |
|||
{ |
|||
hDegrees += 360; |
|||
} |
|||
|
|||
return new CieLch(l, c, hDegrees, input.WhitePoint); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
// <copyright file="CieLchuvToCieLuvConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuv |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLch"/> to <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
internal class CieLchuvToCieLuvConverter : IColorConversion<CieLchuv, CieLuv> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLuv Convert(CieLchuv input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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 = MathF.DegreeToRadian(hDegrees); |
|||
|
|||
float u = c * MathF.Cos(hRadians); |
|||
float v = c * MathF.Sin(hRadians); |
|||
|
|||
return new CieLuv(l, u, v, input.WhitePoint); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <copyright file="CieLuvToCieLchuvConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuv |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLab"/> to <see cref="CieLch"/>.
|
|||
/// </summary>
|
|||
internal class CieLuvToCieLchuvConverter : IColorConversion<CieLuv, CieLchuv> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLchuv Convert(CieLuv input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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 = MathF.RadianToDegree(hRadians); |
|||
|
|||
// Wrap the angle round at 360.
|
|||
hDegrees = hDegrees % 360; |
|||
|
|||
// Make sure it's not negative.
|
|||
while (hDegrees < 0) |
|||
{ |
|||
hDegrees += 360; |
|||
} |
|||
|
|||
return new CieLchuv(l, c, hDegrees, input.WhitePoint); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
// <copyright file="CieLuvToCieXyzConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.CieLuv |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieLuv"/> to <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
internal class CieLuvToCieXyzConverter : IColorConversion<CieLuv, CieXyz> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyz Convert(CieLuv input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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 |
|||
? MathF.Pow((l + 16) / 116, 3) |
|||
: l / CieConstants.Kappa; |
|||
|
|||
float a = ((52 * l / (u + (13 * l * u0))) - 1) / 3; |
|||
float b = -5 * y; |
|||
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(MethodImplOptions.AggressiveInlining)] |
|||
private static float ComputeU0(CieXyz input) |
|||
{ |
|||
return (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(MethodImplOptions.AggressiveInlining)] |
|||
private static float ComputeV0(CieXyz input) |
|||
{ |
|||
return (9 * input.Y) / (input.X + (15 * input.Y) + (3 * input.Z)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,102 @@ |
|||
// <copyright file="CieXyzToCieLuvConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.CieLuv |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Converts from <see cref="CieXyz"/> to <see cref="CieLuv"/>.
|
|||
/// </summary>
|
|||
internal class CieXyzToCieLuvConverter : IColorConversion<CieXyz, CieLuv> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToCieLuvConverter"/> class.
|
|||
/// </summary>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
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>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
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 |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieLuv Convert(CieXyz input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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(CieXyz input) |
|||
{ |
|||
return (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>
|
|||
private static float ComputeVp(CieXyz input) |
|||
{ |
|||
return (9 * input.Y) / (input.X + (15 * input.Y) + (3 * input.Z)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
// <copyright file="CieXyzAndCieXyyConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.CieXyy |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between CIE XYZ and CIE xyY
|
|||
/// <see href="http://www.brucelindbloom.com/"/> for formulas.
|
|||
/// </summary>
|
|||
internal class CieXyzAndCieXyyConverter : IColorConversion<CieXyz, CieXyy>, IColorConversion<CieXyy, CieXyz> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyy Convert(CieXyz input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyz Convert(CieXyy input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
// <copyright file="CmykAndRgbConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Cmyk |
|||
{ |
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between CMYK and Rgb
|
|||
/// </summary>
|
|||
internal class CmykAndRgbConverter : IColorConversion<Cmyk, Rgb>, IColorConversion<Rgb, Cmyk> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb Convert(Cmyk input) |
|||
{ |
|||
float r = (1F - input.C) * (1F - input.K); |
|||
float g = (1F - input.M) * (1F - input.K); |
|||
float b = (1F - input.Y) * (1F - input.K); |
|||
|
|||
return new Rgb(r, g, b); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Cmyk Convert(Rgb input) |
|||
{ |
|||
// To CMYK
|
|||
float c = 1F - input.R; |
|||
float m = 1F - input.G; |
|||
float y = 1F - input.B; |
|||
|
|||
// To CMYK
|
|||
float k = MathF.Min(c, MathF.Min(m, y)); |
|||
|
|||
if (MathF.Abs(k - 1F) < Constants.Epsilon) |
|||
{ |
|||
return new Cmyk(0, 0, 0, 1F); |
|||
} |
|||
|
|||
c = (c - k) / (1F - k); |
|||
m = (m - k) / (1F - k); |
|||
y = (y - k) / (1F - k); |
|||
|
|||
return new Cmyk(c, m, y, k); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,159 @@ |
|||
// <copyright file="HslAndRgbConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Hsl |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between HSL and Rgb
|
|||
/// See <see href="http://www.poynton.com/PDFs/coloureq.pdf"/> for formulas.
|
|||
/// </summary>
|
|||
internal class HslAndRgbConverter : IColorConversion<Hsl, Rgb>, IColorConversion<Rgb, Hsl> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb Convert(Hsl input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Hsl Convert(Rgb input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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 - chroma); |
|||
} |
|||
|
|||
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(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; |
|||
} |
|||
|
|||
/// <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(MethodImplOptions.AggressiveInlining)] |
|||
private static float MoveIntoRange(float value) |
|||
{ |
|||
if (value < 0F) |
|||
{ |
|||
value += 1F; |
|||
} |
|||
else if (value > 1F) |
|||
{ |
|||
value -= 1F; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
// <copyright file="HsvAndRgbConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Hsv |
|||
{ |
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between HSV and Rgb
|
|||
/// See <see href="http://www.poynton.com/PDFs/coloureq.pdf"/> for formulas.
|
|||
/// </summary>
|
|||
internal class HsvAndRgbConverter : IColorConversion<Hsv, Rgb>, IColorConversion<Rgb, Hsv> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb Convert(Hsv input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(input)); |
|||
|
|||
float s = input.S; |
|||
float v = input.V; |
|||
|
|||
if (MathF.Abs(s) < Constants.Epsilon) |
|||
{ |
|||
return new Rgb(v, v, v); |
|||
} |
|||
|
|||
float h = (MathF.Abs(input.H - 360) < Constants.Epsilon) ? 0 : input.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/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Hsv Convert(Rgb input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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 = 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 *= 60; |
|||
if (h < 0.0) |
|||
{ |
|||
h += 360; |
|||
} |
|||
|
|||
s = chroma / v; |
|||
|
|||
return new Hsv(h, s, v); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
// <copyright file="CieXyzAndHunterLabConverterBase.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.HunterLab |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <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(MethodImplOptions.AggressiveInlining)] |
|||
public static float ComputeKa(CieXyz whitePoint) |
|||
{ |
|||
DebugGuard.NotNull(whitePoint, nameof(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(MethodImplOptions.AggressiveInlining)] |
|||
public static float ComputeKb(CieXyz whitePoint) |
|||
{ |
|||
DebugGuard.NotNull(whitePoint, nameof(whitePoint)); |
|||
|
|||
if (whitePoint == Illuminants.C) |
|||
{ |
|||
return 70F; |
|||
} |
|||
|
|||
return 100F * (70F / 218.11F) * (whitePoint.Y + whitePoint.Z); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
// <copyright file="CieXyzToHunterLabConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.HunterLab |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between CieXyz and HunterLab
|
|||
/// </summary>
|
|||
internal class CieXyzToHunterLabConverter : CieXyzAndHunterLabConverterBase, IColorConversion<CieXyz, HunterLab> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyzToHunterLabConverter"/> class.
|
|||
/// </summary>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
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>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
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 |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public HunterLab Convert(CieXyz input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(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 l = 100 * MathF.Sqrt(y / yn); |
|||
float a = ka * (((x / xn) - (y / yn)) / MathF.Sqrt(y / yn)); |
|||
float b = kb * (((y / yn) - (z / zn)) / MathF.Sqrt(y / yn)); |
|||
|
|||
if (float.IsNaN(a)) |
|||
{ |
|||
a = 0; |
|||
} |
|||
|
|||
if (float.IsNaN(b)) |
|||
{ |
|||
b = 0; |
|||
} |
|||
|
|||
return new HunterLab(l, a, b, this.HunterLabWhitePoint); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
// <copyright file="HunterLabToCieXyzConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.HunterLab |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between HunterLab and CieXyz
|
|||
/// </summary>
|
|||
internal class HunterLabToCieXyzConverter : CieXyzAndHunterLabConverterBase, IColorConversion<HunterLab, CieXyz> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyz Convert(HunterLab input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(input)); |
|||
|
|||
// Conversion algorithm described here: http://en.wikipedia.org/wiki/Lab_color_space#Hunter_Lab
|
|||
float l = input.L, a = input.A, b = input.B; |
|||
float xn = input.WhitePoint.X, yn = input.WhitePoint.Y, zn = input.WhitePoint.Z; |
|||
|
|||
float ka = ComputeKa(input.WhitePoint); |
|||
float kb = ComputeKb(input.WhitePoint); |
|||
|
|||
float y = MathF.Pow(l / 100F, 2) * yn; |
|||
float x = (((a / ka) * MathF.Sqrt(y / yn)) + (y / yn)) * xn; |
|||
float z = (((b / kb) * MathF.Sqrt(y / yn)) - (y / yn)) * (-zn); |
|||
|
|||
return new CieXyz(x, y, z); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,85 @@ |
|||
// <copyright file="CieXyzAndLmsConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Lms |
|||
{ |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between CIE XYZ and LMS
|
|||
/// </summary>
|
|||
internal class CieXyzAndLmsConverter : IColorConversion<CieXyz, Lms>, IColorConversion<Lms, CieXyz> |
|||
{ |
|||
/// <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>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
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>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyzAndLmsConverter(Matrix4x4 transformationMatrix) |
|||
{ |
|||
this.TransformationMatrix = transformationMatrix; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the transformation matrix used for the conversion (definition of the cone response domain).
|
|||
/// <see cref="LmsAdaptationMatrix"/>
|
|||
/// </summary>
|
|||
public Matrix4x4 TransformationMatrix |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.transformationMatrix; |
|||
|
|||
set |
|||
{ |
|||
this.transformationMatrix = value; |
|||
Matrix4x4.Invert(this.transformationMatrix, out this.inverseTransformationMatrix); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Lms Convert(CieXyz input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(input)); |
|||
|
|||
Vector3 vector = Vector3.Transform(input.Vector, this.transformationMatrix); |
|||
return new Lms(vector); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public CieXyz Convert(Lms input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(input)); |
|||
|
|||
Vector3 vector = Vector3.Transform(input.Vector, this.inverseTransformationMatrix); |
|||
return new CieXyz(vector); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,101 @@ |
|||
// <copyright file="LmsAdaptationMatrix.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
// ReSharper disable InconsistentNaming
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Lms |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// AdaptionMatrix3X3 used for transformation from XYZ to LMS, defining the cone response domain.
|
|||
/// Used in <see cref="IChromaticAdaptation"/>
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Matrix data obtained from:
|
|||
/// Two New von Kries Based Chromatic Adaptation Transforms Found by Numerical Optimization
|
|||
/// S. Bianco, R. Schettini
|
|||
/// DISCo, Department of Informatics, Systems and Communication, University of Milan-Bicocca, viale Sarca 336, 20126 Milan, Italy
|
|||
/// https://web.stanford.edu/~sujason/ColorBalancing/Papers/Two%20New%20von%20Kries%20Based%20Chromatic%20Adaptation.pdf
|
|||
/// </remarks>
|
|||
public static class LmsAdaptationMatrix |
|||
{ |
|||
/// <summary>
|
|||
/// Von Kries chromatic adaptation transform matrix (Hunt-Pointer-Estevez adjusted for D65)
|
|||
/// </summary>
|
|||
public static readonly Matrix4x4 VonKriesHPEAdjusted |
|||
= Matrix4x4.Transpose(new Matrix4x4 |
|||
{ |
|||
M11 = 0.40024F, M12 = 0.7076F, M13 = -0.08081F, |
|||
M21 = -0.2263F, M22 = 1.16532F, M23 = 0.0457F, |
|||
M31 = 0, M32 = 0, M33 = 0.91822F, |
|||
M44 = 1F // Important for inverse transforms.
|
|||
}); |
|||
|
|||
/// <summary>
|
|||
/// Von Kries chromatic adaptation transform matrix (Hunt-Pointer-Estevez for equal energy)
|
|||
/// </summary>
|
|||
public static readonly Matrix4x4 VonKriesHPE |
|||
= Matrix4x4.Transpose(new Matrix4x4 |
|||
{ |
|||
M11 = 0.3897F, M12 = 0.6890F, M13 = -0.0787F, |
|||
M21 = -0.2298F, M22 = 1.1834F, M23 = 0.0464F, |
|||
M31 = 0, M32 = 0, M33 = 1F, |
|||
M44 = 1F |
|||
}); |
|||
|
|||
/// <summary>
|
|||
/// XYZ scaling chromatic adaptation transform matrix
|
|||
/// </summary>
|
|||
public static readonly Matrix4x4 XyzScaling = Matrix4x4.Transpose(Matrix4x4.Identity); |
|||
|
|||
/// <summary>
|
|||
/// Bradford chromatic adaptation transform matrix (used in CMCCAT97)
|
|||
/// </summary>
|
|||
public static readonly Matrix4x4 Bradford |
|||
= Matrix4x4.Transpose(new Matrix4x4 |
|||
{ |
|||
M11 = 0.8951F, M12 = 0.2664F, M13 = -0.1614F, |
|||
M21 = -0.7502F, M22 = 1.7135F, M23 = 0.0367F, |
|||
M31 = 0.0389F, M32 = -0.0685F, M33 = 1.0296F, |
|||
M44 = 1F |
|||
}); |
|||
|
|||
/// <summary>
|
|||
/// Spectral sharpening and the Bradford transform
|
|||
/// </summary>
|
|||
public static readonly Matrix4x4 BradfordSharp |
|||
= Matrix4x4.Transpose(new Matrix4x4 |
|||
{ |
|||
M11 = 1.2694F, M12 = -0.0988F, M13 = -0.1706F, |
|||
M21 = -0.8364F, M22 = 1.8006F, M23 = 0.0357F, |
|||
M31 = 0.0297F, M32 = -0.0315F, M33 = 1.0018F, |
|||
M44 = 1F |
|||
}); |
|||
|
|||
/// <summary>
|
|||
/// CMCCAT2000 (fitted from all available color data sets)
|
|||
/// </summary>
|
|||
public static readonly Matrix4x4 CMCCAT2000 |
|||
= Matrix4x4.Transpose(new Matrix4x4 |
|||
{ |
|||
M11 = 0.7982F, M12 = 0.3389F, M13 = -0.1371F, |
|||
M21 = -0.5918F, M22 = 1.5512F, M23 = 0.0406F, |
|||
M31 = 0.0008F, M32 = 0.239F, M33 = 0.9753F, |
|||
M44 = 1F |
|||
}); |
|||
|
|||
/// <summary>
|
|||
/// CAT02 (optimized for minimizing CIELAB differences)
|
|||
/// </summary>
|
|||
public static readonly Matrix4x4 CAT02 |
|||
= Matrix4x4.Transpose(new Matrix4x4 |
|||
{ |
|||
M11 = 0.7328F, M12 = 0.4296F, M13 = -0.1624F, |
|||
M21 = -0.7036F, M22 = 1.6975F, M23 = 0.0061F, |
|||
M31 = 0.0030F, M32 = 0.0136F, M33 = 0.9834F, |
|||
M44 = 1F |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
// <copyright file="LinearRgbToRgbConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
using Rgb = ImageSharp.ColorSpaces.Rgb; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between CieXyz and LinearRgb
|
|||
/// </summary>
|
|||
internal class CieXyzToLinearRgbConverter : LinearRgbAndCieXyzConverterBase, IColorConversion<CieXyz, LinearRgb> |
|||
{ |
|||
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(IRgbWorkingSpace workingSpace) |
|||
{ |
|||
this.TargetWorkingSpace = workingSpace; |
|||
this.conversionMatrix = GetRgbToCieXyzMatrix(workingSpace); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the target working space
|
|||
/// </summary>
|
|||
public IRgbWorkingSpace TargetWorkingSpace { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
public LinearRgb Convert(CieXyz input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(input)); |
|||
|
|||
Matrix4x4.Invert(this.conversionMatrix, out Matrix4x4 inverted); |
|||
Vector3 vector = Vector3.Transform(input.Vector, inverted); |
|||
return new LinearRgb(vector, this.TargetWorkingSpace); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// <copyright file="GammaCompanding.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <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 class GammaCompanding : ICompanding |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="GammaCompanding"/> class.
|
|||
/// </summary>
|
|||
/// <param name="gamma">The gamma value.</param>
|
|||
public GammaCompanding(float gamma) |
|||
{ |
|||
this.Gamma = gamma; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the gamma value
|
|||
/// </summary>
|
|||
public float Gamma { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public float Expand(float channel) |
|||
{ |
|||
return MathF.Pow(channel, this.Gamma); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public float Compress(float channel) |
|||
{ |
|||
return MathF.Pow(channel, 1 / this.Gamma); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
// <copyright file="LCompanding.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <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 class LCompanding : ICompanding |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public float Expand(float channel) |
|||
{ |
|||
return channel <= 0.08 ? 100 * channel / CieConstants.Kappa : MathF.Pow((channel + 0.16F) / 1.16F, 3); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public float Compress(float channel) |
|||
{ |
|||
return channel <= CieConstants.Epsilon |
|||
? channel * CieConstants.Kappa / 100F |
|||
: MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
// <copyright file="LinearRgbAndCieXyzConverterBase.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Provides base methods for converting between Rgb and CieXyz color spaces.
|
|||
/// </summary>
|
|||
internal abstract class LinearRgbAndCieXyzConverterBase |
|||
{ |
|||
/// <summary>
|
|||
/// Geturns the correct matrix to convert between the Rgb and CieXyz color space.
|
|||
/// </summary>
|
|||
/// <param name="workingSpace">The Rgb working space.</param>
|
|||
/// <returns>The <see cref="Matrix4x4"/> based on the chromaticity and working space.</returns>
|
|||
public static Matrix4x4 GetRgbToCieXyzMatrix(IRgbWorkingSpace 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; |
|||
const float Yr = 1; |
|||
float mZr = (1 - xr - yr) / yr; |
|||
|
|||
float mXg = xg / yg; |
|||
const float Yg = 1; |
|||
float mZg = (1 - xg - yg) / yg; |
|||
|
|||
float mXb = xb / yb; |
|||
const float Yb = 1; |
|||
float mZb = (1 - xb - yb) / yb; |
|||
|
|||
Matrix4x4 xyzMatrix = new Matrix4x4 |
|||
{ |
|||
M11 = mXr, M21 = mXg, M31 = mXb, |
|||
M12 = Yr, M22 = Yg, M32 = Yb, |
|||
M13 = mZr, M23 = mZg, M33 = mZb, |
|||
M44 = 1F |
|||
}; |
|||
|
|||
Matrix4x4 inverseXyzMatrix; |
|||
Matrix4x4.Invert(xyzMatrix, out inverseXyzMatrix); |
|||
|
|||
Vector3 vector = Vector3.Transform(workingSpace.WhitePoint.Vector, inverseXyzMatrix); |
|||
|
|||
// Use transposed Rows/Coloumns
|
|||
// TODO: Is there a built in method for this multiplication?
|
|||
return new Matrix4x4 |
|||
{ |
|||
M11 = vector.X * mXr, M21 = vector.Y * mXg, M31 = vector.Z * mXb, |
|||
M12 = vector.X * Yr, M22 = vector.Y * Yg, M32 = vector.Z * Yb, |
|||
M13 = vector.X * mZr, M23 = vector.Y * mZg, M33 = vector.Z * mZb, |
|||
M44 = 1F |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
// <copyright file="LinearRgbToCieXyzConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
using Rgb = ImageSharp.ColorSpaces.Rgb; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between LinearRgb and CieXyz
|
|||
/// </summary>
|
|||
internal class LinearRgbToCieXyzConverter : LinearRgbAndCieXyzConverterBase, IColorConversion<LinearRgb, CieXyz> |
|||
{ |
|||
private readonly Matrix4x4 conversionMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="LinearRgbToCieXyzConverter"/> class.
|
|||
/// </summary>
|
|||
public LinearRgbToCieXyzConverter() |
|||
: this(Rgb.DefaultWorkingSpace) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="LinearRgbToCieXyzConverter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="workingSpace">The target working space.</param>
|
|||
public LinearRgbToCieXyzConverter(IRgbWorkingSpace workingSpace) |
|||
{ |
|||
this.SourceWorkingSpace = workingSpace; |
|||
this.conversionMatrix = GetRgbToCieXyzMatrix(workingSpace); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the source working space
|
|||
/// </summary>
|
|||
public IRgbWorkingSpace SourceWorkingSpace { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
public CieXyz Convert(LinearRgb input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(input)); |
|||
Guard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal."); |
|||
|
|||
Vector3 vector = Vector3.Transform(input.Vector, this.conversionMatrix); |
|||
return new CieXyz(vector); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
// <copyright file="LinearRgbToRgbConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
using Rgb = ColorSpaces.Rgb; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between LinearRgb and Rgb
|
|||
/// </summary>
|
|||
internal class LinearRgbToRgbConverter : IColorConversion<LinearRgb, Rgb> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
public Rgb Convert(LinearRgb input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(input)); |
|||
|
|||
Vector3 vector = input.Vector; |
|||
vector.X = input.WorkingSpace.Companding.Compress(vector.X); |
|||
vector.Y = input.WorkingSpace.Companding.Compress(vector.Y); |
|||
vector.Z = input.WorkingSpace.Companding.Compress(vector.Z); |
|||
|
|||
return new Rgb(vector, input.WorkingSpace); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,107 @@ |
|||
// <copyright file="RgbPrimariesChromaticityCoordinates.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System; |
|||
|
|||
/// <summary>
|
|||
/// Represents the chromaticity coordinates of RGB primaries.
|
|||
/// One of the specifiers of <see cref="IRgbWorkingSpace"/>.
|
|||
/// </summary>
|
|||
internal struct RgbPrimariesChromaticityCoordinates : IEquatable<RgbPrimariesChromaticityCoordinates> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="RgbPrimariesChromaticityCoordinates"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The chomaticity coordinates of the red channel.</param>
|
|||
/// <param name="g">The chomaticity coordinates of the green channel.</param>
|
|||
/// <param name="b">The chomaticity coordinates of the blue channel.</param>
|
|||
public RgbPrimariesChromaticityCoordinates(CieXyChromaticityCoordinates r, CieXyChromaticityCoordinates g, CieXyChromaticityCoordinates b) |
|||
{ |
|||
this.R = r; |
|||
this.G = g; |
|||
this.B = b; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the chomaticity coordinates of the red channel.
|
|||
/// </summary>
|
|||
public CieXyChromaticityCoordinates R { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the chomaticity coordinates of the green channel.
|
|||
/// </summary>
|
|||
public CieXyChromaticityCoordinates G { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the chomaticity coordinates of the blue channel.
|
|||
/// </summary>
|
|||
public CieXyChromaticityCoordinates 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>
|
|||
public static bool operator ==(RgbPrimariesChromaticityCoordinates left, RgbPrimariesChromaticityCoordinates right) |
|||
{ |
|||
return 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>
|
|||
public static bool operator !=(RgbPrimariesChromaticityCoordinates left, RgbPrimariesChromaticityCoordinates right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is RgbPrimariesChromaticityCoordinates) |
|||
{ |
|||
return this.Equals((RgbPrimariesChromaticityCoordinates)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(RgbPrimariesChromaticityCoordinates other) |
|||
{ |
|||
return this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = this.R.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.G.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.B.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
// <copyright file="Rec2020Companding.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Implements Rec. 2020 companding function (for 12-bits).
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <see href="http://en.wikipedia.org/wiki/Rec._2020"/>
|
|||
/// For 10-bits, companding is identical to <see cref="Rec709Companding"/>
|
|||
/// </remarks>
|
|||
public class Rec2020Companding : ICompanding |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public float Expand(float channel) |
|||
{ |
|||
return channel < 0.08145F ? channel / 4.5F : MathF.Pow((channel + 0.0993F) / 1.0993F, 2.222222F); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public float Compress(float channel) |
|||
{ |
|||
return channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
// <copyright file="Rec2020Companding.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Implements the Rec. 709 companding function
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// http://en.wikipedia.org/wiki/Rec._709
|
|||
/// </remarks>
|
|||
public class Rec709Companding : ICompanding |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public float Expand(float channel) |
|||
{ |
|||
return channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public float Compress(float channel) |
|||
{ |
|||
return channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
// <copyright file="RgbToLinearRgbConverter.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
using Rgb = ColorSpaces.Rgb; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between Rgb and LinearRgb
|
|||
/// </summary>
|
|||
internal class RgbToLinearRgbConverter : IColorConversion<Rgb, LinearRgb> |
|||
{ |
|||
/// <inheritdoc/>
|
|||
public LinearRgb Convert(Rgb input) |
|||
{ |
|||
Guard.NotNull(input, nameof(input)); |
|||
|
|||
Vector3 vector = input.Vector; |
|||
vector.X = input.WorkingSpace.Companding.Expand(vector.X); |
|||
vector.Y = input.WorkingSpace.Companding.Expand(vector.Y); |
|||
vector.Z = input.WorkingSpace.Companding.Expand(vector.Z); |
|||
|
|||
return new LinearRgb(vector, input.WorkingSpace); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,107 @@ |
|||
// <copyright file="RgbWorkingSpace.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
/// <summary>
|
|||
/// Trivial implementation of <see cref="IRgbWorkingSpace"/>
|
|||
/// </summary>
|
|||
internal struct RgbWorkingSpace : IRgbWorkingSpace |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="RgbWorkingSpace"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="referenceWhite">The reference white point.</param>
|
|||
/// <param name="companding">The function pair for converting to <see cref="CieXyz"/> and back.</param>
|
|||
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
|
|||
public RgbWorkingSpace(CieXyz referenceWhite, ICompanding companding, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) |
|||
{ |
|||
this.WhitePoint = referenceWhite; |
|||
this.Companding = companding; |
|||
this.ChromaticityCoordinates = chromaticityCoordinates; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the reference white point
|
|||
/// </summary>
|
|||
public CieXyz WhitePoint { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the function pair for converting to <see cref="CieXyz"/> and back.
|
|||
/// </summary>
|
|||
public ICompanding Companding { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the chromaticity of the rgb primaries.
|
|||
/// </summary>
|
|||
public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="RgbWorkingSpace"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="RgbWorkingSpace"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="RgbWorkingSpace"/> 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 ==(RgbWorkingSpace left, RgbWorkingSpace right) |
|||
{ |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="RgbWorkingSpace"/> objects for inequality
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="RgbWorkingSpace"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="RgbWorkingSpace"/> 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 !=(RgbWorkingSpace left, RgbWorkingSpace right) |
|||
{ |
|||
return !Equals(left, right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is RgbWorkingSpace) |
|||
{ |
|||
return this.Equals((RgbWorkingSpace)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(IRgbWorkingSpace other) |
|||
{ |
|||
// TODO: Object.Equals for ICompanding will be slow.
|
|||
return this.WhitePoint.Equals(other.WhitePoint) |
|||
&& this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates) |
|||
&& Equals(this.Companding, other.Companding); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = this.WhitePoint.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.ChromaticityCoordinates.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ (this.Companding?.GetHashCode() ?? 0); |
|||
return hashCode; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
// <copyright file="SRgbCompanding.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.Rgb |
|||
{ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <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 class SRgbCompanding : ICompanding |
|||
{ |
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public float Expand(float channel) |
|||
{ |
|||
return channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public float Compress(float channel) |
|||
{ |
|||
return channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
// <copyright file="YCbCrAndRgbConverter .cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion.Implementation.YCbCr |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
|
|||
/// <summary>
|
|||
/// Color converter between YCbCr and Rgb
|
|||
/// See <see href="https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion"/> for formulas.
|
|||
/// </summary>
|
|||
internal class YCbCrAndRgbConverter : IColorConversion<YCbCr, Rgb>, IColorConversion<Rgb, YCbCr> |
|||
{ |
|||
private static readonly Vector3 MaxBytes = new Vector3(255F); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb Convert(YCbCr input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(input)); |
|||
|
|||
float y = input.Y; |
|||
float cb = input.Cb - 128F; |
|||
float cr = input.Cr - 128F; |
|||
|
|||
float r = MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero); |
|||
float g = MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero); |
|||
float b = MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero); |
|||
|
|||
return new Rgb(new Vector3(r, g, b) / MaxBytes); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public YCbCr Convert(Rgb input) |
|||
{ |
|||
DebugGuard.NotNull(input, nameof(input)); |
|||
|
|||
Vector3 rgb = input.Vector * MaxBytes; |
|||
float r = rgb.X; |
|||
float g = rgb.Y; |
|||
float b = rgb.Z; |
|||
|
|||
float y = (0.299F * r) + (0.587F * g) + (0.114F * b); |
|||
float cb = 128F + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b)); |
|||
float cr = 128F + ((0.5F * r) - (0.418688F * g) - (0.081312F * b)); |
|||
|
|||
return new YCbCr(y, cb, cr); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
// <copyright file="VonKriesChromaticAdaptation.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces.Conversion |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.ColorSpaces; |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Lms; |
|||
|
|||
/// <summary>
|
|||
/// Basic implementation of the von Kries chromatic adaptation model
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Transformation described here:
|
|||
/// http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
|
|||
/// </remarks>
|
|||
internal class VonKriesChromaticAdaptation : IChromaticAdaptation |
|||
{ |
|||
private readonly CieXyzAndLmsConverter converter; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="VonKriesChromaticAdaptation"/> class.
|
|||
/// </summary>
|
|||
public VonKriesChromaticAdaptation() |
|||
: this(new CieXyzAndLmsConverter()) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="VonKriesChromaticAdaptation"/> class.
|
|||
/// </summary>
|
|||
/// <param name="transformationMatrix">
|
|||
/// The transformation matrix used for the conversion (definition of the cone response domain).
|
|||
/// <see cref="LmsAdaptationMatrix"/>
|
|||
/// </param>
|
|||
public VonKriesChromaticAdaptation(Matrix4x4 transformationMatrix) |
|||
: this(new CieXyzAndLmsConverter(transformationMatrix)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="VonKriesChromaticAdaptation"/> class.
|
|||
/// </summary>
|
|||
/// <param name="converter">The color converter</param>
|
|||
public VonKriesChromaticAdaptation(CieXyzAndLmsConverter converter) |
|||
{ |
|||
this.converter = converter; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public CieXyz Transform(CieXyz sourceColor, CieXyz sourceWhitePoint, CieXyz targetWhitePoint) |
|||
{ |
|||
Guard.NotNull(sourceColor, nameof(sourceColor)); |
|||
Guard.NotNull(sourceWhitePoint, nameof(sourceWhitePoint)); |
|||
Guard.NotNull(targetWhitePoint, nameof(targetWhitePoint)); |
|||
|
|||
if (sourceWhitePoint.Equals(targetWhitePoint)) |
|||
{ |
|||
return sourceColor; |
|||
} |
|||
|
|||
Lms sourceColorLms = this.converter.Convert(sourceColor); |
|||
Lms sourceWhitePointLms = this.converter.Convert(sourceWhitePoint); |
|||
Lms targetWhitePointLms = this.converter.Convert(targetWhitePoint); |
|||
|
|||
var vector = new Vector3(targetWhitePointLms.L / sourceWhitePointLms.L, targetWhitePointLms.M / sourceWhitePointLms.M, targetWhitePointLms.S / sourceWhitePointLms.S); |
|||
var targetColorLms = new Lms(Vector3.Multiply(vector, sourceColorLms.Vector)); |
|||
|
|||
return this.converter.Convert(targetColorLms); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,223 @@ |
|||
// <copyright file="HunterLab.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents an Hunter LAB color.
|
|||
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space"/>
|
|||
/// </summary>
|
|||
internal struct HunterLab : IColorVector, IEquatable<HunterLab>, IAlmostEquatable<HunterLab, float> |
|||
{ |
|||
/// <summary>
|
|||
/// D50 standard illuminant.
|
|||
/// Used when reference white is not specified explicitly.
|
|||
/// </summary>
|
|||
public static readonly CieXyz DefaultWhitePoint = Illuminants.C; |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="HunterLab"/> that has L, A, B values set to zero.
|
|||
/// </summary>
|
|||
public static readonly HunterLab Empty = default(HunterLab); |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private readonly Vector3 backingVector; |
|||
|
|||
/// <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>
|
|||
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public HunterLab(float l, float a, float b) |
|||
: this(new Vector3(l, a, b), DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <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>
|
|||
/// <param name="whitePoint">The reference white point. <see cref="Illuminants"/></param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public HunterLab(float l, float a, float b, CieXyz whitePoint) |
|||
: this(new Vector3(l, a, b), whitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="HunterLab"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, a, b components.</param>
|
|||
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public HunterLab(Vector3 vector) |
|||
: this(vector, DefaultWhitePoint) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="HunterLab"/> 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(MethodImplOptions.AggressiveInlining)] |
|||
public HunterLab(Vector3 vector, CieXyz whitePoint) |
|||
: this() |
|||
{ |
|||
this.backingVector = vector; |
|||
this.WhitePoint = whitePoint; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the reference white point of this color
|
|||
/// </summary>
|
|||
public CieXyz WhitePoint { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension.
|
|||
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
|
|||
/// </summary>
|
|||
public float L |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.X; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the a color component.
|
|||
/// <remarks>A value ranging from -100 to 100. Negative is green, positive magenta.</remarks>
|
|||
/// </summary>
|
|||
public float A |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the b color component.
|
|||
/// <remarks>A value ranging from -100 to 100. Negative is blue, positive is yellow</remarks>
|
|||
/// </summary>
|
|||
public float B |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="HunterLab"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector3 Vector |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector; |
|||
} |
|||
|
|||
/// <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>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(HunterLab left, HunterLab right) |
|||
{ |
|||
return 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) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = this.WhitePoint.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.backingVector.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "HunterLab [Empty]"; |
|||
} |
|||
|
|||
return $"HunterLab [ L={this.L:#0.##}, A={this.A:#0.##}, B={this.B:#0.##}]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is HunterLab) |
|||
{ |
|||
return this.Equals((HunterLab)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(HunterLab other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector) |
|||
&& this.WhitePoint.Equals(other.WhitePoint); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool AlmostEquals(HunterLab other, float precision) |
|||
{ |
|||
var result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return this.WhitePoint.Equals(other.WhitePoint) |
|||
&& result.X <= precision |
|||
&& result.Y <= precision |
|||
&& result.Z <= precision; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
// <copyright file="IColorVector.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Color represented as a vector in its color space
|
|||
/// </summary>
|
|||
public interface IColorVector |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the vector representation of the color
|
|||
/// </summary>
|
|||
Vector3 Vector { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
// <copyright file="ICompanding.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
/// <summary>
|
|||
/// Pair of companding functions for <see cref="IRgbWorkingSpace"/>.
|
|||
/// Used for conversion to <see cref="CieXyz"/> and backwards.
|
|||
/// See also: <seealso cref="IRgbWorkingSpace.Companding"/>
|
|||
/// </summary>
|
|||
internal interface ICompanding |
|||
{ |
|||
/// <summary>
|
|||
/// Expands a companded channel to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// For more info see:
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
|
|||
/// </remarks>
|
|||
/// <param name="channel">The channel value</param>
|
|||
/// <returns>The linear channel value</returns>
|
|||
float Expand(float channel); |
|||
|
|||
/// <summary>
|
|||
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent (depends on the RGB color system).
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// For more info see:
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
|
|||
/// </remarks>
|
|||
/// <param name="channel">The channel value</param>
|
|||
/// <returns>The nonlinear channel value</returns>
|
|||
float Compress(float channel); |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
// <copyright file="IRgbWorkingSpace.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System; |
|||
|
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Rgb; |
|||
|
|||
/// <summary>
|
|||
/// Encasulates the RGB working color space
|
|||
/// </summary>
|
|||
internal interface IRgbWorkingSpace : IEquatable<IRgbWorkingSpace> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the reference white of the color space
|
|||
/// </summary>
|
|||
CieXyz WhitePoint { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the chromaticity coordinates of the primaries
|
|||
/// </summary>
|
|||
RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the companding function associated with the RGB color system. Used for conversion to XYZ and backwards.
|
|||
/// <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"/>
|
|||
/// </summary>
|
|||
ICompanding Companding { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,71 @@ |
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
/// <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>
|
|||
internal static class Illuminants |
|||
{ |
|||
/// <summary>
|
|||
/// Incandescent / Tungsten
|
|||
/// </summary>
|
|||
public static readonly CieXyz A = new CieXyz(1.09850F, 1F, 0.35585F); |
|||
|
|||
/// <summary>
|
|||
/// Direct sunlight at noon (obsoleteF)
|
|||
/// </summary>
|
|||
public static readonly CieXyz B = new CieXyz(0.99072F, 1F, 0.85223F); |
|||
|
|||
/// <summary>
|
|||
/// Average / North sky Daylight (obsoleteF)
|
|||
/// </summary>
|
|||
public static readonly CieXyz C = new CieXyz(0.98074F, 1F, 1.18232F); |
|||
|
|||
/// <summary>
|
|||
/// Horizon Light. ICC profile PCS
|
|||
/// </summary>
|
|||
public static readonly CieXyz D50 = new CieXyz(0.96422F, 1F, 0.82521F); |
|||
|
|||
/// <summary>
|
|||
/// Mid-morning / Mid-afternoon Daylight
|
|||
/// </summary>
|
|||
public static readonly CieXyz D55 = new CieXyz(0.95682F, 1F, 0.92149F); |
|||
|
|||
/// <summary>
|
|||
/// Noon Daylight: TelevisionF, sRGB color space
|
|||
/// </summary>
|
|||
public static readonly CieXyz D65 = new CieXyz(0.95047F, 1F, 1.08883F); |
|||
|
|||
/// <summary>
|
|||
/// North sky Daylight
|
|||
/// </summary>
|
|||
public static readonly CieXyz D75 = new CieXyz(0.94972F, 1F, 1.22638F); |
|||
|
|||
/// <summary>
|
|||
/// Equal energy
|
|||
/// </summary>
|
|||
public static readonly CieXyz E = new CieXyz(1F, 1F, 1F); |
|||
|
|||
/// <summary>
|
|||
/// Cool White Fluorescent
|
|||
/// </summary>
|
|||
public static readonly CieXyz F2 = new CieXyz(0.99186F, 1F, 0.67393F); |
|||
|
|||
/// <summary>
|
|||
/// D65 simulatorF, Daylight simulator
|
|||
/// </summary>
|
|||
public static readonly CieXyz F7 = new CieXyz(0.95041F, 1F, 1.08747F); |
|||
|
|||
/// <summary>
|
|||
/// Philips TL84F, Ultralume 40
|
|||
/// </summary>
|
|||
public static readonly CieXyz F11 = new CieXyz(1.00962F, 1F, 0.64350F); |
|||
} |
|||
} |
|||
@ -0,0 +1,213 @@ |
|||
// <copyright file="LinearRgb.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents an linear Rgb color with specified <see cref="IRgbWorkingSpace"/> working space
|
|||
/// </summary>
|
|||
internal struct LinearRgb : IColorVector, IEquatable<LinearRgb>, IAlmostEquatable<LinearRgb, float> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="LinearRgb"/> that has R, G, and B values set to zero.
|
|||
/// </summary>
|
|||
public static readonly LinearRgb Empty = default(LinearRgb); |
|||
|
|||
/// <summary>
|
|||
/// The default LinearRgb working space
|
|||
/// </summary>
|
|||
public static readonly IRgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb; |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private readonly Vector3 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="LinearRgb"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component ranging between 0 and 1.</param>
|
|||
/// <param name="g">The green component ranging between 0 and 1.</param>
|
|||
/// <param name="b">The blue component ranging between 0 and 1.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public LinearRgb(float r, float g, float b) |
|||
: this(new Vector3(r, g, b)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="LinearRgb"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component ranging between 0 and 1.</param>
|
|||
/// <param name="g">The green component ranging between 0 and 1.</param>
|
|||
/// <param name="b">The blue component ranging between 0 and 1.</param>
|
|||
/// <param name="workingSpace">The rgb working space.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public LinearRgb(float r, float g, float b, IRgbWorkingSpace workingSpace) |
|||
: this(new Vector3(r, g, b), workingSpace) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="LinearRgb"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the r, g, b components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public LinearRgb(Vector3 vector) |
|||
: this(vector, DefaultWorkingSpace) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="LinearRgb"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the r, g, b components.</param>
|
|||
/// <param name="workingSpace">The LinearRgb working space.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public LinearRgb(Vector3 vector, IRgbWorkingSpace workingSpace) |
|||
: this() |
|||
{ |
|||
// Clamp to 0-1 range.
|
|||
this.backingVector = Vector3.Clamp(vector, Vector3.Zero, Vector3.One); |
|||
this.WorkingSpace = workingSpace; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the red component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float R |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.X; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the green component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float G |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the blue component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float B |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the LinearRgb color space <seealso cref="RgbWorkingSpaces"/>
|
|||
/// </summary>
|
|||
public IRgbWorkingSpace WorkingSpace { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="LinearRgb"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector3 Vector |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="LinearRgb"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="LinearRgb"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="LinearRgb"/> 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 ==(LinearRgb left, LinearRgb right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="LinearRgb"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="LinearRgb"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="LinearRgb"/> 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 !=(LinearRgb left, LinearRgb right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.backingVector.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "LinearRgb [ Empty ]"; |
|||
} |
|||
|
|||
return $"LinearRgb [ R={this.R:#0.##}, G={this.G:#0.##}, B={this.B:#0.##} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is LinearRgb) |
|||
{ |
|||
return this.Equals((LinearRgb)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(LinearRgb other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool AlmostEquals(LinearRgb other, float precision) |
|||
{ |
|||
var result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return result.X <= precision |
|||
&& result.Y <= precision |
|||
&& result.Z <= precision; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,180 @@ |
|||
// <copyright file="Lms.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// LMS is a color space represented by the response of the three types of cones of the human eye,
|
|||
/// named after their responsivity (sensitivity) at long, medium and short wavelengths.
|
|||
/// <see href="https://en.wikipedia.org/wiki/LMS_color_space"/>
|
|||
/// </summary>
|
|||
internal struct Lms : IColorVector, IEquatable<Lms>, IAlmostEquatable<Lms, float> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="Lms"/> that has L, M, and S values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Lms Empty = default(Lms); |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private readonly Vector3 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Lms"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">L represents the responsivity at long wavelengths.</param>
|
|||
/// <param name="m">M represents the responsivity at medium wavelengths.</param>
|
|||
/// <param name="s">S represents the responsivity at short wavelengths.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Lms(float l, float m, float s) |
|||
: this(new Vector3(l, m, s)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Lms"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the l, m, s components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Lms(Vector3 vector) |
|||
: this() |
|||
{ |
|||
// Not clamping as documentation about this space seems to indicate "usual" ranges
|
|||
this.backingVector = vector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the L long component.
|
|||
/// <remarks>A value usually ranging between -1 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float L |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.X; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the M medium component.
|
|||
/// <remarks>A value usually ranging between -1 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float M |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the S short component.
|
|||
/// <remarks>A value usually ranging between -1 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float S |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Lms"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector3 Vector |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Lms"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Lms"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Lms"/> 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 ==(Lms left, Lms right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Lms"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Lms"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Lms"/> 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 !=(Lms left, Lms right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.backingVector.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Lms [ Empty ]"; |
|||
} |
|||
|
|||
return $"Lms [ L={this.L:#0.##}, M={this.M:#0.##}, S={this.S:#0.##} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is Lms) |
|||
{ |
|||
return this.Equals((Lms)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Lms other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool AlmostEquals(Lms other, float precision) |
|||
{ |
|||
var result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return result.X <= precision |
|||
&& result.Y <= precision |
|||
&& result.Z <= precision; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,233 @@ |
|||
// <copyright file="Rgb.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents an RGB color with specified <see cref="IRgbWorkingSpace"/> working space
|
|||
/// </summary>
|
|||
internal struct Rgb : IColorVector, IEquatable<Rgb>, IAlmostEquatable<Rgb, float> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="Rgb"/> that has R, G, and B values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Rgb Empty = default(Rgb); |
|||
|
|||
/// <summary>
|
|||
/// The default rgb working space
|
|||
/// </summary>
|
|||
public static readonly IRgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb; |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private readonly Vector3 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgb"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component ranging between 0 and 1.</param>
|
|||
/// <param name="g">The green component ranging between 0 and 1.</param>
|
|||
/// <param name="b">The blue component ranging between 0 and 1.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb(float r, float g, float b) |
|||
: this(new Vector3(r, g, b)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgb"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component ranging between 0 and 1.</param>
|
|||
/// <param name="g">The green component ranging between 0 and 1.</param>
|
|||
/// <param name="b">The blue component ranging between 0 and 1.</param>
|
|||
/// <param name="workingSpace">The rgb working space.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb(float r, float g, float b, IRgbWorkingSpace workingSpace) |
|||
: this(new Vector3(r, g, b), workingSpace) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgb"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the r, g, b components.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb(Vector3 vector) |
|||
: this(vector, DefaultWorkingSpace) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgb"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector representing the r, g, b components.</param>
|
|||
/// <param name="workingSpace">The rgb working space.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb(Vector3 vector, IRgbWorkingSpace workingSpace) |
|||
: this() |
|||
{ |
|||
// Clamp to 0-1 range.
|
|||
this.backingVector = Vector3.Clamp(vector, Vector3.Zero, Vector3.One); |
|||
this.WorkingSpace = workingSpace; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the red component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float R |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.X; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the green component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float G |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the blue component.
|
|||
/// <remarks>A value usually ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float B |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector.Z; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the Rgb color space <seealso cref="RgbWorkingSpaces"/>
|
|||
/// </summary>
|
|||
public IRgbWorkingSpace WorkingSpace |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Rgb"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector3 Vector |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => this.backingVector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Rgba32"/> to a
|
|||
/// <see cref="Rgb"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Rgba32"/> to convert.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Rgb"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator Rgb(Rgba32 color) |
|||
{ |
|||
return new Rgb(color.R / 255F, color.G / 255F, color.B / 255F); |
|||
} |
|||
|
|||
/// <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) |
|||
{ |
|||
return 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) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.backingVector.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Rgb [ Empty ]"; |
|||
} |
|||
|
|||
return $"Rgb [ R={this.R:#0.##}, G={this.G:#0.##}, B={this.B:#0.##} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is Rgb) |
|||
{ |
|||
return this.Equals((Rgb)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Rgb other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool AlmostEquals(Rgb other, float precision) |
|||
{ |
|||
var result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return result.X <= precision |
|||
&& result.Y <= precision |
|||
&& result.Z <= precision; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,117 @@ |
|||
// <copyright file="RgbWorkingSpaces.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
// ReSharper disable InconsistentNaming
|
|||
namespace ImageSharp.ColorSpaces |
|||
{ |
|||
using ImageSharp.ColorSpaces.Conversion.Implementation.Rgb; |
|||
|
|||
/// <summary>
|
|||
/// Chromaticity coordinates taken from:
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html"/>
|
|||
/// </summary>
|
|||
internal static class RgbWorkingSpaces |
|||
{ |
|||
/// <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 IRgbWorkingSpace SRgb = new RgbWorkingSpace(Illuminants.D65, new SRgbCompanding(), 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 IRgbWorkingSpace SRgbSimplified = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), 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 IRgbWorkingSpace Rec709 = new RgbWorkingSpace(Illuminants.D65, new Rec709Companding(), 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 IRgbWorkingSpace Rec2020 = new RgbWorkingSpace(Illuminants.D65, new Rec2020Companding(), 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 IRgbWorkingSpace ECIRgbv2 = new RgbWorkingSpace(Illuminants.D50, new LCompanding(), 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 IRgbWorkingSpace AdobeRgb1998 = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), 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 IRgbWorkingSpace ApplesRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(1.8F), 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 IRgbWorkingSpace BestRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), 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 IRgbWorkingSpace BetaRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), 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 IRgbWorkingSpace BruceRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), 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 IRgbWorkingSpace CIERgb = new RgbWorkingSpace(Illuminants.E, new GammaCompanding(2.2F), 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 IRgbWorkingSpace ColorMatchRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), 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 IRgbWorkingSpace DonRgb4 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), 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 IRgbWorkingSpace EktaSpacePS5 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), 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 IRgbWorkingSpace NTSCRgb = new RgbWorkingSpace(Illuminants.C, new GammaCompanding(2.2F), 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 IRgbWorkingSpace PALSECAMRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), 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 IRgbWorkingSpace ProPhotoRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), 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 IRgbWorkingSpace SMPTECRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), 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 IRgbWorkingSpace WideGamutRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F))); |
|||
} |
|||
} |
|||
@ -1,167 +0,0 @@ |
|||
// <copyright file="Bgra32.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Colors.Spaces |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Represents an BGRA (blue, green, red, alpha) color.
|
|||
/// </summary>
|
|||
public struct Bgra32 : IEquatable<Bgra32> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a 32 bit <see cref="Bgra32"/> that has B, G, R, and A values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Bgra32 Empty = default(Bgra32); |
|||
|
|||
/// <summary>
|
|||
/// Min range used for clamping
|
|||
/// </summary>
|
|||
private static readonly Vector4 VectorMin = Vector4.Zero; |
|||
|
|||
/// <summary>
|
|||
/// Max range used for clamping
|
|||
/// </summary>
|
|||
private static readonly Vector4 VectorMax = new Vector4(255); |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private readonly Vector4 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgra32"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="b">The blue component of this <see cref="Bgra32"/>.</param>
|
|||
/// <param name="g">The green component of this <see cref="Bgra32"/>.</param>
|
|||
/// <param name="r">The red component of this <see cref="Bgra32"/>.</param>
|
|||
/// <param name="a">The alpha component of this <see cref="Bgra32"/>.</param>
|
|||
public Bgra32(byte b, byte g, byte r, byte a = 255) |
|||
: this() |
|||
{ |
|||
this.backingVector = Vector4.Clamp(new Vector4(b, g, r, a), VectorMin, VectorMax); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the blue component of the color
|
|||
/// </summary>
|
|||
public byte B => (byte)this.backingVector.X; |
|||
|
|||
/// <summary>
|
|||
/// Gets the green component of the color
|
|||
/// </summary>
|
|||
public byte G => (byte)this.backingVector.Y; |
|||
|
|||
/// <summary>
|
|||
/// Gets the red component of the color
|
|||
/// </summary>
|
|||
public byte R => (byte)this.backingVector.Z; |
|||
|
|||
/// <summary>
|
|||
/// Gets the alpha component of the color
|
|||
/// </summary>
|
|||
public byte A => (byte)this.backingVector.W; |
|||
|
|||
/// <summary>
|
|||
/// Gets the <see cref="Bgra32"/> integer representation of the color.
|
|||
/// </summary>
|
|||
public int Bgra => (this.R << 16) | (this.G << 8) | (this.B << 0) | (this.A << 24); |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Bgra32"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Rgba32"/> to a
|
|||
/// <see cref="Bgra32"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Rgba32"/> to convert.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Bgra32"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Bgra32(Rgba32 color) |
|||
{ |
|||
return new Bgra32(color.B, color.G, color.R, color.A); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Bgra32"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Bgra32"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Bgra32"/> 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 ==(Bgra32 left, Bgra32 right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Bgra32"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Bgra32"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Bgra32"/> 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 !=(Bgra32 left, Bgra32 right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is Bgra32) |
|||
{ |
|||
Bgra32 color = (Bgra32)obj; |
|||
|
|||
return this.backingVector == color.backingVector; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.backingVector.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Bgra32 [ Empty ]"; |
|||
} |
|||
|
|||
return $"Bgra32 [ B={this.B}, G={this.G}, R={this.R}, A={this.A} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(Bgra32 other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
// <copyright file="Image.LoadPixelData.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.IO; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Threading.Tasks; |
|||
using Formats; |
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <content>
|
|||
/// Adds static methods allowing the creation of new image from raw pixel data.
|
|||
/// </content>
|
|||
public static partial class Image |
|||
{ |
|||
/// <summary>
|
|||
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the raw <typeparamref name="TPixel"/> data.
|
|||
/// </summary>
|
|||
/// <param name="data">The byte array containing image data.</param>
|
|||
/// <param name="width">The width of the final image.</param>
|
|||
/// <param name="height">The height of the final image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> LoadPixelData<TPixel>(Span<TPixel> data, int width, int height) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
=> LoadPixelData(Configuration.Default, data, width, height); |
|||
|
|||
/// <summary>
|
|||
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given byte array in <typeparamref name="TPixel"/> format.
|
|||
/// </summary>
|
|||
/// <param name="data">The byte array containing image data.</param>
|
|||
/// <param name="width">The width of the final image.</param>
|
|||
/// <param name="height">The height of the final image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> LoadPixelData<TPixel>(Span<byte> data, int width, int height) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
=> LoadPixelData<TPixel>(Configuration.Default, data, width, height); |
|||
|
|||
/// <summary>
|
|||
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given byte array in <typeparamref name="TPixel"/> format.
|
|||
/// </summary>
|
|||
/// <param name="config">The config for the decoder.</param>
|
|||
/// <param name="data">The byte array containing image data.</param>
|
|||
/// <param name="width">The width of the final image.</param>
|
|||
/// <param name="height">The height of the final image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> LoadPixelData<TPixel>(Configuration config, Span<byte> data, int width, int height) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
=> LoadPixelData(config, data.NonPortableCast<byte, TPixel>(), width, height); |
|||
|
|||
/// <summary>
|
|||
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the raw <typeparamref name="TPixel"/> data.
|
|||
/// </summary>
|
|||
/// <param name="config">The config for the decoder.</param>
|
|||
/// <param name="data">The Span containing the image Pixel data.</param>
|
|||
/// <param name="width">The width of the final image.</param>
|
|||
/// <param name="height">The height of the final image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> LoadPixelData<TPixel>(Configuration config, Span<TPixel> data, int width, int height) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
int count = width * height; |
|||
Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); |
|||
|
|||
var image = new Image<TPixel>(config, width, height); |
|||
SpanHelper.Copy(data, image.Pixels, count); |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue