fork download
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. #include <vector>
  4.  
  5. using namespace Eigen;
  6.  
  7. struct Display {
  8. std::string name;
  9. Matrix3d rgb2xyz;
  10. Matrix3d xyz2rgb;
  11. double gain;
  12. Vector3d offset;
  13. Vector3d gamma;
  14. VectorXd gammatest;
  15. };
  16.  
  17. Display o2Ics() {
  18. Display disp;
  19. Vector2d xyW(0.3127, 0.3290);
  20. Vector2d xyR(0.708, 0.292);
  21. Vector2d xyG(0.170, 0.797);
  22. Vector2d xyB(0.131, 0.046);
  23.  
  24. Matrix3d rgb2xyz;
  25. rgb2xyz << xyR, xyG, xyB, Vector2d::Ones() - xyR - xyG - xyB;
  26. Vector3d rgbWei = rgb2xyz.inverse() * Vector3d(xyW, Vector3d::Ones() - Vector3d(xyW.sum(), xyW.sum(), xyW.sum()));
  27. rgb2xyz *= rgbWei.asDiagonal();
  28. rgb2xyz /= rgb2xyz.row(1).sum();
  29.  
  30. double beta = 0.0181;
  31. double alpha = 1.0993;
  32. VectorXd in = VectorXd::LinSpaced(65536, 0, 1);
  33. VectorXd invGamma = (4.5 * in.array()).min(beta).eval() +
  34. ((alpha * in.array().pow(0.45) - (alpha - 1)).max(0)).eval();
  35. VectorXd gamma = (in.array() < beta).select(4.5 * in.array(), invGamma);
  36.  
  37. disp.name = "Rec.2020";
  38. disp.rgb2xyz = rgb2xyz;
  39. disp.xyz2rgb = rgb2xyz.inverse();
  40. disp.gain = 225;
  41. disp.offset.setZero();
  42. disp.gamma = gamma.replicate(3, 1);
  43. disp.gammatest = ((1 / 4.5) * in.array()).min(beta).eval() +
  44. (((1 / alpha) * in.array() + beta / 4.5).pow(1 / 0.45)).max(0).eval();
  45.  
  46. return disp;
  47. }
  48.  
  49. void ConvertSonyPrimaries2ccm(const std::vector<double>& Rx, const std::vector<double>& Ry,
  50. double Luminance, Matrix3d& ccm_colorOptimized,
  51. Matrix3d& ccm_brightnessOptimized) {
  52. double Xw = x(x.size() - 1) * Luminance / y(y.size() - 1);
  53. double Zw = (1 - x(x.size() - 1) - y(y.size() - 1)) * Luminance / y(y.size() - 1);
  54. double Yw = Luminance;
  55.  
  56. Vector3d z = Vector3d::Ones() - x.head(3) - y.head(3);
  57.  
  58. Matrix3d A;
  59. A << x.head(3), y.head(3), z;
  60. Vector3d B(Xw, Yw, Zw);
  61. Vector3d S = A.colPivHouseholderQr().solve(B);
  62.  
  63. Vector3d X = S.array() * x.head(3).array();
  64. Vector3d Y = S.array() * y.head(3).array();
  65. Vector3d Z = S.array() * z.array();
  66.  
  67. Matrix3d XYZ;
  68. XYZ << X, Y, Z;
  69.  
  70. double dispGain = Luminance;
  71. Matrix3d dispXYZnorm = XYZ.array() / dispGain;
  72.  
  73. Vector3d checkWhite = dispXYZnorm.row(1).array().sum() * Vector3d::Ones();
  74. if ((checkWhite - Vector3d::Ones()).cwiseAbs().maxCoeff() > 0.03) {
  75. std::cerr << "*** WARNING: Linearity seems off for white. MUST CHECK. ***" << std::endl;
  76. }
  77.  
  78. Matrix3d disp2xyz = dispXYZnorm.array().colwise() / checkWhite.array();
  79.  
  80. // Assuming you have dispSony.rgb2xyz defined elsewhere
  81. Matrix3d dispIcs; // Initialize dispIcs
  82.  
  83. ccm_brightnessOptimized = dispSony.rgb2xyz.inverse() * dispIcs.rgb2xyz;
  84.  
  85. Matrix3d mat;
  86. mat << 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1;
  87. ccm_colorOptimized = ccm_brightnessOptimized.array() / (ccm_brightnessOptimized * mat).maxCoeff();
  88.  
  89. if (ccm_colorOptimized.minCoeff() < -std::numeric_limits<double>::epsilon()) {
  90. std::cerr << "*** WARNING: Some points in source can't be simulated on the destination. ***" << std::endl;
  91. }
  92. }
  93.  
  94. int main() {
  95. // Given input vectors
  96. std::vector<double> Rx = {0.660, 0.720};
  97. std::vector<double> Ry = {0.277, 0.337};
  98. std::vector<double> Gx = {0.208, 0.268};
  99. std::vector<double> Gy = {0.663, 0.723};
  100. std::vector<double> Bx = {0.117, 0.177};
  101. std::vector<double> By = {0.026, 0.086};
  102. std::vector<double> Wx = {0.293, 0.333};
  103. std::vector<double> Wy = {0.309, 0.349};
  104.  
  105. // Calculate intermediate values
  106. double xr = Rx[0] + ((Rx[1] - Rx[0]) / 2);
  107. double yr = Ry[0] + ((Ry[1] - Ry[0]) / 2);
  108. double xg = Gx[0] + ((Gx[1] - Gx[0]) / 2);
  109. double yg = Gy[0] + ((Gy[1] - Gy[0]) / 2);
  110. double xb = Bx[0] + ((Bx[1] - Bx[0]) / 2);
  111. double yb = By[0] + ((By[1] - By[0]) / 2);
  112. double xw = Wx[0] + ((Wx[1] - Wx[0]) / 2);
  113. double yw = Wy[0] + ((Wy[1] - Wy[0]) / 2);
  114.  
  115. // Create vectors x and y
  116. VectorXd x(4), y(4);
  117. x << xr, xg, xb, xw;
  118. x << yr, yg, yb, yw;
  119. double Luminance = 1.0;
  120.  
  121. Matrix3d ccm_colorOptimized, ccm_brightnessOptimized;
  122. ConvertSonyPrimaries2ccm(Rx, Ry, Luminance, ccm_colorOptimized, ccm_brightnessOptimized);
  123.  
  124. // Verify the result
  125. std::cout << "ccm_colorOptimized:\n" << ccm_colorOptimized << std::endl;
  126.  
  127. return 0;
  128. }
  129.  
Success #stdin #stdout #stderr 0.27s 40852KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Error: unexpected symbol in "using namespace"
Execution halted