-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathXyzConverter.cs
More file actions
128 lines (109 loc) · 3.6 KB
/
Copy pathXyzConverter.cs
File metadata and controls
128 lines (109 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System;
namespace PoshCode.Pansies.ColorSpaces.Conversions
{
internal static class XyzConverter
{
private static readonly object WhiteReferenceLock = new object();
private static readonly Xyz DefaultWhiteReference = new Xyz
{
X = 95.047,
Y = 100.000,
Z = 108.883
};
#region Constants/Helper methods for Xyz related spaces
internal static IXyz WhiteReference { get; private set; }
internal const double Epsilon = 0.008856; // Intent is 216/24389
internal const double Kappa = 903.3; // Intent is 24389/27
static XyzConverter()
{
ResetWhiteReference();
}
public static IXyz GetWhiteReference()
{
lock (WhiteReferenceLock)
{
return Clone(WhiteReference ?? DefaultWhiteReference);
}
}
public static void SetWhiteReference(IXyz whiteReference)
{
if (whiteReference is null)
{
throw new ArgumentNullException(nameof(whiteReference));
}
lock (WhiteReferenceLock)
{
WhiteReference = Clone(whiteReference);
}
}
public static void ResetWhiteReference()
{
lock (WhiteReferenceLock)
{
WhiteReference = Clone(DefaultWhiteReference);
}
}
private static Xyz Clone(IXyz source)
{
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
if (source is Xyz xyz)
{
return new Xyz(xyz.X, xyz.Y, xyz.Z);
}
return new Xyz
{
X = source.X,
Y = source.Y,
Z = source.Z
};
}
internal static double CubicRoot(double n)
{
return Math.Pow(n, 1.0 / 3.0);
}
#endregion
internal static void ToColorSpace(IRgb color, IXyz item)
{
var r = PivotRgb(color.R / 255.0);
var g = PivotRgb(color.G / 255.0);
var b = PivotRgb(color.B / 255.0);
// Observer. = 2°, Illuminant = D65
item.X = r * 0.4124 + g * 0.3576 + b * 0.1805;
item.Y = r * 0.2126 + g * 0.7152 + b * 0.0722;
item.Z = r * 0.0193 + g * 0.1192 + b * 0.9505;
}
internal static IRgb ToColor(IXyz item)
{
// (Observer = 2°, Illuminant = D65)
var x = item.X / 100.0;
var y = item.Y / 100.0;
var z = item.Z / 100.0;
var r = x * 3.2406 + y * -1.5372 + z * -0.4986;
var g = x * -0.9689 + y * 1.8758 + z * 0.0415;
var b = x * 0.0557 + y * -0.2040 + z * 1.0570;
r = r > 0.0031308 ? 1.055 * Math.Pow(r, 1 / 2.4) - 0.055 : 12.92 * r;
g = g > 0.0031308 ? 1.055 * Math.Pow(g, 1 / 2.4) - 0.055 : 12.92 * g;
b = b > 0.0031308 ? 1.055 * Math.Pow(b, 1 / 2.4) - 0.055 : 12.92 * b;
return new Rgb
{
R = ToRgb(r),
G = ToRgb(g),
B = ToRgb(b)
};
}
private static double ToRgb(double n)
{
var result = 255.0 * n;
if (result < 0) return 0;
if (result > 255) return 255;
return result;
}
private static double PivotRgb(double n)
{
return (n > 0.04045 ? Math.Pow((n + 0.055) / 1.055, 2.4) : n / 12.92) * 100.0;
}
}
}