diff --git a/src/modm/math/scaling_unsigned.hpp b/src/modm/math/scaling_unsigned.hpp new file mode 100644 index 0000000000..7c0a816843 --- /dev/null +++ b/src/modm/math/scaling_unsigned.hpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2021, Thomas Sommer + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#pragma once + +#include + +#include +// #include + +namespace modm { + +/** + * @brief Unsigned integer with arbitrary digits and scaling value on conversion + * between instances with different digits. + * + * @tparam D Digits + * + * @author Thomas Sommer + */ +template +class ScalingUnsigned { +public: + static constexpr int Digits = D; + using ValueType = uint_t::least; + + static constexpr ValueType min = 0; + static constexpr ValueType max = bitmask(); + + constexpr ScalingUnsigned() = default; + + // FIXME want both: + // COMPTIME: static_assert(value <= max, "value out of range") + // RUNTIME: std::min(value, max) or modm_assert(value <= max, ...) + constexpr ScalingUnsigned(ValueType value) : value(std::min(value, max)) { + // TODO disable via lbuild option + // modm_assert_continue_fail_debug(value <= max, "ScalingUnsigned", "constructor", "value out of range"); + } + + // Construct from bigger or equal ColorGray + template = nullptr> + constexpr ScalingUnsigned(const ScalingUnsigned& other) + : value(other.value >> (E - D)) {} + + template = nullptr> + constexpr ScalingUnsigned(ScalingUnsigned &&other) + : value(other.value >> (E - D)) {} + + // Construct from smaller ColorGray + template E), void*> = nullptr> + constexpr ScalingUnsigned(const ScalingUnsigned& other) + : value(other.value * max / other.max) + {} + + template E), void*> = nullptr> + constexpr ScalingUnsigned(ScalingUnsigned &&other) + : value(other.value * max / other.max) + {} + + /* // Faster construction from from single digit + constexpr ScalingUnsigned(const ScalingUnsigned<1> &other) : value(other.value ? bitmask() : 0){} + + // constexpr ScalingUnsigned(ScalingUnsigned<1> &&other) : value(other.value ? bitmask() : 0){} + constexpr ScalingUnsigned& operator=(const ScalingUnsigned<1> &other) { + value = other.value ? bitmask() : 0; + return *this; + } */ + + // Assign ScalingUnsigned with more or equal Depth + template = nullptr> + void operator=(const ScalingUnsigned& other) { + value = other.value >> (E - D); + } + + // Assign ScalingUnsigned with less Depth + template E), void*> = nullptr> + void operator=(const ScalingUnsigned& other) { + value = other.value * max / other.max; + } + + // FIXME want both: + // COMPTIME: static_assert(value <= max, "value out of range") + // RUNTIME: std::min(value, max) or modm_assert(value <= max, ...) + void setValue(ValueType value) { + this->value = std::min(value, max); + // TODO disable via lbuild option + // modm_assert_continue_fail_debug(value <= max, "modm::ScalingUnsigned", "setValue()", "value out of range"); + } + + ValueType getValue() const { return value; } + + bool isSaturated() const { + return value == max; + } + + constexpr auto operator<=>(const ScalingUnsigned &) const = default; + +protected: + ValueType value = 0; + + inline void max_cutoff() { value = std::min(value, max); } +private: + template + friend class ScalingUnsigned; +}; + +} \ No newline at end of file diff --git a/src/modm/math/scaling_unsigned.lb b/src/modm/math/scaling_unsigned.lb new file mode 100644 index 0000000000..08d89574cc --- /dev/null +++ b/src/modm/math/scaling_unsigned.lb @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2021, Thomas Sommer +# +# This file is part of the modm project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# ----------------------------------------------------------------------------- + +def init(module): + module.name = ":math:scaling_unsigned" + module.description = """ +# Scaling Unsigned + +Unsigned integer with arbitrary digits and scaling value on conversion between +instances with different digits. F.e. a 2bit scaling unsigned of 0b11 becomes +0b1111 when converted to a 4bit scaling unsigned. + +It's the baseclass to all in modm::color::* but may have wider applications. + +""" + +def prepare(module, options): + module.depends(":utils") + return True + +def build(env): + env.outbasepath = "modm/src/modm/math" + env.copy("scaling_unsigned.hpp") diff --git a/src/modm/math/utils/integer_traits.hpp b/src/modm/math/utils/integer_traits.hpp index 3b0b27b6d5..0864af40b3 100644 --- a/src/modm/math/utils/integer_traits.hpp +++ b/src/modm/math/utils/integer_traits.hpp @@ -45,4 +45,14 @@ namespace modm template using fits_any_t = typename fits_any::type; + + template + struct bitmask { + using value_type = uint_t::least; + static constexpr value_type value = std::pow(2, N) - 1; + constexpr operator value_type() const noexcept { return value; } + }; + + template + using bitmask_t = typename bitmask::value_type; } diff --git a/src/modm/ui/color.cpp b/src/modm/ui/color.cpp deleted file mode 100644 index 7e19a0655f..0000000000 --- a/src/modm/ui/color.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2009-2010, 2012, Fabian Greif - * Copyright (c) 2010, Martin Rosekeit - * Copyright (c) 2012-2013, Niklas Hauser - * Copyright (c) 2013, David Hebbeker - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include "color.hpp" - -// ---------------------------------------------------------------------------- -namespace modm { -namespace color { -template<> template<> -void -HsvT::toRgb(RgbT* color) const -{ - uint16_t vs = value * saturation; - uint16_t h6 = 6 * hue; - - uint8_t p = ((value << 8) - vs) >> 8; - uint8_t i = h6 >> 8; - uint16_t f = ((i | 1) << 8) - h6; - if (i & 1) { - f = -f; - } - - uint8_t u = (((uint32_t) value << 16) - (uint32_t) vs * f) >> 16; - uint8_t r = value; - uint8_t g = value; - uint8_t b = value; - switch(i) - { - case 0: g = u; b = p; break; - case 1: r = u; b = p; break; - case 2: r = p; b = u; break; - case 3: r = p; g = u; break; - case 4: r = u; g = p; break; - case 5: g = p; b = u; break; - } - - color->red = r; - color->green = g; - color->blue = b; -} -} // namespace color -} // namespace modm diff --git a/src/modm/ui/color.hpp b/src/modm/ui/color.hpp index 64e4ef53ce..7df13298a2 100644 --- a/src/modm/ui/color.hpp +++ b/src/modm/ui/color.hpp @@ -1,8 +1,4 @@ /* - * Copyright (c) 2009, Martin Rosekeit - * Copyright (c) 2009-2013, Fabian Greif - * Copyright (c) 2012-2013, 2015, Niklas Hauser - * Copyright (c) 2013, David Hebbeker * Copyright (c) 2021, Thomas Sommer * * This file is part of the modm project. @@ -12,10 +8,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // ---------------------------------------------------------------------------- +#pragma once +#include "color/gray.hpp" #include "color/rgb.hpp" #include "color/hsv.hpp" -#include "color/brightness.hpp" -#include "color/rgb565.hpp" -#include "color/rgbhtml.hpp" +#include "color/rgb_html.hpp" +#include "color/rgb_stacked.hpp" \ No newline at end of file diff --git a/src/modm/ui/color/brightness.hpp b/src/modm/ui/color/brightness.hpp deleted file mode 100644 index bc5e961cb5..0000000000 --- a/src/modm/ui/color/brightness.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2021, Thomas Sommer - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#pragma once - -#include - -#include - -#include "hsv.hpp" -#include "rgb.hpp" -#include "rgb565.hpp" - -namespace modm::color -{ - -// forward declarations for convertion constructors -template -class RgbT; - -template -class HsvT; - -class Rgb565; - -/** - * @brief Brightness as unsigned integral. Add's the math for conversion to and from - * Color-Types. Use with: Grayscale Buffers, Dimmed LEDs, Brightness sensors - * - * @author Thomas Sommer - * - * @tparam T Unsigned integral for the brightness-value - * @ingroup modm_ui_color - */ -template -class BrightnessT -{ -public: - T value{0}; - - constexpr BrightnessT() = default; - - constexpr BrightnessT(T value) : value(value) {} - - /** - * Copy Constructor 8bit->16bit - */ - template - requires std::is_same_v && std::is_same_v - constexpr BrightnessT(const BrightnessT &brightness_other) - : value(brightness_other.value << 8) - {} - - /** - * Copy Constructor 16bit->8bit - */ - template - requires std::is_same_v && std::is_same_v - constexpr BrightnessT(const BrightnessT &brightness_other) - : value(brightness_other.value >> 8) - {} - - /** - * Convertion Constructor for RGB Color - * - * @param rgb RGB Color - */ - template - constexpr BrightnessT(RgbT rgb) - : value((0.2125 * float(rgb.red)) + (0.7154 * float(rgb.green)) + - (0.0721 * float(rgb.blue))) - {} - - /** - * Convertion Constructor for HSV Color - * - * @param hsv HSV Color - */ - template - constexpr BrightnessT(HsvT hsv) : value(hsv.value) - {} - - /** - * Convertion Constructor for RGB565 Color - * - * @param rgb565 RGB565 Color - */ - constexpr BrightnessT(Rgb565 rgb565) : BrightnessT(RgbT(rgb565)) {} - - constexpr bool - operator==(const BrightnessT &other) const = default; -}; - -/// @ingroup modm_ui_color -using Brightness = BrightnessT; - -} // namespace modm::color diff --git a/src/modm/ui/color/color.lb b/src/modm/ui/color/color.lb index f0d4dcf5f1..0dd828c7cd 100644 --- a/src/modm/ui/color/color.lb +++ b/src/modm/ui/color/color.lb @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # -# Copyright (c) 2018, Niklas Hauser +# Copyright (c) 2021, Thomas Sommer # # This file is part of the modm project. # @@ -18,11 +18,20 @@ def init(module): Color containers and converters in various formats: RGB, HSV, Brightness, Rgb565 """ + def prepare(module, options): - module.depends(":math:utils") + module.depends( + ":math:utils", + ":math:scaling_unsigned", + ":math:saturation" + ) return True + def build(env): env.outbasepath = "modm/src/modm/ui/color" - env.copy(".") + + ignore = ["*pattern*"] + env.copy(".", ignore=env.ignore_paths(*ignore)) + env.copy("../color.hpp") diff --git a/src/modm/ui/color/concepts.hpp b/src/modm/ui/color/concepts.hpp new file mode 100644 index 0000000000..2e5762edda --- /dev/null +++ b/src/modm/ui/color/concepts.hpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021, Thomas Sommer + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#pragma once + +#include + +/** + * @brief Concepts for colortypes and groups of colortypes. + * Key applications: + * - Color conversion constructors + * - Specialisation of buffer manipulation algorithms + * + * @author Thomas Sommer + * @ingroup modm_ui_color + */ +namespace modm::color { + +template +class GrayD; + +template +class RgbD; + +template +class RgbStackedD; + +template +class HsvD; + +/** + * @brief Identify template class instance + * @see: https://stackoverflow.com/questions/44012938/how-to-tell-if-template-type-is-an-instance-of-a-template-class + */ +template class> +struct is_instance : public std::false_type {}; + +template class U> +struct is_instance, U> : public std::true_type {}; + +/** + * @brief Concepts to ident specific colortype instance + */ +template +concept ColorGray = is_instance::value; + +template +concept ColorRgb = is_instance::value; + +template +concept ColorRgbStacked = is_instance::value; + +template +concept ColorHsv = is_instance::value; + +/** + * @brief Concept to ident any colortype instance + */ +template +concept Color = ColorGray || ColorRgb || ColorHsv || ColorRgbStacked; // conjunction +// concept Color = std::convertible_to >; // more tolerant alternative: convertability + +/** + * @brief Concept to ident palettizing (stacking) colortype instances + * + * @see: https://en.wikipedia.org/wiki/Framebuffer#Memory_access + */ +template +concept ColorPalletized = ColorGray and C::Digits < 8 and std::popcount(unsigned(C::Digits)) == 1; + +/** + * @brief Concept to ident non-palettizing (planar) colortype instances + * + * @see: https://en.wikipedia.org/wiki/Framebuffer#Memory_access + */ +template +concept ColorPlanar = !ColorPalletized; + +/** + * @brief Concept to ident monochrome colortype + */ +template +concept ColorMonochrome = std::is_same_v>; +// concept ColorMonochrome = ColorGray and C::Digits == 1; Alternative implementation as reference + +} \ No newline at end of file diff --git a/src/modm/ui/color/gray.hpp b/src/modm/ui/color/gray.hpp new file mode 100644 index 0000000000..7a72ed12e2 --- /dev/null +++ b/src/modm/ui/color/gray.hpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2021, Thomas Sommer + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +#include +#include + +#include +#include + +#include "concepts.hpp" + +namespace modm::color { +/** + * @brief Unsigned integer with arbitrary number of digits, symetric conversion + * and saturating arithemtics. Used for grayscale + * + * @tparam D Digits + * @tparam P When forming a Buffer with this color, this would be the internal storage. + * Should be MCUs fastest unsigned int -> just keep the default. + * Some Displays require a specific type therefore it's a template argument. + * + * + * @author Thomas Sommer + * @ingroup modm_color_gray + */ +template +// template // TODO +class GrayD : public modm::ScalingUnsigned +{ + static_assert(D > 0, "Positive number of digits required for grayscale / colorchannel type."); +public: + using ValueType = ScalingUnsigned::ValueType; + + // using PalletType = uint32_t; // Best performance on STM32 + // using PalletType = uint16_t; + using PalletType = uint8_t; // Must for Ssd1306, Sh1106 + // using PalletType = P; // TODO PalletType from template argument + + using ScalingUnsigned::ScalingUnsigned; + + template + constexpr GrayD(const C& rgb) + : ScalingUnsigned(( + 2125 * (modm::WideType)(GrayD(rgb.getRed()).value) + + 7154 * (modm::WideType)(GrayD(rgb.getGreen()).value) + + 0721 * (modm::WideType)(GrayD(rgb.getBlue()).value) + ) / 10000 + ) + {} + + template + constexpr GrayD(const C& hsv) : ScalingUnsigned(hsv.getValue()) + {} + + GrayD& operator+=(const ValueType& value) { + modm::Saturated result(this->value); + result+=value; + this->max_cutoff(); + + return *this; + } + + GrayD& operator+=(const GrayD& other) { + modm::Saturated result(this->value); + result+=other.value; + this->max_cutoff(); + + return *this; + } + + GrayD& operator-=(const ValueType& value) { + modm::Saturated result(this->value); + result-=value; + this->max_cutoff(); + + return *this; + } + + GrayD& operator-=(const GrayD& other) { + modm::Saturated result(this->value); + result-=other.value; + this->max_cutoff(); + + return *this; + } + + // IMPLEMENT missing operators + // operator*=() {} + + template + GrayD operator+(const U value) const { + modm::Saturated result(this->value); + result+=value; + + // When all digits of ValueType are used, std::min should optimize away + return {std::min(result.getValue(), this->max)}; + } + + GrayD operator+(const GrayD& other) const { + modm::Saturated result(this->value); + result+=other.value; + + // When all digits of ValueType are used, std::min should optimize away + return {std::min(result.getValue(), this->max)}; + } + + template + GrayD operator-(const U value) const { + modm::Saturated result(this->value); + result-=value; + + // When all digits of ValueType are used, std::min should optimize away + return {std::min(result.getValue(), this->max)}; + } + + GrayD operator-(const GrayD& other) const { + modm::Saturated result(this->value); + result -= other.value; + + return result.getValue(); + } + + template + GrayD operator*(const ScaleType &scale) const { + modm::Saturated result(this->value); + result *= scale; + + // When all digits of ValueType are used, std::min should optimize away + return {std::min(result.getValue(), this->max)}; + } + + template + GrayD + operator*(const ScaleType &scale) const + { + // OPTIMIZE develop optimal decimals from D + static constexpr int decimals = 10; + using WideType = modm::WideType; + WideType result = this->value * ValueType(scale * decimals) / decimals; + return {ValueType(std::min(result, max))}; + } + + void invert() { + this->value ^= bitmask(); + // alterantive: this->value ^= D - this->value; + // alternative: this->value ^= this->max; + } + +private: + + // template // TODO + template + friend class GrayD; + + template + friend modm::IOStream & + operator<<(modm::IOStream &, const GrayD &); +}; + +template +using GrayT = GrayD::digits>; + +using Monochrome = GrayD<1>; +using Gray2 = GrayD<2>; +using Gray4 = GrayD<4>; +using Gray8 = GrayT; +using Gray16 = GrayT; + +#if __has_include() +#include + +template +modm::IOStream & +operator<<(modm::IOStream &os, const GrayD &color) +{ + os << color.value; + return os; +} +#endif + +} \ No newline at end of file diff --git a/src/modm/ui/color/hsv.hpp b/src/modm/ui/color/hsv.hpp index 57fada273b..35a2ce0eeb 100644 --- a/src/modm/ui/color/hsv.hpp +++ b/src/modm/ui/color/hsv.hpp @@ -1,8 +1,4 @@ /* - * Copyright (c) 2009, Martin Rosekeit - * Copyright (c) 2009-2013, Fabian Greif - * Copyright (c) 2012-2013, 2015, Niklas Hauser - * Copyright (c) 2013, David Hebbeker * Copyright (c) 2021, Thomas Sommer * * This file is part of the modm project. @@ -13,109 +9,116 @@ */ // ---------------------------------------------------------------------------- -#ifndef MODM_COLOR_HSV_HPP -#define MODM_COLOR_HSV_HPP +#pragma once #include #include -#include "brightness.hpp" -#include "rgb.hpp" -#include "rgb565.hpp" +#include "concepts.hpp" +#include "gray.hpp" + +#include namespace modm::color { - -// forward declarations for convertion constructors -template -class RgbT; - -template -class BrightnessT; - -class Rgb565; - /** - * @brief Color in HSV Colorspace + * @brief Color in HSV space. Each channel has it's own Memoryaddress. * - * @author Martin Rosekeit, Fabian Greif, Niklas Hauser, David Hebbeker, Thomas Sommer - * @ingroup modm_ui_color + * @tparam DH Digits for hue + * @tparam DS Digits for saturation + * @tparam DV Digits for value + * + * @author Thomas Sommer + * @ingroup modm_ui_color */ -template -class HsvT +template +class HsvD { public: - T hue{0}; - T saturation{0}; - T value{0}; - - constexpr HsvT() = default; + // TODO HueType should wrap rather than saturate + using HueType = GrayD; + using SaturationType = GrayD; + using ValueType = GrayD; - constexpr HsvT(T hue, T saturation, T value) : hue(hue), saturation(saturation), value(value) {} + constexpr HsvD() = default; - /** - * Copy Constructor 8bit->16bit - */ - template - requires std::is_same_v && std::is_same_v - constexpr HsvT(const HsvT &hsv_other) - : hue(hsv_other.hue << 8), saturation(hsv_other.saturation << 8), value(hsv_other.value << 8) + constexpr HsvD(HueType hue, SaturationType saturation, ValueType value) + : hue(hue), saturation(saturation), value(value) {} - /** - * Copy Constructor 16bit->8bit - */ - template - requires std::is_same_v && std::is_same_v - constexpr HsvT(const HsvT &hsv_other) - : hue(hsv_other.hue >> 8), saturation(hsv_other.saturation >> 8), value(hsv_other.value >> 8) + template + constexpr HsvD(const C &other) + : hue(other.hue), saturation(other.saturation), value(other.value) {} - /** - * Convertion Constructor for RGB Color - * - * @param rgb RGB Color - */ - template - constexpr HsvT(const RgbT& rgb); - - /** - * Convertion Constructor for Brightness - * - * @param brightness Brightness 'Color'-object - */ - template - constexpr HsvT(const BrightnessT gray) : hue(0), saturation(0), value(gray.value) - {} + template + constexpr HsvD(const C& rgb); + + template + constexpr HsvD(const CS& rgbstacked) : HsvD(RgbD(rgbstacked)) {} + + void setHue(HueType hue) { this->hue = hue;} + void setSaturation(SaturationType saturation) { this->saturation = saturation;} + void setValue(ValueType value) { this->value = value;} - /** - * Convertion Constructor for RGB565 Color - * - * @param rgb565 RGB565 Color - */ - constexpr HsvT(const Rgb565& rgb565) : HsvT(RgbT(rgb565)) {} + HueType getHue() const { return hue; } + + SaturationType getSaturation() const { return saturation; } + ValueType getValue() const { return value; } constexpr bool - operator==(const HsvT& other) const = default; + operator==(const HsvD& other) const = default; + + // IMPLEMENT missing operators + // operator+=() + // operator-=() + // operator*=() + + void invert() { + hue.invert(); + } + + // Output in human readable format + // Hue in deg, Sat in pct, Value in pct + void iostream_human_readable(IOStream& io) { + using CalcTypeHue = modm::WideType; + io << (CalcTypeHue(hue.getValue()) * 360 / hue.max) << "deg\t"; + + using CalcTypeSaturation = modm::WideType; + io << (CalcTypeSaturation(saturation.getValue()) * 100 / saturation.max) << "%\t"; + + using CalcTypeValue = modm::WideType; + io << (CalcTypeValue(value.getValue()) * 100 / value.max) << "%"; + } private: - template + HueType hue{0}; + SaturationType saturation{0}; + ValueType value{0}; + + template + friend class HsvD; + + template friend IOStream& - operator<<(IOStream&, const HsvT&); + operator<<(IOStream&, const C&); }; -/// @ingroup modm_ui_color -using Hsv = HsvT; +template +using HsvT = HsvD::digits>; +/// @ingroup modm_ui_color +using Hsv888 = HsvD<8>; // Alternative using Hsv888 = HsvT; +using Hsv161616 = HsvD<16>; // Alternative using Hsv888 = HsvT; #if __has_include() #include -template +template IOStream& -operator<<(IOStream& os, const color::HsvT& color) +operator<<(IOStream& os, const C& hsv) { - os << color.hue << "\t" << color.saturation << "\t" << color.value; + os << hsv.getHue() << "\t" << hsv.getSaturation() << "\t" << hsv.getValue(); return os; } #endif @@ -123,5 +126,3 @@ operator<<(IOStream& os, const color::HsvT& color) } // namespace modm::color #include "hsv_impl.hpp" - -#endif // MODM_COLOR_HSV_HPP diff --git a/src/modm/ui/color/hsv_impl.hpp b/src/modm/ui/color/hsv_impl.hpp index c9851b787f..7bc93c3d3b 100644 --- a/src/modm/ui/color/hsv_impl.hpp +++ b/src/modm/ui/color/hsv_impl.hpp @@ -13,59 +13,52 @@ */ // ---------------------------------------------------------------------------- -#ifndef MODM_COLOR_HSV_HPP -#error "Don't include this file directly, use 'hsv.hpp' instead!" -#endif +#pragma once +#include "hsv.hpp" #include /** - * @see http://de.wikipedia.org/wiki/HSV-Farbraum#Umrechnung_RGB_in_HSV.2FHSL - * @param rgb + * @see https://en.wikipedia.org/wiki/HSL_and_HSV */ -template -template -constexpr modm::color::HsvT::HsvT(const modm::color::RgbT &rgb) +template +template +constexpr modm::color::HsvD::HsvD(const C& rgb) { + // OPTIMIZE No need to calculate sharper than the output + // Develop CalcType from target types: HueType, SaturationType and ValueType using CalcType = float; - const CalcType maxValue = std::numeric_limits::max(); - const CalcType _red = CalcType(rgb.red) / maxValue; - const CalcType _blue = CalcType(rgb.blue) / maxValue; - const CalcType _green = CalcType(rgb.green) / maxValue; - const CalcType _max = std::max(_red, std::max(_green, _blue)); - const CalcType _min = std::min(_red, std::min(_green, _blue)); - const CalcType _diff = _max - _min; + + const CalcType maxValue = ValueType::max; + + const CalcType red = CalcType(ValueType(rgb.getRed()).getValue()) / maxValue; + const CalcType green = CalcType(ValueType(rgb.getGreen()).getValue()) / maxValue; + const CalcType blue = CalcType(ValueType(rgb.getBlue()).getValue()) / maxValue; + const CalcType max = modm::vmax(red, green, blue); + const CalcType min = modm::vmin(red, green, blue); + const CalcType diff = max - min; CalcType hue_temp; - // CALCULATE HUE - if (_max == _min) + if (max == min) { // all three color values are the same hue_temp = 0; - value = _max * maxValue; - } else if (_max == _red) + value = max * maxValue; + } else if (max == red) { - hue_temp = 60 * (0 + (_green - _blue) / _diff); - value = rgb.red; - } else if (_max == _green) + hue_temp = 60 * (0 + (green - blue) / diff); + value = rgb.getRed(); + } else if (max == green) { - hue_temp = 60 * (2 + (_blue - _red) / _diff); - value = rgb.green; - } else /*if(_max == _blue)*/ + hue_temp = 60 * (2 + (blue - red) / diff); + value = rgb.getGreen(); + } else // max == blue { - hue_temp = 60 * (4 + (_red - _green) / _diff); - value = rgb.blue; + hue_temp = 60 * (4 + (red - green) / diff); + value = rgb.getBlue(); } - if (hue_temp < 0) - hue = (hue_temp + 360) * (maxValue / 360); - else - hue = (hue_temp) * (maxValue / 360); - - // CALCULATE SATURATION - if (_max == 0) - saturation = 0; - else - saturation = _diff / _max * maxValue; -} + hue = hue_temp < 0 ? (hue_temp + 360) * (maxValue / 360) : (hue_temp) * (maxValue / 360); + saturation = max ? diff / max * maxValue : 0; +} \ No newline at end of file diff --git a/src/modm/ui/color/rgb.hpp b/src/modm/ui/color/rgb.hpp index cb5df9f00a..82d67c1c81 100644 --- a/src/modm/ui/color/rgb.hpp +++ b/src/modm/ui/color/rgb.hpp @@ -1,8 +1,4 @@ /* - * Copyright (c) 2009, Martin Rosekeit - * Copyright (c) 2009-2013, Fabian Greif - * Copyright (c) 2012-2013, 2015, Niklas Hauser - * Copyright (c) 2013, David Hebbeker * Copyright (c) 2021, Thomas Sommer * * This file is part of the modm project. @@ -13,8 +9,7 @@ */ // ---------------------------------------------------------------------------- -#ifndef MODM_COLOR_RGB_HPP -#define MODM_COLOR_RGB_HPP +#pragma once #include #include @@ -24,102 +19,95 @@ #include #include -#include "brightness.hpp" -#include "hsv.hpp" -#include "rgb565.hpp" +#include "concepts.hpp" +#include "gray.hpp" namespace modm::color { - -// forward declarations for convertion constructors -template -class HsvT; - -template -class BrightnessT; - -class Rgb565; - /** - * Color in HSV Colorspace + * @brief Color in RGB space. Each channel has it's own Memoryaddress. + * + * @tparam DR Digits for red channel + * @tparam DG Digits for green channel + * @tparam DB Digits for blue channel * - * @author Martin Rosekeit, Fabian Greif, Niklas Hauser, David Hebbeker, Thomas Sommer - * @ingroup modm_ui_color + * @author Thomas Sommer + * @ingroup modm_ui_color */ -template -class RgbT +template +class RgbD { public: - T red{0}; - T green{0}; - T blue{0}; + using RedType = GrayD; + using GreenType = GrayD; + using BlueType = GrayD; - using TSum = modm::WideType; + // using RgbSumValueType = modm::fits_any_t; - constexpr RgbT() = default; + constexpr RgbD() = default; - constexpr RgbT(T red, T green, T blue) : red(red), green(green), blue(blue) {} - - /** - * Copy Constructor 8bit->16bit - */ - template - requires std::is_same_v && std::is_same_v - constexpr RgbT(const RgbT &rgb_other) - : red(rgb_other.red << 8), green(rgb_other.green << 8), blue(rgb_other.blue << 8) + constexpr RgbD(RedType red, GreenType green, BlueType blue) + : red(red), green(green), blue(blue) {} - /** - * Copy Constructor 16bit->8bit - */ - template - requires std::is_same_v && std::is_same_v - constexpr RgbT(const RgbT &rgb_other) - : red(rgb_other.red >> 8), green(rgb_other.green >> 8), blue(rgb_other.blue >> 8) + template + constexpr RgbD(const C& rgb_other) + : red(rgb_other.red), green(rgb_other.green), blue(rgb_other.blue) {} - /** - * Convertion Constructor for HSV Color - * - * @param hsv HSV Color - */ - template - constexpr RgbT(const HsvT& hsv); - - /** - * Convertion Constructor for Brightness - * - * @param brightness Brightness 'Color'-object - */ - // TODO Plump conversion, implement the right way - template - constexpr RgbT(const BrightnessT brightness) - : red(brightness), green(brightness), blue(brightness) - {} + template + constexpr RgbD(const C &gray) + : red(gray), green(gray), blue(gray) {} - /** - * Convertion Constructor for RGB565 Color - * - * @param rgb565 RGB565 Color - */ - constexpr RgbT(const Rgb565& rgb565) - : red((rgb565.color >> 8) & 0xF8), - green((rgb565.color >> 3) & 0xFC), - blue(rgb565.color << 3) + template + constexpr RgbD(const C& rgbs) + : red(rgbs.getRed()), green(rgbs.getGreen()), blue(rgbs.getBlue()) {} + template + constexpr RgbD(const C& hsv); + + void setRed(RedType red) { this->red = red;} + void setGreen(GreenType green) { this->green = green;} + void setBlue(BlueType blue) { this->blue = blue;} + + RedType getRed() const { return red; } + GreenType getGreen() const { return green; } + BlueType getBlue() const { return blue; } + + // IMPLEMENT missing operators + // operator+=() + // operator-=() + // operator*=() + constexpr bool - operator==(const RgbT& other) const = default; + operator==(const RgbD& other) const = default; + + void invert() { + red.invert(); + green.invert(); + blue.invert(); + } private: - template + RedType red{0}; + GreenType green{0}; + BlueType blue{0}; + + template + friend class RgbD; + + template friend IOStream& - operator<<(IOStream&, const RgbT&); + operator<<(IOStream&, const C&); }; -/// @ingroup modm_ui_color -using Rgb = RgbT; +template +using RgbT = RgbD::digits>; +/// @ingroup modm_ui_color +using Rgb888 = RgbD<8>; // Alternative using Rgb888 = RgbT +using Rgb161616 = RgbD<16>; // Alternative using Rgb161616 = RgbT /** * Normalize color values based on a clear value @@ -133,32 +121,31 @@ using Rgb = RgbT; * * @ingroup modm_ui_color */ -template +template requires std::is_fundamental_v -constexpr RgbT -normalizeColor(RgbT rgb, IntermediateType multiplier = 1) +constexpr ReturnColor +normalizeColor(C rgb, IntermediateType multiplier = 1) { const IntermediateType sum = IntermediateType(rgb.red) + rgb.green + rgb.blue; - return RgbT(IntermediateType(rgb.red) * multiplier / sum, - IntermediateType(rgb.green) * multiplier / sum, - IntermediateType(rgb.blue) * multiplier / sum); + return { + IntermediateType(rgb.getRed()) * multiplier / sum, + IntermediateType(rgb.getGreen()) * multiplier / sum, + IntermediateType(rgb.getBlue()) * multiplier / sum + }; } - #if __has_include() #include -template +template IOStream& -operator<<(IOStream& os, const color::RgbT& color) +operator<<(IOStream& os, const C& rgb) { - os << color.red << "\t" << color.green << "\t" << color.blue; + os << rgb.getRed() << "\t" << rgb.getGreen() << "\t" << rgb.getBlue(); return os; } #endif } // namespace modm::color -#include "rgb_impl.hpp" - -#endif // MODM_COLOR_RGB_HPP +#include "rgb_impl.hpp" \ No newline at end of file diff --git a/src/modm/ui/color/rgb565.hpp b/src/modm/ui/color/rgb565.hpp deleted file mode 100644 index dbb19aba56..0000000000 --- a/src/modm/ui/color/rgb565.hpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2021, Thomas Sommer - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#pragma once - -#include - -#include "brightness.hpp" -#include "hsv.hpp" -#include "rgb.hpp" - -namespace modm::color -{ - -// forward declarations for convertion constructors -template -class RgbT; - -template -class HsvT; - -template -class BrightnessT; - -/** - * Color in RGB Colorspace, 16 bits: RRRR RGGG GGGB BBBB - * - * @author Fabian Greif, Thomas Sommer - * @ingroup modm_ui_color - */ -class Rgb565 -{ -public: - uint16_t color{0x0000}; - - using RgbCalcType = RgbT; - - constexpr Rgb565() = default; - - /** - * Constructor for preformatted Rgb565 Color - * - * @param color Preformatted RGB-color in 565-format: RRRR RGGG GGGB BBBB - */ - constexpr Rgb565(uint16_t color) : color(color) {} - - /** - * Constructor for components: red, green, blue - * - * @param red Red color component - * @param green Green color component - * @param blue Blue color component - */ - constexpr Rgb565(uint8_t red, uint8_t green, uint8_t blue) - : color(uint16_t(red & 0xF8) << 8 | uint16_t(green & 0xFC) << 3 | uint16_t(blue >> 3)) - {} - - /** - * Convertion Constructor for RGB Color - * - * @param rgb RGB Color - */ - template - constexpr Rgb565(const RgbT &rgb) : Rgb565(rgb.red, rgb.green, rgb.blue) - {} - - /** - * Convertion Constructor for HSV Color - * - * @param hsv HSV Color - */ - template - constexpr Rgb565(const HsvT &hsv) : Rgb565(RgbCalcType(hsv)) - {} - - /** - * Convertion Constructor for Brightness - * - * @param brightness Brightness 'Color'-object - */ - template - constexpr Rgb565(const BrightnessT brightness) : Rgb565(RgbCalcType(brightness)) - {} - - constexpr bool - operator==(const Rgb565 &other) const = default; - - /// Saturated addition ⊕ - Rgb565 - operator+(const Rgb565 other) const - { - const int8_t red_raw = (color >> 11) + (other.color >> 11); - const uint16_t red = std::clamp(red_raw, 0, 31) << 11; - - const int8_t green_raw = (color >> 5 & 0x3F) + (other.color >> 5 & 0x3F); - const uint16_t green = std::clamp(green_raw, 0, 63) << 5; - - const int8_t blue_raw = (color & 0x1F) + (other.color & 0x1F); - const uint16_t blue = std::clamp(blue_raw, 0, 31); - - return Rgb565(red | green | blue); - } - - /// Saturated substraction ⊖ - Rgb565 - operator-(const Rgb565 other) const - { - const int8_t red_raw = (color >> 11) - (other.color >> 11); - const uint16_t red = std::clamp(red_raw, 0, 0x1F) << 11; - - const int8_t green_raw = (color >> 5 & 0x3F) - (other.color >> 5 & 0x3F); - const uint16_t green = std::clamp(green_raw, 0, 0x3F) << 5; - - const int8_t blue_raw = (color & 0x1F) - (other.color & 0x1F); - const uint16_t blue = std::clamp(blue_raw, 0, 0x1F); - - return Rgb565(red | green | blue); - } -}; - -} // namespace modm::color diff --git a/src/modm/ui/color/rgb_html.hpp b/src/modm/ui/color/rgb_html.hpp new file mode 100644 index 0000000000..681c73ef91 --- /dev/null +++ b/src/modm/ui/color/rgb_html.hpp @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2021, Thomas Sommer + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#pragma once + +#include "rgb.hpp" + +namespace modm::color::html +{ + +/** + * Constant HTML Colornames in RGB Colorspace + * + * @see https://htmlcolorcodes.com/color-names/ + * @see modm:color:RgbD + * @author Thomas Sommer + * @ingroup modm_ui_color + * @{ + */ + +// Red HTML Color Names +static constexpr Rgb888 IndianRed(205, 92, 92); +static constexpr Rgb888 LightCoral(240, 128, 128); +static constexpr Rgb888 Salmon(250, 128, 114); +static constexpr Rgb888 DarkSalmon(233, 150, 122); +static constexpr Rgb888 LightSalmon(255, 160, 122); +static constexpr Rgb888 Crimson(220, 20, 60); +static constexpr Rgb888 Red(255, 0, 0); +static constexpr Rgb888 FireBrick(178, 34, 34); +static constexpr Rgb888 DarkRed(139, 0, 0); + +// Pink HTML Color Names +static constexpr Rgb888 Pink(255, 192, 203); +static constexpr Rgb888 LightPink(255, 182, 193); +static constexpr Rgb888 HotPink(255, 105, 180); +static constexpr Rgb888 DeepPink(255, 20, 147); +static constexpr Rgb888 MediumVioletRed(199, 21, 133); +static constexpr Rgb888 PaleVioletRed(219, 112, 147); + +// Orange HTML Color Names +static constexpr Rgb888 Coral(255, 127, 80); +static constexpr Rgb888 Tomato(255, 99, 71); +static constexpr Rgb888 OrangeRed(255, 69, 0); +static constexpr Rgb888 DarkOrange(255, 140, 0); +static constexpr Rgb888 Orange(25, 165, 0); + +// Yellow HTML Color Names +static constexpr Rgb888 Gold(255, 215, 0); +static constexpr Rgb888 Yellow(255, 255, 0); +static constexpr Rgb888 LightYellow(255, 255, 224); +static constexpr Rgb888 LemonChiffon(255, 250, 205); +static constexpr Rgb888 LightGoldenrodYellow(250, 250, 210); +static constexpr Rgb888 PapayaWhip(255, 239, 213); +static constexpr Rgb888 Moccasin(255, 228, 181); +static constexpr Rgb888 PeachPuff(255, 218, 185); +static constexpr Rgb888 PaleGoldenrod(238, 232, 170); +static constexpr Rgb888 Khaki(240, 230, 140); +static constexpr Rgb888 DarkKhaki(189, 183, 107); + +// Purple HTML Color Names +static constexpr Rgb888 Lavender(230, 230, 250); +static constexpr Rgb888 Thistle(216, 191, 216); +static constexpr Rgb888 Plum(221, 160, 221); +static constexpr Rgb888 Violet(238, 130, 238); +static constexpr Rgb888 Orchid(218, 112, 214); +static constexpr Rgb888 Fuchsia(255, 0, 255); +static constexpr Rgb888 Magenta(255, 0, 255); +static constexpr Rgb888 MediumOrchid(186, 85, 211); +static constexpr Rgb888 MediumPurple(147, 112, 219); +static constexpr Rgb888 RebeccaPurple(102, 51, 153); +static constexpr Rgb888 BlueViolet(138, 43, 226); +static constexpr Rgb888 DarkViolet(148, 0, 211); +static constexpr Rgb888 DarkOrchid(153, 50, 204); +static constexpr Rgb888 DarkMagenta(139, 0, 139); +static constexpr Rgb888 Purple(128, 0, 128); +static constexpr Rgb888 Indigo(75, 0, 130); +static constexpr Rgb888 SlateBlue(106, 90, 205); +static constexpr Rgb888 DarkSlateBlue(72, 61, 139); + +// Green HTML Color Names +static constexpr Rgb888 GreenYellow(173, 255, 47); +static constexpr Rgb888 Chartreuse(127, 255, 0); +static constexpr Rgb888 LawnGreen(124, 252, 0); +static constexpr Rgb888 Lime(0, 255, 0); +static constexpr Rgb888 LimeGreen(50, 205, 50); +static constexpr Rgb888 PaleGreen(152, 251, 152); +static constexpr Rgb888 LightGreen(144, 238, 144); +static constexpr Rgb888 MediumSpringGreen(0, 250, 154); +static constexpr Rgb888 SpringGreen(0, 255, 127); +static constexpr Rgb888 MediumSeaGreen(60, 179, 113); +static constexpr Rgb888 SeaGreen(46, 139, 87); +static constexpr Rgb888 ForestGreen(34, 139, 34); +static constexpr Rgb888 Green(0, 128, 0); +static constexpr Rgb888 DarkGreen(0, 100, 0); +static constexpr Rgb888 YellowGreen(154, 205, 50); +static constexpr Rgb888 OliveDrab(107, 142, 35); +static constexpr Rgb888 Olive(128, 128, 0); +static constexpr Rgb888 DarkOliveGreen(85, 107, 47); +static constexpr Rgb888 MediumAquamarine(102, 205, 170); +static constexpr Rgb888 DarkSeaGreen(143, 188, 139); +static constexpr Rgb888 LightSeaGreen(32, 178, 170); +static constexpr Rgb888 DarkCyan(0, 139, 139); +static constexpr Rgb888 Teal(0, 128, 128); + +// Blue HTML Color Names +static constexpr Rgb888 Aqua(0, 255, 255); +static constexpr Rgb888 Cyan(0, 255, 255); +static constexpr Rgb888 LightCyan(224, 255, 255); +static constexpr Rgb888 PaleTurquoise(175, 238, 238); +static constexpr Rgb888 Aquamarine(127, 255, 212); +static constexpr Rgb888 Turquoise(64, 224, 208); +static constexpr Rgb888 MediumTurquoise(72, 209, 204); +static constexpr Rgb888 DarkTurquoise(0, 206, 209); +static constexpr Rgb888 CadetBlue(95, 158, 160); +static constexpr Rgb888 SteelBlue(70, 130, 180); +static constexpr Rgb888 LightSteelBlue(176, 196, 222); +static constexpr Rgb888 PowderBlue(176, 224, 230); +static constexpr Rgb888 LightBlue(173, 216, 230); +static constexpr Rgb888 SkyBlue(135, 206, 235); +static constexpr Rgb888 LightSkyBlue(135, 206, 250); +static constexpr Rgb888 DeepSkyBlue(0, 191, 255); +static constexpr Rgb888 DodgerBlue(30, 144, 255); +static constexpr Rgb888 CornflowerBlue(100, 149, 237); +static constexpr Rgb888 MediumSlateBlue(123, 104, 238); +static constexpr Rgb888 RoyalBlue(65, 105, 225); +static constexpr Rgb888 Blue(0, 0, 255); +static constexpr Rgb888 MediumBlue(0, 0, 205); +static constexpr Rgb888 DarkBlue(0, 0, 139); +static constexpr Rgb888 Navy(0, 0, 128); +static constexpr Rgb888 MidnightBlue(25, 25, 112); + +// Brown HTML Color Names +static constexpr Rgb888 Cornsilk(255, 248, 220); +static constexpr Rgb888 BlanchedAlmond(255, 235, 205); +static constexpr Rgb888 Bisque(255, 228, 196); +static constexpr Rgb888 NavajoWhite(255, 222, 173); +static constexpr Rgb888 Wheat(245, 222, 179); +static constexpr Rgb888 BurlyWood(222, 184, 135); +static constexpr Rgb888 Tan(210, 180, 140); +static constexpr Rgb888 RosyBrown(188, 143, 143); +static constexpr Rgb888 SandyBrown(244, 164, 96); +static constexpr Rgb888 Goldenrod(218, 165, 32); +static constexpr Rgb888 DarkGoldenrod(184, 134, 11); +static constexpr Rgb888 Peru(205, 133, 63); +static constexpr Rgb888 Chocolate(210, 105, 30); +static constexpr Rgb888 SaddleBrown(139, 69, 19); +static constexpr Rgb888 Sienna(160, 82, 45); +static constexpr Rgb888 Brown(165, 42, 42); +static constexpr Rgb888 Maroon(128, 0, 0); + +// White HTML Color Names +static constexpr Rgb888 White(255, 255, 255); +static constexpr Rgb888 Snow(255, 250, 250); +static constexpr Rgb888 HoneyDew(240, 255, 240); +static constexpr Rgb888 MintCream(245, 255, 250); +static constexpr Rgb888 Azure(240, 255, 255); +static constexpr Rgb888 AliceBlue(240, 248, 255); +static constexpr Rgb888 GhostWhite(248, 248, 255); +static constexpr Rgb888 WhiteSmoke(245, 245, 245); +static constexpr Rgb888 SeaShell(255, 245, 238); +static constexpr Rgb888 Beige(245, 245, 220); +static constexpr Rgb888 OldLace(253, 245, 230); +static constexpr Rgb888 FloralWhite(255, 250, 230); +static constexpr Rgb888 Ivory(255, 255, 240); +static constexpr Rgb888 AntiqueWhite(250, 235, 215); +static constexpr Rgb888 Linen(250, 240, 230); +static constexpr Rgb888 LavenderBlush(255, 240, 245); +static constexpr Rgb888 MistyRose(255, 228, 225); + +// Gray HTML Color Names +static constexpr Rgb888 Gainsboro(220, 220, 220); +static constexpr Rgb888 LightGray(211, 211, 211); +static constexpr Rgb888 Silver(192, 192, 192); +static constexpr Rgb888 DarkGray(169, 169, 169); +static constexpr Rgb888 Gray(128, 128, 128); +static constexpr Rgb888 DimGray(105, 105, 105); +static constexpr Rgb888 LightSlateGray(119, 136, 153); +static constexpr Rgb888 SlateGray(112, 128, 144); +static constexpr Rgb888 DarkSlateGray(47, 79, 79); +static constexpr Rgb888 Black(0, 0, 0); + +/// @} + +} // namespace modm::color::html diff --git a/src/modm/ui/color/rgb_impl.hpp b/src/modm/ui/color/rgb_impl.hpp index b8b9a17841..c70299d6c2 100644 --- a/src/modm/ui/color/rgb_impl.hpp +++ b/src/modm/ui/color/rgb_impl.hpp @@ -13,38 +13,43 @@ */ // ---------------------------------------------------------------------------- -#ifndef MODM_COLOR_RGB_HPP -#error "Don't include this file directly, use 'rgb.hpp' instead!" -#endif +#pragma once +#include "rgb.hpp" -#include - -namespace modm::color +template +template +constexpr modm::color::RgbD::RgbD(const C& hsv) { + // OPTIMIZE No need to calculate sharper than the output + // Develop CalcType from types of conversion target: RedType, GreenType and BlueType. + using CalcType = C::ValueType; + using ValueType = CalcType::ValueType; -// TODO Finish generalisation for uint16_t -template -template -constexpr RgbT::RgbT(const HsvT &hsv) -{ - uint16_t vs = hsv.value * hsv.saturation; - uint16_t h6 = 6 * hsv.hue; + using WideType = modm::WideType; + using WideWideType = modm::WideType; + static_assert(!std::is_same_v, "C::ValueType too big"); + + const ValueType hue = CalcType(hsv.getHue()).getValue(); + const ValueType saturation = CalcType(hsv.getSaturation()).getValue(); + const ValueType value = CalcType(hsv.getValue()).getValue(); - T p = ((hsv.value << 8) - vs) >> 8; - T i = h6 >> 8; - uint16_t f = ((i | 1) << 8) - h6; - if (i & 1) { f = -f; } - T u = (((uint32_t)hsv.value << 16) - (uint32_t)vs * f) >> 16; + const WideType vs = value * saturation; + const WideType h6 = 6 * hue; + + ValueType i = h6 >> CalcType::Digits; + WideType f = ((i | 1) << CalcType::Digits) - h6; + if (i & 1) f = -f; + + CalcType p(((value << CalcType::Digits) - vs) >> CalcType::Digits); + CalcType u(((WideWideType(value) << 2 * CalcType::Digits) - WideWideType(vs) * f) >> 2 * CalcType::Digits); switch (i) { - case 0: red = hsv.value; green = u; blue = p; break; - case 1: red = u; green = hsv.value; blue = p; break; - case 2: red = p; green = hsv.value; blue = u; break; - case 3: red = p; green = u; blue = hsv.value; break; - case 4: red = u; green = p; blue = hsv.value; break; - case 5: red = hsv.value; green = p; blue = u; break; + case 0: red = hsv.getValue(); green = u; blue = p; break; + case 1: red = u; green = hsv.getValue(); blue = p; break; + case 2: red = p; green = hsv.getValue(); blue = u; break; + case 3: red = p; green = u; blue = hsv.getValue(); break; + case 4: red = u; green = p; blue = hsv.getValue(); break; + case 5: red = hsv.getValue(); green = p; blue = u; break; } -} - -} // namespace modm::color +} \ No newline at end of file diff --git a/src/modm/ui/color/rgb_stacked.hpp b/src/modm/ui/color/rgb_stacked.hpp new file mode 100644 index 0000000000..4fc181120b --- /dev/null +++ b/src/modm/ui/color/rgb_stacked.hpp @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2021, Thomas Sommer + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#pragma once + +#include "concepts.hpp" + +namespace modm::color { +/** + * @brief Stores a RGB color in a stacked. Consumes potentialy less space but + * does not offer immediate access to each channel making it Inefficient + * to calc with. Primary application as display- or storage-format. + * + * @tparam DR Bits for red channel + * @tparam DG Bits for green channel + * @tparam DB Bits for blue channel + * + * @author Thomas Sommer + * @ingroup modm_ui_color + */ +template +class RgbStackedD +{ +public: + using RedType = GrayD; + using GreenType = GrayD; + using BlueType = GrayD; + + using ValueType = uint_t::least; + + constexpr RgbStackedD() = default; + + constexpr RgbStackedD(const ValueType value) : value(value){}; + + constexpr RgbStackedD(RedType red, GreenType green, BlueType blue) + : value(red.getValue() << (DG + DB) | green.getValue() << DB | blue.getValue()) {} + + template + constexpr RgbStackedD(const C &other) + : RgbStackedD(other.getRed(), other.getGreen(), other.getBlue()) {} + + template + constexpr RgbStackedD(C &&other) + : RgbStackedD(other.getRed(), other.getGreen(), other.getBlue()) {} + + template + constexpr RgbStackedD(const C &gray) + : RgbStackedD(RgbD(gray)) {} + + template + constexpr RgbStackedD(const C &rgb) + : RgbStackedD(rgb.getRed(), rgb.getGreen(), rgb.getBlue()) {} + + template + constexpr RgbStackedD(const C &hsv) + : RgbStackedD(RgbD<5,6,5>(hsv)) {} + + void setRed(RedType red) + { value = (value & ~(RedType::mask << (DG + DB))) | red.value << (DG + DB); } + void setGreen(GreenType green) + { value = (value & ~(GreenType::mask << DB)) | green.value << DB; } + void setBlue(BlueType blue) + { value = (value & ~BlueType::mask) | blue.value; } + + RedType getRed() const { return value >> (DG + DB); } + GreenType getGreen() const { return value >> DB & GreenType::max;} + BlueType getBlue() const { return value & BlueType::max; } + + ValueType getValue() const { return value; } + + template + constexpr RgbStackedD operator+(RgbStackedT_ &other) { + return { + getRed() + other.getRed(), + getGreen() + other.getGreen(), + getBlue() + other.getBlue() + }; + } + + // OPTIMIZE Do move semantics help for these operators? + template + constexpr RgbStackedD operator-(RgbStackedT_ &other) { + return { + getRed() - other.getRed(), + getGreen() - other.getGreen(), + getBlue() - other.getBlue() + }; + } + + template + RgbStackedD& operator+=(RgbStackedT_ &other) { + setRed(getRed() + other.getRed()); + setGreen(getGreen() + other.getGreen()); + setBlue(getBlue() + other.getBlue()); + return *this; + } + + template + RgbStackedD& operator-=(RgbStackedT_ &other) { + setRed(getRed() - other.getRed()); + setGreen(getGreen() - other.getGreen()); + setBlue(getBlue() - other.getBlue()); + return *this; + } + + // IMPLEMENT missing operators + // operator+ + // operator- + + constexpr bool + operator==(const RgbStackedD& other) const = default; + + void invert() { + value ^= bitmask(); + } + + template + constexpr RgbStackedD operator*(ScaleType &scale) { + return { + getRed() * scale, + getGreen() * scale, + getBlue() * scale + }; + } + +private: + ValueType value; + + template + friend IOStream& + operator<<(IOStream&, const C&); +}; + +using Rgb565 = RgbStackedD<5,6,5>; + +#if __has_include() +#include + +template +IOStream& +operator<<(IOStream& os, const C& rgb) +{ + os << rgb.getRed() << "\t" << rgb.getGreen() << "\t" << rgb.getBlue(); + return os; +} +#endif + +} \ No newline at end of file diff --git a/src/modm/ui/color/rgbhtml.hpp b/src/modm/ui/color/rgbhtml.hpp deleted file mode 100644 index 71d6c9dccd..0000000000 --- a/src/modm/ui/color/rgbhtml.hpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2021, Thomas Sommer - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#pragma once - -#include "rgb.hpp" - -namespace modm::color::html -{ - -/** - * Constant HTML Colornames in RGB Colorspace - * - * @see https://htmlcolorcodes.com/color-names/ - * @see modm:color:RgbT - * @ingroup modm_ui_color - * @{ - */ - -// Red HTML Color Names -static constexpr Rgb IndianRed(205, 92, 92); -static constexpr Rgb LightCoral(240, 128, 128); -static constexpr Rgb Salmon(250, 128, 114); -static constexpr Rgb DarkSalmon(233, 150, 122); -static constexpr Rgb LightSalmon(255, 160, 122); -static constexpr Rgb Crimson(220, 20, 60); -static constexpr Rgb Red(255, 0, 0); -static constexpr Rgb FireBrick(178, 34, 34); -static constexpr Rgb DarkRed(139, 0, 0); - -// Pink HTML Color Names -static constexpr Rgb Pink(255, 192, 203); -static constexpr Rgb LightPink(255, 182, 193); -static constexpr Rgb HotPink(255, 105, 180); -static constexpr Rgb DeepPink(255, 20, 147); -static constexpr Rgb MediumVioletRed(199, 21, 133); -static constexpr Rgb PaleVioletRed(219, 112, 147); - -// Orange HTML Color Names -static constexpr Rgb Coral(255, 127, 80); -static constexpr Rgb Tomato(255, 99, 71); -static constexpr Rgb OrangeRed(255, 69, 0); -static constexpr Rgb DarkOrange(255, 140, 0); -static constexpr Rgb Orange(25, 165, 0); - -// Yellow HTML Color Names -static constexpr Rgb Gold(255, 215, 0); -static constexpr Rgb Yellow(255, 255, 0); -static constexpr Rgb LightYellow(255, 255, 224); -static constexpr Rgb LemonChiffon(255, 250, 205); -static constexpr Rgb LightGoldenrodYellow(250, 250, 210); -static constexpr Rgb PapayaWhip(255, 239, 213); -static constexpr Rgb Moccasin(255, 228, 181); -static constexpr Rgb PeachPuff(255, 218, 185); -static constexpr Rgb PaleGoldenrod(238, 232, 170); -static constexpr Rgb Khaki(240, 230, 140); -static constexpr Rgb DarkKhaki(189, 183, 107); - -// Purple HTML Color Names -static constexpr Rgb Lavender(230, 230, 250); -static constexpr Rgb Thistle(216, 191, 216); -static constexpr Rgb Plum(221, 160, 221); -static constexpr Rgb Violet(238, 130, 238); -static constexpr Rgb Orchid(218, 112, 214); -static constexpr Rgb Fuchsia(255, 0, 255); -static constexpr Rgb Magenta(255, 0, 255); -static constexpr Rgb MediumOrchid(186, 85, 211); -static constexpr Rgb MediumPurple(147, 112, 219); -static constexpr Rgb RebeccaPurple(102, 51, 153); -static constexpr Rgb BlueViolet(138, 43, 226); -static constexpr Rgb DarkViolet(148, 0, 211); -static constexpr Rgb DarkOrchid(153, 50, 204); -static constexpr Rgb DarkMagenta(139, 0, 139); -static constexpr Rgb Purple(128, 0, 128); -static constexpr Rgb Indigo(75, 0, 130); -static constexpr Rgb SlateBlue(106, 90, 205); -static constexpr Rgb DarkSlateBlue(72, 61, 139); - -// Green HTML Color Names -static constexpr Rgb GreenYellow(173, 255, 47); -static constexpr Rgb Chartreuse(127, 255, 0); -static constexpr Rgb LawnGreen(124, 252, 0); -static constexpr Rgb Lime(0, 255, 0); -static constexpr Rgb LimeGreen(50, 205, 50); -static constexpr Rgb PaleGreen(152, 251, 152); -static constexpr Rgb LightGreen(144, 238, 144); -static constexpr Rgb MediumSpringGreen(0, 250, 154); -static constexpr Rgb SpringGreen(0, 255, 127); -static constexpr Rgb MediumSeaGreen(60, 179, 113); -static constexpr Rgb SeaGreen(46, 139, 87); -static constexpr Rgb ForestGreen(34, 139, 34); -static constexpr Rgb Green(0, 128, 0); -static constexpr Rgb DarkGreen(0, 100, 0); -static constexpr Rgb YellowGreen(154, 205, 50); -static constexpr Rgb OliveDrab(107, 142, 35); -static constexpr Rgb Olive(128, 128, 0); -static constexpr Rgb DarkOliveGreen(85, 107, 47); -static constexpr Rgb MediumAquamarine(102, 205, 170); -static constexpr Rgb DarkSeaGreen(143, 188, 139); -static constexpr Rgb LightSeaGreen(32, 178, 170); -static constexpr Rgb DarkCyan(0, 139, 139); -static constexpr Rgb Teal(0, 128, 128); - -// Blue HTML Color Names -static constexpr Rgb Aqua(0, 255, 255); -static constexpr Rgb Cyan(0, 255, 255); -static constexpr Rgb LightCyan(224, 255, 255); -static constexpr Rgb PaleTurquoise(175, 238, 238); -static constexpr Rgb Aquamarine(127, 255, 212); -static constexpr Rgb Turquoise(64, 224, 208); -static constexpr Rgb MediumTurquoise(72, 209, 204); -static constexpr Rgb DarkTurquoise(0, 206, 209); -static constexpr Rgb CadetBlue(95, 158, 160); -static constexpr Rgb SteelBlue(70, 130, 180); -static constexpr Rgb LightSteelBlue(176, 196, 222); -static constexpr Rgb PowderBlue(176, 224, 230); -static constexpr Rgb LightBlue(173, 216, 230); -static constexpr Rgb SkyBlue(135, 206, 235); -static constexpr Rgb LightSkyBlue(135, 206, 250); -static constexpr Rgb DeepSkyBlue(0, 191, 255); -static constexpr Rgb DodgerBlue(30, 144, 255); -static constexpr Rgb CornflowerBlue(100, 149, 237); -static constexpr Rgb MediumSlateBlue(123, 104, 238); -static constexpr Rgb RoyalBlue(65, 105, 225); -static constexpr Rgb Blue(0, 0, 255); -static constexpr Rgb MediumBlue(0, 0, 205); -static constexpr Rgb DarkBlue(0, 0, 139); -static constexpr Rgb Navy(0, 0, 128); -static constexpr Rgb MidnightBlue(25, 25, 112); - -// Brown HTML Color Names -static constexpr Rgb Cornsilk(255, 248, 220); -static constexpr Rgb BlanchedAlmond(255, 235, 205); -static constexpr Rgb Bisque(255, 228, 196); -static constexpr Rgb NavajoWhite(255, 222, 173); -static constexpr Rgb Wheat(245, 222, 179); -static constexpr Rgb BurlyWood(222, 184, 135); -static constexpr Rgb Tan(210, 180, 140); -static constexpr Rgb RosyBrown(188, 143, 143); -static constexpr Rgb SandyBrown(244, 164, 96); -static constexpr Rgb Goldenrod(218, 165, 32); -static constexpr Rgb DarkGoldenrod(184, 134, 11); -static constexpr Rgb Peru(205, 133, 63); -static constexpr Rgb Chocolate(210, 105, 30); -static constexpr Rgb SaddleBrown(139, 69, 19); -static constexpr Rgb Sienna(160, 82, 45); -static constexpr Rgb Brown(165, 42, 42); -static constexpr Rgb Maroon(128, 0, 0); - -// White HTML Color Names -static constexpr Rgb White(255, 255, 255); -static constexpr Rgb Snow(255, 250, 250); -static constexpr Rgb HoneyDew(240, 255, 240); -static constexpr Rgb MintCream(245, 255, 250); -static constexpr Rgb Azure(240, 255, 255); -static constexpr Rgb AliceBlue(240, 248, 255); -static constexpr Rgb GhostWhite(248, 248, 255); -static constexpr Rgb WhiteSmoke(245, 245, 245); -static constexpr Rgb SeaShell(255, 245, 238); -static constexpr Rgb Beige(245, 245, 220); -static constexpr Rgb OldLace(253, 245, 230); -static constexpr Rgb FloralWhite(255, 250, 230); -static constexpr Rgb Ivory(255, 255, 240); -static constexpr Rgb AntiqueWhite(250, 235, 215); -static constexpr Rgb Linen(250, 240, 230); -static constexpr Rgb LavenderBlush(255, 240, 245); -static constexpr Rgb MistyRose(255, 228, 225); - -// Gray HTML Color Names -static constexpr Rgb Gainsboro(220, 220, 220); -static constexpr Rgb LightGray(211, 211, 211); -static constexpr Rgb Silver(192, 192, 192); -static constexpr Rgb DarkGray(169, 169, 169); -static constexpr Rgb Gray(128, 128, 128); -static constexpr Rgb DimGray(105, 105, 105); -static constexpr Rgb LightSlateGray(119, 136, 153); -static constexpr Rgb SlateGray(112, 128, 144); -static constexpr Rgb DarkSlateGray(47, 79, 79); -static constexpr Rgb Black(0, 0, 0); - -/// @} - -} // namespace modm::color::html diff --git a/test/modm/ui/color/color_test.cpp b/test/modm/ui/color/color_test.cpp index ce4aca9a24..1cab7864d4 100644 --- a/test/modm/ui/color/color_test.cpp +++ b/test/modm/ui/color/color_test.cpp @@ -15,101 +15,110 @@ #include #include +using namespace modm; using namespace modm::color; -void ColorTest::testRgbCopyConstructors() { - RgbT rgb8(html::Orchid); - RgbT rgb8_b(rgb8); +void ColorTest::testGrayConstructors() { + Gray8 gray8(127); + Gray8 gray8_b(gray8); + TEST_ASSERT_EQUALS(gray8, gray8_b); + + Gray4 gray4(7); + gray4 += 3; + TEST_ASSERT_EQUALS(gray4.getValue(), 10); + gray4 -= 1; + TEST_ASSERT_EQUALS(gray4.getValue(), 9); + gray4 -= 42; // under-saturation + TEST_ASSERT_EQUALS(gray4.getValue(), 0); + gray4 += 66; // over-saturation + TEST_ASSERT_EQUALS(gray4.getValue(), 0b00001111); + gray4 -= 3; + TEST_ASSERT_EQUALS(gray4.getValue(), 0b00001100); + + // not supported + // gray4 -= -6; // another over-saturation + // TEST_ASSERT_EQUALS(gray4.getValue(), 0b00001111); + + + gray8 = gray4; // upscaling + TEST_ASSERT_EQUALS(gray8.getValue(), 0b11001100); + GrayD<13> gray13 = gray4; // more upscaling + TEST_ASSERT_EQUALS(gray13.getValue(), 0b0001100110011000); // last digit rounds down for odd D + gray4 = gray13; // downscaling + TEST_ASSERT_EQUALS(gray4.getValue(), 0b00001100); +} + +void ColorTest::testRgbConstructors() { + Rgb888 rgb8(html::Orchid); + Rgb888 rgb8_b(rgb8); TEST_ASSERT_EQUALS(rgb8, rgb8_b); - RgbT rgb16(rgb8); - TEST_ASSERT_EQUALS(uint16_t(rgb8.red) << 8, rgb16.red); - TEST_ASSERT_EQUALS(uint16_t(rgb8.green) << 8, rgb16.green); - TEST_ASSERT_EQUALS(uint16_t(rgb8.blue) << 8, rgb16.blue); + Rgb161616 rgb16(rgb8); - RgbT rgb8_c(rgb16); + Rgb888 rgb8_c(rgb16); TEST_ASSERT_EQUALS(rgb8, rgb8_c); } -void ColorTest::testHsvCopyConstructors() { - HsvT hsv8(html::Orchid); - HsvT hsv8_b(hsv8); +void ColorTest::testHsvConstructors() { + Hsv888 hsv8(html::Orchid); + Hsv888 hsv8_b(hsv8); TEST_ASSERT_EQUALS(hsv8, hsv8_b); - HsvT hsv16(hsv8); - TEST_ASSERT_EQUALS(uint16_t(hsv8.hue) << 8, hsv16.hue); - TEST_ASSERT_EQUALS(uint16_t(hsv8.saturation) << 8, hsv16.saturation); - TEST_ASSERT_EQUALS(uint16_t(hsv8.value) << 8, hsv16.value); + Hsv161616 hsv16(hsv8); - HsvT hsv8_c(hsv16); + Hsv888 hsv8_c(hsv16); TEST_ASSERT_EQUALS(hsv8, hsv8_c); } -void ColorTest::testBrightnessCopyConstructors() { - BrightnessT brightness8(127); - BrightnessT brightness8_b(brightness8); - TEST_ASSERT_EQUALS(brightness8.value, brightness8_b.value); - - BrightnessT brightness16(brightness8); - TEST_ASSERT_EQUALS(uint16_t(brightness8.value) << 8, brightness16.value); - - BrightnessT brightness8_c(brightness16); - TEST_ASSERT_EQUALS(brightness8.value, brightness8_c.value); -} - void ColorTest::testConvertion_8bit() { - RgbT rgb(124, 128, 10); + Rgb888 rgb(124, 128, 10); - HsvT hsv(rgb); - TEST_ASSERT_EQUALS(hsv.hue, 43); - TEST_ASSERT_EQUALS(hsv.saturation, 235); - TEST_ASSERT_EQUALS(hsv.value, 128); + Hsv888 hsv(rgb); + TEST_ASSERT_EQUALS(hsv.getHue(), 43); + TEST_ASSERT_EQUALS(hsv.getSaturation(), 235); + TEST_ASSERT_EQUALS(hsv.getValue(), 128); - BrightnessT brightness(rgb); - TEST_ASSERT_EQUALS(brightness.value, 118); + Gray8 gray(rgb); + TEST_ASSERT_EQUALS(gray.getValue(), 118); } -// TODO 16bit convertion not yet working -// see hsv_impl.hpp and rgb_impl.hpp -// void ColorTest::testConvertion_16bit() -// { -// RgbT rgb8(html::Orchid); -// HsvT hsv8(rgb8); -// HsvT hsv16(hsv8); -// RgbT rgb16(rgb8); -// HsvT hsv16_b(rgb16); +void ColorTest::testConvertion_16bit() +{ + Rgb888 rgb8(html::Orchid); + Hsv888 hsv8(rgb8); + Hsv161616 hsv16(hsv8); -// // Test, if rgb->hsv conversion produces the same result for 8 and 16bits -// TEST_ASSERT_EQUALS(hsv16, hsv16_b); -// } + Rgb161616 rgb16(rgb8); + Hsv161616 hsv16_b(rgb16); + + // Test, if rgb->hsv conversion produces the same result for 8 and 16bits + // FIXME test fails + // TEST_ASSERT_EQUALS(hsv16, hsv16_b); +} void ColorTest::testRgbHsvPingPongConvertion_8bit() { - RgbT rgb8(html::Orchid); - HsvT hsv8(rgb8); - RgbT rgb8_b(hsv8); - - // Convertion can distort - allow some tolerance. - using namespace modm; - TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb8.red, rgb8_b.red, 1_pct)); - TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb8.green, rgb8_b.green, 1_pct)); - TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb8.blue, rgb8_b.blue, 1_pct)); + Rgb888 rgb8(html::Orchid); + Hsv888 hsv8(rgb8); + Rgb888 rgb8_b(hsv8); + + // Convertion may distort - allow some tolerance. + TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb8.getRed().getValue(), rgb8_b.getRed().getValue(), 1_pct)); + TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb8.getGreen().getValue(), rgb8_b.getGreen().getValue(), 1_pct)); + TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb8.getBlue().getValue(), rgb8_b.getBlue().getValue(), 1_pct)); } -// TODO 16bit convertion not yet working -// see hsv_impl.hpp and rgb_impl.hpp -// void ColorTest::testRgbHsvPingPongConvertion_16bit() -// { -// // Rgb->Hsv->Rgb, both 16 bit -// RgbT rgb16(html::Orchid); -// HsvT hsv16(rgb16); -// RgbT rgb16_b(hsv16); - -// // Convertion can distort - allow some tolerance. -// using namespace modm; -// TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb.red, rgb16_b.red, 1_pct)); -// TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb.green, rgb16_b.green, 1_pct)); -// TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb.blue, rgb16_b.blue, 1_pct)); -// } \ No newline at end of file +void ColorTest::testRgbHsvPingPongConvertion_16bit() +{ + // Rgb->Hsv->Rgb, both 16 bit + Rgb161616 rgb16(html::Orchid); + Hsv161616 hsv16(rgb16); + Rgb161616 rgb16_b(hsv16); + + // Convertion may distort - allow some tolerance. + TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb16.getRed().getValue(), rgb16_b.getRed().getValue(), 1_pct)); + TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb16.getGreen().getValue(), rgb16_b.getGreen().getValue(), 1_pct)); + TEST_ASSERT_TRUE(modm::Tolerance::isValueInTolerance(rgb16.getBlue().getValue(), rgb16_b.getBlue().getValue(), 1_pct)); +} \ No newline at end of file diff --git a/test/modm/ui/color/color_test.hpp b/test/modm/ui/color/color_test.hpp index bb9bb1cc0a..e37f26bd55 100644 --- a/test/modm/ui/color/color_test.hpp +++ b/test/modm/ui/color/color_test.hpp @@ -19,29 +19,25 @@ class ColorTest : public unittest::TestSuite { public: void - testRgbCopyConstructors(); + testGrayConstructors(); void - testHsvCopyConstructors(); + testRgbConstructors(); void - testBrightnessCopyConstructors(); + testHsvConstructors(); void testConvertion_8bit(); - // TODO 16bit convertion not yet working - // see hsv_impl.hpp and rgb_impl.hpp - // void - // testConvertion_16bit(); + void + testConvertion_16bit(); void testRgbHsvPingPongConvertion_8bit(); - // TODO 16bit convertion not yet working - // see hsv_impl.hpp and rgb_impl.hpp - // void - // testRgbHsvPingPongConvertion_16bit(); + void + testRgbHsvPingPongConvertion_16bit(); }; #endif // COLOR_TEST_HPP