Skip to content

Commit f7f94c6

Browse files
author
Thomas Lindemeier
committed
MOved etail functions in private section
1 parent 2f00d40 commit f7f94c6

File tree

2 files changed

+58
-92
lines changed

2 files changed

+58
-92
lines changed

example/main.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ int main()
99
// define custom vec type that is defined by our type trait above
1010
using vec = std::array<double, 3U>;
1111
// Save some typing
12-
using Converter = color::ColorConverter<double, std::array>;
12+
using Converter = color::ColorConverter<double, 3UL, std::array>;
1313

1414
// initialize the converter to standard sRGB illuminant (which is also the
1515
// default argument).
@@ -29,7 +29,8 @@ int main()
2929
// convert back to linear RGB from CIELab
3030
vec convertedLinearRgb;
3131
converter.lab2rgb(cieLab, convertedLinearRgb);
32-
// cpmpute the difference of input and converted linear RGB
32+
33+
// compute the difference of input and converted linear RGB
3334
const auto differenceEuclid =
3435
std::sqrt(std::pow(convertedLinearRgb[0U] - linearRgb[0U], 2.0) +
3536
std::pow(convertedLinearRgb[1U] - linearRgb[1U], 2.0) +

include/ColorConverter/ColorConverter.hxx

Lines changed: 55 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -15,80 +15,35 @@
1515
namespace color
1616
{
1717

18-
namespace detail
19-
{
20-
21-
template <class T>
22-
static T f(T t)
23-
{
24-
return (t > std::pow<T>(6. / 29., 3.))
25-
? std::pow<T>(t, 1. / 3.)
26-
: (1. / 3.) * std::pow<T>(29. / 6., 2.) * t + (4. / 29.);
27-
}
28-
29-
template <class T>
30-
static T fi(T t)
31-
{
32-
return (t > 6. / 29.) ? std::pow<T>(t, 3.)
33-
: 3. * std::pow<T>(6. / 29., 2.) * (t - (4. / 29.));
34-
}
35-
} // namespace detail
36-
3718
/**
3819
* @brief Class that holds color conversion functions with reference to a given
3920
* white point (illuminant).
4021
*
22+
* Only data types of the template form vec<Type, size_t> are supported. Only
23+
* floating points and data types with 3 components are supported.
24+
*
4125
* Most of the conversion and constants were taken from
4226
* http://brucelindbloom.com/index.html (last accessed 2019 April 14th)
4327
* Credits to that guy!
4428
*
45-
* @tparam T precision
29+
* @tparam Scalar Data type of each component. Only floating point values
30+
* supported.
31+
*
32+
* @tparam N Number of components. Has to be equal to 3.
33+
*
34+
* @tparam Vec The data structure template class of the form Vec<Scalar, 3UL>
4635
*/
47-
template <class Scalar, template <class, size_t> class Vec>
36+
template <class Scalar, size_t N, template <class, size_t> class Vec,
37+
typename std::enable_if_t<
38+
std::is_floating_point<Scalar>::value && (N == 3UL), int> = 0>
4839
class ColorConverter
4940
{
50-
using Vec3 = Vec<Scalar, 3UL>;
41+
using Vec3 = Vec<Scalar, N>;
5142

52-
public:
53-
/**
54-
* @brief Represents conversion source2target.
55-
*/
56-
enum class Conversion
57-
{
58-
CIELab_2_XYZ,
59-
XYZ_2_CIELab,
60-
CIELab_2_LCHab, // CIE LCHab
61-
LCH_ab_2_CIELab,
62-
ryb_2_rgb, // http://en.wikipedia.org/wiki/RYB_color_model,
63-
// http://threekings.tk/mirror/ryb_TR.pdf
64-
rgb_2_cmy,
65-
cmy_2_rgb,
66-
rgb_2_XYZ, // uses sRGB chromatic adapted matrix
67-
XYZ_2_rgb, // uses sRGB chromatic adapted matrix
68-
srgb_2_rgb, // make linear rgb, no chromatic adaption
69-
rgb_2_srgb, // make sRGB, with gamma
70-
CIELab_2_srgb, // Lab (whitepoint) -> XYZ -> rgb (D65) -> sRGB (D65)
71-
srgb_2_CIELab, // sRGB (D65) -> rgb (D65) -> XYZ -> Lab (whitepoint)
72-
srgb_2_CIELCHab, // sRGB (D65) -> rgb (D65) -> XYZ -> Lab (whitepoint)
73-
CIELCHab_2_srgb, // sRGB (D65) -> rgb (D65) -> XYZ -> Lab (whitepoint)
74-
rgb_2_CIELCHab,
75-
CIELCHab_2_rgb,
76-
CIELab_2_rgb, // Lab (whitepoint) -> XYZ -> rgb (D65)
77-
rgb_2_CIELab, // rgb (D65) -> XYZ -> Lab (D50)
78-
XYZ_2_srgb, // XYZ -> rgb (D65) -> sRGB (D65)
79-
hsv_2_srgb, // [0..1] -> [0..1]
80-
srgb_2_hsv, // [0..1] -> [0..1]
81-
srgb_2_XYZ, // sRGB (D65) -> XYZ
82-
XYZ_2_xyY,
83-
xyY_2_XYZ,
84-
Luv_2_XYZ,
85-
XYZ_2_Luv,
86-
Luv_2_LCH_uv, // CIE LCHuv
87-
LCH_uv_2_Luv,
88-
Yuv_2_rgb, // Y Cb Cr
89-
rgb_2_Yuv
90-
};
43+
static constexpr Scalar Pi =
44+
static_cast<Scalar>(3.1415926535897932384626433832795);
9145

46+
public:
9247
static constexpr std::array<Scalar, 3U> IM_ILLUMINANT_A = {1.09850, 1.00000,
9348
0.35585};
9449
static constexpr std::array<Scalar, 3U> IM_ILLUMINANT_B = {0.99072, 1.00000,
@@ -134,20 +89,18 @@ public:
13489
void lab2xyz(const Vec3& Lab, Vec3& XYZ) const
13590
{
13691
// chromatic adaption, reference white
137-
XYZ[1] = illuminant[1] * detail::fi((1. / 116.) * (Lab[0] + 16.)); // Y
138-
XYZ[0] = illuminant[0] * detail::fi((1. / 116.) * (Lab[0] + 16.) +
139-
(1. / 500.) * Lab[1]); // X
140-
XYZ[2] = illuminant[2] * detail::fi((1. / 116.) * (Lab[0] + 16.) -
141-
(1. / 200.) * Lab[2]); // Z
92+
XYZ[1] = illuminant[1] * fi((1. / 116.) * (Lab[0] + 16.)); // Y
93+
XYZ[0] = illuminant[0] *
94+
fi((1. / 116.) * (Lab[0] + 16.) + (1. / 500.) * Lab[1]); // X
95+
XYZ[2] = illuminant[2] *
96+
fi((1. / 116.) * (Lab[0] + 16.) - (1. / 200.) * Lab[2]); // Z
14297
}
14398

14499
void xyz2lab(const Vec3& XYZ, Vec3& Lab) const
145100
{
146-
Lab[0] = 116. * detail::f(XYZ[1] / illuminant[1]) - 16.;
147-
Lab[1] = 500. * (detail::f(XYZ[0] / illuminant[0]) -
148-
detail::f(XYZ[1] / illuminant[1]));
149-
Lab[2] = 200. * (detail::f(XYZ[1] / illuminant[1]) -
150-
detail::f(XYZ[2] / illuminant[2]));
101+
Lab[0] = 116. * f(XYZ[1] / illuminant[1]) - 16.;
102+
Lab[1] = 500. * (f(XYZ[0] / illuminant[0]) - f(XYZ[1] / illuminant[1]));
103+
Lab[2] = 200. * (f(XYZ[1] / illuminant[1]) - f(XYZ[2] / illuminant[2]));
151104
}
152105

153106
void lab2LCHab(const Vec3& Lab, Vec3& LCHab) const
@@ -158,17 +111,17 @@ public:
158111
LCHab[2] = std::atan2(Lab[2], Lab[1]);
159112
if (LCHab[2] < 0)
160113
{
161-
LCHab[2] += M_PI * 2.; // [0, 2pi]
114+
LCHab[2] += Pi * 2.; // [0, 2pi]
162115
}
163116
}
164117

165118
void LCHab2lab(const Vec3& LCHab, Vec3& Lab) const
166119
{
167120
Lab[0] = LCHab[0];
168121
Scalar h = LCHab[2];
169-
if (h > M_PI)
122+
if (h > Pi)
170123
{
171-
h -= M_PI * 2.; // [0, 2pi]
124+
h -= Pi * 2.; // [0, 2pi]
172125
}
173126
Lab[1] = LCHab[1] * std::cos(h);
174127
Lab[2] = LCHab[1] * std::sin(h);
@@ -546,6 +499,20 @@ public:
546499
private:
547500
const std::array<Scalar, 3U> illuminant;
548501

502+
static Scalar f(Scalar t)
503+
{
504+
return (t > std::pow<Scalar>(6. / 29., 3.))
505+
? std::pow<Scalar>(t, 1. / 3.)
506+
: (1. / 3.) * std::pow<Scalar>(29. / 6., 2.) * t + (4. / 29.);
507+
}
508+
509+
static Scalar fi(Scalar t)
510+
{
511+
return (t > 6. / 29.)
512+
? std::pow<Scalar>(t, 3.)
513+
: 3. * std::pow<Scalar>(6. / 29., 2.) * (t - (4. / 29.));
514+
}
515+
549516
/**
550517
* @brief Simple fuzzy comparison of floating point values.
551518
*
@@ -580,8 +547,6 @@ private:
580547
Scalar asample = lab2[1];
581548
Scalar bsample = lab2[2];
582549

583-
constexpr Scalar pi = 3.1415926535897932384626433832795;
584-
585550
Scalar Cabstd = std::sqrt(astd * astd + bstd * bstd);
586551
Scalar Cabsample = std::sqrt(asample * asample + bsample * bsample);
587552

@@ -602,11 +567,11 @@ private:
602567
// Ensure hue is between 0 and 2pi
603568
Scalar hpstd = std::atan2(bstd, apstd);
604569
if (hpstd < 0)
605-
hpstd += 2. * pi; // rollover ones that come -ve
570+
hpstd += 2. * Pi; // rollover ones that come -ve
606571

607572
Scalar hpsample = std::atan2(bsample, apsample);
608573
if (hpsample < 0)
609-
hpsample += 2. * pi;
574+
hpsample += 2. * Pi;
610575
if (fuzzy((fabs(apsample) + fabs(bsample)), 0.))
611576
hpsample = 0.;
612577

@@ -615,10 +580,10 @@ private:
615580

616581
// Computation of hue difference
617582
Scalar dhp = (hpsample - hpstd);
618-
if (dhp > pi)
619-
dhp -= 2. * pi;
620-
if (dhp < -pi)
621-
dhp += 2. * pi;
583+
if (dhp > Pi)
584+
dhp -= 2. * Pi;
585+
if (dhp < -Pi)
586+
dhp += 2. * Pi;
622587
// set chroma difference to zero if the product of chromas is zero
623588
if (fuzzy(Cpprod, 0.))
624589
dhp = 0.;
@@ -640,11 +605,11 @@ private:
640605
// where needed
641606
Scalar hp = (hpstd + hpsample) / 2.;
642607
// Identify positions for which abs hue diff exceeds 180 degrees
643-
if (fabs(hpstd - hpsample) > pi)
644-
hp -= pi;
608+
if (fabs(hpstd - hpsample) > Pi)
609+
hp -= Pi;
645610
// rollover ones that come -ve
646611
if (hp < 0)
647-
hp += 2. * pi;
612+
hp += 2. * Pi;
648613

649614
// Check if one of the chroma values is zero, in which case set
650615
// mean hue to the sum which is equivalent to other value
@@ -654,14 +619,14 @@ private:
654619
Scalar Lpm502 = (Lp - 50.) * (Lp - 50.);
655620
Scalar Sl = 1. + 0.015f * Lpm502 / std::sqrt(20.0f + Lpm502);
656621
Scalar Sc = 1. + 0.045f * Cp;
657-
Scalar Ta = 1. - 0.17f * std::cos(hp - pi / 6.) +
622+
Scalar Ta = 1. - 0.17f * std::cos(hp - Pi / 6.) +
658623
0.24f * std::cos(2. * hp) +
659-
0.32f * std::cos(3. * hp + pi / 30.) -
660-
0.20f * std::cos(4. * hp - 63. * pi / 180.);
624+
0.32f * std::cos(3. * hp + Pi / 30.) -
625+
0.20f * std::cos(4. * hp - 63. * Pi / 180.);
661626
Scalar Sh = 1. + 0.015f * Cp * Ta;
662627
Scalar delthetarad =
663-
(30. * pi / 180.) *
664-
std::exp(-std::pow(((180. / pi * hp - 275.) / 25.), 2.));
628+
(30. * Pi / 180.) *
629+
std::exp(-std::pow(((180. / Pi * hp - 275.) / 25.), 2.));
665630
Scalar Rc =
666631
2. * std::sqrt(std::pow(Cp, 7.) / (std::pow(Cp, 7.) + std::pow(25., 7.)));
667632
Scalar RT = -std::sin(2.0f * delthetarad) * Rc;

0 commit comments

Comments
 (0)