Browse Source

Math: new Color[34]::fromSrgb[Alpha]() and Color[34]::toSrgb[Alpha]Int().

For easier conversion of packed 24-/32-bit colors to the Color types.
pull/272/head
Vladimír Vondruš 8 years ago
parent
commit
d88e79cd9e
  1. 5
      doc/changelog.dox
  2. 27
      doc/snippets/MagnumMath.cpp
  3. 119
      src/Magnum/Math/Color.h
  4. 2
      src/Magnum/Math/Complex.h
  5. 2
      src/Magnum/Math/Quaternion.h
  6. 20
      src/Magnum/Math/Test/ColorTest.cpp

5
doc/changelog.dox

@ -61,6 +61,11 @@ See also:
@ref Math::Matrix4::scalingSquared(), @ref Math::Matrix3::scaling() const
and @ref Math::Matrix4::scaling() const getters for extracting further
properties from the rotation/scaling part of a matrix
- Added @ref Math::Color3::fromSrgb(UnsignedInt),
@ref Math::Color4::fromSrgbAlpha(UnsignedInt),
@ref Math::Color4::fromSrgb(UnsignedInt, T), @ref Math::Color3::toSrgbInt(),
and @ref Math::Color4::toSrgbAlphaInt() for easier conversion of packed
24-/32-bit sRGB colors to and from @ref Math::Color3 / @ref Math::Color4
- Added @ref Math::Constants::piQuarter()
- Added a convenience function @ref Math::select() as a constant
interpolation counterpart to @ref Math::lerp()

27
doc/snippets/MagnumMath.cpp

@ -699,6 +699,15 @@ auto rgb = Color3::fromSrgb(srgb);
static_cast<void>(rgb);
}
{
/* [Color3-fromSrgb-int] */
Color3 a = Color3::fromSrgb(0xff3366);
Color3 b = 0xff3366_srgbf;
/* [Color3-fromSrgb-int] */
static_cast<void>(a);
static_cast<void>(b);
}
{
Color3 color;
/* [Color3-toHsv] */
@ -727,11 +736,27 @@ static_cast<void>(rgba);
{
/* [Color4-fromSrgb] */
Math::Vector3<UnsignedByte> srgb;
auto rgba = Color4::fromSrgb(srgb);
auto rgba = Color4::fromSrgb(srgb, 0.5f);
/* [Color4-fromSrgb] */
static_cast<void>(rgba);
}
{
/* [Color4-fromSrgbAlpha-int] */
Color4 a = Color4::fromSrgbAlpha(0xff336680);
Color4 b = 0xff336680_srgbaf;
/* [Color4-fromSrgbAlpha-int] */
static_cast<void>(a);
static_cast<void>(b);
}
{
/* [Color4-fromSrgb-int] */
Color4 rgba = Color4::fromSrgb(0xff3366, 0.5f);
/* [Color4-fromSrgb-int] */
static_cast<void>(rgba);
}
{
Color4 color;
/* [Color4-toHsv] */

119
src/Magnum/Math/Color.h

@ -364,7 +364,9 @@ template<class T> class Color3: public Vector3<T> {
* \left( \dfrac{\boldsymbol{c}_\mathrm{sRGB} + a}{1 + a} \right)^{2.4}, & \boldsymbol{c}_\mathrm{sRGB} > 0.04045
* \end{cases}
* @f]
* @see @link operator""_srgbf() @endlink, @ref toSrgb()
* @see @ref fromSrgb(const Vector3<Integral>&), @ref fromSrgb(UnsignedInt),
* @link operator""_srgbf() @endlink, @ref toSrgb(),
* @ref Color4::fromSrgbAlpha()
*/
/* Input is a Vector3 to hint that it doesn't have any (additive,
multiplicative) semantics of a linear RGB color */
@ -381,6 +383,9 @@ template<class T> class Color3: public Vector3<T> {
* out of it:
*
* @snippet MagnumMath.cpp Color3-fromSrgb
*
* @see @ref fromSrgb(UnsignedInt), @link operator""_srgbf() @endlink,
* @ref Color4::fromSrgbAlpha(const Vector4<Integral>&)
*/
/* Input is a Vector3 to hint that it doesn't have any (additive,
multiplicative) semantics of a linear RGB color */
@ -388,6 +393,25 @@ template<class T> class Color3: public Vector3<T> {
return Implementation::fromSrgbIntegral<T, Integral>(srgb);
}
/** @overload
* @brief Create linear RGB color from 24-bit sRGB representation
* @param srgb 24-bit sRGB color
*
* See @ref fromSrgb() for more information and @ref toSrgbInt() for an
* inverse operation. There's also a @link operator""_srgbf() @endlink
* that does this conversion directly from hexadecimal literals. The
* following two statements are equivalent:
*
* @snippet MagnumMath.cpp Color3-fromSrgb-int
*
* @see @ref Color4::fromSrgbAlpha(UnsignedInt)
*/
static Color3<T> fromSrgb(UnsignedInt srgb) {
return fromSrgb<UnsignedByte>({UnsignedByte(srgb >> 16),
UnsignedByte(srgb >> 8),
UnsignedByte(srgb)});
}
/**
* @brief Create RGB color from CIE XYZ representation
* @param xyz Color in CIE XYZ color space
@ -525,7 +549,7 @@ template<class T> class Color3: public Vector3<T> {
* (1 + a) \boldsymbol{c}_\mathrm{linear}^{1/2.4}-a, & \boldsymbol{c}_\mathrm{linear} > 0.0031308
* \end{cases}
* @f]
* @see @ref fromSrgb()
* @see @ref fromSrgb(), @ref toSrgbInt(), @ref Color4::toSrgbAlpha()
*/
Vector3<FloatingPointType> toSrgb() const {
return Implementation::toSrgb<T>(*this);
@ -538,11 +562,25 @@ template<class T> class Color3: public Vector3<T> {
* want to create for example an 8-bit sRGB representation out of it:
*
* @snippet MagnumMath.cpp Color3-toSrgb
*
* @see @ref toSrgbInt(), @ref Color4::toSrgbAlpha()
*/
template<class Integral> Vector3<Integral> toSrgb() const {
return Implementation::toSrgbIntegral<T, Integral>(*this);
}
/**
* @brief Convert to 24-bit integral sRGB representation
*
* See @ref toSrgb() const for more information and
* @ref fromSrgb(UnsignedInt) for an inverse operation.
* @see @ref Color4::toSrgbAlphaInt()
*/
UnsignedInt toSrgbInt() const {
const auto srgb = toSrgb<UnsignedByte>();
return (srgb[0] << 16) | (srgb[1] << 8) | srgb[2];
}
/**
* @brief Convert to CIE XYZ representation
*
@ -737,9 +775,11 @@ class Color4: public Vector4<T> {
*
* Useful in cases where you have for example an 8-bit sRGB + alpha
* representation and want to create a floating-point linear RGBA color
* out of it:
* out of it. See @ref Color3::fromSrgb() for more information.
*
* @snippet MagnumMath.cpp Color4-fromSrgbAlpha
*
* @see @ref fromSrgbAlpha(UnsignedInt)
*/
/* Input is a Vector4 to hint that it doesn't have any (additive,
multiplicative) semantics of a linear RGB color */
@ -756,9 +796,11 @@ class Color4: public Vector4<T> {
*
* Useful in cases where you have for example an 8-bit sRGB
* representation and want to create a floating-point linear RGBA color
* out of it:
* out of it. See @ref Color3::fromSrgb() for more information.
*
* @snippet MagnumMath.cpp Color4-fromSrgb
*
* @see @ref fromSrgb(UnsignedInt, T)
*/
/* Input is a Vector3 to hint that it doesn't have any (additive,
multiplicative) semantics of a linear RGB color */
@ -766,6 +808,45 @@ class Color4: public Vector4<T> {
return {Implementation::fromSrgbIntegral<T, Integral>(srgb), a};
}
/** @overload
* @brief Create linear RGBA color from 32-bit sRGB + alpha representation
* @param srgbAlpha 32-bit sRGB color with linear alpha
*
* See @ref Color3::fromSrgb() for more information and
* @ref toSrgbAlphaInt() for an inverse operation. There's also a
* @link operator""_srgbaf() @endlink that does this conversion
* directly from hexadecimal literals.
*
* @snippet MagnumMath.cpp Color4-fromSrgbAlpha-int
*/
static Color4<T> fromSrgbAlpha(UnsignedInt srgbAlpha) {
return fromSrgbAlpha<UnsignedByte>({UnsignedByte(srgbAlpha >> 24),
UnsignedByte(srgbAlpha >> 16),
UnsignedByte(srgbAlpha >> 8),
UnsignedByte(srgbAlpha)});
}
/** @overload
* @brief Create linear RGBA color from 32-bit sRGB + alpha representation
* @param srgb 24-bit sRGB color
* @param a Alpha value, defaults to @cpp 1.0 @ce for
* floating-point types and maximum positive value for integral
* types
*
* See @ref Color3::fromSrgb() for more information and
* @ref toSrgbAlphaInt() for an inverse operation. There's also a
* @link operator""_srgbaf() @endlink that does this conversion
* directly from hexadecimal literals. The following two statements are
* equivalent:
*
* @snippet MagnumMath.cpp Color4-fromSrgb-int
*/
static Color4<T> fromSrgb(UnsignedInt srgb, T a = Implementation::fullChannel<T>()) {
return fromSrgb<UnsignedByte>({UnsignedByte(srgb >> 16),
UnsignedByte(srgb >> 8),
UnsignedByte(srgb)}, a);
}
/**
* @brief Create RGBA color from CIE XYZ representation
* @param xyz Color in CIE XYZ color space
@ -897,7 +978,7 @@ class Color4: public Vector4<T> {
* channel is kept linear. See @ref Color3::toSrgb() for more
* information.
*
* @see @ref fromSrgbAlpha()
* @see @ref fromSrgbAlpha(), @ref toSrgbAlphaInt()
*/
Vector4<FloatingPointType> toSrgbAlpha() const {
return Implementation::toSrgbAlpha<T>(*this);
@ -911,11 +992,26 @@ class Color4: public Vector4<T> {
* out of it:
*
* @snippet MagnumMath.cpp Color4-toSrgbAlpha
*
* @see @ref toSrgbAlphaInt()
*/
template<class Integral> Vector4<Integral> toSrgbAlpha() const {
return Implementation::toSrgbAlphaIntegral<T, Integral>(*this);
}
/**
* @brief Convert to 32-bit integral sRGB + linear alpha representation
*
* See @ref Color3::toSrgb() const for more information and
* @ref fromSrgbAlpha(UnsignedInt) for an inverse operation. Use
* @ref rgb() together with @ref Color3::toSrgbInt() to output a 24-bit
* sRGB color.
*/
UnsignedInt toSrgbAlphaInt() const {
const auto srgbAlpha = toSrgbAlpha<UnsignedByte>();
return (srgbAlpha[0] << 24) | (srgbAlpha[1] << 16) | (srgbAlpha[2] << 8) | srgbAlpha[3];
}
/**
* @brief Convert to CIE XYZ representation
*
@ -1092,9 +1188,7 @@ inline Color3<Float> operator "" _rgbf(unsigned long long value) {
/** @relatesalso Magnum::Math::Color3
@brief Float sRGB literal
Unpacks the 8-bit values into three floats and converts the color space from
sRGB to linear RGB. See @ref Color3::fromSrgb() for more information. Example
usage:
Calls @ref Color3::fromSrgb(UnsignedInt) on the literal value. Example usage:
@snippet MagnumMath.cpp _srgbf
@ -1103,7 +1197,7 @@ usage:
@m_keywords{_srgbf srgbf}
*/
inline Color3<Float> operator "" _srgbf(unsigned long long value) {
return Color3<Float>::fromSrgb<UnsignedByte>({UnsignedByte(value >> 16), UnsignedByte(value >> 8), UnsignedByte(value)});
return Color3<Float>::fromSrgb(value);
}
/** @relatesalso Magnum::Math::Color4
@ -1128,9 +1222,8 @@ inline Color4<Float> operator "" _rgbaf(unsigned long long value) {
/** @relatesalso Magnum::Math::Color4
@brief Float sRGB + alpha literal
Unpacks the 8-bit values into four floats and converts the color space from
sRGB + alpha to linear RGBA. See @ref Color4::fromSrgbAlpha() for more
information. Example usage:
Calls @ref Color4::fromSrgbAlpha(UnsignedInt) on the literal value. Example
usage:
@snippet MagnumMath.cpp _srgbaf
@ -1139,7 +1232,7 @@ information. Example usage:
@m_keywords{_srgbaf srgbaf}
*/
inline Color4<Float> operator "" _srgbaf(unsigned long long value) {
return Color4<Float>::fromSrgbAlpha<UnsignedByte>({UnsignedByte(value >> 24), UnsignedByte(value >> 16), UnsignedByte(value >> 8), UnsignedByte(value)});
return Color4<Float>::fromSrgbAlpha(value);
}
}

2
src/Magnum/Math/Complex.h

@ -67,7 +67,7 @@ Expects that both complex numbers are normalized. @f[
@f]
@see @ref Complex::isNormalized(),
@ref angle(const Quaternion<T>&, const Quaternion<T>&),
@ref angle(const Vector<size, T>&, const Vector<size, T>&)
@ref angle(const Vector<size, FloatingPoint>&, const Vector<size, FloatingPoint>&)
*/
template<class T> inline Rad<T> angle(const Complex<T>& normalizedA, const Complex<T>& normalizedB) {
CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(),

2
src/Magnum/Math/Quaternion.h

@ -70,7 +70,7 @@ Expects that both quaternions are normalized. @f[
@f]
@see @ref Quaternion::isNormalized(),
@ref angle(const Complex<T>&, const Complex<T>&),
@ref angle(const Vector<size, T>&, const Vector<size, T>&)
@ref angle(const Vector<size, FloatingPoint>&, const Vector<size, FloatingPoint>&)
*/
template<class T> inline Rad<T> angle(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB) {
CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(),

20
src/Magnum/Math/Test/ColorTest.cpp

@ -621,26 +621,46 @@ void ColorTest::srgb() {
/* Integral 8bit sRGB -- slight precision loss */
CORRADE_COMPARE(Color3::fromSrgb<UnsignedByte>({0xf3, 0x2a, 0x80}),
(Color3{0.896269f, 0.0231534f, 0.215861f}));
CORRADE_COMPARE(Color3::fromSrgb(0xf32a80),
(Color3{0.896269f, 0.0231534f, 0.215861f}));
CORRADE_COMPARE(Color4::fromSrgbAlpha<UnsignedByte>({0xf3, 0x2a, 0x80, 0x23}),
(Color4{0.896269f, 0.0231534f, 0.215861f, 0.137255f}));
CORRADE_COMPARE(Color4::fromSrgbAlpha(0xf32a8023),
(Color4{0.896269f, 0.0231534f, 0.215861f, 0.137255f}));
CORRADE_COMPARE(Color4::fromSrgb<UnsignedByte>({0xf3, 0x2a, 0x80}, 0.175f),
(Color4{0.896269f, 0.0231534f, 0.215861f, 0.175f}));
CORRADE_COMPARE(Color4::fromSrgb(0xf32a80, 0.175f),
(Color4{0.896269f, 0.0231534f, 0.215861f, 0.175f}));
CORRADE_COMPARE((Color3{0.896269f, 0.0231534f, 0.215861f}).toSrgb<UnsignedByte>(),
(Math::Vector3<UnsignedByte>{0xf2, 0x2a, 0x80}));
CORRADE_COMPARE((Color3{0.896269f, 0.0231534f, 0.215861f}).toSrgbInt(),
0xf22a80);
CORRADE_COMPARE((Color4{0.896269f, 0.0231534f, 0.215861f, 0.137255f}).toSrgbAlpha<UnsignedByte>(),
(Math::Vector4<UnsignedByte>{0xf2, 0x2a, 0x80, 0x23}));
CORRADE_COMPARE((Color4{0.896269f, 0.0231534f, 0.215861f, 0.137255f}).toSrgbAlphaInt(),
0xf22a8023);
/* Integral both -- larger precision loss */
CORRADE_COMPARE(Math::Color3<UnsignedShort>::fromSrgb<UnsignedByte>({0xf3, 0x2a, 0x80}),
(Math::Color3<UnsignedShort>{58737, 1517, 14146}));
CORRADE_COMPARE(Math::Color3<UnsignedShort>::fromSrgb(0xf32a80),
(Math::Color3<UnsignedShort>{58737, 1517, 14146}));
CORRADE_COMPARE(Math::Color4<UnsignedShort>::fromSrgbAlpha<UnsignedByte>({0xf3, 0x2a, 0x80, 0x23}),
(Math::Color4<UnsignedShort>{58737, 1517, 14146, 8995}));
CORRADE_COMPARE(Math::Color4<UnsignedShort>::fromSrgbAlpha(0xf32a8023),
(Math::Color4<UnsignedShort>{58737, 1517, 14146, 8995}));
CORRADE_COMPARE(Math::Color4<UnsignedShort>::fromSrgb<UnsignedByte>({0xf3, 0x2a, 0x80}, 15299),
(Math::Color4<UnsignedShort>{58737, 1517, 14146, 15299}));
CORRADE_COMPARE(Math::Color4<UnsignedShort>::fromSrgb(0xf32a80, 15299),
(Math::Color4<UnsignedShort>{58737, 1517, 14146, 15299}));
CORRADE_COMPARE((Math::Color3<UnsignedShort>{58737, 1517, 14146}).toSrgb<UnsignedByte>(),
(Math::Vector3<UnsignedByte>{0xf2, 0x29, 0x7f}));
CORRADE_COMPARE((Math::Color3<UnsignedShort>{58737, 1517, 14146}).toSrgbInt(),
0xf2297f);
CORRADE_COMPARE((Math::Color4<UnsignedShort>{58737, 1517, 14146, 8995}).toSrgbAlpha<UnsignedByte>(),
(Math::Vector4<UnsignedByte>{0xf2, 0x29, 0x7f, 0x23}));
CORRADE_COMPARE((Math::Color4<UnsignedShort>{58737, 1517, 14146, 8995}).toSrgbAlphaInt(),
0xf2297f23);
/* Round-trip */
CORRADE_COMPARE(Color3::fromSrgb({0.00646f, 0.403027f, 0.563877f}).toSrgb(),

Loading…
Cancel
Save