Commit 24e295f6 authored by Leander Schulten's avatar Leander Schulten
Browse files

Module Types: Add HSL color type that is convertible to the RGB color type

parent 61fa4491
Pipeline #176725 passed with stage
in 3 minutes and 2 seconds
......@@ -2,21 +2,26 @@
#define TYPES_H
#include "property.hpp"
#include <vector>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <iostream>
#include <stdexcept>
#include <assert.h>
#include <vector>
namespace Modules {
enum ValueType{Brightness, RGB};
typedef int time_diff_t;
using time_diff_t = int;
typedef unsigned char brightness_t;
static_assert (sizeof (brightness_t)==1, "size of unsigned char is not 1");
using brightness_t = unsigned char;
static_assert(sizeof(brightness_t) == 1, "size of unsigned char is not 1");
struct rgb_t{
struct hsl_t;
struct rgb_t {
union{
struct{
union{
......@@ -35,7 +40,9 @@ namespace Modules {
brightness_t rgb[3];
};
rgb_t(brightness_t r=0, brightness_t g=0, brightness_t b=0):r(r),g(g),b(b){}
rgb_t & operator * (brightness_t b){
rgb_t(Modules::hsl_t hsl);
hsl_t toHSL() const;
rgb_t &operator*(brightness_t b) {
this->r *= b / 255.f;
this->g *= b / 255.f;
this->b *= b / 255.f;
......@@ -44,28 +51,112 @@ namespace Modules {
bool operator==(rgb_t other)const{
return r == other.r && g == other.g && b == other.b;
}
bool operator!=(rgb_t other)const{
return !(*this==other);
bool operator!=(rgb_t other) const { return !(*this == other); }
};
static_assert(sizeof(rgb_t) == 3, "size of rgb_t is not 3");
inline std::ostream &operator<<(std::ostream &o, const rgb_t rgb) {
o << "rgb{red=" << rgb.r << ",green=" << rgb.g << ",blue=" << rgb.b << "}";
return o;
}
struct hsl_t {
union {
float h;
float hue;
};
union {
float s;
float saturation;
};
union {
float l;
float lightness;
};
hsl_t(float hue, float saturation = 1.f, float lightness = .5f) : h(hue), s(saturation), l(lightness) {}
hsl_t() : h(0), s(1.f), l(0.f) {}
hsl_t(const rgb_t rgb);
bool isValid() const { return h >= 0 && h <= 360 && s >= 0 && s <= 1 && l >= 0 && l <= 1; }
void clampHueToRange() {
hue = std::fmod(hue, 360.f);
if (hue < 0) {
hue += 360;
}
}
void clampToRanges() {
s = std::clamp(s, 0.f, 1.f);
l = std::clamp(l, 0.f, 1.f);
clampHueToRange();
}
rgb_t toRGB() const { return rgb_t(*this); }
};
static_assert (sizeof (rgb_t)==3, "size of rgb_t is not 3");
inline std::ostream &operator<<(std::ostream &o, const hsl_t hsl) {
o << "hsl{hue=" << hsl.hue << ",saturation=" << hsl.saturation << ",lightness=" << hsl.lightness << "}";
return o;
}
inline hsl_t::hsl_t(const rgb_t rgb) {
// see https://de.wikipedia.org/wiki/HSV-Farbraum#Umrechnung_RGB_in_HSV/HSL
const auto max = std::max(rgb.r, std::max(rgb.g, rgb.b));
const auto min = std::min(rgb.r, std::min(rgb.g, rgb.b));
const auto c = max - min;
if (c == 0) {
hue = 0;
} else {
const auto cf = c / 255.f;
if (max == rgb.r) {
const float diff = (rgb.g - rgb.b) / cf;
hue = diff / c;
} else if (max == rgb.g) {
const float diff = (rgb.b - rgb.r) / cf;
hue = 2 + diff / c;
} else if (max == rgb.b) {
const float diff = (rgb.r - rgb.g) / cf;
hue = 4 + diff / c;
}
hue *= 60.f;
if (hue < 0) {
hue *= 360.f;
}
}
if (min == 255 || max == 0) {
s = 0;
} else {
const float m = (max - min) / 255.f;
const float p = (max + min) / 255.f;
s = m / (1 - std::abs(p - 1));
}
l = (max + min) / (2 * 255.f);
}
inline hsl_t rgb_t::toHSL() const { return hsl_t(*this); }
inline rgb_t::rgb_t(const hsl_t hsl) {
// see https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative
const auto kf = [&](const auto n) { return std::fmod(n + hsl.h / 30, 12.f); };
const auto a = [&](const auto n) { return hsl.s * std::min(hsl.l, 1 - hsl.l); };
const auto f = [&](const auto n) {
const auto k = kf(n);
return hsl.l - a(n) * std::max(std::min(1.f, std::min(k - 3, 9 - k)), -1.f);
};
r = static_cast<brightness_t>(f(0) * 255.f);
g = static_cast<brightness_t>(f(8) * 255.f);
b = static_cast<brightness_t>(f(4) * 255.f);
}
/**
* @brief typeToEnum return for the brightness_t and rgb_t the right enum value
* @return the enum value represents the real type
*/
template<typename VT>
ValueType typeToEnum(){
static_assert (std::is_same<VT,brightness_t>::value || std::is_same<VT,rgb_t>::value, "Not a value type");
if(std::is_same<VT,brightness_t>::value){
template <typename VT> ValueType typeToEnum() {
static_assert (std::is_same<VT, brightness_t>::value || std::is_same<VT,rgb_t>::value, "Not a value type");
if constexpr (std::is_same<VT, brightness_t>::value) {
return Brightness;
}else{
return RGB;
}
return RGB;
}
/**
* @brief getSizeOfEnumType return for Brightness and RGB the size of the type brightness_t and rwg_t
* @param t the type
......@@ -249,5 +340,6 @@ namespace Modules {
}
};
}
} // namespace Modules
#endif // TYPES_H
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment