Given the chromaticity coordinates of an RGB system ($x_r$, $y_r$), ($x_g$, $y_g$) and ($x_b$, $y_b$) and its reference white ($X_W$, $Y_W$, $Z_W$), here is the method to compute the 3 × 3 matrix for converting RGB to XYZ:
$$\left[\matrix{X\\Y\\Z}\right] = [M]\left[\matrix{R\\G\\B}\right]$$where
$$[M] = \left[\matrix{{S_r X_r} & {S_g X_g} & {S_b X_b} \\ {S_r Y_r} & {S_g Y_g} & {S_b Y_b} \\ {S_r Z_r} & {S_g Z_g} & {S_b Z_b}}\right]$$ $$X_r = x_r / y_r$$ $$Y_r = 1$$ $$Z_r = (1 - x_r - y_r) / y_r$$ $$X_g = x_g / y_g$$ $$Y_g = 1$$ $$Z_g = (1 - x_g - y_g) / y_g$$ $$X_b = x_b / y_b$$ $$Y_b = 1$$ $$Z_b = (1 - x_b - y_b) / y_b$$ $$\left[\matrix{S_r\\S_g\\S_b}\right] = {\left[\matrix{X_r & X_g & X_b \\ Y_r & Y_g & Y_b \\ Z_r & Z_g & Z_b}\right]}^{-1} \left[\matrix{X_W\\Y_W\\Z_W}\right]$$Implementation Notes:
Using the chromaticities and reference whites of common RGB working spaces, I have done the math for you to compute the RGB-to-XYZ and XYZ-to-RGB matrices. Note that these matrices are given relative to their own reference whites. If you examine the matrices for these working spaces found inside ICC profiles (through the redColorantTag, greenColorantTag and blueColorantTag), those matrices will always be relative to D50, and therefore, the colorants have been subjected to a chromatic adaptation transformation if the working space reference white is not also D50.
RGB Working Space | Reference White | RGB to XYZ [M] | XYZ to RGB [M]-1 |
Adobe RGB (1998) | D65 | 0.5767309 0.1855540 0.1881852 |
2.0413690 -0.5649464 -0.3446944 |
AppleRGB | D65 | 0.4497288 0.3162486 0.1844926 |
2.9515373 -1.2894116 -0.4738445 |
Best RGB | D50 | 0.6326696 0.2045558 0.1269946 |
1.7552599 -0.4836786 -0.2530000 |
Beta RGB | D50 | 0.6712537 0.1745834 0.1183829 |
1.6832270 -0.4282363 -0.2360185 |
Bruce RGB | D65 | 0.4674162 0.2944512 0.1886026 |
2.7454669 -1.1358136 -0.4350269 |
CIE RGB | E | 0.4887180 0.3106803 0.2006017 |
2.3706743 -0.9000405 -0.4706338 |
ColorMatch RGB | D50 | 0.5093439 0.3209071 0.1339691 |
2.6422874 -1.2234270 -0.3930143 |
Don RGB 4 | D50 | 0.6457711 0.1933511 0.1250978 |
1.7603902 -0.4881198 -0.2536126 |
ECI RGB | D50 | 0.6502043 0.1780774 0.1359384 |
1.7827618 -0.4969847 -0.2690101 |
Ekta Space PS5 | D50 | 0.5938914 0.2729801 0.0973485 |
2.0043819 -0.7304844 -0.2450052 |
NTSC RGB | C | 0.6068909 0.1735011 0.2003480 |
1.9099961 -0.5324542 -0.2882091 |
PAL/SECAM RGB | D65 | 0.4306190 0.3415419 0.1783091 |
3.0628971 -1.3931791 -0.4757517 |
ProPhoto RGB | D50 | 0.7976749 0.1351917 0.0313534 |
1.3459433 -0.2556075 -0.0511118 |
SMPTE-C RGB | D65 | 0.3935891 0.3652497 0.1916313 |
3.5053960 -1.7394894 -0.5439640 |
sRGB | D65 | 0.4124564 0.3575761 0.1804375 |
3.2404542 -1.5371385 -0.4985314 |
Wide Gamut RGB | D50 | 0.7161046 0.1009296 0.1471858 |
1.4628067 -0.1840623 -0.2743606 |
For those RGB working spaces that are not natively D50, the Bradford-adapted, D50 matrices are:
RGB Working Space | Reference White | RGB to XYZ [M] | XYZ to RGB [M]-1 |
Adobe RGB (1998) | D50 | 0.6097559 0.2052401 0.1492240 |
1.9624274 -0.6105343 -0.3413404 |
AppleRGB | D50 | 0.4755678 0.3396722 0.1489800 |
2.8510695 -1.3605261 -0.4708281 |
Bruce RGB | D50 | 0.4941816 0.3204834 0.1495550 |
2.6502856 -1.2014485 -0.4289936 |
CIE RGB | D50 | 0.4868870 0.3062984 0.1710347 |
2.3638081 -0.8676030 -0.4988161 |
NTSC RGB | D50 | 0.6343706 0.1852204 0.1446290 |
1.8464881 -0.5521299 -0.2766458 |
PAL/SECAM RGB | D50 | 0.4552773 0.3675500 0.1413926 |
2.9603944 -1.4678519 -0.4685105 |
SMPTE-C RGB | D50 | 0.4163290 0.3931464 0.1547446 |
3.3921940 -1.8264027 -0.5385522 |
sRGB | D50 | 0.4360747 0.3850649 0.1430804 |
3.1338561 -1.6168667 -0.4906146 |