These algorithms were found at easyrgb.com under the heading "Color math/formulas":
//XYZ —> RGB
var_X = X / 100 //X from 0 to 95.047 (Observer = 2°, Illuminant = D65)
var_Y = Y / 100 //Y from 0 to 100.000
var_Z = Z / 100 //Z from 0 to 108.883
var_R = var_X * 3.2406 + var_Y * 1.5372 + var_Z * 0.4986
var_G = var_X * 0.9689 + var_Y * 1.8758 + var_Z * 0.0415
var_B = var_X * 0.0557 + var_Y * 0.2040 + var_Z * 1.0570
if ( var_R > 0.0031308 ) var_R = 1.055 * ( var_R ^ ( 1 / 2.4 ) )  0.055
else var_R = 12.92 * var_R
if ( var_G > 0.0031308 ) var_G = 1.055 * ( var_G ^ ( 1 / 2.4 ) )  0.055
else var_G = 12.92 * var_G
if ( var_B > 0.0031308 ) var_B = 1.055 * ( var_B ^ ( 1 / 2.4 ) )  0.055
else var_B = 12.92 * var_B
R = var_R * 255
G = var_G * 255
B = var_B * 255
Implemented in CooRecorder as:
Public Class CCmatrix
Public m(0 To 2, 0 To 2) As Double
End Class
Public D65TosRGB, D50TosRGB As CCmatrix
Public Sub setupConversionMatrixes()
D65TosRGB = New CCmatrix : D50TosRGB = New CCmatrix
With D65TosRGB 'see http://www.w3.org/Graphics/Color/srgb (see srgb.pdf file in ./dok directory
.m(0, 0) = 3.2406 : .m(0, 1) = 1.5372 : .m(0, 2) = 0.4986
.m(1, 0) = 0.9689 : .m(1, 1) = 1.8758 : .m(1, 2) = 0.0415
.m(2, 0) = 0.0557 : .m(2, 1) = 0.204 : .m(2, 2) = 1.057
End With
With D50TosRGB 'http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
.m(0, 0) = 3.1338561 : .m(0, 1) = 1.6168667 : .m(0, 2) = 0.4906146
.m(1, 0) = 0.9787684 : .m(1, 1) = 1.9161415 : .m(1, 2) = 0.033454
.m(2, 0) = 0.0719453 : .m(2, 1) = 0.2289914 : .m(2, 2) = 1.4052427
End With
End Sub
Public Function XYZ_To_RGB(ByVal X As Double, ByVal Y As Double, ByVal Z As Double, ByRef R As Double, ByRef G As Double, ByRef B As Double) As Boolean
Dim result As Boolean = False
On Error GoTo atExit
If D50TosRGB Is Nothing Then setupConversionMatrixes()
Dim ccM As CCmatrix
If p_CI_CalibrationTargetCardIsD50 Then
ccM = D50TosRGB
Else
ccM = D65TosRGB
End If
Dim var_X As Double = X / 100 'X from 0 to 95.047 (Observer = 2Â°, Illuminant = D65)
Dim var_Y As Double = Y / 100 'Y from 0 to 100.000
Dim var_Z As Double = Z / 100 'Z from 0 to 108.883
Dim var_R, var_G, var_B As Double
With ccM
var_R = var_X * .m(0, 0) + var_Y * .m(0, 1) + var_Z * .m(0, 2)
var_G = var_X * .m(1, 0) + var_Y * .m(1, 1) + var_Z * .m(1, 2)
var_B = var_X * .m(2, 0) + var_Y * .m(2, 1) + var_Z * .m(2, 2)
End With
If (var_R > 0.0031308) Then var_R = 1.055 * (var_R ^ (1 / 2.4))  0.055 Else var_R = 12.92 * var_R
If (var_G > 0.0031308) Then var_G = 1.055 * (var_G ^ (1 / 2.4))  0.055 Else var_G = 12.92 * var_G
If (var_B > 0.0031308) Then var_B = 1.055 * (var_B ^ (1 / 2.4))  0.055 Else var_B = 12.92 * var_B
R = var_R * 255 : If R < 0 Then R = 0 'seems to be missing in the specification at www.easyrgb.com
G = var_G * 255 : If G < 0 Then G = 0 'though apparently their Color calculator has implemented this test on zero.
B = var_B * 255 : If B < 0 Then B = 0
result = True
atExit: Return result
End Function
