Files
Speckle.Material.Avalonia/Material.Colors/ColorManipulation/XyzConverter.cs
T
2022-07-05 10:21:35 +09:00

71 lines
2.2 KiB
C#

using System;
using Avalonia.Media;
namespace Material.Colors.ColorManipulation
{
internal static class XyzConverter
{
public static Color ToColor(this Xyz xyz)
{
double XyzRgb(double d)
{
if (d > 0.0031308)
return 255.0 * (1.055 * Math.Pow(d, 1.0 / 2.4) - 0.055);
return 255.0 * (12.92 * d);
}
byte Clip(double d)
{
if (d < 0) return 0;
if (d > 255) return 255;
return (byte) Math.Round(d);
}
var r = XyzRgb(3.2404542 * xyz.X - 1.5371385 * xyz.Y - 0.4985314 * xyz.Z);
var g = XyzRgb(-0.9692660 * xyz.X + 1.8760108 * xyz.Y + 0.0415560 * xyz.Z);
var b = XyzRgb(0.0556434 * xyz.X - 0.2040259 * xyz.Y + 1.0572252 * xyz.Z);
return Color.FromRgb(Clip(r), Clip(g), Clip(b));
}
public static Xyz ToXyz(this Color c)
{
double RgbXyz(double v)
{
v /= 255;
if (v > 0.04045)
return Math.Pow((v + 0.055) / 1.055, 2.4);
return v / 12.92;
}
var r = RgbXyz(c.R);
var g = RgbXyz(c.G);
var b = RgbXyz(c.B);
var x = 0.4124564 * r + 0.3575761 * g + 0.1804375 * b;
var y = 0.2126729 * r + 0.7151522 * g + 0.0721750 * b;
var z = 0.0193339 * r + 0.1191920 * g + 0.9503041 * b;
return new Xyz(x, y, z);
}
public static Xyz ToXyz(this Lab lab)
{
double LabXyz(double d)
{
if (d > LabConstants.ECubedRoot)
return d * d * d;
return (116 * d - 16) / LabConstants.K;
}
var y = (lab.L + 16.0) / 116.0;
var x = double.IsNaN(lab.A) ? y : y + lab.A / 500.0;
var z = double.IsNaN(lab.B) ? y : y - lab.B / 200.0;
y = LabConstants.WhitePointY * LabXyz(y);
x = LabConstants.WhitePointX * LabXyz(x);
z = LabConstants.WhitePointZ * LabXyz(z);
return new Xyz(x, y, z);
}
}
}