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

Generated on Mon Aug 16 2010 14:25:45 for FCam by  doxygen 1.7.1