diff options
author | Jeroen Bakker <jeroen@blender.org> | 2021-05-25 18:03:54 +0300 |
---|---|---|
committer | Jeroen Bakker <jeroen@blender.org> | 2021-05-25 18:03:54 +0300 |
commit | 00955cd31eda95aca619842064d22663af4c812b (patch) | |
tree | 85a4650d260f2fdc250d433d51d7309b77f08510 /source/blender/blenlib | |
parent | fd94e033446c72fb92048a9864c1d539fccde59a (diff) |
Revert "Blenlib: Explicit Colors."
This reverts commit fd94e033446c72fb92048a9864c1d539fccde59a.
does not compile against latest master.
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/BLI_color.hh | 302 | ||||
-rw-r--r-- | source/blender/blenlib/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_color.cc | 55 | ||||
-rw-r--r-- | source/blender/blenlib/tests/BLI_color_test.cc | 133 |
4 files changed, 35 insertions, 457 deletions
diff --git a/source/blender/blenlib/BLI_color.hh b/source/blender/blenlib/BLI_color.hh index 287587e04be..e57a5109a66 100644 --- a/source/blender/blenlib/BLI_color.hh +++ b/source/blender/blenlib/BLI_color.hh @@ -22,122 +22,41 @@ namespace blender { -/** - * CPP based color structures. - * - * Strongly typed color storage structures with space and alpha association. - * Will increase readability and visibility of typical mistakes when - * working with colors. - * - * The storage structs can hold 4 channels (r, g, b and a). - * - * Usage: - * - * Convert a theme byte color to a linearrgb premultiplied. - * ``` - * ColorTheme4b theme_color; - * ColorSceneLinear4f<eAlpha::Premultiplied> linearrgb_color = - * BLI_color_convert_to_scene_linear(theme_color).premultiply_alpha(); - * ``` - * - * The API is structured to make most use of inlining. Most notable are space - * conversions done via `BLI_color_convert_to*` functions. - * - * - Conversions between spaces (theme <=> scene linear) should always be done by - * invoking the `BLI_color_convert_to*` methods. - * - Encoding colors (compressing to store colors inside a less precision storage) - * should be done by invoking the `encode` and `decode` methods. - * - Changing alpha association should be done by invoking `premultiply_alpha` or - * `unpremultiply_alpha` methods. - * - * # Encoding. - * - * Color encoding is used to store colors with less precision as in using `uint8_t` in - * stead of `float`. This encoding is supported for `eSpace::SceneLinear`. - * To make this clear to the developer the `eSpace::SceneLinearByteEncoded` - * space is added. - * - * # Precision - * - * Colors can be stored using `uint8_t` or `float` colors. The conversion - * between the two precisions are available as methods. (`to_4b` and - * `to_4f`). - * - * # Alpha conversion - * - * Alpha conversion is only supported in SceneLinear space. - * - * Extending this file: - * - This file can be extended with `ColorHex/Hsl/Hsv` for different representations - * of rgb based colors. `ColorHsl4f<eSpace::SceneLinear, eAlpha::Premultiplied>` - * - Add non RGB spaces/storages ColorXyz. - */ - -/* Enumeration containing the different alpha modes. */ -enum class eAlpha { - /* Color and alpha are unassociated. */ - Straight, - /* Color and alpha are associated. */ - Premultiplied, -}; -std::ostream &operator<<(std::ostream &stream, const eAlpha &space); +struct Color4f { + float r, g, b, a; -/* Enumeration containing internal spaces. */ -enum class eSpace { - /* Blender theme color space (sRGB). */ - Theme, - /* Blender internal scene linear color space (maps to SceneReference role in OCIO). */ - SceneLinear, - /* Blender internal scene linear color space compressed to be stored in 4 uint8_t. */ - SceneLinearByteEncoded, -}; -std::ostream &operator<<(std::ostream &stream, const eSpace &space); + Color4f() = default; -/* Template class to store RGBA values with different precision, space and alpha association. */ -template<typename ChannelStorageType, eSpace Space, eAlpha Alpha> class ColorRGBA { - public: - ChannelStorageType r, g, b, a; - constexpr ColorRGBA() = default; - - constexpr ColorRGBA(const ChannelStorageType rgba[4]) - : r(rgba[0]), g(rgba[1]), b(rgba[2]), a(rgba[3]) + Color4f(const float *rgba) : r(rgba[0]), g(rgba[1]), b(rgba[2]), a(rgba[3]) { } - constexpr ColorRGBA(const ChannelStorageType r, - const ChannelStorageType g, - const ChannelStorageType b, - const ChannelStorageType a) - : r(r), g(g), b(b), a(a) + Color4f(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) { } - operator ChannelStorageType *() + operator float *() { return &r; } - operator const ChannelStorageType *() const + operator const float *() const { return &r; } - friend std::ostream &operator<<(std::ostream &stream, - const ColorRGBA<ChannelStorageType, Space, Alpha> &c) + friend std::ostream &operator<<(std::ostream &stream, Color4f c) { - - stream << Space << Alpha << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")"; + stream << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")"; return stream; } - friend bool operator==(const ColorRGBA<ChannelStorageType, Space, Alpha> &a, - const ColorRGBA<ChannelStorageType, Space, Alpha> &b) + friend bool operator==(const Color4f &a, const Color4f &b) { return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; } - friend bool operator!=(const ColorRGBA<ChannelStorageType, Space, Alpha> &a, - const ColorRGBA<ChannelStorageType, Space, Alpha> &b) + friend bool operator!=(const Color4f &a, const Color4f &b) { return !(a == b); } @@ -152,209 +71,58 @@ template<typename ChannelStorageType, eSpace Space, eAlpha Alpha> class ColorRGB } }; -/* Forward declarations of concrete color classes. */ -template<eAlpha Alpha> class ColorSceneLinear4f; -template<eAlpha Alpha> class ColorSceneLinearByteEncoded4b; -template<typename ChannelStorageType> class ColorTheme4; - -/* Forward declation of precision conversion methods. */ -BLI_INLINE ColorTheme4<float> BLI_color_convert_to_theme4f(const ColorTheme4<uint8_t> &srgb4b); -BLI_INLINE ColorTheme4<uint8_t> BLI_color_convert_to_theme4b(const ColorTheme4<float> &srgb4f); - -template<eAlpha Alpha> -class ColorSceneLinear4f final : public ColorRGBA<float, eSpace::SceneLinear, Alpha> { - public: - constexpr ColorSceneLinear4f<Alpha>() : ColorRGBA<float, eSpace::SceneLinear, Alpha>() - { - } - - constexpr ColorSceneLinear4f<Alpha>(const float *rgba) - : ColorRGBA<float, eSpace::SceneLinear, Alpha>(rgba) - { - } - - constexpr ColorSceneLinear4f<Alpha>(float r, float g, float b, float a) - : ColorRGBA<float, eSpace::SceneLinear, Alpha>(r, g, b, a) - { - } +struct Color4b { + uint8_t r, g, b, a; - /** - * Convert to its byte encoded counter space. - **/ - ColorSceneLinearByteEncoded4b<Alpha> encode() const - { - ColorSceneLinearByteEncoded4b<Alpha> encoded; - linearrgb_to_srgb_uchar4(encoded, *this); - return encoded; - } + Color4b() = default; - /** - * Convert color and alpha association to premultiplied alpha. - * - * Does nothing when color has already a premultiplied alpha. - */ - ColorSceneLinear4f<eAlpha::Premultiplied> premultiply_alpha() const + Color4b(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) { - if constexpr (Alpha == eAlpha::Straight) { - ColorSceneLinear4f<eAlpha::Premultiplied> premultiplied; - straight_to_premul_v4_v4(premultiplied, *this); - return premultiplied; - } - else { - return *this; - } } - /** - * Convert color and alpha association to straight alpha. - * - * Does nothing when color has straighten alpha. - */ - ColorSceneLinear4f<eAlpha::Straight> unpremultiply_alpha() const + Color4b(Color4f other) { - if constexpr (Alpha == eAlpha::Premultiplied) { - ColorSceneLinear4f<eAlpha::Straight> straighten; - premul_to_straight_v4_v4(straighten, *this); - return straighten; - } - else { - return *this; - } + rgba_float_to_uchar(*this, other); } -}; - -template<eAlpha Alpha> -class ColorSceneLinearByteEncoded4b final - : public ColorRGBA<uint8_t, eSpace::SceneLinearByteEncoded, Alpha> { - public: - constexpr ColorSceneLinearByteEncoded4b() = default; - constexpr ColorSceneLinearByteEncoded4b(const uint8_t *rgba) - : ColorRGBA<uint8_t, eSpace::SceneLinearByteEncoded, Alpha>(rgba) + operator Color4f() const { + Color4f result; + rgba_uchar_to_float(result, *this); + return result; } - constexpr ColorSceneLinearByteEncoded4b(uint8_t r, uint8_t g, uint8_t b, uint8_t a) - : ColorRGBA<uint8_t, eSpace::SceneLinearByteEncoded, Alpha>(r, g, b, a) + operator uint8_t *() { + return &r; } - /** - * Convert to back to float color. - */ - ColorSceneLinear4f<Alpha> decode() const + operator const uint8_t *() const { - ColorSceneLinear4f<Alpha> decoded; - srgb_to_linearrgb_uchar4(decoded, *this); - return decoded; + return &r; } -}; - -/** - * Theme color template class. - * - * Don't use directly, but use `ColorTheme4b/ColorTheme4b`. - * - * This has been implemented as a template to improve inlining. When implemented as concrete - * classes (ColorTheme4b/f) the functions would be hidden in a compile unit what wouldn't be - * inlined. - */ -template<typename ChannelStorageType> -class ColorTheme4 final : public ColorRGBA<ChannelStorageType, eSpace::Theme, eAlpha::Straight> { - public: - constexpr ColorTheme4() : ColorRGBA<ChannelStorageType, eSpace::Theme, eAlpha::Straight>(){}; - constexpr ColorTheme4(const ChannelStorageType *rgba) - : ColorRGBA<ChannelStorageType, eSpace::Theme, eAlpha::Straight>(rgba) + friend std::ostream &operator<<(std::ostream &stream, Color4b c) { + stream << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")"; + return stream; } - constexpr ColorTheme4(ChannelStorageType r, - ChannelStorageType g, - ChannelStorageType b, - ChannelStorageType a) - : ColorRGBA<ChannelStorageType, eSpace::Theme, eAlpha::Straight>(r, g, b, a) + friend bool operator==(const Color4b &a, const Color4b &b) { + return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; } - /** - * Change precision of color to float. - */ - ColorTheme4<float> to_4f() const + friend bool operator!=(const Color4b &a, const Color4b &b) { - if constexpr ((std::is_same_v<ChannelStorageType, uint8_t>)) { - return BLI_color_convert_to_theme4f(*this); - } - else { - return *this; - } + return !(a == b); } - /** - * Change precision of color to uint8_t. - */ - ColorTheme4<uint8_t> to_4b() const + uint64_t hash() const { - if constexpr ((std::is_same_v<ChannelStorageType, float>)) { - return BLI_color_convert_to_theme4b(*this); - } - else { - return *this; - } + return static_cast<uint64_t>(r * 1283591) ^ static_cast<uint64_t>(g * 850177) ^ + static_cast<uint64_t>(b * 735391) ^ static_cast<uint64_t>(a * 442319); } }; -using ColorTheme4b = ColorTheme4<uint8_t>; -using ColorTheme4f = ColorTheme4<float>; - -BLI_INLINE ColorTheme4b BLI_color_convert_to_theme4b(const ColorTheme4f &theme4f) -{ - ColorTheme4b theme4b; - rgba_float_to_uchar(theme4b, theme4f); - return theme4b; -} - -BLI_INLINE ColorTheme4f BLI_color_convert_to_theme4f(const ColorTheme4b &theme4b) -{ - ColorTheme4f theme4f; - rgba_uchar_to_float(theme4f, theme4b); - return theme4f; -} - -BLI_INLINE ColorSceneLinear4f<eAlpha::Straight> BLI_color_convert_to_scene_linear( - const ColorTheme4f &theme4f) -{ - ColorSceneLinear4f<eAlpha::Straight> scene_linear; - srgb_to_linearrgb_v4(scene_linear, theme4f); - return scene_linear; -} - -BLI_INLINE ColorSceneLinear4f<eAlpha::Straight> BLI_color_convert_to_scene_linear( - const ColorTheme4b &theme4b) -{ - ColorSceneLinear4f<eAlpha::Straight> scene_linear; - srgb_to_linearrgb_uchar4(scene_linear, theme4b); - return scene_linear; -} - -BLI_INLINE ColorTheme4f -BLI_color_convert_to_theme4f(const ColorSceneLinear4f<eAlpha::Straight> &scene_linear) -{ - ColorTheme4f theme4f; - linearrgb_to_srgb_v4(theme4f, scene_linear); - return theme4f; -} - -BLI_INLINE ColorTheme4b -BLI_color_convert_to_theme4b(const ColorSceneLinear4f<eAlpha::Straight> &scene_linear) -{ - ColorTheme4b theme4b; - linearrgb_to_srgb_uchar4(theme4b, scene_linear); - return theme4b; -} - -/* Internal roles. For convenience to shorten the type names and hide complexity. */ -using ColorGeometry4f = ColorSceneLinear4f<eAlpha::Premultiplied>; -using ColorGeometry4b = ColorSceneLinearByteEncoded4b<eAlpha::Premultiplied>; - } // namespace blender diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index f3dc343ee20..ce3515ac153 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -39,7 +39,6 @@ set(SRC intern/BLI_args.c intern/BLI_array.c intern/BLI_assert.c - intern/BLI_color.cc intern/BLI_dial_2d.c intern/BLI_dynstr.c intern/BLI_filelist.c @@ -390,7 +389,6 @@ if(WITH_GTESTS) tests/BLI_array_store_test.cc tests/BLI_array_test.cc tests/BLI_array_utils_test.cc - tests/BLI_color_test.cc tests/BLI_delaunay_2d_test.cc tests/BLI_disjoint_set_test.cc tests/BLI_edgehash_test.cc diff --git a/source/blender/blenlib/intern/BLI_color.cc b/source/blender/blenlib/intern/BLI_color.cc deleted file mode 100644 index 6dcef4f4688..00000000000 --- a/source/blender/blenlib/intern/BLI_color.cc +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "BLI_color.hh" - -namespace blender { - -std::ostream &operator<<(std::ostream &stream, const eAlpha &space) -{ - switch (space) { - case eAlpha::Straight: { - stream << "Straight"; - break; - } - case eAlpha::Premultiplied: { - stream << "Premultiplied"; - break; - } - } - return stream; -} - -std::ostream &operator<<(std::ostream &stream, const eSpace &space) -{ - switch (space) { - case eSpace::Theme: { - stream << "Theme"; - break; - } - case eSpace::SceneLinear: { - stream << "SceneLinear"; - break; - } - case eSpace::SceneLinearByteEncoded: { - stream << "SceneLinearByteEncoded"; - break; - } - } - return stream; -} - -} // namespace blender diff --git a/source/blender/blenlib/tests/BLI_color_test.cc b/source/blender/blenlib/tests/BLI_color_test.cc deleted file mode 100644 index 14796e6bf71..00000000000 --- a/source/blender/blenlib/tests/BLI_color_test.cc +++ /dev/null @@ -1,133 +0,0 @@ -/* Apache License, Version 2.0 */ - -#include "testing/testing.h" - -#include "BLI_color.hh" - -namespace blender::tests { - -/** - * \name Conversions - * \{ */ - -TEST(color, ThemeByteToFloat) -{ - ColorTheme4b theme_byte(192, 128, 64, 128); - ColorTheme4f theme_float = theme_byte.to_4f(); - EXPECT_NEAR(0.75f, theme_float.r, 0.01f); - EXPECT_NEAR(0.5f, theme_float.g, 0.01f); - EXPECT_NEAR(0.25f, theme_float.b, 0.01f); - EXPECT_NEAR(0.5f, theme_float.a, 0.01f); -} - -TEST(color, SrgbStraightFloatToByte) -{ - ColorTheme4f theme_float(0.75f, 0.5f, 0.25f, 0.5f); - ColorTheme4b theme_byte = theme_float.to_4b(); - EXPECT_EQ(191, theme_byte.r); - EXPECT_EQ(128, theme_byte.g); - EXPECT_EQ(64, theme_byte.b); - EXPECT_EQ(128, theme_byte.a); -} - -TEST(color, SrgbStraightToSceneLinearPremultiplied) -{ - BLI_init_srgb_conversion(); - - ColorTheme4b theme(192, 128, 64, 128); - ColorSceneLinear4f<eAlpha::Premultiplied> linear = - BLI_color_convert_to_scene_linear(theme).premultiply_alpha(); - EXPECT_NEAR(0.26f, linear.r, 0.01f); - EXPECT_NEAR(0.11f, linear.g, 0.01f); - EXPECT_NEAR(0.02f, linear.b, 0.01f); - EXPECT_NEAR(0.5f, linear.a, 0.01f); -} - -TEST(color, SceneLinearStraightToPremultiplied) -{ - ColorSceneLinear4f<eAlpha::Straight> straight(0.75f, 0.5f, 0.25f, 0.5f); - ColorSceneLinear4f<eAlpha::Premultiplied> premultiplied = straight.premultiply_alpha(); - EXPECT_NEAR(0.37f, premultiplied.r, 0.01f); - EXPECT_NEAR(0.25f, premultiplied.g, 0.01f); - EXPECT_NEAR(0.12f, premultiplied.b, 0.01f); - EXPECT_NEAR(0.5f, premultiplied.a, 0.01f); -} - -TEST(color, SceneLinearPremultipliedToStraight) -{ - ColorSceneLinear4f<eAlpha::Premultiplied> premultiplied(0.75f, 0.5f, 0.25f, 0.5f); - ColorSceneLinear4f<eAlpha::Straight> straight = premultiplied.unpremultiply_alpha(); - EXPECT_NEAR(1.5f, straight.r, 0.01f); - EXPECT_NEAR(1.0f, straight.g, 0.01f); - EXPECT_NEAR(0.5f, straight.b, 0.01f); - EXPECT_NEAR(0.5f, straight.a, 0.01f); -} - -TEST(color, SceneLinearStraightSrgbFloat) -{ - BLI_init_srgb_conversion(); - ColorSceneLinear4f<eAlpha::Straight> linear(0.75f, 0.5f, 0.25f, 0.5f); - ColorTheme4f theme = BLI_color_convert_to_theme4f(linear); - EXPECT_NEAR(0.88f, theme.r, 0.01); - EXPECT_NEAR(0.73f, theme.g, 0.01); - EXPECT_NEAR(0.53f, theme.b, 0.01); - EXPECT_NEAR(0.5f, theme.a, 0.01); -} - -TEST(color, SceneLinearPremultipliedToSrgbFloat) -{ - BLI_init_srgb_conversion(); - ColorSceneLinear4f<eAlpha::Premultiplied> linear(0.75f, 0.5f, 0.25f, 0.5f); - ColorTheme4f theme = BLI_color_convert_to_theme4f(linear.unpremultiply_alpha()); - - EXPECT_NEAR(1.19f, theme.r, 0.01); - EXPECT_NEAR(1.0f, theme.g, 0.01); - EXPECT_NEAR(0.74f, theme.b, 0.01); - EXPECT_NEAR(0.5f, theme.a, 0.01); -} - -TEST(color, SceneLinearStraightSrgbByte) -{ - BLI_init_srgb_conversion(); - ColorSceneLinear4f<eAlpha::Straight> linear(0.75f, 0.5f, 0.25f, 0.5f); - ColorTheme4b theme = BLI_color_convert_to_theme4b(linear); - EXPECT_EQ(225, theme.r); - EXPECT_EQ(188, theme.g); - EXPECT_EQ(137, theme.b); - EXPECT_EQ(128, theme.a); -} - -TEST(color, SceneLinearPremultipliedToSrgbByte) -{ - BLI_init_srgb_conversion(); - ColorSceneLinear4f<eAlpha::Premultiplied> linear(0.75f, 0.5f, 0.25f, 0.5f); - ColorTheme4b theme = BLI_color_convert_to_theme4b(linear.unpremultiply_alpha()); - EXPECT_EQ(255, theme.r); - EXPECT_EQ(255, theme.g); - EXPECT_EQ(188, theme.b); - EXPECT_EQ(128, theme.a); -} - -TEST(color, SceneLinearByteEncoding) -{ - ColorSceneLinear4f<eAlpha::Premultiplied> linear(0.75f, 0.5f, 0.25f, 0.5f); - ColorSceneLinearByteEncoded4b<eAlpha::Premultiplied> encoded = linear.encode(); - EXPECT_EQ(225, encoded.r); - EXPECT_EQ(188, encoded.g); - EXPECT_EQ(137, encoded.b); - EXPECT_EQ(128, encoded.a); -} - -TEST(color, SceneLinearByteDecoding) -{ - ColorSceneLinearByteEncoded4b<eAlpha::Premultiplied> encoded(225, 188, 137, 128); - ColorSceneLinear4f<eAlpha::Premultiplied> decoded = encoded.decode(); - EXPECT_NEAR(0.75f, decoded.r, 0.01f); - EXPECT_NEAR(0.5f, decoded.g, 0.01f); - EXPECT_NEAR(0.25f, decoded.b, 0.01f); - EXPECT_NEAR(0.5f, decoded.a, 0.01f); -} - -/* \} */ - -} // namespace blender::tests |