22 #ifndef CRNPixel_HEADER
23 #define CRNPixel_HEADER
41 static constexpr
BW BWWhite =
true;
42 static constexpr
BW BWBlack =
false;
55 template<
typename T>
struct RGB
58 constexpr
RGB() noexcept {}
59 constexpr
RGB(T val) noexcept:
r(val),
g(val),
b(val) {}
60 constexpr
RGB(T r_, T g_, T b_) noexcept:
r(r_),
g(g_),
b(b_) {}
61 template<
typename Y> constexpr
RGB(
const RGB<Y> &p) noexcept:
r(T(p.r)),
g(T(p.g)),
b(T(p.b)) {}
62 RGB(
const HSV &val) noexcept;
63 RGB(
const XYZ &p) noexcept;
64 RGB(
const YUV &p) noexcept;
65 RGB(
const Lab &p) noexcept;
66 RGB(
const Luv &p) noexcept;
71 if (
r < other.r)
return true;
72 else if (
r == other.r)
74 if (
g < other.g)
return true;
75 else if (
g == other.g)
80 constexpr
bool operator==(
const RGB &other)
const noexcept {
return (
r == other.r) && (
g == other.g) && (
b == other.b); }
81 constexpr
bool operator!=(
const RGB &other)
const noexcept {
return !(*
this == other); }
85 T
r = 0,
g = 0,
b = 0;
131 template<
typename T>
class numeric_limits<crn::
pixel::RGB<T>>
134 static constexpr
bool is_specialized =
true;
138 static constexpr
int digits = numeric_limits<T>::digits;
139 static constexpr
int digits10 = numeric_limits<T>::digits10;
140 static constexpr
bool is_signed = numeric_limits<T>::is_signed;
141 static constexpr
bool is_integer = numeric_limits<T>::is_integer;
142 static constexpr
bool is_exact = numeric_limits<T>::is_exact;
143 static constexpr
int radix = numeric_limits<T>::radix;
147 static constexpr
int min_exponent = numeric_limits<T>::min_exponent;
148 static constexpr
int min_exponent10 = numeric_limits<T>::min_exponent10;
149 static constexpr
int max_exponent = numeric_limits<T>::max_exponent;
150 static constexpr
int max_exponent10 = numeric_limits<T>::max_exponent10;
152 static constexpr
bool has_infinity = numeric_limits<T>::has_infinity;
153 static constexpr
bool has_quiet_NaN = numeric_limits<T>::has_quiet_NaN;
154 static constexpr
bool has_signaling_NaN = numeric_limits<T>::has_signaling_NaN;
155 static constexpr float_denorm_style has_denorm = numeric_limits<T>::has_denorm;
156 static constexpr
bool has_denorm_loss = numeric_limits<T>::has_denorm_loss;
162 static constexpr
bool is_iec559 = numeric_limits<T>::is_iec559;
163 static constexpr
bool is_bounded = numeric_limits<T>::is_bounded;
164 static constexpr
bool is_modulo = numeric_limits<T>::is_modulo;
166 static constexpr
bool traps = numeric_limits<T>::traps;
167 static constexpr
bool tinyness_before = numeric_limits<T>::tinyness_before;
168 static constexpr float_round_style round_style = numeric_limits<T>::round_style;
183 constexpr
HSV() noexcept {}
184 constexpr
HSV(uint8_t h_, uint8_t s_, uint8_t v_) noexcept:
h(h_),
s(s_),
v(v_) {}
185 constexpr
HSV(uint8_t v_) noexcept:
v(v_) {}
188 auto max =
Max(val.r, val.g, val.b);
189 auto min =
Min(val.r, val.g, val.b);
190 auto diff = max - min;
193 auto coeffh = 255.0 / 360.0;
202 hue = 60 * (( val.g / 255.0 - val.b / 255.0 ) / (diff / 255.0));
204 else if (max == val.g)
206 hue = 60 * ((val.b / 255.0 - val.r / 255.0) / (diff / 255.0)) + 120;
210 hue = 60 * ((val.r / 255.0 - val.g / 255.0) / (diff / 255.0)) + 240;
213 if (hue < 0) hue += 360;
220 sat = 1.0 - (double(min) / max);
221 s = uint8_t(sat * coeffs);
227 if (
h < other.h)
return true;
228 else if (
h == other.h)
230 if (
s < other.s)
return true;
231 else if (
s == other.s)
236 constexpr
bool operator==(
const HSV &other)
const noexcept {
return (
h == other.h) && (
s == other.s) && (
v == other.v); }
237 constexpr
bool operator!=(
const HSV &other)
const noexcept {
return !(*
this == other); }
238 uint8_t
h = 0,
s = 0,
v = 0;
243 auto hue = double(val.h) / 42.5;
244 if (hue == 6) hue = 0;
246 auto v1 = int(val.v) * (255 - val.s) / 255;
247 auto v2 = int(val.v * (255 - val.s * (hue - i)) / 255);
248 auto v3 = int(val.v * (255 - val.s * (1 - (hue - i))) / 255);
326 template<
typename R,
typename T>
struct Polar2D;
332 constexpr
Cart2D(T x_, T y_ = 0) noexcept:
x(x_),
y(y_) {}
333 Cart2D(
const std::complex<double> &cx) :
x(T(cx.real())),
y(T(cx.imag())) {}
336 operator std::complex<double>()
const {
return {double(
x), double(
y)}; }
341 if (
x < other.x)
return true;
342 else if (
x == other.x)
return y < other.y;
345 constexpr
bool operator==(
const Cart2D &other)
const noexcept {
return (
x == other.x) && (
y == other.y); }
346 constexpr
bool operator!=(
const Cart2D &other)
const noexcept {
return !(*
this == other); }
353 template<
typename I>
struct TypeInfo<pixel::Cart2D<I>>
397 template<
typename R,
typename T>
struct Polar2D
403 Polar2D(
const std::complex<double> &cx) :
rho(R(std::abs(cx))),
theta(T(std::arg(cx))) { }
405 template<
typename Y>
Polar2D(
const Cart2D<Y> &p):
rho(R(sqrt(typename std::common_type<R, double>::type(
Sqr(p.x) +
Sqr(p.y))))),
theta(T::
Atan(typename std::common_type<R, double>::type(p.y), typename std::common_type<R, double>::type(p.x))) {}
406 operator std::complex<double>()
const {
return std::complex<double>(
Cart2D<double>(*this)); }
411 if (
rho < other.rho)
return true;
412 else if (
rho == other.rho)
return theta.value < other.theta.value;
424 x(T(p.rho *
Cos(p.theta))),
425 y(T(p.rho *
Sin(p.theta)))
429 template<
typename I,
typename J>
struct TypeInfo<pixel::Polar2D<I, J>>
477 constexpr
XYZ(
double x_,
double y_ = 0.0,
double z_ = 0.0):
x(x_),
y(y_),
z(z_) {}
482 double x = 0.0,
y = 0.0,
z = 0.0;
487 auto var_X = val.x / 100;
488 auto var_Y = val.y / 100;
489 auto var_Z = val.z / 100;
491 auto var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
492 auto var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415;
493 auto var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570;
495 if (var_R > 0.0031308)
496 var_R = 1.055 * pow(var_R, 1 / 2.4) - 0.055;
499 if (var_G > 0.0031308)
500 var_G = 1.055 * pow(var_G, 1 / 2.4) - 0.055;
503 if (var_B > 0.0031308)
504 var_B = 1.055 * pow(var_B, 1 / 2.4) - 0.055;
508 r = T(
Cap((
int)(var_R * 255), 0, 255));
509 g = T(
Cap((
int)(var_G * 255), 0, 255));
510 b = T(
Cap((
int)(var_B * 255), 0, 255));
530 constexpr
YUV(
double y_,
double u_ = 0.0,
double v_ = 0.0):
y(y_),
u(u_),
v(v_) {}
533 constexpr
bool operator==(
const YUV &other)
const noexcept {
return (
y == other.y) && (
u == other.u) && (
v == other.v); }
534 constexpr
bool operator!=(
const YUV &other)
const noexcept {
return !(*
this == other); }
538 double y = 0.0,
u = 0.0,
v = 0.0;
543 auto var_R = val.y + 1.13983 * val.v;
544 auto var_G = val.y - 0.39465 * val.u - 0.58060 * val.v;
545 auto var_B = val.y + 2.03211 * val.u;
547 r = T(
Cap((
int)(var_R * 255), 0, 255));
548 g = T(
Cap((
int)(var_G * 255), 0, 255));
549 b = T(
Cap((
int)(var_B * 255), 0, 255));
598 constexpr
Lab(
double l_,
double a_ = 0.0,
double b_ = 0.0):
l(l_),
a(a_),
b(b_) {}
603 const auto s =
RGB8(*
this) +
RGB8(p);
608 double l = 0.0,
a = 0.0,
b = 0.0;
648 constexpr
Luv(
double l_,
double u_ = 0.0,
double v_ = 0.0):
l(l_),
u(u_),
v(v_) {}
657 double l = 0.0,
u = 0.0,
v = 0.0;
typename TypeInfo< T >::SumType SumType
constexpr bool operator!=(const HSV &other) const noexcept
constexpr HSV(uint8_t h_, uint8_t s_, uint8_t v_) noexcept
constexpr Polar2D(const Polar2D< Y, Z > &p) noexcept
Cart2D(const std::complex< double > &cx)
static constexpr crn::pixel::RGB< T > infinity() noexcept
constexpr Cart2D(T x_, T y_=0) noexcept
constexpr bool operator==(const Cart2D &other) const noexcept
constexpr RGB(T val) noexcept
constexpr XYZ(double x_, double y_=0.0, double z_=0.0)
const T & Cap(const T &v, const T &min, const T &max)
Bounds a value to an interval.
Cart2D & operator+=(const Cart2D &other)
double Cos(const A &a) noexcept
constexpr bool operator==(const YUV &other) const noexcept
constexpr Cart2D() noexcept
static constexpr crn::pixel::RGB< T > max() noexcept
const T & Max(const T &a, const T &b)
Returns the max of two values.
constexpr bool operator==(const RGB &other) const noexcept
constexpr bool operator!=(const Polar2D &other) const noexcept
crn::SumType< T > Abs(const crn::pixel::RGB< T > &p)
constexpr Luv(double l_, double u_=0.0, double v_=0.0)
constexpr YUV(double y_, double u_=0.0, double v_=0.0)
constexpr bool operator!=(const YUV &other) const noexcept
static constexpr crn::pixel::RGB< T > min() noexcept
bool operator<(const RGB &other) const noexcept
static constexpr crn::pixel::RGB< T > epsilon() noexcept
RGB & operator-=(const RGB &other)
constexpr bool operator==(const HSV &other) const noexcept
static constexpr crn::pixel::RGB< T > round_error() noexcept
bool operator<(const Cart2D &other) const noexcept
HSV(const RGB< uint8_t > &val) noexcept
constexpr crn::SumType< crn::pixel::RGB< T > > operator+(const crn::pixel::RGB< T > &p1, const crn::pixel::RGB< T > &p2)
constexpr Cart2D(const Cart2D< Y > &p) noexcept
RGB & operator+=(const RGB &other)
Luv & operator+=(const Luv &p)
Lab & operator+=(const Lab &p)
constexpr Lab(double l_, double a_=0.0, double b_=0.0)
static constexpr crn::pixel::RGB< T > denorm_min() noexcept
static constexpr crn::pixel::RGB< T > quiet_NaN() noexcept
constexpr bool operator==(const Polar2D &other) const noexcept
bool operator<(const HSV &other) const noexcept
constexpr RGB(T r_, T g_, T b_) noexcept
constexpr SumType< T > Sqr(const T &v) noexcept(noexcept(v *v))
Returns the square of a value.
constexpr Polar2D(R r, T t=0) noexcept
bool operator<(const Polar2D &other) const noexcept
A Atan(double s, double c) noexcept
static constexpr crn::pixel::RGB< T > lowest() noexcept
typename TypeInfo< T >::DecimalType DecimalType
YUV & operator+=(const YUV &other)
void Abs(Image< T > &img, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr) noexcept
Replaces each pixel by its absolute value.
typename TypeInfo< T >::DiffType DiffType
Polar2D & operator+=(const Polar2D &other)
const T & Min(const T &a, const T &b)
Returns the min of two values.
constexpr bool operator!=(const Cart2D &other) const noexcept
YUV & operator-=(const YUV &other)
Polar2D(const std::complex< double > &cx)
constexpr crn::DecimalType< crn::pixel::RGB< T > > operator*(const crn::pixel::RGB< T > &p, double d)
constexpr RGB(const RGB< Y > &p) noexcept
double Sin(const A &a) noexcept
static constexpr crn::pixel::RGB< T > signaling_NaN() noexcept
constexpr bool operator!=(const RGB &other) const noexcept
constexpr crn::DecimalType< crn::pixel::RGB< T > > operator/(const crn::pixel::RGB< T > &p, double d)
constexpr crn::DiffType< crn::pixel::RGB< T > > operator-(const crn::pixel::RGB< T > &p1, const crn::pixel::RGB< T > &p2)
Polar2D(const Cart2D< Y > &p)
A class containing informations on a type.
constexpr Polar2D() noexcept
constexpr HSV(uint8_t v_) noexcept