cc.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. #include <assert.h>
  2. #define _USE_MATH_DEFINES
  3. #include <math.h>
  4. #include"cc.h"
  5. using namespace OBJREC;
  6. using namespace std;
  7. /*
  8. * Tristimulus reference values
  9. */
  10. const double _ccTristimulusValues[ccNTristimulus][3] =
  11. {
  12. /* 2 degrees */
  13. /*ccTA_2*/{109.850, 100.000, 35.585},
  14. /*ccTC_2*/{98.074, 100.000, 118.232},
  15. /* D50 */ {96.422, 100.000, 82.521},
  16. /* D55 */ {95.682, 100.000, 92.149},
  17. /* D65 */ {95.047, 100.000, 108.883},
  18. /* D75 */ {94.972, 100.000, 122.638},
  19. /* F2 */ {99.187, 100.000, 67.395},
  20. /* F7 */ {95.044, 100.000, 108.755},
  21. /* F11 */ {100.966, 100.000, 64.370},
  22. /* 10 degrees */
  23. /* A */ {111.144, 100.000, 35.200},
  24. /* C */ {97.285, 100.000, 116.145},
  25. /* D50 */ {96.720, 100.000, 81.427},
  26. /* D55 */ {95.799, 100.000, 90.926},
  27. /* D65 */ {94.811, 100.000, 107.304},
  28. /* D75 */ {94.416, 100.000, 120.641},
  29. /* F2 */ {103.280, 100.000, 69.026},
  30. /* F7 */ {95.792, 100.000, 107.687},
  31. /* F11 */ {103.866, 100.000, 65.627}
  32. };
  33. double ColorConversion::ccmin(double val1, double val2, double val3)
  34. {
  35. if (val1 < val2)
  36. {
  37. if(val1 < val3) return val1;
  38. else return val3;
  39. }
  40. else if (val2 < val3)
  41. return val2;
  42. return val3;
  43. }
  44. double ColorConversion::ccmax(double val1, double val2, double val3)
  45. {
  46. if (val1 > val2)
  47. {
  48. if(val1 > val3) return val1;
  49. else return val3;
  50. }
  51. else if (val2 > val3)
  52. return val2;
  53. return val3;
  54. }
  55. double ColorConversion::Hue_2_RGB( double v1, double v2, double vH )
  56. {
  57. if ( vH < 0 ) vH += 1;
  58. if ( vH > 1 ) vH -= 1;
  59. if ( ( 6 * vH ) < 1 ) return ( v1 + ( v2 - v1 ) * 6 * vH );
  60. if ( ( 2 * vH ) < 1 ) return ( v2 );
  61. if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ) * ( ( 2./3 ) - vH ) * 6 );
  62. return ( v1 );
  63. }
  64. double ColorConversion::degree_2_radian(double val)
  65. {
  66. return (val*M_PI)/180;
  67. }
  68. //RGB values = From 0 to 1
  69. int ColorConversion::ccRGBtoHSL(double r, double g, double b, double* h, double* s, double* l)
  70. {
  71. double vmin, vmax, delta;
  72. double dr,dg,db;
  73. vmin = ccmin( r, g, b ); // Min. value of RGB
  74. vmax = ccmax( r, g, b ); // Max. value of RGB
  75. delta = vmax - vmin; // Delta RGB value
  76. *l = ( vmax + vmin ) / 2;
  77. if ( delta == 0 ) // This is a gray, no chroma...
  78. {
  79. *h = 0; // HSL results = From 0 to 1
  80. *s = 0;
  81. }
  82. else // Chromatic data...
  83. {
  84. if ( *l < 0.5 ) *s = delta / ( vmax + vmin );
  85. else *s = delta / ( 2 - vmax - vmin );
  86. dr = ( ( ( vmax - r ) / 6 ) + ( delta / 2 ) ) / delta;
  87. dg = ( ( ( vmax - g ) / 6 ) + ( delta / 2 ) ) / delta;
  88. db = ( ( ( vmax - b ) / 6 ) + ( delta / 2 ) ) / delta;
  89. if ( r == vmax ) *h = db - dg;
  90. else if ( g == vmax ) *h = ( 1./3 ) + dr - db;
  91. else if ( b == vmax ) *h = ( 2./3 ) + dg - dr;
  92. if ( *h < 0 ) *h += 1;
  93. if ( *h > 1 ) *h -= 1;
  94. }
  95. return 1;
  96. }
  97. int ColorConversion::ccHSLtoRGB(double h, double s, double l, double* r, double* g, double* b)
  98. {
  99. double v1, v2;
  100. if ( s == 0 ) // HSL values = From 0 to 1
  101. {
  102. *r = l * 255; // RGB results = From 0 to 255
  103. *g = l * 255;
  104. *b = l * 255;
  105. }
  106. else
  107. {
  108. if ( l < 0.5 )
  109. v2 = l * ( 1 + s );
  110. else
  111. v2 = ( l + s ) - ( s * l );
  112. v1 = 2 * l - v2;
  113. *r = 255 * Hue_2_RGB( v1, v2, h + ( 1./3 ) );
  114. *g = 255 * Hue_2_RGB( v1, v2, h );
  115. *b = 255 * Hue_2_RGB( v1, v2, h - ( 1./3 ) );
  116. }
  117. return 1;
  118. }
  119. // RGB values = From 0 to 1
  120. int ColorConversion::ccfRGBtoCMY(double r, double g, double b, double* c, double* m, double* y)
  121. {
  122. assert(c && m && y);
  123. *c = 1 - r;
  124. *m = 1 - g;
  125. *y = 1 - b;
  126. return 1;
  127. }
  128. // RGB values = From 0 to 255
  129. int ColorConversion::cciRGBtoCMY(int r, int g, int b, double* c, double* m, double* y)
  130. {
  131. assert(c && m && y);
  132. assert(r >= 0 && r < 256);
  133. assert(g >= 0 && g < 256);
  134. assert(b >= 0 && b < 256);
  135. *c = 1 - ( (double)r / 255 );
  136. *m = 1 - ( (double)g / 255 );
  137. *y = 1 - ( (double)b / 255 );
  138. return 1;
  139. }
  140. // CMY values = From 0 to 255
  141. int ColorConversion::ccCMYtofRGB(double c, double m, double y, double* r, double* g, double* b)
  142. {
  143. assert(r && g && b);
  144. assert(c >= 0 && c <= 1);
  145. assert(m >= 0 && m <= 1);
  146. assert(y >= 0 && y <= 1);
  147. *r = ( 1 - c );
  148. *g = ( 1 - m );
  149. *b = ( 1 - y );
  150. return 1;
  151. }
  152. // CMY values = From 0 to 1
  153. int ColorConversion::ccCMYtoiRGB(double c, double m, double y, int* r, int* g, int* b)
  154. {
  155. assert(r && g && b);
  156. assert(c >= 0 && c <= 1);
  157. assert(m >= 0 && m <= 1);
  158. assert(y >= 0 && y <= 1);
  159. *r = (int)( 1 - c ) * 255;
  160. *g = (int)( 1 - m ) * 255;
  161. *b = (int)( 1 - y ) * 255;
  162. return 1;
  163. }
  164. // CMY values = From 0 to 1
  165. int ColorConversion::ccCMYtoCMYK(double c, double m, double y, double* C, double* M, double* Y, double* K)
  166. {
  167. double var_K = 1;
  168. assert(C && M && Y && K);
  169. assert(c >= 0 && c <= 1);
  170. assert(m >= 0 && m <= 1);
  171. assert(y >= 0 && y <= 1);
  172. if ( c < var_K )
  173. var_K = c;
  174. if ( m < var_K )
  175. var_K = m;
  176. if ( y < var_K )
  177. var_K = y;
  178. *C = ( c - var_K ) / ( 1 - var_K );
  179. *M = ( m - var_K ) / ( 1 - var_K );
  180. *Y = ( y - var_K ) / ( 1 - var_K );
  181. *K = var_K;
  182. return 1;
  183. }
  184. // CMYK values = From 0 to 1
  185. int ColorConversion::ccCMYKtoCMY(double c, double m, double y, double k, double* C, double* M, double* Y)
  186. {
  187. assert(C && M && Y);
  188. assert(c >= 0 && c <= 1);
  189. assert(m >= 0 && m <= 1);
  190. assert(y >= 0 && y <= 1);
  191. assert(k >= 0 && k <= 1);
  192. *C = ( c * ( 1 - k ) + k );
  193. *M = ( m * ( 1 - k ) + k );
  194. *Y = ( y * ( 1 - k ) + k );
  195. return 1;
  196. }
  197. int ColorConversion::ccRGBtoHSV(double r, double g, double b, double* h, double* s, double* v)
  198. {
  199. double var_Min;
  200. double var_Max;
  201. double del_Max;
  202. var_Min = ccmin( r, g, b ); //Min. value of RGB
  203. var_Max = ccmax( r, g, g ); //Max. value of RGB
  204. del_Max = var_Max - var_Min; //Delta RGB value
  205. *v = var_Max;
  206. if ( del_Max == 0 ) // This is a gray, no chroma...
  207. {
  208. *h = 0; // HSV results = From 0 to 1
  209. *s = 0;
  210. }
  211. else // Chromatic data...
  212. {
  213. double del_R = ( ( ( var_Max - r ) / 6 ) + ( del_Max / 2 ) ) / del_Max;
  214. double del_G = ( ( ( var_Max - g ) / 6 ) + ( del_Max / 2 ) ) / del_Max;
  215. double del_B = ( ( ( var_Max - b ) / 6 ) + ( del_Max / 2 ) ) / del_Max;
  216. *s = del_Max / var_Max;
  217. if ( r == var_Max ) *h = del_B - del_G;
  218. else if ( g == var_Max ) *h = ( 1./3 ) + del_R - del_B;
  219. else if ( b == var_Max ) *h = ( 2./3 ) + del_G - del_R;
  220. if ( *h < 0 ) *h += 1;
  221. if ( *h > 1 ) *h -= 1;
  222. }
  223. return 1;
  224. }
  225. int ColorConversion::ccHSVtoRGB(double h, double s, double v, double* r, double* g, double* b)
  226. {
  227. if ( s == 0 ) // HSV values = From 0 to 1
  228. {
  229. *r = v;
  230. *g = v;
  231. *b = v;
  232. }
  233. else
  234. {
  235. double var_h = h * 6;
  236. double var_i = floor( var_h );
  237. double var_1 = v * ( 1 - s );
  238. double var_2 = v * ( 1 - s * ( var_h - var_i ) );
  239. double var_3 = v * ( 1 - s * ( 1 - ( var_h - var_i ) ) );
  240. if ( var_i == 0 ) { *r = v ; *g = var_3 ; *b = var_1; }
  241. else if ( var_i == 1 ) { *r = var_2 ; *g = v ; *b = var_1; }
  242. else if ( var_i == 2 ) { *r = var_1 ; *g = v ; *b = var_3; }
  243. else if ( var_i == 3 ) { *r = var_1 ; *g = var_2 ; *b = v; }
  244. else if ( var_i == 4 ) { *r = var_3 ; *g = var_1 ; *b = v; }
  245. else { *r = v ; *g = var_1 ; *b = var_2; }
  246. }
  247. return 1;
  248. }
  249. int ColorConversion::ccXYZtoHunterLab(double x, double y, double z, double* L, double* a, double* b)
  250. {
  251. *L = 10 * sqrt( y );
  252. *a = 17.5 * ( ( ( 1.02 * x ) - y ) / sqrt( y ) );
  253. *b = 7 * ( ( y - ( 0.847 * z ) ) / sqrt( y ) );
  254. return 1;
  255. }
  256. int ccHunterLabtoXYZ(double L, double a, double b, double* x, double* y, double* z)
  257. {
  258. double var_Y = L / 10;
  259. double var_X = a / 17.5 * L / 10;
  260. double var_Z = b / 7 * L / 10;
  261. *y = pow(var_Y,2);
  262. *x = ( var_X + *y ) / 1.02;
  263. *z = -( var_Z - *y ) / 0.847;
  264. return 1;
  265. }
  266. int ColorConversion::ccXYZtoYxy(double x, double y, double z, double* rY, double* rx, double* ry)
  267. {
  268. *rY = y;
  269. *rx = x / ( x + y + z );
  270. *ry = y / ( x + y + z );
  271. return 1;
  272. }
  273. int ColorConversion::ccXYZtoLMS(double x, double y, double z, double* l, double* m, double* s)
  274. {
  275. *l=0.7328*x+0.4296*y-0.1624*z;
  276. *m=-0.7036*x+1.6975*y+0.0061*z;
  277. *s=0.0030*x+0.0136*y+0.9834*z;
  278. return 1;
  279. }
  280. int ColorConversion::ccLMStoOPP(double l, double m, double s, double* lum, double* lm, double* slm)
  281. {
  282. *lum=l+m;
  283. if (fabs(*lum)>1.0e-8)
  284. {
  285. *lm=(l-m)/ *lum;
  286. }
  287. else
  288. {
  289. *lm=l-m; //linear model
  290. }
  291. if(fabs(s+ *lum)>1.0e-8)
  292. {
  293. *slm=(s- *lum)/(s+ *lum);
  294. }
  295. else
  296. {
  297. *slm=2*s- *lum;//linear model
  298. }
  299. return 1;
  300. }
  301. int ColorConversion::ccYxytoXYZ(double Y, double x, double y, double* rx, double* ry, double* rz)
  302. {
  303. //Y = From 0 to 100
  304. //x = From 0 to 1
  305. //y = From 0 to 1
  306. *rx = x * ( Y / y );
  307. *ry = Y;
  308. *rz = ( 1 - x - y ) * ( Y / y );
  309. return 1;
  310. }
  311. int ColorConversion::ccFixRGB(double* r, double* g, double* b)
  312. {
  313. double min,max;
  314. int mod=0;
  315. min=(*r>*g)?*g:*r;
  316. min=(min>*b)?*b:min;
  317. if (min<0) {*r+=-min; *g+=-min; *b+=-min; mod=1;}
  318. max=(*r>*g)?*r:*g;
  319. max=(max>*b)?max:*b;
  320. if (max>1){*r/=max; *g/=max; *b/=max; mod=1;}
  321. return mod;
  322. }
  323. //r,g,b from 0 to 1
  324. int ColorConversion::ccXYZtoRGB(double x, double y, double z, double* r, double* g, double* b, char ObsIll)
  325. {
  326. double ref_X = 100.0;//_ccTristimulusValues[ObsIll][ccX];
  327. double ref_Y = 100.0;//_ccTristimulusValues[ObsIll][ccY];
  328. double ref_Z = 100.0;//_ccTristimulusValues[ObsIll][ccZ];
  329. double var_X = x / ref_X; //X = From 0 to ref_X
  330. double var_Y = y / ref_Y; //Y = From 0 to ref_Y
  331. double var_Z = z / ref_Z; //Z = From 0 to ref_Y
  332. double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
  333. double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415;
  334. double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570;
  335. if ( var_R > 0.0031308 ) var_R = 1.055 * ( pow(var_R,( 1 / 2.4 )) ) - 0.055;
  336. else var_R = 12.92 * var_R;
  337. if ( var_G > 0.0031308 ) var_G = 1.055 * ( pow(var_G,( 1 / 2.4 )) ) - 0.055;
  338. else var_G = 12.92 * var_G;
  339. if ( var_B > 0.0031308 ) var_B = 1.055 * ( pow(var_B,( 1 / 2.4 )) ) - 0.055;
  340. else var_B = 12.92 * var_B;
  341. *r = var_R;
  342. *g = var_G;
  343. *b = var_B;
  344. return 1;
  345. }
  346. int ColorConversion::ccRGBtoXYZ(double r, double g, double b, double* x, double* y, double* z, char ObsIll)
  347. {
  348. double var_R = r; //R = From 0 to 1
  349. double var_G = g; //G = From 0 to 1
  350. double var_B = b; //B = From 0 to 1
  351. if ( var_R > 0.04045 ) var_R = pow(( ( var_R + 0.055 ) / 1.055 ),2.4);
  352. else var_R = var_R / 12.92;
  353. if ( var_G > 0.04045 ) var_G = pow(( ( var_G + 0.055 ) / 1.055 ),2.4);
  354. else var_G = var_G / 12.92;
  355. if ( var_B > 0.04045 ) var_B = pow(( ( var_B + 0.055 ) / 1.055 ),2.4);
  356. else var_B = var_B / 12.92;
  357. var_R = var_R * 100;
  358. var_G = var_G * 100;
  359. var_B = var_B * 100;
  360. *x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
  361. *y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
  362. *z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
  363. return 1;
  364. }
  365. int ColorConversion::ccXYZtoCIE_Lab(double x, double y, double z, double* L, double* a, double* b, char ObsIll)
  366. {
  367. double var_X = x/_ccTristimulusValues[ObsIll][ccX];
  368. double var_Y = y/_ccTristimulusValues[ObsIll][ccY];
  369. double var_Z = z/_ccTristimulusValues[ObsIll][ccZ];
  370. if ( var_X > 0.008856 ) var_X = pow(var_X,( 1./3 ));
  371. else var_X = ( 7.787 * var_X ) + ( 16./ 116 );
  372. if ( var_Y > 0.008856 ) var_Y = pow(var_Y,( 1./3 ));
  373. else var_Y = ( 7.787 * var_Y ) + ( 16./ 116 );
  374. if ( var_Z > 0.008856 ) var_Z = pow(var_Z,( 1./3 ));
  375. else var_Z = ( 7.787 * var_Z ) + ( 16./ 116 );
  376. *L = ( 116 * var_Y ) - 16;
  377. *a = 500 * ( var_X - var_Y );
  378. *b = 200 * ( var_Y - var_Z );
  379. return 1;
  380. }
  381. int ColorConversion::ccCIE_LabtoXYZ(double L, double a, double b, double* x, double* y, double* z, char ObsIll)
  382. {
  383. double var_Y = ( L + 16 ) / 116;
  384. double var_X = a / 500 + var_Y;
  385. double var_Z = var_Y - b / 200;
  386. if ( pow(var_Y,3) > 0.008856 ) var_Y = pow(var_Y,3);
  387. else var_Y = ( var_Y - 16./ 116 ) / 7.787;
  388. if ( pow(var_X,3) > 0.008856 ) var_X = pow(var_X,3);
  389. else var_X = ( var_X - 16./ 116 ) / 7.787;
  390. if ( pow(var_Z,3) > 0.008856 ) var_Z = pow(var_Z,3);
  391. else var_Z = ( var_Z - 16./ 116 ) / 7.787;
  392. *x = _ccTristimulusValues[ObsIll][ccX] * var_X;
  393. *y = _ccTristimulusValues[ObsIll][ccY] * var_Y;
  394. *z = _ccTristimulusValues[ObsIll][ccZ] * var_Z;
  395. return 1;
  396. }
  397. int ColorConversion::ccCIE_LabtoCIE_LCH(double L, double a, double b, double* rL, double* rC, double* rH)
  398. {
  399. double var_H = atan2( b, a ); //Quadrant by signs
  400. if ( var_H > 0 ) var_H = ( var_H / M_PI ) * 180;
  401. else var_H = 360 - ( (int)var_H / M_PI ) * 180;
  402. *rL = L;
  403. *rC = sqrt( pow(a,2) + pow(b,2) );
  404. *rH = var_H;
  405. return 1;
  406. }
  407. int ColorConversion::ccCIE_LCHtoCIE_Lab(double L, double C, double H, double* rL, double* ra, double* rb)
  408. {
  409. //CIE-H = From 0 to 360
  410. *rL = L;
  411. *ra = cos( degree_2_radian(H) ) * C;
  412. *rb = sin( degree_2_radian(H) ) * C;
  413. return 1;
  414. }
  415. int ColorConversion::ccXYZtoCIE_Luv(double x, double y, double z, double* L, double* u, double* v, char ObsIll)
  416. {
  417. double ref_X = _ccTristimulusValues[ObsIll][ccX];
  418. double ref_Y = _ccTristimulusValues[ObsIll][ccY];
  419. double ref_Z = _ccTristimulusValues[ObsIll][ccZ];
  420. double ref_U = ( 4 * ref_X ) / ( ref_X + ( 15 * ref_Y ) + ( 3 * ref_Z ) );
  421. double ref_V = ( 9 * ref_Y ) / ( ref_X + ( 15 * ref_Y ) + ( 3 * ref_Z ) );
  422. double var_U = ( 4 * x ) / ( x + ( 15 * y ) + ( 3 * z ) );
  423. double var_V = ( 9 * y ) / ( x + ( 15 * y ) + ( 3 * z ) );
  424. double var_Y = y / 100;
  425. if ( var_Y > 0.008856 ) var_Y = pow(var_Y,( 1./3 ));
  426. else var_Y = ( 7.787 * var_Y ) + ( 16./ 116 );
  427. *L = ( 116 * var_Y ) - 16;
  428. *u = 13 * *L * ( var_U - ref_U );
  429. *v = 13 * *L * ( var_V - ref_V );
  430. return 1;
  431. }
  432. int ColorConversion::ccCIE_LuvtoXYZ(double L, double u, double v, double* x, double* y, double* z, char ObsIll)
  433. {
  434. double ref_X = _ccTristimulusValues[ObsIll][ccX];
  435. double ref_Y = _ccTristimulusValues[ObsIll][ccY];
  436. double ref_Z = _ccTristimulusValues[ObsIll][ccZ];
  437. double ref_U = ( 4 * ref_X ) / ( ref_X + ( 15 * ref_Y ) + ( 3 * ref_Z ) );
  438. double ref_V = ( 9 * ref_Y ) / ( ref_X + ( 15 * ref_Y ) + ( 3 * ref_Z ) );
  439. double var_U = u / ( 13 * L ) + ref_U;
  440. double var_V = v / ( 13 * L ) + ref_V;
  441. double var_Y = ( L + 16 ) / 116;
  442. if ( pow(var_Y,3) > 0.008856 ) var_Y = pow(var_Y,3);
  443. else var_Y = ( var_Y - 16./ 116 ) / 7.787;
  444. (*y) = var_Y * 100;
  445. (*x) = - ( 9 * *y * var_U ) / ( ( var_U - 4 ) * var_V - var_U * var_V );
  446. (*z) = ( 9 * *y - ( 15 * var_V * *y ) - ( var_V * *x ) ) / ( 3 * var_V );
  447. return 1;
  448. }