Browse Source

Math: improve docs for color (un)packing and sRGB conversion.

mousecapture
Vladimír Vondruš 6 years ago
parent
commit
bc99e6fa57
  1. 57
      doc/snippets/MagnumMath.cpp
  2. 104
      src/Magnum/Math/Color.h

57
doc/snippets/MagnumMath.cpp

@ -713,14 +713,6 @@ if(!(b < a - epsilon || a + epsilon < b)) {
/* [BoolVector-boolean] */ /* [BoolVector-boolean] */
} }
{
/* [Color3-pack] */
Color3 a{1.0f, 0.5f, 0.75f};
auto b = Math::pack<Color3ub>(a); // b == {255, 127, 191}
/* [Color3-pack] */
static_cast<void>(b);
}
{ {
/* [Color3-fromSrgb] */ /* [Color3-fromSrgb] */
Math::Vector3<UnsignedByte> srgb; Math::Vector3<UnsignedByte> srgb;
@ -738,6 +730,16 @@ static_cast<void>(a);
static_cast<void>(b); static_cast<void>(b);
} }
{
/* [Color3-unpack] */
Color3ub a{0xff, 0x33, 0x66};
auto bFromSrgb = Color3::fromSrgb(a); // {1.0f, 0.03311f, 0.1329f}
auto bFromLinear = Math::unpack<Color3>(a); // {1.0f, 0.2f, 0.4f}
/* [Color3-unpack] */
static_cast<void>(bFromLinear);
static_cast<void>(bFromSrgb);
}
{ {
/* [Color3-toSrgb] */ /* [Color3-toSrgb] */
Color3 color; Color3 color;
@ -746,6 +748,16 @@ Math::Vector3<UnsignedByte> srgb = color.toSrgb<UnsignedByte>();
static_cast<void>(srgb); static_cast<void>(srgb);
} }
{
/* [Color3-pack] */
Color3 a{1.0f, 0.2f, 0.4f};
auto bSrgb = a.toSrgb<UnsignedByte>(); // {0xff, 0x7c, 0xaa}
auto bLinear = Math::pack<Color3ub>(a); // {0xff, 0x33, 0x66}
/* [Color3-pack] */
static_cast<void>(bLinear);
static_cast<void>(bSrgb);
}
{ {
/* [Color4-fromSrgbAlpha] */ /* [Color4-fromSrgbAlpha] */
Math::Vector4<UnsignedByte> srgbAlpha; Math::Vector4<UnsignedByte> srgbAlpha;
@ -754,14 +766,6 @@ auto rgba = Color4::fromSrgbAlpha(srgbAlpha);
static_cast<void>(rgba); static_cast<void>(rgba);
} }
{
/* [Color4-fromSrgb] */
Math::Vector3<UnsignedByte> srgb;
auto rgba = Color4::fromSrgb(srgb, 0.5f);
/* [Color4-fromSrgb] */
static_cast<void>(rgba);
}
{ {
/* [Color4-fromSrgbAlpha-int] */ /* [Color4-fromSrgbAlpha-int] */
Color4 a = Color4::fromSrgbAlpha(0xff336680); Color4 a = Color4::fromSrgbAlpha(0xff336680);
@ -772,10 +776,13 @@ static_cast<void>(b);
} }
{ {
/* [Color4-fromSrgb-int] */ /* [Color4-unpack] */
Color4 rgba = Color4::fromSrgb(0xff3366, 0.5f); Color4ub a{0xff, 0x33, 0x66, 0x99};
/* [Color4-fromSrgb-int] */ auto bFromSrgb = Color4::fromSrgbAlpha(a); // {1.0f, 0.03311f, 0.1329f, 0.6f}
static_cast<void>(rgba); auto bFromLinear = Math::unpack<Color4>(a); // {1.0f, 0.2f, 0.4f, 0.6f}
/* [Color4-unpack] */
static_cast<void>(bFromLinear);
static_cast<void>(bFromSrgb);
} }
{ {
@ -786,6 +793,16 @@ Math::Vector4<UnsignedByte> srgbAlpha = color.toSrgbAlpha<UnsignedByte>();
static_cast<void>(srgbAlpha); static_cast<void>(srgbAlpha);
} }
{
/* [Color4-pack] */
Color4 a{1.0f, 0.2f, 0.4f, 0.6f};
auto bSrgb = a.toSrgbAlpha<UnsignedByte>(); // {0xff, 0x7c, 0xaa, 0x99}
auto bLinear = Math::pack<Color4ub>(a); // {0xff, 0x33, 0x66, 0x99}
/* [Color4-pack] */
static_cast<void>(bLinear);
static_cast<void>(bSrgb);
}
{ {
/* [Color3-debug] */ /* [Color3-debug] */
Debug{Debug::Flag::Color} << 0xdcdcdc_rgb << 0xa5c9ea_rgb << 0x3bd267_rgb Debug{Debug::Flag::Color} << 0xdcdcdc_rgb << 0xa5c9ea_rgb << 0x3bd267_rgb

104
src/Magnum/Math/Color.h

@ -221,15 +221,18 @@ template<> constexpr long double fullChannel<long double>() { return 1.0l; }
/** /**
@brief Color in linear RGB color space @brief Color in linear RGB color space
The class can store either floating-point (normalized) or integral The class can store either a floating-point or an integral representation of a
(denormalized) representation of linear RGB color. Colors in sRGB color space linear RGB color. Colors in sRGB color space should not beused directly in
should not be used directly in calculations --- they should be converted to calculations --- they should be converted to linear RGB using @ref fromSrgb(),
linear RGB using @ref fromSrgb(), calculation done on the linear representation calculation done on the linear representation and then converted back to sRGB
and then converted back to sRGB using @ref toSrgb(). using @ref toSrgb().
Note that constructor conversion between different types (like in @ref Vector Integral colors are assumed to be in a packed representation where the
classes) doesn't do any (de)normalization, you should use @ref pack() and @f$ [0.0, 1.0] @f$ range is mapped to @f$ [0, 2^b - 1] @f$ with @f$ b @f$ being
@ref unpack() instead, for example: bit count of given integer type. Note that constructor conversion between
different types (like in @ref Vector classes) doesn't do any (un)packing, you
need to use either @ref pack() / @ref unpack() or the integer variants of
@ref toSrgb() / @ref fromSrgb() instead:
@snippet MagnumMath.cpp Color3-pack @snippet MagnumMath.cpp Color3-pack
@ -378,6 +381,11 @@ template<class T> class Color3: public Vector3<T> {
* *
* @snippet MagnumMath.cpp Color3-fromSrgb * @snippet MagnumMath.cpp Color3-fromSrgb
* *
* For conversion from a *linear* 24-bit representation (i.e, without
* applying the sRGB curve), use @ref unpack():
*
* @snippet MagnumMath.cpp Color3-unpack
*
* @see @ref fromSrgb(UnsignedInt), @link operator""_srgbf() @endlink, * @see @ref fromSrgb(UnsignedInt), @link operator""_srgbf() @endlink,
* @ref Color4::fromSrgbAlpha(const Vector4<Integral>&) * @ref Color4::fromSrgbAlpha(const Vector4<Integral>&)
*/ */
@ -398,6 +406,10 @@ template<class T> class Color3: public Vector3<T> {
* *
* @snippet MagnumMath.cpp Color3-fromSrgb-int * @snippet MagnumMath.cpp Color3-fromSrgb-int
* *
* Note that the integral value is endian-dependent (the red channel
* being in the *last* byte on little-endian platforms), for conversion
* from endian-independent sRGB / linear representation use
* @ref fromSrgb(const Vector3<Integral>&) / @ref unpack().
* @see @ref Color4::fromSrgbAlpha(UnsignedInt) * @see @ref Color4::fromSrgbAlpha(UnsignedInt)
*/ */
static Color3<T> fromSrgb(UnsignedInt srgb) { static Color3<T> fromSrgb(UnsignedInt srgb) {
@ -460,9 +472,10 @@ template<class T> class Color3: public Vector3<T> {
/** /**
* @copydoc Vector::Vector(const Vector<size, U>&) * @copydoc Vector::Vector(const Vector<size, U>&)
* *
* @attention This function doesn't do any (un)packing, use @ref pack() * @attention This function doesn't do any (un)packing, use either
* and @ref unpack() instead. See class documentation for more * @ref pack() / @ref unpack() or the integer variants of
* information. * @ref toSrgb() / @ref fromSrgb() instead. See class
* documentation for more information.
*/ */
template<class U> constexpr explicit Color3(const Vector<3, U>& other) noexcept: Vector3<T>(other) {} template<class U> constexpr explicit Color3(const Vector<3, U>& other) noexcept: Vector3<T>(other) {}
@ -543,6 +556,11 @@ template<class T> class Color3: public Vector3<T> {
* *
* @snippet MagnumMath.cpp Color3-toSrgb * @snippet MagnumMath.cpp Color3-toSrgb
* *
* For conversion to a *linear* 24-bit representation (i.e, without
* applying the sRGB curve), use @ref pack():
*
* @snippet MagnumMath.cpp Color3-pack
*
* @see @ref toSrgbInt(), @ref Color4::toSrgbAlpha() * @see @ref toSrgbInt(), @ref Color4::toSrgbAlpha()
*/ */
template<class Integral> Vector3<Integral> toSrgb() const { template<class Integral> Vector3<Integral> toSrgb() const {
@ -552,8 +570,10 @@ template<class T> class Color3: public Vector3<T> {
/** /**
* @brief Convert to 24-bit integral sRGB representation * @brief Convert to 24-bit integral sRGB representation
* *
* See @ref toSrgb() const for more information and * See @ref toSrgb() const for more information. Note that the integral
* @ref fromSrgb(UnsignedInt) for an inverse operation. * value is endian-dependent (the red channel being in the *last* byte
* on little-endian platforms), for conversion to an endian-independent
* sRGB / linear representation use @ref toSrgb() const / @ref pack().
* @see @ref Color4::toSrgbAlphaInt() * @see @ref Color4::toSrgbAlphaInt()
*/ */
UnsignedInt toSrgbInt() const { UnsignedInt toSrgbInt() const {
@ -742,10 +762,15 @@ class Color4: public Vector4<T> {
* *
* Useful in cases where you have for example an 8-bit sRGB + alpha * Useful in cases where you have for example an 8-bit sRGB + alpha
* representation and want to create a floating-point linear RGBA color * representation and want to create a floating-point linear RGBA color
* out of it. See @ref Color3::fromSrgb() for more information. * out of it:
* *
* @snippet MagnumMath.cpp Color4-fromSrgbAlpha * @snippet MagnumMath.cpp Color4-fromSrgbAlpha
* *
* For conversion from a *linear* 32-bit representation (i.e, without
* applying the sRGB curve), use @ref unpack():
*
* @snippet MagnumMath.cpp Color4-unpack
*
* @see @ref fromSrgbAlpha(UnsignedInt) * @see @ref fromSrgbAlpha(UnsignedInt)
*/ */
/* Input is a Vector4 to hint that it doesn't have any (additive, /* Input is a Vector4 to hint that it doesn't have any (additive,
@ -757,16 +782,11 @@ class Color4: public Vector4<T> {
/** @overload /** @overload
* @brief Create linear RGB color from integral sRGB representation * @brief Create linear RGB color from integral sRGB representation
* @param srgb Color in sRGB color space * @param srgb Color in sRGB color space
* @param a Alpha value, defaults to @cpp 1.0 @ce for * @param a Linear alpha value, defaults to @cpp 1.0 @ce for
* floating-point types and maximum positive value for integral * floating-point types and maximum positive value for integral
* types * types
* *
* Useful in cases where you have for example an 8-bit sRGB * Same as above, but with alpha as a separate parameter.
* representation and want to create a floating-point linear RGBA color
* out of it. See @ref Color3::fromSrgb() for more information.
*
* @snippet MagnumMath.cpp Color4-fromSrgb
*
* @see @ref fromSrgb(UnsignedInt, T) * @see @ref fromSrgb(UnsignedInt, T)
*/ */
/* Input is a Vector3 to hint that it doesn't have any (additive, /* Input is a Vector3 to hint that it doesn't have any (additive,
@ -782,9 +802,15 @@ class Color4: public Vector4<T> {
* See @ref Color3::fromSrgb() for more information and * See @ref Color3::fromSrgb() for more information and
* @ref toSrgbAlphaInt() for an inverse operation. There's also a * @ref toSrgbAlphaInt() for an inverse operation. There's also a
* @link operator""_srgbaf() @endlink that does this conversion * @link operator""_srgbaf() @endlink that does this conversion
* directly from hexadecimal literals. * directly from hexadecimal literals. The following two statements are
* equivalent:
* *
* @snippet MagnumMath.cpp Color4-fromSrgbAlpha-int * @snippet MagnumMath.cpp Color4-fromSrgbAlpha-int
*
* Note that the integral value is endian-dependent (the red channel
* being in the *last* byte on little-endian platforms), for conversion
* from an endian-independent sRGB / linear representation use
* @ref fromSrgbAlpha(const Vector4<Integral>&) / @ref unpack().
*/ */
static Color4<T> fromSrgbAlpha(UnsignedInt srgbAlpha) { static Color4<T> fromSrgbAlpha(UnsignedInt srgbAlpha) {
return fromSrgbAlpha<UnsignedByte>({UnsignedByte(srgbAlpha >> 24), return fromSrgbAlpha<UnsignedByte>({UnsignedByte(srgbAlpha >> 24),
@ -796,17 +822,11 @@ class Color4: public Vector4<T> {
/** @overload /** @overload
* @brief Create linear RGBA color from 32-bit sRGB + alpha representation * @brief Create linear RGBA color from 32-bit sRGB + alpha representation
* @param srgb 24-bit sRGB color * @param srgb 24-bit sRGB color
* @param a Alpha value, defaults to @cpp 1.0 @ce for * @param a Linear alpha value, defaults to @cpp 1.0 @ce for
* floating-point types and maximum positive value for integral * floating-point types and maximum positive value for integral
* types * types
* *
* See @ref Color3::fromSrgb() for more information and * Same as above, but with alpha as a separate parameter.
* @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>()) { static Color4<T> fromSrgb(UnsignedInt srgb, T a = Implementation::fullChannel<T>()) {
return fromSrgb<UnsignedByte>({UnsignedByte(srgb >> 16), return fromSrgb<UnsignedByte>({UnsignedByte(srgb >> 16),
@ -876,9 +896,10 @@ class Color4: public Vector4<T> {
/** /**
* @copydoc Vector::Vector(const Vector<size, U>&) * @copydoc Vector::Vector(const Vector<size, U>&)
* *
* @attention This function doesn't do any (un)packing, use @ref pack) * @attention This function doesn't do any (un)packing, use either
* and @ref unpack() instead. See @ref Color3 class documentation * @ref pack() / @ref unpack() or the integer variants of
* for more information. * @ref toSrgbAlpha() / @ref fromSrgbAlpha() instead. See
* @ref Color3 class documentation for more information.
*/ */
template<class U> constexpr explicit Color4(const Vector<4, U>& other) noexcept: Vector4<T>(other) {} template<class U> constexpr explicit Color4(const Vector<4, U>& other) noexcept: Vector4<T>(other) {}
@ -945,6 +966,11 @@ class Color4: public Vector4<T> {
* *
* @snippet MagnumMath.cpp Color4-toSrgbAlpha * @snippet MagnumMath.cpp Color4-toSrgbAlpha
* *
* For conversion to a *linear* 32-bit representation (i.e, without
* applying the sRGB curve), use @ref pack():
*
* @snippet MagnumMath.cpp Color4-pack
*
* @see @ref toSrgbAlphaInt() * @see @ref toSrgbAlphaInt()
*/ */
template<class Integral> Vector4<Integral> toSrgbAlpha() const { template<class Integral> Vector4<Integral> toSrgbAlpha() const {
@ -954,10 +980,12 @@ class Color4: public Vector4<T> {
/** /**
* @brief Convert to 32-bit integral sRGB + linear alpha representation * @brief Convert to 32-bit integral sRGB + linear alpha representation
* *
* See @ref Color3::toSrgb() const for more information and * See @ref Color3::toSrgb() const for more information. Use @ref rgb()
* @ref fromSrgbAlpha(UnsignedInt) for an inverse operation. Use * together with @ref Color3::toSrgbInt() to output a 24-bit sRGB
* @ref rgb() together with @ref Color3::toSrgbInt() to output a 24-bit * color. Note that the integral value is endian-dependent (the red
* sRGB color. * channel being in the *last* byte on little-endian platforms), for
* conversion to an endian-independent sRGB / linear representation use
* @ref toSrgbAlpha() const / @ref pack().
*/ */
UnsignedInt toSrgbAlphaInt() const { UnsignedInt toSrgbAlphaInt() const {
const auto srgbAlpha = toSrgbAlpha<UnsignedByte>(); const auto srgbAlpha = toSrgbAlpha<UnsignedByte>();

Loading…
Cancel
Save