1// LAF Gfx Library
2// Copyright (c) 2020-2022 Igara Studio S.A.
3// Copyright (c) 2001-2017 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "gfx/hsv.h"
13#include "gfx/rgb.h"
14
15#include <algorithm>
16
17namespace gfx {
18
19using namespace std;
20
21Hsv::Hsv(double hue, double saturation, double value)
22 : m_hue(hue)
23 , m_saturation(std::clamp(saturation, 0.0, 1.0))
24 , m_value(std::clamp(value, 0.0, 1.0))
25{ }
26
27// Reference: http://en.wikipedia.org/wiki/HSL_and_HSV
28Hsv::Hsv(const Rgb& rgb)
29{
30 const int M = rgb.maxComponent();
31 const int m = rgb.minComponent();
32 const int c = M - m;
33 const double chroma = double(c) / 255.0;
34 const double v = double(M) / 255.0;
35 double hue_prime = 0.0;
36 double h, s;
37
38 if (c == 0) {
39 h = 0.0; // Undefined Hue because max == min
40 s = 0.0;
41 }
42 else {
43 const double r = double(rgb.red()) / 255.0;
44 const double g = double(rgb.green()) / 255.0;
45 const double b = double(rgb.blue()) / 255.0;
46
47 if (M == rgb.red()) {
48 hue_prime = (g - b) / chroma;
49
50 while (hue_prime < 0.0)
51 hue_prime += 6.0;
52 hue_prime = std::fmod(hue_prime, 6.0);
53 }
54 else if (M == rgb.green()) {
55 hue_prime = ((b - r) / chroma) + 2.0;
56 }
57 else if (M == rgb.blue()) {
58 hue_prime = ((r - g) / chroma) + 4.0;
59 }
60
61 h = hue_prime * 60.0;
62 s = chroma / v;
63 }
64
65 m_hue = h;
66 m_saturation = s;
67 m_value = v;
68}
69
70int Hsv::hueInt() const
71{
72 return int(std::floor(m_hue + 0.5));
73}
74
75int Hsv::saturationInt() const
76{
77 return int(std::floor(m_saturation*100.0 + 0.5));
78}
79
80int Hsv::valueInt() const
81{
82 return int(std::floor(m_value*100.0 + 0.5));
83}
84
85} // namespace gfx
86