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
|
using System;
using Vector = System.Collections.Generic.IReadOnlyList<double>;
using Matrix = System.Collections.Generic.IReadOnlyList<System.Collections.Generic.IReadOnlyList<double>>;
namespace Colourful.Implementation.Conversion
{
/// <summary>
/// Base class for conversions between <see cref="RGBColor" /> and <see cref="XYZColor" />.
/// </summary>
public abstract class LinearRGBAndXYZConverterBase
{
/// <summary>
/// Computes RGB/XYZ matrix
/// </summary>
protected static Matrix GetRGBToXYZMatrix(IRGBWorkingSpace workingSpace)
{
if (workingSpace == null) throw new ArgumentNullException(nameof(workingSpace));
// for more info, see: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
var chromaticity = workingSpace.ChromaticityCoordinates;
double xr = chromaticity.R.x,
xg = chromaticity.G.x,
xb = chromaticity.B.x,
yr = chromaticity.R.y,
yg = chromaticity.G.y,
yb = chromaticity.B.y;
var Xr = xr / yr;
const double Yr = 1;
var Zr = (1 - xr - yr) / yr;
var Xg = xg / yg;
const double Yg = 1;
var Zg = (1 - xg - yg) / yg;
var Xb = xb / yb;
const double Yb = 1;
var Zb = (1 - xb - yb) / yb;
var S = new Vector[]
{
new[] { Xr, Xg, Xb },
new[] { Yr, Yg, Yb },
new[] { Zr, Zg, Zb },
}.Inverse();
var W = workingSpace.WhitePoint.Vector;
var SW = S.MultiplyBy(W);
var Sr = SW[0];
var Sg = SW[1];
var Sb = SW[2];
Matrix M = new Vector[]
{
new[] { Sr * Xr, Sg * Xg, Sb * Xb },
new[] { Sr * Yr, Sg * Yg, Sb * Yb },
new[] { Sr * Zr, Sg * Zg, Sb * Zb },
};
return M;
}
/// <summary>
/// Computes XYZ/RGB matrix
/// </summary>
protected static Matrix GetXYZToRGBMatrix(IRGBWorkingSpace workingSpace) => GetRGBToXYZMatrix(workingSpace).Inverse();
}
}
|