ImageHDR.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  1. #include "pch.h"
  2. #include "ImageHDR.hpp"
  3. #include "MT_exposure.hpp"
  4. #include "MT_contrast.hpp"
  5. #include "MT_histogram_regularization.hpp"
  6. #include "MT_lightnessMask.hpp"
  7. #include "MT_saturation.hpp"
  8. #include "MT_colorEditor.hpp"
  9. #include "Conversion.hpp"
  10. #include "YCurve.hpp"
  11. #include "Utils.hpp"
  12. #include <cmath>
  13. #include <thread>
  14. #include <iostream>
  15. #include <vector>
  16. #include <ctime>
  17. #include <cstdlib>
  18. /* Member methods*/
  19. ImageHDR::ImageHDR(float* d, unsigned int w, unsigned int h)
  20. {
  21. width = w;
  22. height = h;
  23. this->min_intensity = d[0];
  24. this->max_intensity = d[0];
  25. data = new float[width*height*3];
  26. for (unsigned int i = 0; i < width*height*3; i++) {
  27. data[i]=d[i];
  28. if (this->min_intensity > data[i])
  29. this->min_intensity = data[i];
  30. if (this->max_intensity < data[i])
  31. this->max_intensity = data[i];
  32. }
  33. linear = true;
  34. colorspace = Colorspace::RGB;
  35. }
  36. void ImageHDR::display_pixel(unsigned int i) const
  37. {
  38. if (linear)
  39. std::cout << "LINEAIRE - ";
  40. else
  41. std::cout << "NON LINEAIRE - ";
  42. std::cout << "Pixel : ( " << data[i * 3] << " " << data[i * 3 + 1] << " " << data[i * 3 + 2] << " )" << std::endl;
  43. }
  44. void ImageHDR::display_pixel(unsigned int i, unsigned int j) const
  45. {
  46. display_pixel(j * width + i);
  47. }
  48. /****************************************/
  49. /**************** LINEAR ****************/
  50. /****************************************/
  51. void ImageHDR::linear_to_non_linear()
  52. {
  53. float* non_linear = Conversion::linear_to_non_linear(data, width * height * 3);
  54. delete[](data);
  55. data = non_linear;
  56. }
  57. void ImageHDR::non_linear_to_linear()
  58. {
  59. float* linear = Conversion::non_linear_to_linear(data, width * height * 3);
  60. delete[](data);
  61. data = linear;
  62. }
  63. /****************************************/
  64. /*************** EXPOSURE ***************/
  65. /****************************************/
  66. #ifdef _MT_
  67. void* exposure_MT(void* arg)
  68. {
  69. MT_exposure* a = (MT_exposure*)arg;
  70. float* data = a->data;
  71. for (unsigned int i = 0; i < a->length; i++)
  72. data[i] *= a->coeff;
  73. return arg;
  74. }
  75. void ImageHDR::exposure(const float ev)
  76. {
  77. float coeff = powf(2, ev);
  78. if (!linear)
  79. {
  80. non_linear_to_linear();
  81. linear = true;
  82. }
  83. std::thread tab_t[_MT_];
  84. MT_exposure tab_a[_MT_];
  85. unsigned int id;
  86. unsigned int tab_length = width * height * 3;
  87. unsigned int block_size = tab_length / _MT_;
  88. for (id = 0; id < _MT_; id++) {
  89. tab_a[id].data = data + (id * block_size);
  90. tab_a[id].length = block_size;
  91. tab_a[id].coeff = coeff;
  92. if (id == (_MT_ - 1))
  93. tab_a[id].length = tab_length - ((_MT_ - 1) * block_size);
  94. tab_t[id] = std::thread(exposure_MT, (void*)(tab_a + id));
  95. }
  96. for (id = 0; id < _MT_; id++) {
  97. tab_t[id].join();
  98. }
  99. }
  100. #else
  101. void ImageHDR::exposure(const float ev)
  102. {
  103. float coef = powf(2, ev);
  104. if (!linear)
  105. {
  106. non_linear_to_linear();
  107. linear = true;
  108. }
  109. for (unsigned int i = 0; i < width * height * 3; i++)
  110. data[i] *= coef;
  111. }
  112. #endif
  113. /****************************************/
  114. /*************** CONTRAST ***************/
  115. /****************************************/
  116. #ifdef _MT_
  117. void* contrast_MT(void* arg)
  118. {
  119. MT_contrast* a = (MT_contrast*)arg;
  120. float* data = a->data;
  121. for (unsigned int i = 0; i < a->length; i++)
  122. data[i] = a->coeff * (data[i] - 0.5f) + 0.5f;
  123. return arg;
  124. }
  125. void ImageHDR::contrast(const float c)
  126. {
  127. float max_contrast_factor = 2.0f, scaling_factor = 1.0f, contrast_value = c;
  128. if (linear)
  129. {
  130. linear_to_non_linear();
  131. linear = false;
  132. }
  133. if (contrast_value != 0.0f)
  134. {
  135. contrast_value = contrast_value / 100.0f;
  136. if (contrast_value > 0.0f)
  137. {
  138. scaling_factor = 1 * (1 - contrast_value) + max_contrast_factor * contrast_value;
  139. }
  140. else
  141. {
  142. contrast_value = -contrast_value;
  143. scaling_factor = 1 * (1 - contrast_value) + max_contrast_factor * contrast_value;
  144. scaling_factor = 1 / scaling_factor;
  145. }
  146. }
  147. std::thread tab_t[_MT_];
  148. MT_contrast tab_a[_MT_];
  149. unsigned int id;
  150. unsigned int tab_length = width * height * 3;
  151. unsigned int block_size = tab_length / _MT_;
  152. for (id = 0; id < _MT_; id++)
  153. {
  154. tab_a[id].data = data + (id * block_size);
  155. tab_a[id].length = block_size;
  156. tab_a[id].coeff = scaling_factor;
  157. if (id == (_MT_ - 1))
  158. tab_a[id].length = tab_length - ((_MT_ - 1) * block_size);
  159. tab_t[id] = std::thread(contrast_MT, (void*)(tab_a + id));
  160. }
  161. for (id = 0; id < _MT_; id++) {
  162. tab_t[id].join();
  163. }
  164. }
  165. #else
  166. void ImageHDR::contrast(const float c)
  167. {
  168. float max_contrast_factor = 2.0f, scaling_factor = 1.0f, contrast_value = c;
  169. if (linear)
  170. {
  171. linear_to_non_linear();
  172. linear = false;
  173. }
  174. if (contrast_value != 0.0f)
  175. {
  176. contrast_value = contrast_value / 100.0f;
  177. if (contrast_value > 0.0f)
  178. {
  179. scaling_factor = 1 * (1 - contrast_value) + max_contrast_factor * contrast_value;
  180. }
  181. else
  182. {
  183. contrast_value = -contrast_value;
  184. scaling_factor = 1 * (1 - contrast_value) + max_contrast_factor * contrast_value;
  185. scaling_factor = 1 / scaling_factor;
  186. }
  187. }
  188. for (unsigned int i = 0; i < width * height * 3; i++)
  189. data[i] = scaling_factor * (data[i] - 0.5f) + 0.5f;
  190. }
  191. #endif
  192. /****************************************/
  193. /**************** YCURVE ****************/
  194. /****************************************/
  195. #ifdef _MT_
  196. void* histogram_regularization_MT(void* arg)
  197. {
  198. MT_histogram_regularization* a = (MT_histogram_regularization*)arg;
  199. float* data = a->data;
  200. float* colorDataY = a->colorDataY;
  201. float* colorDataFY = a->colorDataFY;
  202. for (unsigned int i = 0; i < a->length; i++)
  203. {
  204. data[i * 3] = data[i * 3] * colorDataFY[i] / colorDataY[i];
  205. data[i * 3 + 1] = data[i * 3 + 1] * colorDataFY[i] / colorDataY[i];
  206. data[i * 3 + 2] = data[i * 3 + 2] * colorDataFY[i] / colorDataY[i];
  207. }
  208. return arg;
  209. }
  210. void ImageHDR::ycurve_histogram_regularization(float* colorDataY, float* colorDataFY)
  211. {
  212. float yMin = colorDataY[0];
  213. unsigned int i = 1;
  214. while (yMin == 0)
  215. yMin = colorDataY[i++];
  216. for (unsigned int i = 0; i < width * height; i++)
  217. if (colorDataY[i] != 0 && colorDataY[i] < yMin)
  218. yMin = colorDataY[i];
  219. for (unsigned int i = 0; i < width * height; i++)
  220. if (colorDataY[i] == 0)
  221. colorDataY[i] = yMin;
  222. std::thread tab_t[_MT_];
  223. MT_histogram_regularization tab_a[_MT_];
  224. unsigned int id;
  225. unsigned int tab_length = width * height;
  226. unsigned int block_size = tab_length / _MT_;
  227. for (id = 0; id < _MT_; id++) {
  228. tab_a[id].data = data + (id * block_size * 3);
  229. tab_a[id].length = block_size;
  230. tab_a[id].colorDataY = colorDataY + (id * block_size);
  231. tab_a[id].colorDataFY = colorDataFY + (id * block_size);
  232. if (id == (_MT_ - 1))
  233. tab_a[id].length = tab_length - ((_MT_ - 1) * block_size);
  234. tab_t[id] = std::thread(histogram_regularization_MT, (void*)(tab_a + id));
  235. }
  236. for (id = 0; id < _MT_; id++) {
  237. tab_t[id].join();
  238. }
  239. }
  240. void ImageHDR::yCurve(float s, float b, float m, float w, float h)
  241. {
  242. if (linear)
  243. {
  244. linear_to_non_linear();
  245. linear = false;
  246. }
  247. float* colorDataY = Conversion::sRGB_to_Y_of_XYZ(data, width * height);
  248. float yMax = colorDataY[0];
  249. for (unsigned int i = 0; i < width * height; i++)
  250. if (yMax < colorDataY[i])
  251. yMax = colorDataY[i];
  252. yMax = yMax * 100;
  253. YCurve yc(s, b, m, w, h, yMax);
  254. Eigen::MatrixXf* points = yc.evalpts(100);
  255. Eigen::RowVectorXf y = (*points).col(0) / 100;
  256. Eigen::RowVectorXf fy = (*points).col(1) / 100;
  257. delete(points);
  258. // TODO - try to optimize ?!
  259. // The index of the search method in utils.cpp could be calculated or determined ?
  260. float* colorDataFY = Utils::interp(colorDataY, width * height, y, fy);
  261. ycurve_histogram_regularization(colorDataY, colorDataFY);
  262. delete[](colorDataY);
  263. delete[](colorDataFY);
  264. }
  265. #else
  266. void ImageHDR::ycurve_histogram_regularization(float* colorDataY, float* colorDataFY)
  267. {
  268. float yMin = colorDataY[0];
  269. unsigned int i = 1;
  270. while (yMin == 0)
  271. yMin = colorDataY[i++];
  272. for (unsigned int i = 0; i < width * height; i++)
  273. if (colorDataY[i] != 0 && colorDataY[i] < yMin)
  274. yMin = colorDataY[i];
  275. for (unsigned int i = 0; i < width * height; i++)
  276. if (colorDataY[i] == 0)
  277. colorDataY[i] = yMin;
  278. for (unsigned int i = 0; i < width * height; i++)
  279. {
  280. data[i * 3] = data[i * 3] * colorDataFY[i] / colorDataY[i];
  281. data[i * 3 + 1] = data[i * 3 + 1] * colorDataFY[i] / colorDataY[i];
  282. data[i * 3 + 2] = data[i * 3 + 2] * colorDataFY[i] / colorDataY[i];
  283. }
  284. }
  285. void ImageHDR::yCurve(float s, float b, float m, float w, float h)
  286. {
  287. if (linear)
  288. {
  289. linear_to_non_linear();
  290. linear = false;
  291. }
  292. float* colorDataY = Conversion::sRGB_to_Y_of_XYZ(data, width * height);
  293. float yMax = colorDataY[0];
  294. for (unsigned int i = 0; i < width * height; i++)
  295. if (yMax < colorDataY[i])
  296. yMax = colorDataY[i];
  297. yMax = yMax * 100;
  298. YCurve yc(s, b, m, w, h, yMax);
  299. Eigen::MatrixXf* points = yc.evalpts(100);
  300. Eigen::RowVectorXf y = (*points).col(0) / 100;
  301. Eigen::RowVectorXf fy = (*points).col(1) / 100;
  302. delete(points);
  303. float* colorDataFY = Utils::interp(colorDataY, width * height, y, fy);
  304. ycurve_histogram_regularization(colorDataY, colorDataFY);
  305. delete[](colorDataY);
  306. delete[](colorDataFY);
  307. }
  308. #endif
  309. /****************************************/
  310. /************** LIGHTNESSMASK ***********/
  311. /****************************************/
  312. #ifdef _MT_
  313. void* lightness_MT(void* arg)
  314. {
  315. MT_lightnessMask* a = (MT_lightnessMask*)arg;
  316. float* data = a->data;
  317. float* colorDataY = a->colorDataY;
  318. bool* mask = a->mask;
  319. float rangeMask[5][2] =
  320. {
  321. {0.0f, 0.2f},
  322. {0.2f, 0.4f},
  323. {0.4f, 0.6f},
  324. {0.6f, 0.8f},
  325. {0.8f, 1.0f}
  326. };
  327. unsigned int maskColor[5][3] =
  328. {
  329. {0, 0, 1},
  330. {0, 1, 1},
  331. {0, 1, 0},
  332. {1, 1, 0},
  333. {1, 0, 0}
  334. };
  335. for (unsigned int i = 0; i < a->length; i++)
  336. {
  337. for (unsigned int j = 0; j < 5; j++)
  338. if (mask[j])
  339. if (colorDataY[i] >= rangeMask[j][0] && colorDataY[i] <= rangeMask[j][1])
  340. {
  341. data[i * 3] = (float)(maskColor[j][0]);
  342. data[i * 3 + 1] = (float)(maskColor[j][1]);
  343. data[i * 3 + 2] = (float)(maskColor[j][2]);
  344. }
  345. }
  346. return arg;
  347. }
  348. void ImageHDR::lightnessMask(bool s, bool b, bool m, bool w, bool h)
  349. {
  350. bool mask[5] = { s, b, m, w, h };
  351. if (linear)
  352. {
  353. linear_to_non_linear();
  354. linear = false;
  355. }
  356. float* colorDataY = Conversion::sRGB_to_Y_of_XYZ(data, width * height);
  357. std::thread tab_t[_MT_];
  358. MT_lightnessMask tab_a[_MT_];
  359. unsigned int id;
  360. unsigned int tab_length = width * height;
  361. unsigned int block_size = tab_length / _MT_;
  362. for (id = 0; id < _MT_; id++) {
  363. tab_a[id].data = data + (id * block_size * 3);
  364. tab_a[id].length = block_size;
  365. tab_a[id].colorDataY = colorDataY + (id * block_size);
  366. tab_a[id].mask = mask;
  367. if (id == (_MT_ - 1))
  368. tab_a[id].length = tab_length - ((_MT_ - 1) * block_size);
  369. tab_t[id] = std::thread(lightness_MT, (void*)(tab_a + id));
  370. }
  371. for (id = 0; id < _MT_; id++) {
  372. tab_t[id].join();
  373. }
  374. delete[](colorDataY);
  375. }
  376. #else
  377. void ImageHDR::lightnessMask(bool s, bool b, bool m, bool w, bool h)
  378. {
  379. bool mask[5] = { s, b, m, w, h };
  380. float rangeMask[5][2] =
  381. {
  382. {0.0f, 0.2f},
  383. {0.2f, 0.4f},
  384. {0.4f, 0.6f},
  385. {0.6f, 0.8f},
  386. {0.8f, 1.0f}
  387. };
  388. unsigned int maskColor[5][3] =
  389. {
  390. {0, 0, 1},
  391. {0, 1, 1},
  392. {0, 1, 0},
  393. {1, 1, 0},
  394. {1, 0, 0}
  395. };
  396. if (linear)
  397. {
  398. linear_to_non_linear();
  399. linear = false;
  400. }
  401. float* colorDataY = Conversion::sRGB_to_Y_of_XYZ(data, width * height);
  402. for (unsigned int i = 0; i < width * height; i++)
  403. {
  404. for (unsigned int j = 0; j < 5; j++)
  405. if (mask[j])
  406. if (colorDataY[i] >= rangeMask[j][0] && colorDataY[i] <= rangeMask[j][1])
  407. {
  408. data[i * 3] = (float)(maskColor[j][0]);
  409. data[i * 3 + 1] = (float)(maskColor[j][1]);
  410. data[i * 3 + 2] = (float)(maskColor[j][2]);
  411. }
  412. }
  413. delete[](colorDataY);
  414. }
  415. #endif
  416. /****************************************/
  417. /************** SATURATION **************/
  418. /****************************************/
  419. #ifdef _MT_
  420. void* saturation_MT(void* arg)
  421. {
  422. MT_saturation* a = (MT_saturation*)arg;
  423. float* dataLab = a->dataLab;
  424. for (unsigned int i = 0; i < a->length; i++)
  425. {
  426. float a_of_Lab = dataLab[i * 3 + 1];
  427. float b_of_Lab = dataLab[i * 3 + 2];
  428. dataLab[i * 3 + 1] = Conversion::Lab_to_C_of_LCH(a_of_Lab, b_of_Lab);
  429. // Application de la saturation
  430. dataLab[i * 3 + 1] = powf(dataLab[i * 3 + 1] / 100.0f, a->gamma) * 100.0f;
  431. dataLab[i * 3 + 2] = Conversion::Lab_to_H_of_LCH(a_of_Lab, b_of_Lab);
  432. }
  433. return arg;
  434. }
  435. void ImageHDR::saturation(float s)
  436. {
  437. float gamma = 1.0f / ((s / 25.0f) + 1.0f);
  438. if (s < 0)
  439. gamma = (-s / 25.0f) + 1.0f;
  440. if (!linear)
  441. {
  442. non_linear_to_linear();
  443. linear = false;
  444. }
  445. float* dataLab = Conversion::sRGB_to_Lab(data, width * height);
  446. std::thread tab_t[_MT_];
  447. MT_saturation tab_a[_MT_];
  448. unsigned int id;
  449. unsigned int tab_length = width * height;
  450. unsigned int block_size = tab_length / _MT_;
  451. for (id = 0; id < _MT_; id++) {
  452. tab_a[id].dataLab = dataLab + (id * block_size * 3);
  453. tab_a[id].length = block_size;
  454. tab_a[id].gamma = gamma;
  455. if (id == (_MT_ - 1))
  456. tab_a[id].length = tab_length - ((_MT_ - 1) * block_size);
  457. tab_t[id] = std::thread(saturation_MT, (void*)(tab_a + id));
  458. }
  459. for (id = 0; id < _MT_; id++) {
  460. tab_t[id].join();
  461. }
  462. delete[](data);
  463. data = dataLab;
  464. linear = false;
  465. colorspace = Colorspace::LCH;
  466. }
  467. #else
  468. void ImageHDR::saturation(float s)
  469. {
  470. float gamma = 1.0f / ((s / 25.0f) + 1.0f);
  471. if (s < 0)
  472. gamma = (-s / 25.0f) + 1.0f;
  473. if (!linear)
  474. {
  475. non_linear_to_linear();
  476. linear = false;
  477. }
  478. float* dataLab = Conversion::sRGB_to_Lab(data, width * height);
  479. for (unsigned int i = 0; i < width * height; i++)
  480. {
  481. float a = dataLab[i * 3 + 1];
  482. float b = dataLab[i * 3 + 2];
  483. dataLab[i * 3 + 1] = Conversion::Lab_to_C_of_LCH(a, b);
  484. // Application de la saturation
  485. dataLab[i * 3 + 1] = powf(dataLab[i * 3 + 1] / 100.0f, gamma) * 100.0f;
  486. dataLab[i * 3 + 2] = Conversion::Lab_to_H_of_LCH(a, b);
  487. }
  488. delete[](data);
  489. data = dataLab;
  490. linear = false;
  491. colorspace = Colorspace::LCH;
  492. }
  493. #endif
  494. /*************************************/
  495. /************ COLOREDITOR ************/
  496. /*************************************/
  497. #ifdef _MT_
  498. void* colorEditor_MT(void* arg)
  499. {
  500. MT_colorEditor* a = (MT_colorEditor*)arg;
  501. float* data = a->data;
  502. unsigned int length = a->length;
  503. unsigned int colorspace = a->colorspace;
  504. bool linear = a->linear;
  505. float lMin = a->lMin, lMax = a->lMax;
  506. float cMin = a->cMin, cMax = a->cMax;
  507. float hMin = a->hMin, hMax = a->hMax;
  508. float tolerance = a->tolerance;
  509. float edit_hue = a->edit_hue;
  510. float edit_exposure = a->edit_exposure;
  511. float edit_contrast = a->edit_contrast;
  512. float edit_saturation = a->edit_saturation;
  513. float hueTolerance = tolerance * 360.0f;
  514. float chromaTolerance = tolerance * 100.0f;
  515. float lightTolerance = tolerance * 100.0f;
  516. bool mask = a->mask;
  517. float* dataLCH = NULL;
  518. float* minMask = NULL;
  519. float* compMask = NULL;
  520. // not the default parameter
  521. if (!(lMin == 0.0f && lMax == 100.0f
  522. && cMin == 0.0f && cMax == 100.0f
  523. && hMin == 0.0f && hMax == 360.0f
  524. && tolerance == 0.1f
  525. && edit_hue == 0.0f
  526. && edit_exposure == 0.0f
  527. && edit_contrast == 0.0f
  528. && edit_saturation == 0.0f
  529. && mask == false))
  530. {
  531. if (colorspace == Colorspace::RGB)
  532. {
  533. if (!linear)
  534. {
  535. data = Conversion::non_linear_to_linear(data, length * 3);
  536. linear = true;
  537. }
  538. dataLCH = Conversion::sRGB_to_Lab(data, length);
  539. for (unsigned int i = 0; i < length; i++)
  540. {
  541. float a = dataLCH[i * 3 + 1];
  542. float b = dataLCH[i * 3 + 2];
  543. dataLCH[i * 3 + 1] = Conversion::Lab_to_C_of_LCH(a, b);
  544. dataLCH[i * 3 + 2] = Conversion::Lab_to_H_of_LCH(a, b);
  545. }
  546. }
  547. else
  548. dataLCH = data;
  549. float* lChannel = new float[length];
  550. float* cChannel = new float[length];
  551. float* hChannel = new float[length];
  552. for (unsigned int i = 0; i < length; i++)
  553. {
  554. lChannel[i] = dataLCH[i * 3];
  555. cChannel[i] = dataLCH[i * 3 + 1];
  556. hChannel[i] = dataLCH[i * 3 + 2];
  557. }
  558. // Récupération du max du canal L et C
  559. float lMaxChannel = dataLCH[0];
  560. float cMaxChannel = dataLCH[1];
  561. for (unsigned int i = 1; i < length; i++)
  562. {
  563. if (dataLCH[i * 3] > lMaxChannel)
  564. lMaxChannel = dataLCH[i * 3];
  565. if (dataLCH[i * 3 + 1] > cMaxChannel)
  566. cMaxChannel = dataLCH[i * 3 + 1];
  567. }
  568. if (lMaxChannel < 100.0f)
  569. lMaxChannel = 100.0f;
  570. if (cMaxChannel < 100.0f)
  571. cMaxChannel = 100.0f;
  572. lMax = lMax * lMaxChannel / 100.0f;
  573. cMax = cMax * cMaxChannel / 100.0f;
  574. float* lightnessMask = Utils::NPlinearWeightMask(lChannel, length, lMin, lMax, lightTolerance);
  575. float* chromaMask = Utils::NPlinearWeightMask(cChannel, length, cMin, cMax, chromaTolerance);
  576. float* hueMask = Utils::NPlinearWeightMask(hChannel, length, hMin, hMax, hueTolerance);
  577. minMask = new float[length];
  578. compMask = new float[length];
  579. for (unsigned int i = 0; i < length; i++)
  580. {
  581. minMask[i] = lightnessMask[i];
  582. if (chromaMask[i] < minMask[i])
  583. minMask[i] = chromaMask[i];
  584. if (hueMask[i] < minMask[i])
  585. minMask[i] = hueMask[i];
  586. compMask[i] = 1.0f - minMask[i];
  587. }
  588. delete[](lightnessMask);
  589. delete[](chromaMask);
  590. delete[](hueMask);
  591. float hueShift = edit_hue;
  592. for (unsigned int i = 0; i < length; i++) {
  593. float oldValue = hChannel[i];
  594. hChannel[i] = oldValue + hueShift;
  595. while (hChannel[i] < 0.0f)
  596. hChannel[i] += 360.0f;
  597. while (hChannel[i] >= 360.0f)
  598. hChannel[i] -= 360.0f;
  599. hChannel[i] = hChannel[i] * minMask[i] + oldValue * compMask[i];
  600. }
  601. float saturation = edit_saturation;
  602. float gamma = 1.0f / ((saturation / 25.0f) + 1.0f);
  603. if (saturation < 0)
  604. gamma = (-saturation / 25.0f) + 1.0f;
  605. for (unsigned int i = 0; i < length; i++) {
  606. cChannel[i] = powf(cChannel[i] / 100.0f, gamma) * 100 * minMask[i] + cChannel[i] * compMask[i];
  607. }
  608. float* colorLCH = new float[length * 3];
  609. for (unsigned int i = 0; i < length; i++)
  610. {
  611. colorLCH[i * 3] = lChannel[i];
  612. colorLCH[i * 3 + 1] = cChannel[i];
  613. colorLCH[i * 3 + 2] = hChannel[i];
  614. }
  615. delete[](lChannel);
  616. delete[](cChannel);
  617. delete[](hChannel);
  618. float ev = edit_exposure;
  619. float* colorRGB = NULL;
  620. if (ev != 0)
  621. {
  622. colorRGB = Conversion::LCH_to_sRGB(colorLCH, length);
  623. float* colorRGBev = new float[length * 3];
  624. float coeff = powf(2, ev);
  625. for (unsigned int i = 0; i < length; i++)
  626. {
  627. colorRGBev[i * 3] = colorRGB[i * 3] * coeff * minMask[i];
  628. colorRGBev[i * 3 + 1] = colorRGB[i * 3 + 1] * coeff * minMask[i];
  629. colorRGBev[i * 3 + 2] = colorRGB[i * 3 + 2] * coeff * minMask[i];
  630. colorRGB[i * 3] = colorRGB[i * 3] * compMask[i] + colorRGBev[i * 3];
  631. colorRGB[i * 3 + 1] = colorRGB[i * 3 + 1] * compMask[i] + colorRGBev[i * 3 + 1];
  632. colorRGB[i * 3 + 2] = colorRGB[i * 3 + 2] * compMask[i] + colorRGBev[i * 3 + 2];
  633. }
  634. delete[](colorRGBev);
  635. }
  636. if (edit_contrast != 0)
  637. {
  638. float contrast = edit_contrast / 100.0f;
  639. float maxContrastFactor = 2.0f;
  640. float scalingFactor = (1.0f - contrast) + maxContrastFactor * contrast;
  641. if (contrast < 0.0f)
  642. {
  643. contrast = -contrast;
  644. scalingFactor = 1.0f / scalingFactor;
  645. }
  646. float pivot = powf(2, ev) * (lMin + lMax) / 2.0f / 100.0f;
  647. if (colorRGB == NULL)
  648. colorRGB = Conversion::LCH_to_sRGB(colorLCH, length);
  649. float* colorRGB2 = Conversion::linear_to_non_linear(colorRGB, length * 3);
  650. delete[](colorRGB);
  651. colorRGB=colorRGB2;
  652. float* colorRGBcon = new float[length * 3];
  653. for (unsigned int i = 0; i < length; i++)
  654. {
  655. colorRGBcon[i * 3] = (colorRGB[i * 3] - pivot) * scalingFactor + pivot;
  656. colorRGBcon[i * 3 + 1] = (colorRGB[i * 3 + 1] - pivot) * scalingFactor + pivot;
  657. colorRGBcon[i * 3 + 2] = (colorRGB[i * 3 + 2] - pivot) * scalingFactor + pivot;
  658. colorRGB[i * 3] = colorRGBcon[i * 3] * minMask[i] + colorRGB[i * 3] * compMask[i];
  659. colorRGB[i * 3 + 1] = colorRGBcon[i * 3 + 1] * minMask[i] + colorRGB[i * 3 + 1] * compMask[i];
  660. colorRGB[i * 3 + 2] = colorRGBcon[i * 3 + 2] * minMask[i] + colorRGB[i * 3 + 2] * compMask[i];
  661. }
  662. delete[](colorRGBcon);
  663. colorRGB2 = Conversion::non_linear_to_linear(colorRGB, length * 3);
  664. delete[](colorRGB);
  665. colorRGB=colorRGB2;
  666. }
  667. if (colorRGB == NULL)
  668. colorRGB = Conversion::LCH_to_sRGB(colorLCH, length);
  669. for (unsigned int i = 0; i < length * 3; i++)
  670. {
  671. data[i] = colorRGB[i];
  672. }
  673. delete[](colorRGB);
  674. delete[](colorLCH);
  675. colorspace = Colorspace::RGB;
  676. linear = true;
  677. }
  678. else
  679. {
  680. //TODO - To test for memory leak ?
  681. if (colorspace == Colorspace::LCH)
  682. {
  683. float* colorRGB = Conversion::LCH_to_sRGB(data, length);
  684. for (unsigned int i = 0; i < length * 3; i++)
  685. {
  686. data[i] = colorRGB[i];
  687. }
  688. delete[](colorRGB);
  689. colorspace = Colorspace::RGB;
  690. linear = true;
  691. }
  692. }
  693. if (mask)
  694. {
  695. for (unsigned int i = 0; i < length; i++)
  696. {
  697. data[i * 3] = minMask[i];
  698. data[i * 3 + 1] = minMask[i];
  699. data[i * 3 + 2] = minMask[i];
  700. }
  701. colorspace = Colorspace::RGB;
  702. linear = false;
  703. }
  704. delete[](minMask);
  705. delete[](compMask);
  706. return arg;
  707. }
  708. void ImageHDR::colorEditor(float* selection_lightness, float* selection_chroma, float* selection_hue, float tolerance, float edit_hue, float edit_exposure, float edit_contrast, float edit_saturation, bool mask)
  709. {
  710. float lMin = selection_lightness[0], lMax = selection_lightness[1];
  711. float cMin = selection_chroma[0], cMax = selection_chroma[1];
  712. float hMin = selection_hue[0], hMax = selection_hue[1];
  713. std::thread tab_t[_MT_];
  714. MT_colorEditor tab_a[_MT_];
  715. unsigned int id;
  716. unsigned int length = width * height;
  717. unsigned int block_size = length / _MT_;
  718. for (id = 0; id < _MT_; id++) {
  719. tab_a[id].data = data + (id * block_size * 3);
  720. tab_a[id].length = block_size;
  721. tab_a[id].colorspace = colorspace;
  722. tab_a[id].linear = linear;
  723. tab_a[id].lMin = lMin;
  724. tab_a[id].lMax = lMax;
  725. tab_a[id].cMin = cMin;
  726. tab_a[id].cMax = cMax;
  727. tab_a[id].hMin = hMin;
  728. tab_a[id].hMax = hMax;
  729. tab_a[id].tolerance = tolerance;
  730. tab_a[id].edit_hue = edit_hue;
  731. tab_a[id].edit_exposure = edit_exposure;
  732. tab_a[id].edit_contrast = edit_contrast;
  733. tab_a[id].edit_saturation = edit_saturation;
  734. tab_a[id].mask = mask;
  735. if (id == (_MT_ - 1))
  736. tab_a[id].length = length - ((_MT_ - 1) * block_size);
  737. tab_t[id] = std::thread(colorEditor_MT, (void*)(tab_a + id));
  738. }
  739. for (id = 0; id < _MT_; id++) {
  740. tab_t[id].join();
  741. }
  742. colorspace = Colorspace::RGB;
  743. linear = true;
  744. }
  745. #else
  746. void ImageHDR::colorEditor(float* selection_lightness, float* selection_chroma, float* selection_hue, float tolerance, float edit_hue, float edit_exposure, float edit_contrast, float edit_saturation, bool mask)
  747. {
  748. float lMin = selection_lightness[0], lMax = selection_lightness[1];
  749. float cMin = selection_chroma[0], cMax = selection_chroma[1];
  750. float hMin = selection_hue[0], hMax = selection_hue[1];
  751. float hueTolerance = tolerance * 360.0f;
  752. float chromaTolerance = tolerance * 100.0f;
  753. float lightTolerance = tolerance * 100.0f;
  754. float* dataLCH = NULL;
  755. float* minMask = NULL;
  756. float* compMask = NULL;
  757. // not the default parameter
  758. if (!(selection_lightness[0] == 0.0f && selection_lightness[1] == 100.0f
  759. && selection_chroma[0] == 0.0f && selection_chroma[1] == 100.0f
  760. && selection_hue[0] == 0.0f && selection_hue[1] == 360.0f
  761. && tolerance == 0.1f
  762. && edit_hue == 0.0f
  763. && edit_exposure == 0.0f
  764. && edit_contrast == 0.0f
  765. && edit_saturation == 0.0f
  766. && mask == false))
  767. {
  768. if (colorspace == Colorspace::RGB)
  769. {
  770. if (!linear)
  771. {
  772. non_linear_to_linear();
  773. linear = true;
  774. }
  775. dataLCH = Conversion::sRGB_to_Lab(data, width * height);
  776. for (unsigned int i = 0; i < width * height; i++)
  777. {
  778. float a = dataLCH[i * 3 + 1];
  779. float b = dataLCH[i * 3 + 2];
  780. dataLCH[i * 3 + 1] = Conversion::Lab_to_C_of_LCH(a, b);
  781. dataLCH[i * 3 + 2] = Conversion::Lab_to_H_of_LCH(a, b);
  782. }
  783. }
  784. else
  785. dataLCH = data;
  786. float* lChannel = new float[width * height];
  787. float* cChannel = new float[width * height];
  788. float* hChannel = new float[width * height];
  789. for (unsigned int i = 0; i < width * height; i++)
  790. {
  791. lChannel[i] = dataLCH[i * 3];
  792. cChannel[i] = dataLCH[i * 3 + 1];
  793. hChannel[i] = dataLCH[i * 3 + 2];
  794. }
  795. // Récupération du max du canal L et C
  796. float lMaxChannel = dataLCH[0];
  797. float cMaxChannel = dataLCH[1];
  798. for (unsigned int i = 1; i < width * height; i++)
  799. {
  800. if (dataLCH[i * 3] > lMaxChannel)
  801. lMaxChannel = dataLCH[i * 3];
  802. if (dataLCH[i * 3 + 1] > cMaxChannel)
  803. cMaxChannel = dataLCH[i * 3 + 1];
  804. }
  805. if (lMaxChannel < 100.0f)
  806. lMaxChannel = 100.0f;
  807. if (cMaxChannel < 100.0f)
  808. cMaxChannel = 100.0f;
  809. lMax = lMax * lMaxChannel / 100.0f;
  810. cMax = cMax * cMaxChannel / 100.0f;
  811. float* lightnessMask = Utils::NPlinearWeightMask(lChannel, width * height, lMin, lMax, lightTolerance);
  812. float* chromaMask = Utils::NPlinearWeightMask(cChannel, width * height, cMin, cMax, chromaTolerance);
  813. float* hueMask = Utils::NPlinearWeightMask(hChannel, width * height, hMin, hMax, hueTolerance);
  814. minMask = new float[width * height];
  815. compMask = new float[width * height];
  816. for (unsigned int i = 0; i < width * height; i++)
  817. {
  818. minMask[i] = lightnessMask[i];
  819. if (chromaMask[i] < minMask[i])
  820. minMask[i] = chromaMask[i];
  821. if (hueMask[i] < minMask[i])
  822. minMask[i] = hueMask[i];
  823. compMask[i] = 1.0f - minMask[i];
  824. }
  825. delete[](lightnessMask);
  826. delete[](chromaMask);
  827. delete[](hueMask);
  828. float hueShift = edit_hue;
  829. for (unsigned int i = 0; i < width * height; i++) {
  830. float oldValue = hChannel[i];
  831. hChannel[i] = oldValue + hueShift;
  832. while (hChannel[i] < 0.0f)
  833. hChannel[i] += 360.0f;
  834. while (hChannel[i] >= 360.0f)
  835. hChannel[i] -= 360.0f;
  836. hChannel[i] = hChannel[i] * minMask[i] + oldValue * compMask[i];
  837. }
  838. float saturation = edit_saturation;
  839. float gamma = 1.0f / ((saturation / 25.0f) + 1.0f);
  840. if (saturation < 0)
  841. gamma = (-saturation / 25.0f) + 1.0f;
  842. for (unsigned int i = 0; i < width * height; i++) {
  843. cChannel[i] = powf(cChannel[i] / 100.0f, gamma) * 100 * minMask[i] + cChannel[i] * compMask[i];
  844. }
  845. float* colorLCH = new float[width * height * 3];
  846. for (unsigned int i = 0; i < width * height; i++)
  847. {
  848. colorLCH[i * 3] = lChannel[i];
  849. colorLCH[i * 3 + 1] = cChannel[i];
  850. colorLCH[i * 3 + 2] = hChannel[i];
  851. }
  852. delete[](lChannel);
  853. delete[](cChannel);
  854. delete[](hChannel);
  855. float ev = edit_exposure;
  856. float* colorRGB = NULL;
  857. if (ev != 0)
  858. {
  859. colorRGB = Conversion::LCH_to_sRGB(colorLCH, width * height);
  860. float* colorRGBev = new float[width * height * 3];
  861. float coeff = powf(2, ev);
  862. for (unsigned int i = 0; i < width * height; i++)
  863. {
  864. colorRGBev[i * 3] = colorRGB[i * 3] * coeff * minMask[i];
  865. colorRGBev[i * 3 + 1] = colorRGB[i * 3 + 1] * coeff * minMask[i];
  866. colorRGBev[i * 3 + 2] = colorRGB[i * 3 + 2] * coeff * minMask[i];
  867. colorRGB[i * 3] = colorRGB[i * 3] * compMask[i] + colorRGBev[i * 3];
  868. colorRGB[i * 3 + 1] = colorRGB[i * 3 + 1] * compMask[i] + colorRGBev[i * 3 + 1];
  869. colorRGB[i * 3 + 2] = colorRGB[i * 3 + 2] * compMask[i] + colorRGBev[i * 3 + 2];
  870. }
  871. delete[](colorRGBev);
  872. }
  873. if (edit_contrast != 0)
  874. {
  875. float contrast = edit_contrast / 100.0f;
  876. float maxContrastFactor = 2.0f;
  877. float scalingFactor = (1.0f - contrast) + maxContrastFactor * contrast;
  878. if (contrast < 0.0f)
  879. {
  880. contrast = -contrast;
  881. scalingFactor = 1.0f / scalingFactor;
  882. }
  883. float pivot = powf(2, ev) * (lMin + lMax) / 2.0f / 100.0f;
  884. if (colorRGB == NULL)
  885. colorRGB = Conversion::LCH_to_sRGB(colorLCH, width * height);
  886. float* colorRGB2 = Conversion::linear_to_non_linear(colorRGB, width * height * 3);
  887. delete[](colorRGB);
  888. colorRGB=colorRGB2;
  889. float* colorRGBcon = new float[width * height * 3];
  890. for (unsigned int i = 0; i < width * height; i++)
  891. {
  892. colorRGBcon[i * 3] = (colorRGB[i * 3] - pivot) * scalingFactor + pivot;
  893. colorRGBcon[i * 3 + 1] = (colorRGB[i * 3 + 1] - pivot) * scalingFactor + pivot;
  894. colorRGBcon[i * 3 + 2] = (colorRGB[i * 3 + 2] - pivot) * scalingFactor + pivot;
  895. colorRGB[i * 3] = colorRGBcon[i * 3] * minMask[i] + colorRGB[i * 3] * compMask[i];
  896. colorRGB[i * 3 + 1] = colorRGBcon[i * 3 + 1] * minMask[i] + colorRGB[i * 3 + 1] * compMask[i];
  897. colorRGB[i * 3 + 2] = colorRGBcon[i * 3 + 2] * minMask[i] + colorRGB[i * 3 + 2] * compMask[i];
  898. }
  899. delete[](colorRGBcon);
  900. colorRGB2 = Conversion::non_linear_to_linear(colorRGB, width * height * 3);
  901. delete[](colorRGB);
  902. colorRGB=colorRGB2;
  903. }
  904. if (colorRGB == NULL)
  905. colorRGB = Conversion::LCH_to_sRGB(colorLCH, width * height);
  906. for (unsigned int i = 0; i < width*height * 3; i++)
  907. {
  908. data[i] = colorRGB[i];
  909. }
  910. delete[](colorRGB);
  911. delete[](colorLCH);
  912. colorspace = Colorspace::RGB;
  913. linear = true;
  914. }
  915. else
  916. {
  917. if (colorspace == Colorspace::LCH)
  918. {
  919. float* colorRGB = Conversion::LCH_to_sRGB(data, width * height);
  920. for (unsigned int i = 0; i < width*height * 3; i++)
  921. {
  922. data[i] = colorRGB[i];
  923. }
  924. delete[](colorRGB);
  925. colorspace = Colorspace::RGB;
  926. linear = true;
  927. }
  928. }
  929. if (mask)
  930. {
  931. for (unsigned int i = 0; i < width * height; i++)
  932. {
  933. data[i * 3] = minMask[i];
  934. data[i * 3 + 1] = minMask[i];
  935. data[i * 3 + 2] = minMask[i];
  936. }
  937. colorspace = Colorspace::RGB;
  938. linear = false;
  939. }
  940. delete[](minMask);
  941. delete[](compMask);
  942. }
  943. #endif
  944. /* Private methods */
  945. Eigen::VectorXf ImageHDR::to_EigenVector() const
  946. {
  947. Eigen::VectorXf v(width * height * 3);
  948. for (unsigned int i = 0; i < width; i++)
  949. v(i) = data[i];
  950. return v;
  951. }