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] */
}
{
/* [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] */
Math::Vector3<UnsignedByte> srgb;
@ -738,6 +730,16 @@ static_cast<void>(a);
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 color;
@ -746,6 +748,16 @@ Math::Vector3<UnsignedByte> srgb = color.toSrgb<UnsignedByte>();
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] */
Math::Vector4<UnsignedByte> srgbAlpha;
@ -754,14 +766,6 @@ auto rgba = Color4::fromSrgbAlpha(srgbAlpha);
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 a = Color4::fromSrgbAlpha(0xff336680);
@ -772,10 +776,13 @@ static_cast<void>(b);
}
{
/* [Color4-fromSrgb-int] */
Color4 rgba = Color4::fromSrgb(0xff3366, 0.5f);
/* [Color4-fromSrgb-int] */
static_cast<void>(rgba);
/* [Color4-unpack] */
Color4ub a{0xff, 0x33, 0x66, 0x99};
auto bFromSrgb = Color4::fromSrgbAlpha(a); // {1.0f, 0.03311f, 0.1329f, 0.6f}
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);
}
{
/* [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] */
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
The class can store either floating-point (normalized) or integral
(denormalized) representation of linear RGB color. Colors in sRGB color space
should not be used directly in calculations --- they should be converted to
linear RGB using @ref fromSrgb(), calculation done on the linear representation
and then converted back to sRGB using @ref toSrgb().
Note that constructor conversion between different types (like in @ref Vector
classes) doesn't do any (de)normalization, you should use @ref pack() and
@ref unpack() instead, for example:
The class can store either a floating-point or an integral representation of a
linear RGB color. Colors in sRGB color space should not beused directly in
calculations --- they should be converted to linear RGB using @ref fromSrgb(),
calculation done on the linear representation and then converted back to sRGB
using @ref toSrgb().
Integral colors are assumed to be in a packed representation where the
@f$ [0.0, 1.0] @f$ range is mapped to @f$ [0, 2^b - 1] @f$ with @f$ b @f$ being
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
@ -378,6 +381,11 @@ template<class T> class Color3: public Vector3<T> {
*
* @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,
* @ref Color4::fromSrgbAlpha(const Vector4<Integral>&)
*/
@ -398,6 +406,10 @@ template<class T> class Color3: public Vector3<T> {
*
* @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)
*/
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>&)
*
* @attention This function doesn't do any (un)packing, use @ref pack()
* and @ref unpack() instead. See class documentation for more
* information.
* @attention This function doesn't do any (un)packing, use either
* @ref pack() / @ref unpack() or the integer variants of
* @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) {}
@ -543,6 +556,11 @@ template<class T> class Color3: public Vector3<T> {
*
* @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()
*/
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
*
* See @ref toSrgb() const for more information and
* @ref fromSrgb(UnsignedInt) for an inverse operation.
* See @ref toSrgb() const for more information. Note that the integral
* 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()
*/
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
* 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
*
* 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)
*/
/* Input is a Vector4 to hint that it doesn't have any (additive,
@ -757,16 +782,11 @@ class Color4: public Vector4<T> {
/** @overload
* @brief Create linear RGB color from integral sRGB representation
* @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
* types
*
* 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. See @ref Color3::fromSrgb() for more information.
*
* @snippet MagnumMath.cpp Color4-fromSrgb
*
* Same as above, but with alpha as a separate parameter.
* @see @ref fromSrgb(UnsignedInt, T)
*/
/* 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
* @ref toSrgbAlphaInt() for an inverse operation. There's also a
* @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
*
* 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) {
return fromSrgbAlpha<UnsignedByte>({UnsignedByte(srgbAlpha >> 24),
@ -796,17 +822,11 @@ class Color4: public Vector4<T> {
/** @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
* @param a Linear 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
* Same as above, but with alpha as a separate parameter.
*/
static Color4<T> fromSrgb(UnsignedInt srgb, T a = Implementation::fullChannel<T>()) {
return fromSrgb<UnsignedByte>({UnsignedByte(srgb >> 16),
@ -876,9 +896,10 @@ class Color4: public Vector4<T> {
/**
* @copydoc Vector::Vector(const Vector<size, U>&)
*
* @attention This function doesn't do any (un)packing, use @ref pack)
* and @ref unpack() instead. See @ref Color3 class documentation
* for more information.
* @attention This function doesn't do any (un)packing, use either
* @ref pack() / @ref unpack() or the integer variants of
* @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) {}
@ -945,6 +966,11 @@ class Color4: public Vector4<T> {
*
* @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()
*/
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
*
* 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.
* See @ref Color3::toSrgb() const for more information. Use @ref rgb()
* together with @ref Color3::toSrgbInt() to output a 24-bit sRGB
* color. Note that the integral 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 toSrgbAlpha() const / @ref pack().
*/
UnsignedInt toSrgbAlphaInt() const {
const auto srgbAlpha = toSrgbAlpha<UnsignedByte>();

Loading…
Cancel
Save