• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/processing/Color.cpp

00001 #include <cmath>
00002 
00003 #include <FCam/Event.h>
00004 
00005 namespace FCam {
00006 
00007     const float RGBtoXYZ[9] = {
00008     0.4124564, 0.3575761, 0.1804375,
00009     0.2126729, 0.7151522, 0.0721750,
00010     0.0193339, 0.1191920, 0.9503041
00011     };
00012 
00013     int xyToCCT(float x, float y) {
00014         const float x_e = 0.3366;
00015         const float y_e = 0.1735;
00016         const float A0 = -949.86315;
00017         const float A1 = 6253.80338;
00018         const float t1 = 0.92159;
00019         const float A2 = 28.70599;
00020         const float t2 = 0.20039;
00021         const float A3 = 0.00004;
00022         const float t3 = 0.07125;
00023 
00024         float n = (x - x_e)/(y - y_e);
00025 
00026         float CCT = A0 + A1 * std::exp(-n/t1) + A2 * std::exp(-n/t2) + A3 * std::exp(-n/t3);
00027         if (CCT < 3000 || CCT > 50000) {
00028             warning(Event::OutOfRange, "xyToCCT: Conversion only accurate within 3000 to 50000K, result was %d K.\n", CCT);
00029         }
00030         return std::floor(CCT+0.5f);
00031     }
00032 
00033     void kelvinToXY(int T, float *x, float *y) {
00034         if (!x || !y) return;
00035 
00036         if (T < 1667 || T > 25000) {
00037             warning(Event::OutOfRange, "KelvinToXY: Conversion only accurate within 1667K to 25000K, requested %d K\n", T);
00038         }
00039         // chromaticity x coefficients for T <= 4000K
00040         const float A_x00 = -0.2661239;
00041         const float A_x01 = -0.2343580;
00042         const float A_x02 = 0.8776956;
00043         const float A_x03 = 0.179910;
00044         // chromaticity x coefficients for T > 4000K
00045         const float A_x10 = -3.0258469;
00046         const float A_x11 = 2.1070379;
00047         const float A_x12 = 0.2226347;
00048         const float A_x13 = 0.24039;
00049         // chromaticity y coefficients for T <= 2222K
00050         const float A_y00 = -1.1063814;
00051         const float A_y01 = -1.34811020;
00052         const float A_y02 = 2.18555832;
00053         const float A_y03 = -0.20219683;
00054         // chromaticity y coefficients for 2222K < T <= 4000K
00055         const float A_y10 = -0.9549476;
00056         const float A_y11 = -1.37418593;
00057         const float A_y12 = 2.09137015;
00058         const float A_y13 = -0.16748867;
00059         // chromaticity y coefficients for T > 4000K
00060         const float A_y20 = 3.0817580;
00061         const float A_y21 = -5.87338670;
00062         const float A_y22 = 3.75112997;
00063         const float A_y23 = -0.37001483;
00064 
00065         float invKiloK = 1000.f/T;
00066         float xc, yc;
00067         if (T <= 4000) {
00068             xc = A_x00*invKiloK*invKiloK*invKiloK +
00069                 A_x01*invKiloK*invKiloK +
00070                 A_x02*invKiloK +
00071                 A_x03;
00072         } else {
00073             xc = A_x10*invKiloK*invKiloK*invKiloK +
00074                 A_x11*invKiloK*invKiloK +
00075                 A_x12*invKiloK +
00076                 A_x13;
00077         }
00078 
00079         if (T <= 2222) {
00080             yc = A_y00*xc*xc*xc +
00081                 A_y01*xc*xc +
00082                 A_y02*xc +
00083                 A_y03;
00084         } else if (T <= 4000) {
00085             yc = A_y10*xc*xc*xc +
00086                 A_y11*xc*xc +
00087                 A_y12*xc +
00088                 A_y13;
00089         } else {
00090             yc = A_y20*xc*xc*xc +
00091                 A_y21*xc*xc +
00092                 A_y22*xc +
00093                 A_y23;
00094         }
00095 
00096         *x = xc;
00097         *y = yc;
00098 
00099     }
00100 
00101     void invert3x3(float *in, float *out) {
00102         out[0] = in[4]*in[8]-in[5]*in[7];
00103         out[3] = in[5]*in[6]-in[3]*in[8];
00104         out[6] = in[3]*in[7]-in[4]*in[6];
00105 
00106         float invdet = 1.0f/(in[0]*out[0] + in[1]*out[3] + in[2]*out[6]);
00107 
00108         out[0] *= invdet;
00109         out[3] *= invdet;
00110         out[6] *= invdet;
00111 
00112         out[1] = invdet*(in[7]*in[2]-in[8]*in[1]);
00113         out[4] = invdet*(in[8]*in[0]-in[6]*in[2]);
00114         out[7] = invdet*(in[6]*in[1]-in[7]*in[0]);
00115         
00116         out[2] = invdet*(in[1]*in[5]-in[2]*in[4]);
00117         out[5] = invdet*(in[2]*in[3]-in[0]*in[5]);
00118         out[8] = invdet*(in[0]*in[4]-in[1]*in[3]);
00119 
00120     }
00121 
00122     void invert3x3(double *in, double *out) {
00123         out[0] = in[4]*in[8]-in[5]*in[7];
00124         out[3] = in[5]*in[6]-in[3]*in[8];
00125         out[6] = in[3]*in[7]-in[4]*in[6];
00126 
00127         double invdet = 1.0/(in[0]*out[0] + in[1]*out[3] + in[2]*out[6]);
00128 
00129         out[0] *= invdet;
00130         out[3] *= invdet;
00131         out[6] *= invdet;
00132 
00133         out[1] = invdet*(in[7]*in[2]-in[8]*in[1]);
00134         out[4] = invdet*(in[8]*in[0]-in[6]*in[2]);
00135         out[7] = invdet*(in[6]*in[1]-in[7]*in[0]);
00136         
00137         out[2] = invdet*(in[1]*in[5]-in[2]*in[4]);
00138         out[5] = invdet*(in[2]*in[3]-in[0]*in[5]);
00139         out[8] = invdet*(in[0]*in[4]-in[1]*in[3]);
00140 
00141     }
00142 
00143     void colorMatrixInterpolate(const float *a, const float *b, float alpha, float *result) {
00144         // Check for identity interpolations
00145         if (alpha == 0.f) {
00146             for (int i=0; i < 12; i++)  result[i] = a[i];
00147             return;
00148         } 
00149         if (alpha == 1.f) {
00150             for (int i=0; i < 12; i++)  result[i] = b[i];
00151             return;
00152         }
00153         // just do a linear interpolation between two known settings
00154         for (int i = 0; i < 12; i++) {
00155             result[i] = (1-alpha)*a[i] + alpha*b[i];
00156         }
00157 
00158         // rescale the result so that the minimum row sum is one
00159         float rowSum[3] = {result[0] + result[1] + result[2],
00160                            result[4] + result[5] + result[6],
00161                            result[8] + result[9] + result[10]};
00162         float scale = 1.0f;
00163         if (rowSum[0] < rowSum[1] && rowSum[0] < rowSum[2]) {
00164             scale = 1.0f/rowSum[0];
00165         } else if (rowSum[1] < rowSum[2]) {
00166             scale = 1.0f/rowSum[1];
00167         } else {
00168             scale = 1.0f/rowSum[2];
00169         }
00170 
00171         for (int j = 0; j < 3; j++) {
00172             for (int i = 0; i < 3; i++) {
00173                 result[j*4+i] *= scale;
00174             }
00175         }                           
00176 
00177     }
00178 
00179 }

Generated on Thu Jul 15 2010 17:51:28 for FCam by  doxygen 1.7.1