cie-1931.cpp (1973B)
1 #include <cmath> 2 #include <iostream> 3 #include <sstream> 4 5 inline double gaussian(double x, double a, double u, double s1, double s2) { 6 double t = (x - u) / (x < u ? s1 : s2); 7 return a * exp(-(t * t) / 2); 8 } 9 10 struct XYZ 11 { 12 double x = 0, y = 0, z = 0; 13 14 XYZ() = default; 15 XYZ(double _x, double _y, double _z) 16 : x(_x) 17 , y(_y) 18 , z(_z) 19 {} 20 21 XYZ(double w) 22 : x(gaussian(w, 1.056, 599.8, 37.9, 31.0) + gaussian(w, 0.362, 442.0, 16.0, 26.7) + gaussian(w, -0.065, 501.1, 20.4, 26.2)) 23 , y(gaussian(w, 0.821, 568.8, 46.9, 40.5) + gaussian(w, 0.286, 530.9, 16.3, 31.1)) 24 , z(gaussian(w, 1.217, 437.0, 11.8, 36.0) + gaussian(w, 0.681, 459.0, 26.0, 13.8)) 25 {} 26 27 XYZ operator *(double mult) const 28 { 29 return XYZ{x*mult, y*mult, z*mult}; 30 } 31 XYZ& operator +=(XYZ rhs) 32 { 33 x += rhs.x; 34 y += rhs.y; 35 z += rhs.z; 36 return *this; 37 } 38 double sum(void) const 39 { 40 return x + y + z; 41 } 42 }; 43 44 struct XYZ xyzFromWavelength(double) { 45 struct XYZ color; // TODO 46 return color; 47 } 48 49 struct XYZ xyzFromWavelengthDistribution(double x, double s) 50 { 51 struct XYZ color; 52 double delta = 0.1; 53 54 for (double l = 380; l <= 780; l += delta) 55 color += xyzFromWavelength(l) *gaussian(l, 1, x, s, s); 56 57 return color * delta; 58 } 59 60 int main(int argc, char* argv[]) 61 { 62 /**/ 63 if (2 > argc || argc > 3) 64 { 65 std::cerr << "cie-1931 wavelength [spread]\n"; 66 return 1; 67 } 68 69 double x[2]; 70 71 for (int i = 1; i < argc; ++i) 72 { 73 std::string num(argv[i]); 74 std::istringstream ss(num); 75 76 if (not (ss >> x[i-1])) 77 { 78 std::cerr << "Wavelength must be in nanometers\n"; 79 return 1; 80 } 81 } 82 83 struct XYZ xyz; 84 if (argc == 2) 85 { 86 xyz = xyzFromWavelength(x[0]); 87 std::cout << x[0] << "nm\n\n"; 88 } else 89 { 90 xyz = xyzFromWavelengthDistribution(x[0], x[1]); 91 std::cout << x[0] << "nm +-(" << x[1] << ")\n\n"; 92 } 93 /**/ 94 95 std::cout << "X: " << xyz.x << "\nY: " << xyz.y << "\nZ: " << xyz.z << "\n\n"; 96 97 double sum = xyz.sum(); 98 99 std::cout << "x: " << (xyz.x / sum) << "\ny: " << (xyz.y / sum) << "\n"; 100 101 return 0; 102 }