mirror of
https://github.com/DarthAffe/RGB.NET.git
synced 2025-12-13 01:58:30 +00:00
Added XYZ, Lab and LCh color-methods
This commit is contained in:
parent
105fdea2d7
commit
1975b9bf48
203
RGB.NET.Core/Color/HclColor.cs
Normal file
203
RGB.NET.Core/Color/HclColor.cs
Normal file
@ -0,0 +1,203 @@
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
using System;
|
||||
|
||||
namespace RGB.NET.Core
|
||||
{
|
||||
public static class HclColor
|
||||
{
|
||||
#region Getter
|
||||
|
||||
/// <summary>
|
||||
/// Gets the H component value (Hcl-color space) of this <see cref="Color"/> in the range [0..360].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetHclH(this in Color color) => color.GetHcl().l;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the c component value (Hcl-color space) of this <see cref="Color"/> in the range [0..1].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetHclC(this in Color color) => color.GetHcl().c;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the l component value (Hcl-color space) of this <see cref="Color"/> in the range [0..1].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetHclL(this in Color color) => color.GetHcl().h;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the H, c and l component values (Hcl-color space) of this <see cref="Color"/>.
|
||||
/// H in the range [0..360].
|
||||
/// c in the range [0..1].
|
||||
/// l in the range [0..1].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static (float h, float c, float l) GetHcl(this in Color color)
|
||||
=> CalculateHclFromRGB(color.R, color.G, color.B);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Manipulation
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given Hcl values to this color.
|
||||
/// </summary>
|
||||
/// <param name="h">The H value to add.</param>
|
||||
/// <param name="c">The c value to add.</param>
|
||||
/// <param name="l">The l value to add.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color AddHcl(this in Color color, float h = 0, float c = 0, float l = 0)
|
||||
{
|
||||
(float cH, float cC, float cL) = color.GetHcl();
|
||||
return Create(color.A, cH + h, cC + c, cL + l);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given Hcl values to this color.
|
||||
/// </summary>
|
||||
/// <param name="h">The H value to subtract.</param>
|
||||
/// <param name="c">The c value to subtract.</param>
|
||||
/// <param name="l">The l value to subtract.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SubtractHcl(this in Color color, float h = 0, float c = 0, float l = 0)
|
||||
{
|
||||
(float cH, float cC, float cL) = color.GetHcl();
|
||||
return Create(color.A, cH - h, cC - c, cL - l);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies the given Hcl values to this color.
|
||||
/// </summary>
|
||||
/// <param name="h">The H value to multiply.</param>
|
||||
/// <param name="c">The c value to multiply.</param>
|
||||
/// <param name="l">The l value to multiply.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color MultiplyHcl(this in Color color, float h = 1, float c = 1, float l = 1)
|
||||
{
|
||||
(float cH, float cC, float cL) = color.GetHcl();
|
||||
return Create(color.A, cH * h, cC * c, cL * l);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the given Hcl values to this color.
|
||||
/// </summary>
|
||||
/// <param name="h">The H value to divide.</param>
|
||||
/// <param name="c">The c value to divide.</param>
|
||||
/// <param name="l">The l value to divide.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color DivideHcl(this in Color color, float h = 1, float c = 1, float l = 1)
|
||||
{
|
||||
(float cH, float cC, float cL) = color.GetHcl();
|
||||
return Create(color.A, cH / h, cC / c, cL / l);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given X value of this color.
|
||||
/// </summary>
|
||||
/// <param name="h">The H value to set.</param>
|
||||
/// <param name="c">The c value to set.</param>
|
||||
/// <param name="l">The l value to set.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SetHcl(this in Color color, float? h = null, float? c = null, float? l = null)
|
||||
{
|
||||
(float cH, float cC, float cL) = color.GetHcl();
|
||||
return Create(color.A, h ?? cH, c ?? cC, l ?? cL);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Factory
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using Hcl-Values.
|
||||
/// </summary>
|
||||
/// <param name="h">The H component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="c">The c component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="l">The l component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(float h, float c, float l)
|
||||
=> Create(1.0f, h, c, l);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using alpha and Hcl-Values.
|
||||
/// </summary>
|
||||
/// <param name="alpha">The alphc component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="h">The H component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="c">The c component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="l">The l component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(byte alpha, float h, float c, float l)
|
||||
=> Create((float)alpha / byte.MaxValue, h, c, l);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using alpha and Hcl-Values.
|
||||
/// </summary>
|
||||
/// <param name="alpha">The alphc component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="h">The H component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="c">The c component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="l">The l component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(int alpha, float h, float c, float l)
|
||||
=> Create((float)alpha / byte.MaxValue, h, c, l);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using alpha and Hcl-Values.
|
||||
/// </summary>
|
||||
/// <param name="alpha">The alphc component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="h">The H component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="c">The c component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="l">The l component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(float alpha, float h, float c, float l)
|
||||
{
|
||||
(float r, float g, float _b) = CalculateRGBFromHcl(h, c, l);
|
||||
return new Color(alpha, r, g, _b);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper
|
||||
|
||||
private static (float h, float c, float l) CalculateHclFromRGB(float r, float g, float b)
|
||||
{
|
||||
const float RADIANS_DEGREES_CONVERSION = 180.0f / MathF.PI;
|
||||
|
||||
(float l, float a, float _b) = LabColor.CalculateLabFromRGB(r, g, b);
|
||||
|
||||
float h, c;
|
||||
if (r.EqualsInTolerance(g) && r.EqualsInTolerance(b)) //DarthAffe 26.02.2021: The cumulated rounding errors are big enough to cause problems in that case
|
||||
{
|
||||
h = 0;
|
||||
c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = MathF.Atan2(_b, a);
|
||||
if (h >= 0) h *= RADIANS_DEGREES_CONVERSION;
|
||||
else h = 360 - (-h * RADIANS_DEGREES_CONVERSION);
|
||||
|
||||
c = MathF.Sqrt((a * a) + (_b * _b));
|
||||
}
|
||||
|
||||
return (h, c, l);
|
||||
}
|
||||
|
||||
private static (float r, float g, float b) CalculateRGBFromHcl(float h, float c, float l)
|
||||
{
|
||||
const float DEGREES_RADIANS_CONVERSION = MathF.PI / 180.0f;
|
||||
|
||||
h *= DEGREES_RADIANS_CONVERSION;
|
||||
float a = c * MathF.Cos(h);
|
||||
float b = c * MathF.Sign(h);
|
||||
|
||||
return LabColor.CalculateRGBFromLab(l, a, b);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
228
RGB.NET.Core/Color/LabColor.cs
Normal file
228
RGB.NET.Core/Color/LabColor.cs
Normal file
@ -0,0 +1,228 @@
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
using System;
|
||||
|
||||
namespace RGB.NET.Core
|
||||
{
|
||||
public static class LabColor
|
||||
{
|
||||
#region Getter
|
||||
|
||||
/// <summary>
|
||||
/// Gets the L component value (Lab-color space) of this <see cref="Color"/> in the range [0..100].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetLabL(this in Color color) => color.GetLab().l;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the a component value (Lab-color space) of this <see cref="Color"/> in the range [0..1].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetLabA(this in Color color) => color.GetLab().a;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the b component value (Lab-color space) of this <see cref="Color"/> in the range [0..1].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetLabB(this in Color color) => color.GetLab().b;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the L, a and b component values (Lab-color space) of this <see cref="Color"/>.
|
||||
/// L in the range [0..100].
|
||||
/// a in the range [0..1].
|
||||
/// b in the range [0..1].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static (float l, float a, float b) GetLab(this in Color color)
|
||||
=> CalculateLabFromRGB(color.R, color.G, color.B);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Manipulation
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given Lab values to this color.
|
||||
/// </summary>
|
||||
/// <param name="l">The L value to add.</param>
|
||||
/// <param name="a">The a value to add.</param>
|
||||
/// <param name="b">The b value to add.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color AddLab(this in Color color, float l = 0, float a = 0, float b = 0)
|
||||
{
|
||||
(float cL, float cA, float cB) = color.GetLab();
|
||||
return Create(color.A, cL + l, cA + a, cB + b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given Lab values to this color.
|
||||
/// </summary>
|
||||
/// <param name="l">The L value to subtract.</param>
|
||||
/// <param name="a">The a value to subtract.</param>
|
||||
/// <param name="b">The b value to subtract.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SubtractLab(this in Color color, float l = 0, float a = 0, float b = 0)
|
||||
{
|
||||
(float cL, float cA, float cB) = color.GetLab();
|
||||
return Create(color.A, cL - l, cA - a, cB - b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies the given Lab values to this color.
|
||||
/// </summary>
|
||||
/// <param name="l">The L value to multiply.</param>
|
||||
/// <param name="a">The a value to multiply.</param>
|
||||
/// <param name="b">The b value to multiply.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color MultiplyLab(this in Color color, float l = 1, float a = 1, float b = 1)
|
||||
{
|
||||
(float cL, float cA, float cB) = color.GetLab();
|
||||
return Create(color.A, cL * l, cA * a, cB * b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the given Lab values to this color.
|
||||
/// </summary>
|
||||
/// <param name="l">The L value to divide.</param>
|
||||
/// <param name="a">The a value to divide.</param>
|
||||
/// <param name="b">The b value to divide.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color DivideLab(this in Color color, float l = 1, float a = 1, float b = 1)
|
||||
{
|
||||
(float cL, float cA, float cB) = color.GetLab();
|
||||
return Create(color.A, cL / l, cA / a, cB / b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given X valueof this color.
|
||||
/// </summary>
|
||||
/// <param name="l">The L value to set.</param>
|
||||
/// <param name="a">The a value to set.</param>
|
||||
/// <param name="b">The b value to set.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SetLab(this in Color color, float? l = null, float? a = null, float? b = null)
|
||||
{
|
||||
(float cL, float cA, float cB) = color.GetLab();
|
||||
return Create(color.A, l ?? cL, a ?? cA, b ?? cB);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Factory
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using Lab-Values.
|
||||
/// </summary>
|
||||
/// <param name="l">The L component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="a">The a component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The b component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(float l, float a, float b)
|
||||
=> Create(1.0f, l, a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using alpha and Lab-Values.
|
||||
/// </summary>
|
||||
/// <param name="alpha">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="l">The L component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="a">The a component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The b component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(byte alpha, float l, float a, float b)
|
||||
=> Create((float)alpha / byte.MaxValue, l, a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using alpha and Lab-Values.
|
||||
/// </summary>
|
||||
/// <param name="alpha">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="l">The L component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="a">The a component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The b component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(int alpha, float l, float a, float b)
|
||||
=> Create((float)alpha / byte.MaxValue, l, a, b);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using alpha and Lab-Values.
|
||||
/// </summary>
|
||||
/// <param name="alpha">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="l">The L component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="a">The a component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The b component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(float alpha, float l, float a, float b)
|
||||
{
|
||||
(float r, float g, float _b) = CalculateRGBFromLab(l, a, b);
|
||||
return new Color(alpha, r, g, _b);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper
|
||||
|
||||
internal static (float l, float a, float b) CalculateLabFromRGB(float r, float g, float b)
|
||||
{
|
||||
(float x, float y, float z) = XYZColor.CaclulateXYZFromRGB(r, g, b);
|
||||
return CaclulateLabFromXYZ(x, y, z);
|
||||
|
||||
//const float LAB_MULTIPLIER = (1f / 127f) * 0.5f;
|
||||
|
||||
//(float x, float y, float z) = XYZColor.CaclulateXYZFromRGB(r, g, b);
|
||||
//(float l, float a, float _b) = CaclulateLabFromXYZ(x, y, z);
|
||||
//return (l / 100.0f, 0.5f + (a * LAB_MULTIPLIER), 0.5f + (_b * LAB_MULTIPLIER));
|
||||
}
|
||||
|
||||
internal static (float r, float g, float b) CalculateRGBFromLab(float l, float a, float b)
|
||||
{
|
||||
(float x, float y, float z) = CalculateXYZFromLab(l, a, b);
|
||||
return XYZColor.CalculateRGBFromXYZ(x, y, z);
|
||||
|
||||
//(float x, float y, float z) = CalculateXYZFromLab(100.0f * l, 254.0f * (a - 0.5f), 2.0f * 254.0f * (b - 0.5f));
|
||||
//return XYZColor.CalculateRGBFromXYZ(x, y, z);
|
||||
}
|
||||
|
||||
private static (float l, float a, float b) CaclulateLabFromXYZ(float x, float y, float z)
|
||||
{
|
||||
const float ONETHRID = 1.0f / 3.0f;
|
||||
const float FACTOR2 = 16.0f / 116.0f;
|
||||
|
||||
x /= 95.047f;
|
||||
y /= 100.0f;
|
||||
z /= 108.883f;
|
||||
|
||||
x = ((x > 0.008856f) ? (MathF.Pow(x, ONETHRID)) : ((7.787f * x) + FACTOR2));
|
||||
y = ((y > 0.008856f) ? (MathF.Pow(y, ONETHRID)) : ((7.787f * y) + FACTOR2));
|
||||
z = ((z > 0.008856f) ? (MathF.Pow(z, ONETHRID)) : ((7.787f * z) + FACTOR2));
|
||||
|
||||
float l = (116.0f * y) - 16.0f;
|
||||
float a = 500.0f * (x - y);
|
||||
float b = 200.0f * (y - z);
|
||||
|
||||
return (l, a, b);
|
||||
}
|
||||
|
||||
private static (float x, float y, float z) CalculateXYZFromLab(float l, float a, float b)
|
||||
{
|
||||
const float FACTOR2 = 16.0f / 116.0f;
|
||||
|
||||
float y = (l + 16.0f) / 116.0f;
|
||||
float x = (a / 500.0f) + y;
|
||||
float z = y - (b / 200.0f);
|
||||
|
||||
float powX = MathF.Pow(y, 3.0f);
|
||||
float powY = MathF.Pow(y, 3.0f);
|
||||
float powZ = MathF.Pow(y, 3.0f);
|
||||
|
||||
y = ((powY > 0.008856f) ? (powY) : ((y - FACTOR2) / 7.787f));
|
||||
x = ((powX > 0.008856f) ? (powX) : ((x - FACTOR2) / 7.787f));
|
||||
z = ((powZ > 0.008856f) ? (powZ) : ((z - FACTOR2) / 7.787f));
|
||||
|
||||
return (95.047f * x, 100.0f * y, 108.883f * z);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
200
RGB.NET.Core/Color/XYZColor.cs
Normal file
200
RGB.NET.Core/Color/XYZColor.cs
Normal file
@ -0,0 +1,200 @@
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
using System;
|
||||
|
||||
namespace RGB.NET.Core
|
||||
{
|
||||
public static class XYZColor
|
||||
{
|
||||
#region Getter
|
||||
|
||||
/// <summary>
|
||||
/// Gets the X component value (XYZ-color space) of this <see cref="Color"/> in the range [0..95.047].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetX(this in Color color) => color.GetXYZ().x;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Y component value (XYZ-color space) of this <see cref="Color"/> in the range [0..100].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetY(this in Color color) => color.GetXYZ().y;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Z component value (XYZ-color space) of this <see cref="Color"/> in the range [0..108.883].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetZ(this in Color color) => color.GetXYZ().z;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the X, Y and Z component values (XYZ-color space) of this <see cref="Color"/>.
|
||||
/// X in the range [0..95.047].
|
||||
/// Y in the range [0..100].
|
||||
/// Z in the range [0..108.883].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static (float x, float y, float z) GetXYZ(this in Color color)
|
||||
=> CaclulateXYZFromRGB(color.R, color.G, color.B);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Manipulation
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given XYZ values to this color.
|
||||
/// </summary>
|
||||
/// <param name="x">The X value to add.</param>
|
||||
/// <param name="y">The Y value to add.</param>
|
||||
/// <param name="z">The Z value to add.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color AddXYZ(this in Color color, float x = 0, float y = 0, float z = 0)
|
||||
{
|
||||
(float cX, float cY, float cZ) = color.GetXYZ();
|
||||
return Create(color.A, cX + x, cY + y, cZ + z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given XYZ values to this color.
|
||||
/// </summary>
|
||||
/// <param name="x">The X value to subtract.</param>
|
||||
/// <param name="y">The Y value to subtract.</param>
|
||||
/// <param name="z">The Z value to subtract.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SubtractXYZ(this in Color color, float x = 0, float y = 0, float z = 0)
|
||||
{
|
||||
(float cX, float cY, float cZ) = color.GetXYZ();
|
||||
return Create(color.A, cX - x, cY - y, cZ - z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies the given XYZ values to this color.
|
||||
/// </summary>
|
||||
/// <param name="x">The X value to multiply.</param>
|
||||
/// <param name="y">The Y value to multiply.</param>
|
||||
/// <param name="z">The Z value to multiply.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color MultiplyXYZ(this in Color color, float x = 1, float y = 1, float z = 1)
|
||||
{
|
||||
(float cX, float cY, float cZ) = color.GetXYZ();
|
||||
return Create(color.A, cX * x, cY * y, cZ * z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the given XYZ values to this color.
|
||||
/// </summary>
|
||||
/// <param name="x">The X value to divide.</param>
|
||||
/// <param name="y">The Y value to divide.</param>
|
||||
/// <param name="z">The Z value to divide.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color DivideXYZ(this in Color color, float x = 1, float y = 1, float z = 1)
|
||||
{
|
||||
(float cX, float cY, float cZ) = color.GetXYZ();
|
||||
return Create(color.A, cX / x, cY / y, cZ / z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given X valueof this color.
|
||||
/// </summary>
|
||||
/// <param name="x">The X value to set.</param>
|
||||
/// <param name="y">The Y value to set.</param>
|
||||
/// <param name="z">The Z value to set.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SetXYZ(this in Color color, float? x = null, float? y = null, float? value = null)
|
||||
{
|
||||
(float cX, float cY, float cZ) = color.GetXYZ();
|
||||
return Create(color.A, x ?? cX, y ?? cY, value ?? cZ);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Factory
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using XYZ-Values.
|
||||
/// </summary>
|
||||
/// <param name="x">The X component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="y">The Y component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="z">The Z component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(float x, float y, float z)
|
||||
=> Create(1.0f, x, y, z);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using alpha and XYZ-Values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="x">The X component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="y">The Y component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="z">The Z component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(byte a, float x, float y, float z)
|
||||
=> Create((float)a / byte.MaxValue, x, y, z);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using alpha and XYZ-Values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="x">The X component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="y">The Y component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="z">The Z component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(int a, float x, float y, float z)
|
||||
=> Create((float)a / byte.MaxValue, x, y, z);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using alpha and XYZ-Values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="x">The X component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="y">The Y component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="z">The Z component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(float a, float x, float y, float z)
|
||||
{
|
||||
(float r, float g, float b) = CalculateRGBFromXYZ(x, y, z);
|
||||
return new Color(a, r, g, b);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper
|
||||
|
||||
internal static (float x, float y, float z) CaclulateXYZFromRGB(float r, float g, float b)
|
||||
{
|
||||
r = ((r > 0.04045f) ? MathF.Pow(((r + 0.055f) / 1.055f), 2.4f) : (r / 12.92f)) * 100.0f;
|
||||
g = ((g > 0.04045f) ? MathF.Pow(((g + 0.055f) / 1.055f), 2.4f) : (g / 12.92f)) * 100.0f;
|
||||
b = ((b > 0.04045f) ? MathF.Pow(((b + 0.055f) / 1.055f), 2.4f) : (b / 12.92f)) * 100.0f;
|
||||
|
||||
float x = (r * 0.4124f) + (g * 0.3576f) + (b * 0.1805f);
|
||||
float y = (r * 0.2126f) + (g * 0.7152f) + (b * 0.0722f);
|
||||
float z = (r * 0.0193f) + (g * 0.1192f) + (b * 0.9505f);
|
||||
|
||||
return (x, y, z);
|
||||
}
|
||||
|
||||
internal static (float r, float g, float b) CalculateRGBFromXYZ(float x, float y, float z)
|
||||
{
|
||||
const float INVERSE_EXPONENT = 1.0f / 2.4f;
|
||||
|
||||
x /= 100.0f;
|
||||
y /= 100.0f;
|
||||
z /= 100.0f;
|
||||
|
||||
float r = (x * 3.2406f) + (y * -1.5372f) + (z * -0.4986f);
|
||||
float g = (x * -0.9689f) + (y * 1.8758f) + (z * 0.0415f);
|
||||
float b = (x * 0.0557f) + (y * -0.2040f) + (z * 1.0570f);
|
||||
|
||||
r = ((r > 0.0031308f) ? ((1.055f * (MathF.Pow(r, INVERSE_EXPONENT))) - 0.055f) : (12.92f * r));
|
||||
g = ((g > 0.0031308f) ? ((1.055f * (MathF.Pow(g, INVERSE_EXPONENT))) - 0.055f) : (12.92f * g));
|
||||
b = ((b > 0.0031308f) ? ((1.055f * (MathF.Pow(b, INVERSE_EXPONENT))) - 0.055f) : (12.92f * b));
|
||||
|
||||
return (r, g, b);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user