16#ifndef MiL_SVG_COLOR_H
17#define MiL_SVG_COLOR_H 1
232 using enum_map_type = std::map<color, std::string>;
234 static enum_map_type enum_map;
235 if (enum_map.empty())
433 string m(
"to_string(color)::color map size fail ");
435 m += std::to_string(enum_map.size());
436 m +=
" not equal to named colors of size ";
439 throw std::runtime_error(
m);
461 std::ostringstream oss;
462 oss <<
"rgb(" << s.
r <<
',' << s.
g <<
',' << s.
b <<
")";
471 if (s.empty() || s.size() < 5 || s[0] !=
'r')
473 string m(
"color_qi::from_string input is not in rbg form: ");
476 throw std::runtime_error(
m);
485 std::istringstream iss(s);
527 const bool t1 = c1.
r == c2.
r;
528 const bool t2 = c1.
g == c2.
g;
529 const bool t3 = c1.
b == c2.
b;
530 return t1 && t2 && t3;
580 std::ostringstream oss;
581 oss << std::fixed << std::setprecision(2);
582 oss <<
"hsv(" <<
s.h <<
',' <<
s.s <<
',' <<
s.v <<
")";
598 double r = rgb.
r / 255.0;
599 double g = rgb.
g / 255.0;
600 double b = rgb.
b / 255.0;
602 double max_val = std::max({r, g, b});
603 double min_val = std::min({r, g, b});
604 double delta = max_val - min_val;
611 else if (max_val == r)
613 hsv.
h = 60.0 * fmod(((g - b) / delta), 6.0);
615 else if (max_val == g)
617 hsv.
h = 60.0 * (((b - r) / delta) + 2.0);
622 hsv.
h = 60.0 * (((r - g) / delta) + 4.0);
629 hsv.
s = (max_val == 0.0) ? 0.0 : (delta / max_val);
644 double c = hsv.
v * hsv.
s;
645 double x = c * (1.0 - std::abs(fmod(hsv.
h / 60.0, 2.0) - 1.0));
646 double m = hsv.
v - c;
648 double r_prime, g_prime, b_prime;
650 if (hsv.
h >= 0.0 && hsv.
h < 60.0)
652 r_prime = c; g_prime =
x; b_prime = 0.0;
654 else if (hsv.
h >= 60.0 && hsv.
h < 120.0)
656 r_prime =
x; g_prime = c; b_prime = 0.0;
658 else if (hsv.
h >= 120.0 && hsv.
h < 180.0)
660 r_prime = 0.0; g_prime = c; b_prime =
x;
662 else if (hsv.
h >= 180.0 && hsv.
h < 240.0)
664 r_prime = 0.0; g_prime =
x; b_prime = c;
666 else if (hsv.
h >= 240.0 && hsv.
h < 300.0)
668 r_prime =
x; g_prime = 0.0; b_prime = c;
673 r_prime = c; g_prime = 0.0; b_prime =
x;
677 rgb.
r =
static_cast<itype
>(std::clamp((r_prime +
m) * 255.0, 0.0, 255.0));
678 rgb.
g =
static_cast<itype
>(std::clamp((g_prime +
m) * 255.0, 0.0, 255.0));
679 rgb.
b =
static_cast<itype
>(std::clamp((b_prime +
m) * 255.0, 0.0, 255.0));
691 uint step = std::min(n, 10u);
702 double t = step / 4.0;
704 result_hsv.
v =
v + t * (1.0 -
v);
709 double sat_t = (step - 4) / 6.0;
710 double target_sat = 1.0 - 0.7 * sat_t;
711 result_hsv.
s =
s * target_sat;
723 const double rmin = 0,
const double rmax = 100)
725 double percentage = std::clamp(tp, rmin, rmax);
730 double saturationf = percentage / 100.0;
736 result_hsv.
s *= saturationf;
740 result_hsv.
v =
v + (1.0 -
v) * (1.0 - saturationf) * 0.5;
757 const bool eqh = k1.
h == k2.
h;
758 const bool lth = k1.
h < k2.
h;
759 const bool lts = k1.
v < k2.
v;
770 const bool eqh = k1.
h == k2.
h;
771 const bool lth = k1.
h < k2.
h;
777 const bool ltothers = k1hyp < k2hyp;
788 const ftype sdist = std::abs(k1.
s - k2.
s);
789 const ftype vdist = std::abs(k1.
v - k2.
v);
791 const ftype habs = std::abs(k1.
h - k2.
h);
792 const ftype hdist = habs > 180 ? 360 - habs : habs;
799 return hdist*1.2 + sdist*2 + vdist*3;
814 const bool ret = d1 < d2;
828 const bool t1 = c1.
h == c2.
h;
829 const bool t2 = c1.
s == c2.
s;
830 const bool t3 = c1.
v == c2.
v;
831 return t1 && t2 && t3;
844 static std::mt19937_64 rg(std::random_device{}());
845 auto distr = std::uniform_real_distribution<>(0.5, 1);
848 double stry = distr(rg);
853 double vtry = distr(rg);
875 double denom = ad + bd;
876 double ur = ((a.r * ad) + (b.r * bd)) / denom;
877 double ug = ((a.g * ad) + (b.g * bd)) / denom;
878 double ub = ((a.b * ad) + (b.b * bd)) / denom;
881 itype cr =
static_cast<itype
>(ur);
882 itype cg =
static_cast<itype
>(ug);
883 itype cb =
static_cast<itype
>(ub);
constexpr uint color_max_size
Total number of enumerated colors.
color
Color enumerated as types.
unsigned short ushort
Base integer type: positive and negative, signed integral value.
std::vector< color_qf > color_qfs
const string to_string(const unit e)
std::vector< color_qi > color_qis
Types for Color iteration and combinatorics.
bool operator<(const color_qf &c1, const color_qf &c2)
color_qi average_color_qi(const color_qi &a, const color_qi &b)
Average two colors, return the result.
color_qf mutate_color_qf(const color_qf &k)
Return a variant on saturation/value only.
bool color_qf_lt_hue_v2(const color_qf &k1, const color_qf &k2)
bool operator==(const color_qi &c1, const color_qi &c2)
color_qi combine_color_qi(const color_qi &a, const double ad, const color_qi &b, const double bd)
color_qf::ftype color_qf_distance(const color_qf &k1, const color_qf &k2)
bool color_qf_lt_v(const color_qf &k1, const color_qf &k2)
Default compare distances from k1,k2 to black.
bool color_qf_lt(const color_qf &k1, const color_qf &k2)
Forwarding function.
bool color_qf_lt_hue_v1(const color_qf &k1, const color_qf &k2)
Less than compare for color_qf.
ftype v
Saturation between 0.0 (gray) and 1.0.
color_qf rgb_to_hsv(const color_qi &rgb) const
Convert RGB to HSV.
color_qf(ftype vh, ftype vs, ftype vv)
color_qf()=default
Value between 0.0 (black) and 1.0.
color_qi tint_percentage(const double tp, const double rmin=0, const double rmax=100)
Procedural tinting algorithm.
ftype s
Hue degree between 0.0 and 360.0.
color_qf & operator=(const color_qf &)=default
color_qf(const color_qf &)=default
static string to_string(color_qf s)
color_qi tint_perceptual(const uint n)
Interpolated tinting algorithm from palette (ciecam16j70_palette).
color_qf(const color_qi &cqi)
color_qi to_color_qi() const
Back to RGB https://www.rapidtables.com/convert/color/hsv-to-rgb.html.
color_qi hsv_to_rgb(const color_qf &hsv) const
Convert HSV to RGB.
Color quantified as integral RGB components in the range [0,255]. aka like Scalar in OpenCV.
color_qi(const color_qi &)=default
color_qi & operator=(const color_qi &)=default
static string to_string(color_qi s)
color_qi(itype ra, itype ga, itype ba)
static color_qi from_string(string s)