Browse Source

Added Color3 and Color4 classes with HSV conversion.

They can be used for both floating-point (normalized) and integral
(denormalized) representation and support conversion between them.

HSV conversion is done always using floating-point types.

Getters for RGB(A) were removed from Vector3 and Vector4, they are now
part of Color3 and Color4. Because of this, Framebuffer now accepts
Color instead of Vector.
vectorfields
Vladimír Vondruš 14 years ago
parent
commit
c8aa005e86
  1. 3
      src/AbstractTexture.h
  2. 1
      src/CMakeLists.txt
  3. 409
      src/Color.h
  4. 3
      src/Framebuffer.h
  5. 16
      src/Math/Vector3.h
  6. 30
      src/Math/Vector4.h
  7. 2
      src/Test/CMakeLists.txt
  8. 121
      src/Test/ColorTest.cpp
  9. 44
      src/Test/ColorTest.h

3
src/AbstractTexture.h

@ -20,6 +20,7 @@
*/ */
#include "Magnum.h" #include "Magnum.h"
#include "Color.h"
namespace Magnum { namespace Magnum {
@ -611,7 +612,7 @@ class MAGNUM_EXPORT AbstractTexture {
* to `ClampToBorder`. * to `ClampToBorder`.
* @requires_gl * @requires_gl
*/ */
inline void setBorderColor(const Vector4& color) { inline void setBorderColor(const Color4& color) {
bind(); bind();
glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, color.data()); glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, color.data());
} }

1
src/CMakeLists.txt

@ -40,6 +40,7 @@ set(Magnum_HEADERS
BufferedTexture.h BufferedTexture.h
Buffer.h Buffer.h
Camera.h Camera.h
Color.h
CubeMapTextureArray.h CubeMapTextureArray.h
CubeMapTexture.h CubeMapTexture.h
Framebuffer.h Framebuffer.h

409
src/Color.h

@ -0,0 +1,409 @@
#ifndef Magnum_Color_h
#define Magnum_Color_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum 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 Lesser General Public License version 3 for more details.
*/
/** @file
* @brief Class Magnum::Color3, Magnum::Color4
*/
#include <tuple>
#include "Math/MathTypeTraits.h"
#include "Math/Math.h"
#include "Math/Vector4.h"
namespace Magnum {
template<class T> class Color3;
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
/* Convert color from HSV */
template<class T> inline typename std::enable_if<std::is_floating_point<T>::value, Color3<T>>::type fromHSV(typename Color3<T>::HSV hsv) {
T hue, saturation, value;
std::tie(hue, saturation, value) = hsv;
/* Remove repeats */
hue -= int(hue/T(360))*T(360);
if(hue < T(0)) hue += T(360);
int h = int(hue/T(60)) % 6;
T f = hue/T(60) - h;
T p = value * (T(1) - saturation);
T q = value * (T(1) - f*saturation);
T t = value * (T(1) - (T(1) - f)*saturation);
switch(h) {
case 0: return {value, t, p};
case 1: return {q, value, p};
case 2: return {p, value, t};
case 3: return {p, q, value};
case 4: return {t, p, value};
case 5: return {value, p, q};
default:
CORRADE_ASSERT(false, "It shouldn't get here.", {});
}
}
template<class T> inline typename std::enable_if<std::is_integral<T>::value, Color3<T>>::type fromHSV(typename Color3<T>::HSV hsv) {
return Color3<T>::fromNormalized(fromHSV<typename Color3<T>::FloatingPointType>(hsv));
}
/* Internal hue computing function */
template<class T> T hue(const Color3<T>& color, T max, T delta) {
T deltaInv60 = T(60)/delta;
T hue(0);
if(delta != T(0)) {
if(max == color.r())
hue = (color.g()-color.b())*deltaInv60 + (color.g() < color.b() ? T(360) : T(0));
else if(max == color.g())
hue = (color.b()-color.r())*deltaInv60 + T(120);
else /* max == color.b() */
hue = (color.r()-color.g())*deltaInv60 + T(240);
}
return hue;
}
/* Hue, saturation, value for floating-point types */
template<class T> inline T hue(typename std::enable_if<std::is_floating_point<T>::value, const Color3<T>&>::type color) {
T max = color.max();
T delta = max - color.min();
return hue(color, max, delta);
}
template<class T> inline T saturation(typename std::enable_if<std::is_floating_point<T>::value, const Color3<T>&>::type color) {
T max = color.max();
T delta = max - color.min();
return max != T(0) ? delta/max : T(0);
}
template<class T> inline T value(typename std::enable_if<std::is_floating_point<T>::value, const Color3<T>&>::type color) {
return color.max();
}
/* Hue, saturation, value for integral types */
template<class T> inline typename Color3<T>::FloatingPointType hue(typename std::enable_if<std::is_integral<T>::value, const Color3<T>&>::type color) {
return hue<typename Color3<T>::FloatingPointType>(Color3<typename Color3<T>::FloatingPointType>::fromDenormalized(color));
}
template<class T> inline typename Color3<T>::FloatingPointType saturation(typename std::enable_if<std::is_integral<T>::value, const Color3<T>&>::type& color) {
return saturation<typename Color3<T>::FloatingPointType>(Color3<typename Color3<T>::FloatingPointType>::fromDenormalized(color));
}
template<class T> inline typename Color3<T>::FloatingPointType value(typename std::enable_if<std::is_integral<T>::value, const Color3<T>&>::type color) {
return Math::normalize<typename Color3<T>::FloatingPointType>(color.max());
}
/* Convert color to HSV */
template<class T> inline typename Color3<T>::HSV toHSV(typename std::enable_if<std::is_floating_point<T>::value, const Color3<T>&>::type color) {
T max = color.max();
T delta = max - color.min();
return typename Color3<T>::HSV(hue<typename Color3<T>::FloatingPointType>(color, max, delta), max != T(0) ? delta/max : T(0), max);
}
template<class T> inline typename Color3<T>::HSV toHSV(typename std::enable_if<std::is_integral<T>::value, const Color3<T>&>::type color) {
return toHSV<typename Color3<T>::FloatingPointType>(Color3<typename Color3<T>::FloatingPointType>::fromDenormalized(color));
}
/* Default alpha value */
template<class T> inline constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type defaultAlpha() {
return T(1);
}
template<class T> inline constexpr typename std::enable_if<std::is_integral<T>::value, T>::type defaultAlpha() {
return std::numeric_limits<T>::max();
}
}
#endif
/**
@brief Three-component (RGB) color
The class can store both floating-point (normalized) and integral
(denormalized) representation of color. You can convert between these two
representations using fromNormalized() and fromDenormalized().
Conversion from and to HSV is done always using floating-point types, so hue
is always in range in range @f$ [0.0, 360.0] @f$, saturation and value in
range @f$ [0.0, 1.0] @f$.
@see Color4
*/
template<class T> class Color3: public Math::Vector3<T> {
public:
/** @brief Corresponding floating-point type for HSV computation */
typedef typename Math::MathTypeTraits<T>::FloatingPointType FloatingPointType;
/**
* @brief Type for storing HSV values
*
* Hue in range @f$ [0.0, 360.0] @f$, saturation and value in
* range @f$ [0.0, 1.0] @f$.
*/
typedef std::tuple<FloatingPointType, FloatingPointType, FloatingPointType> HSV;
/**
* @brief Create integral color from floating-point color
*
* E.g. `{0.294118, 0.45098, 0.878431}` is converted to
* `{75, 115, 224}`, if resulting type is `unsigned char`.
*
* @note This function is enabled only if source type is floating-point
* and destination type is integral.
*/
template<class U> inline constexpr static typename std::enable_if<std::is_integral<T>::value && std::is_floating_point<U>::value, Color3<T>>::type fromNormalized(const Color3<U>& color) {
return Color3<T>(Math::denormalize<T>(color.r()),
Math::denormalize<T>(color.g()),
Math::denormalize<T>(color.b()));
}
/**
* @brief Create floating-point color from integral color
*
* E.g. `{75, 115, 224}` is converted to
* `{0.294118, 0.45098, 0.878431}`, if source type is `unsigned char`.
*
* @note This function is enabled only if source type is integral
* and destination type is floating-point.
*/
template<class U> inline constexpr static typename std::enable_if<std::is_floating_point<T>::value && std::is_integral<U>::value, Color3<T>>::type fromDenormalized(const Color3<U>& color) {
return Color3<T>(Math::normalize<T>(color.r()),
Math::normalize<T>(color.g()),
Math::normalize<T>(color.b()));
}
/**
* @brief Create RGB color from HSV representation
* @param hsv Hue, saturation and value
*
* Hue can overflow the range @f$ [0.0, 360.0] @f$.
*/
inline constexpr static Color3<T> fromHSV(HSV hsv) {
return Implementation::fromHSV<T>(hsv);
}
/** @overload */
inline constexpr static Color3<T> fromHSV(FloatingPointType hue, FloatingPointType saturation, FloatingPointType value) {
return fromHSV(std::make_tuple(hue, saturation, value));
}
/**
* @brief Default constructor
*
* All components are set to zero.
*/
inline constexpr Color3() {}
/**
* @brief Gray constructor
* @param rgb RGB value
*/
inline constexpr explicit Color3(T rgb): Math::Vector3<T>(rgb) {}
/** @copydoc Math::Vector::Vector(const Vector&) */
inline constexpr Color3(const Math::Vector<3, T>& other): Math::Vector3<T>(other) {}
/**
* @brief Constructor
* @param r R value
* @param g G value
* @param b B value
*/
inline constexpr Color3(T r, T g, T b): Math::Vector3<T>(r, g, b) {}
inline constexpr T r() const { return Math::Vector3<T>::x(); } /**< @brief R component */
inline constexpr T g() const { return Math::Vector3<T>::y(); } /**< @brief G component */
inline constexpr T b() const { return Math::Vector3<T>::z(); } /**< @brief B component */
inline void setR(T value) { Math::Vector3<T>::setX(value); } /**< @brief Set R component */
inline void setG(T value) { Math::Vector3<T>::setY(value); } /**< @brief Set G component */
inline void setB(T value) { Math::Vector3<T>::setZ(value); } /**< @brief Set B component */
/**
* @brief Convert to HSV
*
* Example usage:
* @code
* T hue, saturation, value;
* std::tie(hue, saturation, value) = color.toHSV();
* @endcode
*
* @see hue(), saturation(), value(), fromHSV()
*/
inline constexpr HSV toHSV() const {
return Implementation::toHSV<T>(*this);
}
/**
* @brief Hue
* @return Hue in range @f$ [0.0, 360.0] @f$.
*
* @see saturation(), value(), toHSV(), fromHSV()
*/
inline constexpr FloatingPointType hue() const {
return Implementation::hue<T>(*this);
}
/**
* @brief Saturation
* @return Saturation in range @f$ [0.0, 1.0] @f$.
*
* @see hue(), value(), toHSV(), fromHSV()
*/
inline constexpr FloatingPointType saturation() const {
return Implementation::saturation<T>(*this);
}
/**
* @brief Value
* @return Value in range @f$ [0.0, 1.0] @f$.
*
* @see hue(), saturation(), toHSV(), fromHSV()
*/
inline constexpr FloatingPointType value() const {
return Implementation::value<T>(*this);
}
};
/**
@brief Four-component (RGBA) color
See Color3 for more information.
*/
template<class T> class Color4: public Math::Vector4<T> {
public:
/** @copydoc Color3::FloatingPointType */
typedef typename Color3<T>::FloatingPointType FloatingPointType;
/** @copydoc Color3::HSV */
typedef typename Color3<T>::HSV HSV;
/** @copydoc Color3::fromNormalized() */
template<class U> inline constexpr static typename std::enable_if<std::is_integral<T>::value && std::is_floating_point<U>::value, Color4<T>>::type fromNormalized(const Color4<U>& color) {
return Color4<T>(Math::denormalize<T>(color.r()),
Math::denormalize<T>(color.g()),
Math::denormalize<T>(color.b()),
Math::denormalize<T>(color.a()));
}
/** @copydoc Color3::fromDenormalized() */
template<class U> inline constexpr static typename std::enable_if<std::is_floating_point<T>::value && std::is_integral<U>::value, Color4<T>>::type fromDenormalized(const Color4<U>& color) {
return Color4<T>(Math::normalize<T>(color.r()),
Math::normalize<T>(color.g()),
Math::normalize<T>(color.b()),
Math::normalize<T>(color.a()));
}
/**
* @copydoc Color3::fromHSV()
* @param a Alpha value, defaults to 1.0 for floating-point types
* and maximum positive value for integral types.
*/
inline constexpr static Color4<T> fromHSV(HSV hsv, T a = Implementation::defaultAlpha<T>()) {
return Color4<T>(Implementation::fromHSV<T>(hsv), a);
}
/** @overload */
inline constexpr static Color4<T> fromHSV(FloatingPointType hue, FloatingPointType saturation, FloatingPointType value, T alpha) {
return fromHSV(std::make_tuple(hue, saturation, value), alpha);
}
/**
* @brief Default constructor
*
* RGB components are set to zero, A component is set to 1.0 for
* floating-point types and maximum positive value for integral types.
*/
inline constexpr Color4(): Math::Vector4<T>(T(0), T(0), T(0), Implementation::defaultAlpha<T>()) {}
/**
* @copydoc Color3::Color3(T)
* @param alpha Alpha value, defaults to 1.0 for floating-point types
* and maximum positive value for integral types.
*/
inline constexpr explicit Color4(T rgb, T alpha = Implementation::defaultAlpha<T>()): Math::Vector4<T>(rgb, rgb, rgb, alpha) {}
/** @copydoc Math::Vector::Vector(const Vector&) */
inline constexpr Color4(const Math::Vector<4, T>& other): Math::Vector4<T>(other) {}
/**
* @brief Constructor
* @param r R value
* @param g G value
* @param b B value
* @param a A value, defaults to 1.0 for floating-point types and
* maximum positive value for integral types.
*/
inline constexpr Color4(T r, T g, T b, T a = Implementation::defaultAlpha<T>()): Math::Vector4<T>(r, g, b, a) {}
/**
* @brief Constructor
* @param rgb Three-component color
* @param a A value
*/
/* Not marked as explicit, because conversion from Color3 to Color4
is fairly common, nearly always with A set to 1 */
inline constexpr Color4(const Math::Vector<3, T>& rgb, T a = Implementation::defaultAlpha<T>()): Math::Vector4<T>(rgb[0], rgb[1], rgb[2], a) {}
inline constexpr T r() const { return Math::Vector4<T>::x(); } /**< @brief R component */
inline constexpr T g() const { return Math::Vector4<T>::y(); } /**< @brief G component */
inline constexpr T b() const { return Math::Vector4<T>::z(); } /**< @brief B component */
inline constexpr T a() const { return Math::Vector4<T>::w(); } /**< @brief A component */
inline void setR(T value) { Math::Vector4<T>::setX(value); } /**< @brief Set R component */
inline void setG(T value) { Math::Vector4<T>::setY(value); } /**< @brief Set G component */
inline void setB(T value) { Math::Vector4<T>::setZ(value); } /**< @brief Set B component */
inline void setA(T value) { Math::Vector4<T>::setW(value); } /**< @brief Set A component */
/**
* @brief RGB part of the vector
* @return First three components of the vector
*
* @see swizzle()
*/
inline constexpr Color3<T> rgb() const { return Math::Vector4<T>::xyz(); }
/** @copydoc Color3::toHSV() */
inline constexpr HSV toHSV() const {
return Implementation::toHSV<T>(rgb());
}
/** @copydoc Color3::hue() */
inline constexpr FloatingPointType hue() const {
return Implementation::hue<T>(rgb());
}
/** @copydoc Color3::saturation() */
inline constexpr FloatingPointType saturation() const {
return Implementation::saturation<T>(rgb());
}
/** @copydoc Color3::value() */
inline constexpr FloatingPointType value() const {
return Implementation::value<T>(rgb());
}
};
/** @debugoperator{Color3} */
template<class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Color3<T>& value) {
return debug << static_cast<const Magnum::Math::Vector3<T>&>(value);
}
/** @debugoperator{Color4} */
template<class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Color4<T>& value) {
return debug << static_cast<const Magnum::Math::Vector4<T>&>(value);
}
}
#endif

3
src/Framebuffer.h

@ -23,6 +23,7 @@
#include "BufferedImage.h" #include "BufferedImage.h"
#include "CubeMapTexture.h" #include "CubeMapTexture.h"
#include "Color.h"
#include "Image.h" #include "Image.h"
#include "Renderbuffer.h" #include "Renderbuffer.h"
@ -192,7 +193,7 @@ class MAGNUM_EXPORT Framebuffer {
* *
* Initial value is `{0.0f, 0.0f, 0.0f, 1.0f}`. * Initial value is `{0.0f, 0.0f, 0.0f, 1.0f}`.
*/ */
inline static void setClearColor(const Vector4& color) { inline static void setClearColor(const Color4<GLfloat>& color) {
glClearColor(color.r(), color.g(), color.b(), color.a()); glClearColor(color.r(), color.g(), color.b(), color.a());
} }

16
src/Math/Vector3.h

@ -57,16 +57,16 @@ template<class T> class Vector3: public Vector<3, T> {
/** /**
* @brief Constructor * @brief Constructor
* @param x X / R value * @param x X value
* @param y Y / G value * @param y Y value
* @param z Z / B value * @param z Z value
*/ */
inline constexpr Vector3(T x, T y, T z): Vector<3, T>(x, y, z) {} inline constexpr Vector3(T x, T y, T z): Vector<3, T>(x, y, z) {}
/** /**
* @brief Constructor * @brief Constructor
* @param other Two component vector * @param other Two component vector
* @param z Z / B value * @param z Z value
*/ */
inline constexpr Vector3(const Vector<2, T>& other, T z): Vector<3, T>(other[0], other[1], z) {} inline constexpr Vector3(const Vector<2, T>& other, T z): Vector<3, T>(other[0], other[1], z) {}
@ -86,14 +86,6 @@ template<class T> class Vector3: public Vector<3, T> {
*/ */
inline constexpr Vector2<T> xy() const { return Vector2<T>::from(Vector<3, T>::data()); } inline constexpr Vector2<T> xy() const { return Vector2<T>::from(Vector<3, T>::data()); }
inline constexpr T r() const { return x(); } /**< @brief R component */
inline constexpr T g() const { return y(); } /**< @brief G component */
inline constexpr T b() const { return z(); } /**< @brief B component */
inline void setR(T value) { setX(value); } /**< @brief Set R component */
inline void setG(T value) { setY(value); } /**< @brief Set G component */
inline void setB(T value) { setZ(value); } /**< @brief Set B component */
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector3, 3) MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector3, 3)
}; };

30
src/Math/Vector4.h

@ -29,7 +29,7 @@ template<class T> class Vector4: public Vector<4, T> {
/** /**
* @copydoc Vector::Vector * @copydoc Vector::Vector
* *
* W / A component is set to one. * W component is set to one.
*/ */
inline constexpr Vector4(): Vector<4, T>(T(0), T(0), T(0), T(1)) {} inline constexpr Vector4(): Vector<4, T>(T(0), T(0), T(0), T(1)) {}
@ -41,17 +41,17 @@ template<class T> class Vector4: public Vector<4, T> {
/** /**
* @brief Constructor * @brief Constructor
* @param x X / R value * @param x X value
* @param y Y / G value * @param y Y value
* @param z Z / B value * @param z Z value
* @param w W / A value * @param w W value
*/ */
inline constexpr Vector4(T x, T y, T z, T w = T(1)): Vector<4, T>(x, y, z, w) {} inline constexpr Vector4(T x, T y, T z, T w = T(1)): Vector<4, T>(x, y, z, w) {}
/** /**
* @brief Constructor * @brief Constructor
* @param other Three component vector * @param other Three component vector
* @param w W / A value * @param w W value
*/ */
/* Not marked as explicit, because conversion from Vector3 to Vector4 /* Not marked as explicit, because conversion from Vector3 to Vector4
is fairly common, nearly always with W set to 1 */ is fairly common, nearly always with W set to 1 */
@ -83,24 +83,6 @@ template<class T> class Vector4: public Vector<4, T> {
*/ */
inline constexpr Vector2<T> xy() const { return Vector2<T>::from(Vector<4, T>::data()); } inline constexpr Vector2<T> xy() const { return Vector2<T>::from(Vector<4, T>::data()); }
inline constexpr T r() const { return x(); } /**< @brief R component */
inline constexpr T g() const { return y(); } /**< @brief G component */
inline constexpr T b() const { return z(); } /**< @brief B component */
inline constexpr T a() const { return w(); } /**< @brief A component */
inline void setR(T value) { setX(value); } /**< @brief Set R component */
inline void setG(T value) { setY(value); } /**< @brief Set G component */
inline void setB(T value) { setZ(value); } /**< @brief Set B component */
inline void setA(T value) { setW(value); } /**< @brief Set A component */
/**
* @brief RGB part of the vector
* @return First three components of the vector
*
* @see swizzle()
*/
inline constexpr Vector3<T> rgb() const { return xyz(); }
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector4, 4) MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector4, 4)
}; };

2
src/Test/CMakeLists.txt

@ -1,3 +1,5 @@
corrade_add_test2(ObjectTest ObjectTest.cpp LIBRARIES MagnumTestLib) corrade_add_test2(ObjectTest ObjectTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test2(CameraTest CameraTest.cpp LIBRARIES Magnum) corrade_add_test2(CameraTest CameraTest.cpp LIBRARIES Magnum)
corrade_add_test2(SceneTest SceneTest.cpp LIBRARIES Magnum) corrade_add_test2(SceneTest SceneTest.cpp LIBRARIES Magnum)
corrade_add_test2(ColorTest ColorTest.cpp)

121
src/Test/ColorTest.cpp

@ -0,0 +1,121 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum 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 Lesser General Public License version 3 for more details.
*/
#include "ColorTest.h"
#include "Color.h"
using namespace std;
CORRADE_TEST_MAIN(Magnum::Test::ColorTest)
namespace Magnum { namespace Test {
typedef Magnum::Color3<unsigned char> Color3;
typedef Magnum::Color4<unsigned char> Color4;
typedef Magnum::Color3<float> Color3f;
ColorTest::ColorTest() {
addTests(&ColorTest::fromDenormalized,
&ColorTest::fromNormalized,
&ColorTest::fromHue,
&ColorTest::fromSaturation,
&ColorTest::fromValue,
&ColorTest::hue,
&ColorTest::saturation,
&ColorTest::value,
&ColorTest::hsv,
&ColorTest::hsvOverflow,
&ColorTest::hsvAlpha);
}
void ColorTest::fromDenormalized() {
CORRADE_COMPARE(Color3f::fromDenormalized(Color3(75, 115, 224)), Color3f(0.294118, 0.45098, 0.878431));
}
void ColorTest::fromNormalized() {
CORRADE_COMPARE(Color3::fromNormalized(Color3f(0.294118, 0.45098, 0.878431)), Color3(75, 115, 224));
}
void ColorTest::fromHue() {
CORRADE_COMPARE(Color3::fromHSV(27.0f, 1.0f, 1.0f), Color3(255, 115, 0));
CORRADE_COMPARE(Color3::fromHSV(86.0f, 1.0f, 1.0f), Color3(145, 255, 0));
CORRADE_COMPARE(Color3::fromHSV(134.0f, 1.0f, 1.0f), Color3(0, 255, 60));
CORRADE_COMPARE(Color3::fromHSV(191.0f, 1.0f, 1.0f), Color3(0, 208, 255));
CORRADE_COMPARE(Color3::fromHSV(269.0f, 1.0f, 1.0f), Color3(123, 0, 255));
CORRADE_COMPARE(Color3::fromHSV(317.0f, 1.0f, 1.0f), Color3(255, 0, 183));
}
void ColorTest::hue() {
CORRADE_COMPARE(Color3(255, 115, 0).hue(), 27.058824f);
CORRADE_COMPARE(Color3(145, 255, 0).hue(), 85.882353f);
CORRADE_COMPARE(Color3(0, 255, 60).hue(), 134.11765f);
CORRADE_COMPARE(Color3(0, 208, 255).hue(), 191.05882f);
CORRADE_COMPARE(Color3(123, 0, 255).hue(), 268.94117f);
CORRADE_COMPARE(Color3(255, 0, 183).hue(), 316.94117f);
}
void ColorTest::fromSaturation() {
CORRADE_COMPARE(Color3::fromHSV(0.0f, 0.702f, 1.0f), Color3(255, 76, 76));
}
void ColorTest::saturation() {
CORRADE_COMPARE(Color3(255, 76, 76).saturation(), 0.701961f);
CORRADE_COMPARE(Color3().saturation(), 0.0f);
}
void ColorTest::fromValue() {
CORRADE_COMPARE(Color3::fromHSV(0.0f, 1.0f, 0.522f), Color3(133, 0, 0));
}
void ColorTest::value() {
CORRADE_COMPARE(Color3(133, 0, 0).value(), 0.521569f);
}
void ColorTest::hsv() {
CORRADE_COMPARE(Color3::fromHSV(230.0f, 0.749f, 0.427f), Color3(27, 41, 109));
float hue, saturation, value;
tie(hue, saturation, value) = Color3(27, 41, 109).toHSV();
CORRADE_COMPARE(hue, 229.756106f);
CORRADE_COMPARE(saturation, 0.752294f);
CORRADE_COMPARE(value, 0.427451f);
}
void ColorTest::hsvOverflow() {
CORRADE_COMPARE(Color3::fromHSV(27.0f-360.0f, 1.0f, 1.0f), Color3(255, 115, 0));
CORRADE_COMPARE(Color3::fromHSV(86.0f-360.0f, 1.0f, 1.0f), Color3(145, 255, 0));
CORRADE_COMPARE(Color3::fromHSV(134.0f-360.0f, 1.0f, 1.0f), Color3(0, 255, 60));
CORRADE_COMPARE(Color3::fromHSV(191.0f-360.0f, 1.0f, 1.0f), Color3(0, 208, 255));
CORRADE_COMPARE(Color3::fromHSV(269.0f-360.0f, 1.0f, 1.0f), Color3(123, 0, 255));
CORRADE_COMPARE(Color3::fromHSV(317.0f-360.0f, 1.0f, 1.0f), Color3(255, 0, 183));
CORRADE_COMPARE(Color3::fromHSV(360.0f+27.0f, 1.0f, 1.0f), Color3(255, 115, 0));
CORRADE_COMPARE(Color3::fromHSV(360.0f+86.0f, 1.0f, 1.0f), Color3(145, 255, 0));
CORRADE_COMPARE(Color3::fromHSV(360.0f+134.0f, 1.0f, 1.0f), Color3(0, 255, 60));
CORRADE_COMPARE(Color3::fromHSV(360.0f+191.0f, 1.0f, 1.0f), Color3(0, 208, 255));
CORRADE_COMPARE(Color3::fromHSV(360.0f+269.0f, 1.0f, 1.0f), Color3(123, 0, 255));
CORRADE_COMPARE(Color3::fromHSV(360.0f+317.0f, 1.0f, 1.0f), Color3(255, 0, 183));
}
void ColorTest::hsvAlpha() {
CORRADE_COMPARE(Color4::fromHSV(make_tuple(230.0f, 0.749f, 0.427f), 23), Color4(27, 41, 109, 23));
CORRADE_COMPARE(Color4::fromHSV(230.0f, 0.749f, 0.427f, 23), Color4(27, 41, 109, 23));
}
}}

44
src/Test/ColorTest.h

@ -0,0 +1,44 @@
#ifndef Magnum_Test_ColorTest_h
#define Magnum_Test_ColorTest_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum 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 Lesser General Public License version 3 for more details.
*/
#include <TestSuite/Tester.h>
namespace Magnum { namespace Test {
class ColorTest: public Corrade::TestSuite::Tester<ColorTest> {
public:
ColorTest();
void fromDenormalized();
void fromNormalized();
void fromHue();
void fromSaturation();
void fromValue();
void hue();
void saturation();
void value();
void hsv();
void hsvOverflow();
void hsvAlpha();
};
}}
#endif
Loading…
Cancel
Save