Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen Bakker <jeroen@blender.org>2021-05-25 18:03:54 +0300
committerJeroen Bakker <jeroen@blender.org>2021-05-25 18:03:54 +0300
commit00955cd31eda95aca619842064d22663af4c812b (patch)
tree85a4650d260f2fdc250d433d51d7309b77f08510 /source/blender/blenlib
parentfd94e033446c72fb92048a9864c1d539fccde59a (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.hh302
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/BLI_color.cc55
-rw-r--r--source/blender/blenlib/tests/BLI_color_test.cc133
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