1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 //
5 //
6 // License Agreement
7 // For Open Source Computer Vision Library
8 //
9 // Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved.
10 // Third party copyrights are property of their respective owners.
11 //
12 // Licensed under the Apache License, Version 2.0 (the "License");
13 // you may not use this file except in compliance with the License.
14 // You may obtain a copy of the License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the License is distributed on an "AS IS" BASIS,
20 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 // See the License for the specific language governing permissions and
22 // limitations under the License.
23 //
24 // Author: Longbu Wang <wanglongbu@huawei.com.com>
25 // Jinheng Zhang <zhangjinheng1@huawei.com>
26 // Chenqi Shan <shanchenqi@huawei.com>
27
28 #include "precomp.hpp"
29
30 #include "colorspace.hpp"
31 #include "operations.hpp"
32 #include "io.hpp"
33
34 namespace cv {
35 namespace ccm {
getIlluminants(const IO & io)36 static const std::vector<double>& getIlluminants(const IO& io)
37 {
38 static const std::map<IO, std::vector<double>> illuminants = {
39 { IO::getIOs(A_2), { 1.098466069456375, 1, 0.3558228003436005 } },
40 { IO::getIOs(A_10), { 1.111420406956693, 1, 0.3519978321919493 } },
41 { IO::getIOs(D50_2), { 0.9642119944211994, 1, 0.8251882845188288 } },
42 { IO::getIOs(D50_10), { 0.9672062750333777, 1, 0.8142801513128616 } },
43 { IO::getIOs(D55_2), { 0.956797052643698, 1, 0.9214805860173273 } },
44 { IO::getIOs(D55_10), { 0.9579665682254781, 1, 0.9092525159847462 } },
45 { IO::getIOs(D65_2), { 0.95047, 1., 1.08883 } },
46 { IO::getIOs(D65_10), { 0.94811, 1., 1.07304 } },
47 { IO::getIOs(D75_2), { 0.9497220898840717, 1, 1.226393520724154 } },
48 { IO::getIOs(D75_10), { 0.9441713925645873, 1, 1.2064272211720228 } },
49 { IO::getIOs(E_2), { 1., 1., 1. } },
50 { IO::getIOs(E_10), { 1., 1., 1. } },
51 };
52 auto it = illuminants.find(io);
53 CV_Assert(it != illuminants.end());
54 return it->second;
55 };
56
57 /* @brief Basic class for ColorSpace.
58 */
relate(const ColorSpace & other) const59 bool ColorSpace::relate(const ColorSpace& other) const
60 {
61 return (type == other.type) && (io == other.io);
62 };
63
relation(const ColorSpace &) const64 Operations ColorSpace::relation(const ColorSpace& /*other*/) const
65 {
66 return Operations::get_IDENTITY_OPS();
67 }
68
operator <(const ColorSpace & other) const69 bool ColorSpace::operator<(const ColorSpace& other) const
70 {
71 return (io < other.io || (io == other.io && type < other.type) || (io == other.io && type == other.type && linear < other.linear));
72 }
73
74 /* @brief Base of RGB color space;
75 * the argument values are from AdobeRGB;
76 * Data from https://en.wikipedia.org/wiki/Adobe_RGB_color_space
77 */
relation(const ColorSpace & other) const78 Operations RGBBase_::relation(const ColorSpace& other) const
79 {
80 if (linear == other.linear)
81 {
82 return Operations::get_IDENTITY_OPS();
83 }
84 if (linear)
85 {
86 return Operations({ Operation(fromL) });
87 }
88 return Operations({ Operation(toL) });
89 }
90
91 /* @brief Initial operations.
92 */
init()93 void RGBBase_::init()
94 {
95 setParameter();
96 calLinear();
97 calM();
98 calOperations();
99 }
100
101 /* @brief Produce color space instance with linear and non-linear versions.
102 * @param rgbl type of RGBBase_.
103 */
bind(RGBBase_ & rgbl)104 void RGBBase_::bind(RGBBase_& rgbl)
105 {
106 init();
107 rgbl.init();
108 l = &rgbl;
109 rgbl.l = &rgbl;
110 nl = this;
111 rgbl.nl = this;
112 }
113
114 /* @brief Calculation of M_RGBL2XYZ_base.
115 */
calM()116 void RGBBase_::calM()
117 {
118 Mat XYZr, XYZg, XYZb, XYZ_rgbl, Srgb;
119 XYZr = Mat(xyY2XYZ({ xr, yr }), true);
120 XYZg = Mat(xyY2XYZ({ xg, yg }), true);
121 XYZb = Mat(xyY2XYZ({ xb, yb }), true);
122 merge(std::vector<Mat> { XYZr, XYZg, XYZb }, XYZ_rgbl);
123 XYZ_rgbl = XYZ_rgbl.reshape(1, XYZ_rgbl.rows);
124 Mat XYZw = Mat(getIlluminants(io), true);
125 solve(XYZ_rgbl, XYZw, Srgb);
126 merge(std::vector<Mat> { Srgb.at<double>(0) * XYZr, Srgb.at<double>(1) * XYZg,
127 Srgb.at<double>(2) * XYZb },
128 M_to);
129 M_to = M_to.reshape(1, M_to.rows);
130 M_from = M_to.inv();
131 };
132
133 /* @brief operations to or from XYZ.
134 */
calOperations()135 void RGBBase_::calOperations()
136 {
137 // rgb -> rgbl
138 toL = [this](Mat rgb) -> Mat { return toLFunc(rgb); };
139
140 // rgbl -> rgb
141 fromL = [this](Mat rgbl) -> Mat { return fromLFunc(rgbl); };
142
143 if (linear)
144 {
145 to = Operations({ Operation(M_to.t()) });
146 from = Operations({ Operation(M_from.t()) });
147 }
148 else
149 {
150 to = Operations({ Operation(toL), Operation(M_to.t()) });
151 from = Operations({ Operation(M_from.t()), Operation(fromL) });
152 }
153 }
154
toLFunc(Mat &)155 Mat RGBBase_::toLFunc(Mat& /*rgb*/) { return Mat(); }
156
fromLFunc(Mat &)157 Mat RGBBase_::fromLFunc(Mat& /*rgbl*/) { return Mat(); }
158
159 /* @brief Base of Adobe RGB color space;
160 */
161
toLFunc(Mat & rgb)162 Mat AdobeRGBBase_::toLFunc(Mat& rgb) { return gammaCorrection(rgb, gamma); }
163
fromLFunc(Mat & rgbl)164 Mat AdobeRGBBase_::fromLFunc(Mat& rgbl)
165 {
166 return gammaCorrection(rgbl, 1. / gamma);
167 }
168
169 /* @brief Base of sRGB color space;
170 */
171
calLinear()172 void sRGBBase_::calLinear()
173 {
174 alpha = a + 1;
175 K0 = a / (gamma - 1);
176 phi = (pow(alpha, gamma) * pow(gamma - 1, gamma - 1)) / (pow(a, gamma - 1) * pow(gamma, gamma));
177 beta = K0 / phi;
178 }
179
180 /* @brief Used by toLFunc.
181 */
toLFuncEW(double & x)182 double sRGBBase_::toLFuncEW(double& x)
183 {
184 if (x > K0)
185 {
186 return pow(((x + alpha - 1) / alpha), gamma);
187 }
188 else if (x >= -K0)
189 {
190 return x / phi;
191 }
192 else
193 {
194 return -(pow(((-x + alpha - 1) / alpha), gamma));
195 }
196 }
197
198 /* @brief Linearization.
199 * @param rgb the input array, type of cv::Mat.
200 * @return the output array, type of cv::Mat.
201 */
toLFunc(Mat & rgb)202 Mat sRGBBase_::toLFunc(Mat& rgb)
203 {
204 return elementWise(rgb,
205 [this](double a_) -> double { return toLFuncEW(a_); });
206 }
207
208 /* @brief Used by fromLFunc.
209 */
fromLFuncEW(double & x)210 double sRGBBase_::fromLFuncEW(double& x)
211 {
212 if (x > beta)
213 {
214 return alpha * pow(x, 1 / gamma) - (alpha - 1);
215 }
216 else if (x >= -beta)
217 {
218 return x * phi;
219 }
220 else
221 {
222 return -(alpha * pow(-x, 1 / gamma) - (alpha - 1));
223 }
224 }
225
226 /* @brief Delinearization.
227 * @param rgbl the input array, type of cv::Mat.
228 * @return the output array, type of cv::Mat.
229 */
fromLFunc(Mat & rgbl)230 Mat sRGBBase_::fromLFunc(Mat& rgbl)
231 {
232 return elementWise(rgbl,
233 [this](double a_) -> double { return fromLFuncEW(a_); });
234 }
235
236 /* @brief sRGB color space.
237 * data from https://en.wikipedia.org/wiki/SRGB.
238 */
setParameter()239 void sRGB_::setParameter()
240 {
241 xr = 0.64;
242 yr = 0.33;
243 xg = 0.3;
244 yg = 0.6;
245 xb = 0.15;
246 yb = 0.06;
247 a = 0.055;
248 gamma = 2.4;
249 }
250
251 /* @brief Adobe RGB color space.
252 */
setParameter()253 void AdobeRGB_::setParameter()
254 {
255 xr = 0.64;
256 yr = 0.33;
257 xg = 0.21;
258 yg = 0.71;
259 xb = 0.15;
260 yb = 0.06;
261 gamma = 2.2;
262 }
263
264 /* @brief Wide-gamut RGB color space.
265 * data from https://en.wikipedia.org/wiki/Wide-gamut_RGB_color_space.
266 */
setParameter()267 void WideGamutRGB_::setParameter()
268 {
269 xr = 0.7347;
270 yr = 0.2653;
271 xg = 0.1152;
272 yg = 0.8264;
273 xb = 0.1566;
274 yb = 0.0177;
275 gamma = 2.2;
276 }
277
278 /* @brief ProPhoto RGB color space.
279 * data from https://en.wikipedia.org/wiki/ProPhoto_RGB_color_space.
280 */
setParameter()281 void ProPhotoRGB_::setParameter()
282 {
283 xr = 0.734699;
284 yr = 0.265301;
285 xg = 0.159597;
286 yg = 0.840403;
287 xb = 0.036598;
288 yb = 0.000105;
289 gamma = 1.8;
290 }
291
292 /* @brief DCI-P3 RGB color space.
293 * data from https://en.wikipedia.org/wiki/DCI-P3.
294 */
295
setParameter()296 void DCI_P3_RGB_::setParameter()
297 {
298 xr = 0.68;
299 yr = 0.32;
300 xg = 0.265;
301 yg = 0.69;
302 xb = 0.15;
303 yb = 0.06;
304 gamma = 2.2;
305 }
306
307 /* @brief Apple RGB color space.
308 * data from
309 * http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html.
310 */
setParameter()311 void AppleRGB_::setParameter()
312 {
313 xr = 0.625;
314 yr = 0.34;
315 xg = 0.28;
316 yg = 0.595;
317 xb = 0.155;
318 yb = 0.07;
319 gamma = 1.8;
320 }
321
322 /* @brief REC_709 RGB color space.
323 * data from https://en.wikipedia.org/wiki/Rec._709.
324 */
setParameter()325 void REC_709_RGB_::setParameter()
326 {
327 xr = 0.64;
328 yr = 0.33;
329 xg = 0.3;
330 yg = 0.6;
331 xb = 0.15;
332 yb = 0.06;
333 a = 0.099;
334 gamma = 1 / 0.45;
335 }
336
337 /* @brief REC_2020 RGB color space.
338 * data from https://en.wikipedia.org/wiki/Rec._2020.
339 */
340
setParameter()341 void REC_2020_RGB_::setParameter()
342 {
343 xr = 0.708;
344 yr = 0.292;
345 xg = 0.17;
346 yg = 0.797;
347 xb = 0.131;
348 yb = 0.046;
349 a = 0.09929682680944;
350 gamma = 1 / 0.45;
351 }
352
cam(IO dio,CAM method)353 Operations XYZ::cam(IO dio, CAM method)
354 {
355 return (io == dio) ? Operations()
356 : Operations({ Operation(cam_(io, dio, method).t()) });
357 }
cam_(IO sio,IO dio,CAM method) const358 Mat XYZ::cam_(IO sio, IO dio, CAM method) const
359 {
360 static std::map<std::tuple<IO, IO, CAM>, Mat> cams;
361
362 if (sio == dio)
363 {
364 return Mat::eye(cv::Size(3, 3), CV_64FC1);
365 }
366 if (cams.count(std::make_tuple(dio, sio, method)) == 1)
367 {
368 return cams[std::make_tuple(dio, sio, method)];
369 }
370 /* @brief XYZ color space.
371 * Chromatic adaption matrices.
372 */
373
374 static const Mat Von_Kries = (Mat_<double>(3, 3) << 0.40024, 0.7076, -0.08081, -0.2263, 1.16532, 0.0457, 0., 0., 0.91822);
375 static const Mat Bradford = (Mat_<double>(3, 3) << 0.8951, 0.2664, -0.1614, -0.7502, 1.7135, 0.0367, 0.0389, -0.0685, 1.0296);
376 static const std::map<CAM, std::vector<Mat>> MAs = {
377 { IDENTITY, { Mat::eye(Size(3, 3), CV_64FC1), Mat::eye(Size(3, 3), CV_64FC1) } },
378 { VON_KRIES, { Von_Kries, Von_Kries.inv() } },
379 { BRADFORD, { Bradford, Bradford.inv() } }
380 };
381
382 // Function from http://www.brucelindbloom.com/index.html?ColorCheckerRGB.html.
383 Mat XYZws = Mat(getIlluminants(dio));
384 Mat XYZWd = Mat(getIlluminants(sio));
385 Mat MA = MAs.at(method)[0];
386 Mat MA_inv = MAs.at(method)[1];
387 Mat M = MA_inv * Mat::diag((MA * XYZws) / (MA * XYZWd)) * MA;
388 cams[std::make_tuple(dio, sio, method)] = M;
389 cams[std::make_tuple(sio, dio, method)] = M.inv();
390 return M;
391 }
392
get(IO io)393 std::shared_ptr<XYZ> XYZ::get(IO io)
394 {
395 static std::map<IO, std::shared_ptr<XYZ>> xyz_cs;
396
397 if (xyz_cs.count(io) == 1)
398 {
399 return xyz_cs[io];
400 }
401 std::shared_ptr<XYZ> XYZ_CS = std::make_shared<XYZ>(io);
402 xyz_cs[io] = XYZ_CS;
403 return xyz_cs[io];
404 }
405
406 /* @brief Lab color space.
407 */
Lab(IO io_)408 Lab::Lab(IO io_)
409 : ColorSpace(io_, "Lab", true)
410 {
411 to = { Operation([this](Mat src) -> Mat { return tosrc(src); }) };
412 from = { Operation([this](Mat src) -> Mat { return fromsrc(src); }) };
413 }
414
fromxyz(cv::Vec3d & xyz)415 Vec3d Lab::fromxyz(cv::Vec3d& xyz)
416 {
417 auto& il = getIlluminants(io);
418 double x = xyz[0] / il[0],
419 y = xyz[1] / il[1],
420 z = xyz[2] / il[2];
421 auto f = [](double t) -> double {
422 return t > t0 ? std::cbrt(t) : (m * t + c);
423 };
424 double fx = f(x), fy = f(y), fz = f(z);
425 return { 116. * fy - 16., 500 * (fx - fy), 200 * (fy - fz) };
426 }
427
428 /* @brief Calculate From.
429 * @param src the input array, type of cv::Mat.
430 * @return the output array, type of cv::Mat
431 */
fromsrc(Mat & src)432 Mat Lab::fromsrc(Mat& src)
433 {
434 return channelWise(src,
435 [this](cv::Vec3d a) -> cv::Vec3d { return fromxyz(a); });
436 }
437
tolab(cv::Vec3d & lab)438 Vec3d Lab::tolab(cv::Vec3d& lab)
439 {
440 auto f_inv = [](double t) -> double {
441 return t > delta ? pow(t, 3.0) : (t - c) / m;
442 };
443 double L = (lab[0] + 16.) / 116., a = lab[1] / 500., b = lab[2] / 200.;
444 auto& il = getIlluminants(io);
445 return { il[0] * f_inv(L + a),
446 il[1] * f_inv(L),
447 il[2] * f_inv(L - b) };
448 }
449
450 /* @brief Calculate To.
451 * @param src the input array, type of cv::Mat.
452 * @return the output array, type of cv::Mat
453 */
tosrc(Mat & src)454 Mat Lab::tosrc(Mat& src)
455 {
456 return channelWise(src,
457 [this](cv::Vec3d a) -> cv::Vec3d { return tolab(a); });
458 }
459
get(IO io)460 std::shared_ptr<Lab> Lab::get(IO io)
461 {
462 static std::map<IO, std::shared_ptr<Lab>> lab_cs;
463
464 if (lab_cs.count(io) == 1)
465 {
466 return lab_cs[io];
467 }
468 std::shared_ptr<Lab> Lab_CS(new Lab(io));
469 lab_cs[io] = Lab_CS;
470 return lab_cs[io];
471 }
472
GetCS()473 GetCS::GetCS()
474 {
475 // nothing
476 }
477
getInstance()478 GetCS& GetCS::getInstance()
479 {
480 static GetCS instance;
481 return instance;
482 }
483
get_rgb(enum COLOR_SPACE cs_name)484 std::shared_ptr<RGBBase_> GetCS::get_rgb(enum COLOR_SPACE cs_name)
485 {
486 switch (cs_name)
487 {
488 case cv::ccm::COLOR_SPACE_sRGB:
489 {
490 if (map_cs.count(cs_name) < 1)
491 {
492 std::shared_ptr<sRGB_> sRGB_CS(new sRGB_(false));
493 std::shared_ptr<sRGB_> sRGBL_CS(new sRGB_(true));
494 (*sRGB_CS).bind(*sRGBL_CS);
495 map_cs[COLOR_SPACE_sRGB] = sRGB_CS;
496 map_cs[COLOR_SPACE_sRGBL] = sRGBL_CS;
497 }
498 break;
499 }
500 case cv::ccm::COLOR_SPACE_AdobeRGB:
501 {
502 if (map_cs.count(cs_name) < 1)
503 {
504 std::shared_ptr<AdobeRGB_> AdobeRGB_CS(new AdobeRGB_(false));
505 std::shared_ptr<AdobeRGB_> AdobeRGBL_CS(new AdobeRGB_(true));
506 (*AdobeRGB_CS).bind(*AdobeRGBL_CS);
507 map_cs[COLOR_SPACE_AdobeRGB] = AdobeRGB_CS;
508 map_cs[COLOR_SPACE_AdobeRGBL] = AdobeRGBL_CS;
509 }
510 break;
511 }
512 case cv::ccm::COLOR_SPACE_WideGamutRGB:
513 {
514 if (map_cs.count(cs_name) < 1)
515 {
516 std::shared_ptr<WideGamutRGB_> WideGamutRGB_CS(new WideGamutRGB_(false));
517 std::shared_ptr<WideGamutRGB_> WideGamutRGBL_CS(new WideGamutRGB_(true));
518 (*WideGamutRGB_CS).bind(*WideGamutRGBL_CS);
519 map_cs[COLOR_SPACE_WideGamutRGB] = WideGamutRGB_CS;
520 map_cs[COLOR_SPACE_WideGamutRGBL] = WideGamutRGBL_CS;
521 }
522 break;
523 }
524 case cv::ccm::COLOR_SPACE_ProPhotoRGB:
525 {
526 if (map_cs.count(cs_name) < 1)
527 {
528 std::shared_ptr<ProPhotoRGB_> ProPhotoRGB_CS(new ProPhotoRGB_(false));
529 std::shared_ptr<ProPhotoRGB_> ProPhotoRGBL_CS(new ProPhotoRGB_(true));
530 (*ProPhotoRGB_CS).bind(*ProPhotoRGBL_CS);
531 map_cs[COLOR_SPACE_ProPhotoRGB] = ProPhotoRGB_CS;
532 map_cs[COLOR_SPACE_ProPhotoRGBL] = ProPhotoRGBL_CS;
533 }
534 break;
535 }
536 case cv::ccm::COLOR_SPACE_DCI_P3_RGB:
537 {
538 if (map_cs.count(cs_name) < 1)
539 {
540 std::shared_ptr<DCI_P3_RGB_> DCI_P3_RGB_CS(new DCI_P3_RGB_(false));
541 std::shared_ptr<DCI_P3_RGB_> DCI_P3_RGBL_CS(new DCI_P3_RGB_(true));
542 (*DCI_P3_RGB_CS).bind(*DCI_P3_RGBL_CS);
543 map_cs[COLOR_SPACE_DCI_P3_RGB] = DCI_P3_RGB_CS;
544 map_cs[COLOR_SPACE_DCI_P3_RGBL] = DCI_P3_RGBL_CS;
545 }
546 break;
547 }
548 case cv::ccm::COLOR_SPACE_AppleRGB:
549 {
550 if (map_cs.count(cs_name) < 1)
551 {
552 std::shared_ptr<AppleRGB_> AppleRGB_CS(new AppleRGB_(false));
553 std::shared_ptr<AppleRGB_> AppleRGBL_CS(new AppleRGB_(true));
554 (*AppleRGB_CS).bind(*AppleRGBL_CS);
555 map_cs[COLOR_SPACE_AppleRGB] = AppleRGB_CS;
556 map_cs[COLOR_SPACE_AppleRGBL] = AppleRGBL_CS;
557 }
558 break;
559 }
560 case cv::ccm::COLOR_SPACE_REC_709_RGB:
561 {
562 if (map_cs.count(cs_name) < 1)
563 {
564 std::shared_ptr<REC_709_RGB_> REC_709_RGB_CS(new REC_709_RGB_(false));
565 std::shared_ptr<REC_709_RGB_> REC_709_RGBL_CS(new REC_709_RGB_(true));
566 (*REC_709_RGB_CS).bind(*REC_709_RGBL_CS);
567 map_cs[COLOR_SPACE_REC_709_RGB] = REC_709_RGB_CS;
568 map_cs[COLOR_SPACE_REC_709_RGBL] = REC_709_RGBL_CS;
569 }
570 break;
571 }
572 case cv::ccm::COLOR_SPACE_REC_2020_RGB:
573 {
574 if (map_cs.count(cs_name) < 1)
575 {
576 std::shared_ptr<REC_2020_RGB_> REC_2020_RGB_CS(new REC_2020_RGB_(false));
577 std::shared_ptr<REC_2020_RGB_> REC_2020_RGBL_CS(new REC_2020_RGB_(true));
578 (*REC_2020_RGB_CS).bind(*REC_2020_RGBL_CS);
579 map_cs[COLOR_SPACE_REC_2020_RGB] = REC_2020_RGB_CS;
580 map_cs[COLOR_SPACE_REC_2020_RGBL] = REC_2020_RGBL_CS;
581 }
582 break;
583 }
584 case cv::ccm::COLOR_SPACE_sRGBL:
585 case cv::ccm::COLOR_SPACE_AdobeRGBL:
586 case cv::ccm::COLOR_SPACE_WideGamutRGBL:
587 case cv::ccm::COLOR_SPACE_ProPhotoRGBL:
588 case cv::ccm::COLOR_SPACE_DCI_P3_RGBL:
589 case cv::ccm::COLOR_SPACE_AppleRGBL:
590 case cv::ccm::COLOR_SPACE_REC_709_RGBL:
591 case cv::ccm::COLOR_SPACE_REC_2020_RGBL:
592 CV_Error(Error::StsBadArg, "linear RGB colorspaces are not supported, you should assigned as normal RGB color space");
593 break;
594
595 default:
596 CV_Error(Error::StsBadArg, "Only RGB color spaces are supported");
597 }
598 return (std::dynamic_pointer_cast<RGBBase_>)(map_cs[cs_name]);
599 }
600
get_cs(enum COLOR_SPACE cs_name)601 std::shared_ptr<ColorSpace> GetCS::get_cs(enum COLOR_SPACE cs_name)
602 {
603 switch (cs_name)
604 {
605 case cv::ccm::COLOR_SPACE_sRGB:
606 case cv::ccm::COLOR_SPACE_sRGBL:
607 {
608 if (map_cs.count(cs_name) < 1)
609 {
610 std::shared_ptr<sRGB_> sRGB_CS(new sRGB_(false));
611 std::shared_ptr<sRGB_> sRGBL_CS(new sRGB_(true));
612 (*sRGB_CS).bind(*sRGBL_CS);
613 map_cs[COLOR_SPACE_sRGB] = sRGB_CS;
614 map_cs[COLOR_SPACE_sRGBL] = sRGBL_CS;
615 }
616 break;
617 }
618 case cv::ccm::COLOR_SPACE_AdobeRGB:
619 case cv::ccm::COLOR_SPACE_AdobeRGBL:
620 {
621 if (map_cs.count(cs_name) < 1)
622 {
623 std::shared_ptr<AdobeRGB_> AdobeRGB_CS(new AdobeRGB_(false));
624 std::shared_ptr<AdobeRGB_> AdobeRGBL_CS(new AdobeRGB_(true));
625 (*AdobeRGB_CS).bind(*AdobeRGBL_CS);
626 map_cs[COLOR_SPACE_AdobeRGB] = AdobeRGB_CS;
627 map_cs[COLOR_SPACE_AdobeRGBL] = AdobeRGBL_CS;
628 }
629 break;
630 }
631 case cv::ccm::COLOR_SPACE_WideGamutRGB:
632 case cv::ccm::COLOR_SPACE_WideGamutRGBL:
633 {
634 if (map_cs.count(cs_name) < 1)
635 {
636 std::shared_ptr<WideGamutRGB_> WideGamutRGB_CS(new WideGamutRGB_(false));
637 std::shared_ptr<WideGamutRGB_> WideGamutRGBL_CS(new WideGamutRGB_(true));
638 (*WideGamutRGB_CS).bind(*WideGamutRGBL_CS);
639 map_cs[COLOR_SPACE_WideGamutRGB] = WideGamutRGB_CS;
640 map_cs[COLOR_SPACE_WideGamutRGBL] = WideGamutRGBL_CS;
641 }
642 break;
643 }
644 case cv::ccm::COLOR_SPACE_ProPhotoRGB:
645 case cv::ccm::COLOR_SPACE_ProPhotoRGBL:
646 {
647 if (map_cs.count(cs_name) < 1)
648 {
649 std::shared_ptr<ProPhotoRGB_> ProPhotoRGB_CS(new ProPhotoRGB_(false));
650 std::shared_ptr<ProPhotoRGB_> ProPhotoRGBL_CS(new ProPhotoRGB_(true));
651 (*ProPhotoRGB_CS).bind(*ProPhotoRGBL_CS);
652 map_cs[COLOR_SPACE_ProPhotoRGB] = ProPhotoRGB_CS;
653 map_cs[COLOR_SPACE_ProPhotoRGBL] = ProPhotoRGBL_CS;
654 }
655 break;
656 }
657 case cv::ccm::COLOR_SPACE_DCI_P3_RGB:
658 case cv::ccm::COLOR_SPACE_DCI_P3_RGBL:
659 {
660 if (map_cs.count(cs_name) < 1)
661 {
662 std::shared_ptr<DCI_P3_RGB_> DCI_P3_RGB_CS(new DCI_P3_RGB_(false));
663 std::shared_ptr<DCI_P3_RGB_> DCI_P3_RGBL_CS(new DCI_P3_RGB_(true));
664 (*DCI_P3_RGB_CS).bind(*DCI_P3_RGBL_CS);
665 map_cs[COLOR_SPACE_DCI_P3_RGB] = DCI_P3_RGB_CS;
666 map_cs[COLOR_SPACE_DCI_P3_RGBL] = DCI_P3_RGBL_CS;
667 }
668 break;
669 }
670 case cv::ccm::COLOR_SPACE_AppleRGB:
671 case cv::ccm::COLOR_SPACE_AppleRGBL:
672 {
673 if (map_cs.count(cs_name) < 1)
674 {
675 std::shared_ptr<AppleRGB_> AppleRGB_CS(new AppleRGB_(false));
676 std::shared_ptr<AppleRGB_> AppleRGBL_CS(new AppleRGB_(true));
677 (*AppleRGB_CS).bind(*AppleRGBL_CS);
678 map_cs[COLOR_SPACE_AppleRGB] = AppleRGB_CS;
679 map_cs[COLOR_SPACE_AppleRGBL] = AppleRGBL_CS;
680 }
681 break;
682 }
683 case cv::ccm::COLOR_SPACE_REC_709_RGB:
684 case cv::ccm::COLOR_SPACE_REC_709_RGBL:
685 {
686 if (map_cs.count(cs_name) < 1)
687 {
688 std::shared_ptr<REC_709_RGB_> REC_709_RGB_CS(new REC_709_RGB_(false));
689 std::shared_ptr<REC_709_RGB_> REC_709_RGBL_CS(new REC_709_RGB_(true));
690 (*REC_709_RGB_CS).bind(*REC_709_RGBL_CS);
691 map_cs[COLOR_SPACE_REC_709_RGB] = REC_709_RGB_CS;
692 map_cs[COLOR_SPACE_REC_709_RGBL] = REC_709_RGBL_CS;
693 }
694 break;
695 }
696 case cv::ccm::COLOR_SPACE_REC_2020_RGB:
697 case cv::ccm::COLOR_SPACE_REC_2020_RGBL:
698 {
699 if (map_cs.count(cs_name) < 1)
700 {
701 std::shared_ptr<REC_2020_RGB_> REC_2020_RGB_CS(new REC_2020_RGB_(false));
702 std::shared_ptr<REC_2020_RGB_> REC_2020_RGBL_CS(new REC_2020_RGB_(true));
703 (*REC_2020_RGB_CS).bind(*REC_2020_RGBL_CS);
704 map_cs[COLOR_SPACE_REC_2020_RGB] = REC_2020_RGB_CS;
705 map_cs[COLOR_SPACE_REC_2020_RGBL] = REC_2020_RGBL_CS;
706 }
707 break;
708 }
709 case cv::ccm::COLOR_SPACE_XYZ_D65_2:
710 return XYZ::get(IO::getIOs(D65_2));
711 break;
712 case cv::ccm::COLOR_SPACE_XYZ_D50_2:
713 return XYZ::get(IO::getIOs(D50_2));
714 break;
715 case cv::ccm::COLOR_SPACE_XYZ_D65_10:
716 return XYZ::get(IO::getIOs(D65_10));
717 break;
718 case cv::ccm::COLOR_SPACE_XYZ_D50_10:
719 return XYZ::get(IO::getIOs(D50_10));
720 break;
721 case cv::ccm::COLOR_SPACE_XYZ_A_2:
722 return XYZ::get(IO::getIOs(A_2));
723 break;
724 case cv::ccm::COLOR_SPACE_XYZ_A_10:
725 return XYZ::get(IO::getIOs(A_10));
726 break;
727 case cv::ccm::COLOR_SPACE_XYZ_D55_2:
728 return XYZ::get(IO::getIOs(D55_2));
729 break;
730 case cv::ccm::COLOR_SPACE_XYZ_D55_10:
731 return XYZ::get(IO::getIOs(D55_10));
732 break;
733 case cv::ccm::COLOR_SPACE_XYZ_D75_2:
734 return XYZ::get(IO::getIOs(D75_2));
735 break;
736 case cv::ccm::COLOR_SPACE_XYZ_D75_10:
737 return XYZ::get(IO::getIOs(D75_10));
738 break;
739 case cv::ccm::COLOR_SPACE_XYZ_E_2:
740 return XYZ::get(IO::getIOs(E_2));
741 break;
742 case cv::ccm::COLOR_SPACE_XYZ_E_10:
743 return XYZ::get(IO::getIOs(E_10));
744 break;
745 case cv::ccm::COLOR_SPACE_Lab_D65_2:
746 return Lab::get(IO::getIOs(D65_2));
747 break;
748 case cv::ccm::COLOR_SPACE_Lab_D50_2:
749 return Lab::get(IO::getIOs(D50_2));
750 break;
751 case cv::ccm::COLOR_SPACE_Lab_D65_10:
752 return Lab::get(IO::getIOs(D65_10));
753 break;
754 case cv::ccm::COLOR_SPACE_Lab_D50_10:
755 return Lab::get(IO::getIOs(D50_10));
756 break;
757 case cv::ccm::COLOR_SPACE_Lab_A_2:
758 return Lab::get(IO::getIOs(A_2));
759 break;
760 case cv::ccm::COLOR_SPACE_Lab_A_10:
761 return Lab::get(IO::getIOs(A_10));
762 break;
763 case cv::ccm::COLOR_SPACE_Lab_D55_2:
764 return Lab::get(IO::getIOs(D55_2));
765 break;
766 case cv::ccm::COLOR_SPACE_Lab_D55_10:
767 return Lab::get(IO::getIOs(D55_10));
768 break;
769 case cv::ccm::COLOR_SPACE_Lab_D75_2:
770 return Lab::get(IO::getIOs(D75_2));
771 break;
772 case cv::ccm::COLOR_SPACE_Lab_D75_10:
773 return Lab::get(IO::getIOs(D75_10));
774 break;
775 case cv::ccm::COLOR_SPACE_Lab_E_2:
776 return Lab::get(IO::getIOs(E_2));
777 break;
778 case cv::ccm::COLOR_SPACE_Lab_E_10:
779 return Lab::get(IO::getIOs(E_10));
780 break;
781 default:
782 break;
783 }
784
785 return map_cs[cs_name];
786 }
787
788 }
789 } // namespace cv::ccm
790