Browse Source

Math: switch to our type traits in Color internals.

In preparation for having the Half type usable in Color.
pull/369/head
Vladimír Vondruš 6 years ago
parent
commit
3734568cdf
  1. 56
      src/Magnum/Math/Color.h

56
src/Magnum/Math/Color.h

@ -42,7 +42,7 @@ namespace Magnum { namespace Math {
namespace Implementation { namespace Implementation {
/* Convert color from HSV */ /* Convert color from HSV */
template<class T> typename std::enable_if<std::is_floating_point<T>::value, Color3<T>>::type fromHsv(ColorHsv<T> hsv) { template<class T> typename std::enable_if<IsFloatingPoint<T>::value, Color3<T>>::type fromHsv(ColorHsv<T> hsv) {
/* Remove repeats */ /* Remove repeats */
hsv.hue -= floor(T(hsv.hue)/T(360))*Deg<T>(360); hsv.hue -= floor(T(hsv.hue)/T(360))*Deg<T>(360);
if(hsv.hue < Deg<T>(0)) hsv.hue += Deg<T>(360); if(hsv.hue < Deg<T>(0)) hsv.hue += Deg<T>(360);
@ -64,7 +64,7 @@ template<class T> typename std::enable_if<std::is_floating_point<T>::value, Colo
default: CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ default: CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
} }
template<class T> inline typename std::enable_if<std::is_integral<T>::value, Color3<T>>::type fromHsv(const ColorHsv<typename TypeTraits<T>::FloatingPointType>& hsv) { template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color3<T>>::type fromHsv(const ColorHsv<typename TypeTraits<T>::FloatingPointType>& hsv) {
return pack<Color3<T>>(fromHsv<typename TypeTraits<T>::FloatingPointType>(hsv)); return pack<Color3<T>>(fromHsv<typename TypeTraits<T>::FloatingPointType>(hsv));
} }
@ -86,90 +86,90 @@ template<class T> Deg<T> hue(const Color3<T>& color, T max, T delta) {
} }
/* Hue, saturation, value for floating-point types */ /* Hue, saturation, value for floating-point types */
template<class T> inline Deg<T> hue(typename std::enable_if<std::is_floating_point<T>::value, const Color3<T>&>::type color) { template<class T> inline Deg<T> hue(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type color) {
T max = color.max(); T max = color.max();
T delta = max - color.min(); T delta = max - color.min();
return hue(color, max, delta); 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) { template<class T> inline T saturation(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type color) {
T max = color.max(); T max = color.max();
T delta = max - color.min(); T delta = max - color.min();
return max != T(0) ? delta/max : T(0); 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) { template<class T> inline T value(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type color) {
return color.max(); return color.max();
} }
/* Hue, saturation, value for integral types */ /* Hue, saturation, value for integral types */
template<class T> inline Deg<typename Color3<T>::FloatingPointType> hue(typename std::enable_if<std::is_integral<T>::value, const Color3<T>&>::type color) { template<class T> inline Deg<typename Color3<T>::FloatingPointType> hue(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type color) {
return hue<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(color)); return hue<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(color));
} }
template<class T> inline typename Color3<T>::FloatingPointType saturation(typename std::enable_if<std::is_integral<T>::value, const Color3<T>&>::type& color) { template<class T> inline typename Color3<T>::FloatingPointType saturation(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type& color) {
return saturation<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(color)); return saturation<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(color));
} }
template<class T> inline typename Color3<T>::FloatingPointType value(typename std::enable_if<std::is_integral<T>::value, const Color3<T>&>::type color) { template<class T> inline typename Color3<T>::FloatingPointType value(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type color) {
return unpack<typename Color3<T>::FloatingPointType>(color.max()); return unpack<typename Color3<T>::FloatingPointType>(color.max());
} }
/* Convert color to HSV */ /* Convert color to HSV */
template<class T> inline ColorHsv<T> toHsv(typename std::enable_if<std::is_floating_point<T>::value, const Color3<T>&>::type color) { template<class T> inline ColorHsv<T> toHsv(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type color) {
T max = color.max(); T max = color.max();
T delta = max - color.min(); T delta = max - color.min();
return ColorHsv<T>{hue<typename Color3<T>::FloatingPointType>(color, max, delta), max != T(0) ? delta/max : T(0), max}; return ColorHsv<T>{hue<typename Color3<T>::FloatingPointType>(color, max, delta), max != T(0) ? delta/max : T(0), max};
} }
template<class T> inline ColorHsv<typename TypeTraits<T>::FloatingPointType> toHsv(typename std::enable_if<std::is_integral<T>::value, const Color3<T>&>::type color) { template<class T> inline ColorHsv<typename TypeTraits<T>::FloatingPointType> toHsv(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type color) {
return toHsv<typename TypeTraits<T>::FloatingPointType>(unpack<Color3<typename TypeTraits<T>::FloatingPointType>>(color)); return toHsv<typename TypeTraits<T>::FloatingPointType>(unpack<Color3<typename TypeTraits<T>::FloatingPointType>>(color));
} }
/* sRGB -> RGB conversion */ /* sRGB -> RGB conversion */
template<class T> typename std::enable_if<std::is_floating_point<T>::value, Color3<T>>::type fromSrgb(const Vector3<T>& srgb) { template<class T> typename std::enable_if<IsFloatingPoint<T>::value, Color3<T>>::type fromSrgb(const Vector3<T>& srgb) {
constexpr const T a(T(0.055)); constexpr const T a(T(0.055));
return lerp(srgb/T(12.92), pow((srgb + Vector3<T>{a})/(T(1.0) + a), T(2.4)), srgb > Vector3<T>(T(0.04045))); return lerp(srgb/T(12.92), pow((srgb + Vector3<T>{a})/(T(1.0) + a), T(2.4)), srgb > Vector3<T>(T(0.04045)));
} }
template<class T> typename std::enable_if<std::is_floating_point<T>::value, Color4<T>>::type fromSrgbAlpha(const Vector4<T>& srgbAlpha) { template<class T> typename std::enable_if<IsFloatingPoint<T>::value, Color4<T>>::type fromSrgbAlpha(const Vector4<T>& srgbAlpha) {
return {fromSrgb<T>(srgbAlpha.rgb()), srgbAlpha.a()}; return {fromSrgb<T>(srgbAlpha.rgb()), srgbAlpha.a()};
} }
template<class T> inline typename std::enable_if<std::is_integral<T>::value, Color3<T>>::type fromSrgb(const Vector3<typename Color3<T>::FloatingPointType>& srgb) { template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color3<T>>::type fromSrgb(const Vector3<typename Color3<T>::FloatingPointType>& srgb) {
return pack<Color3<T>>(fromSrgb<typename Color3<T>::FloatingPointType>(srgb)); return pack<Color3<T>>(fromSrgb<typename Color3<T>::FloatingPointType>(srgb));
} }
template<class T> inline typename std::enable_if<std::is_integral<T>::value, Color4<T>>::type fromSrgbAlpha(const Vector4<typename Color4<T>::FloatingPointType>& srgbAlpha) { template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color4<T>>::type fromSrgbAlpha(const Vector4<typename Color4<T>::FloatingPointType>& srgbAlpha) {
return {fromSrgb<T>(srgbAlpha.rgb()), pack<T>(srgbAlpha.a())}; return {fromSrgb<T>(srgbAlpha.rgb()), pack<T>(srgbAlpha.a())};
} }
template<class T, class Integral> inline Color3<T> fromSrgbIntegral(const Vector3<Integral>& srgb) { template<class T, class Integral> inline Color3<T> fromSrgbIntegral(const Vector3<Integral>& srgb) {
static_assert(std::is_integral<Integral>::value, "only conversion from different integral type is supported"); static_assert(IsIntegral<Integral>::value, "only conversion from different integral type is supported");
return fromSrgb<T>(unpack<Vector3<typename Color3<T>::FloatingPointType>>(srgb)); return fromSrgb<T>(unpack<Vector3<typename Color3<T>::FloatingPointType>>(srgb));
} }
template<class T, class Integral> inline Color4<T> fromSrgbAlphaIntegral(const Vector4<Integral>& srgbAlpha) { template<class T, class Integral> inline Color4<T> fromSrgbAlphaIntegral(const Vector4<Integral>& srgbAlpha) {
static_assert(std::is_integral<Integral>::value, "only conversion from different integral type is supported"); static_assert(IsIntegral<Integral>::value, "only conversion from different integral type is supported");
return fromSrgbAlpha<T>(unpack<Vector4<typename Color4<T>::FloatingPointType>>(srgbAlpha)); return fromSrgbAlpha<T>(unpack<Vector4<typename Color4<T>::FloatingPointType>>(srgbAlpha));
} }
/* RGB -> sRGB conversion */ /* RGB -> sRGB conversion */
template<class T> Vector3<typename Color3<T>::FloatingPointType> toSrgb(typename std::enable_if<std::is_floating_point<T>::value, const Color3<T>&>::type rgb) { template<class T> Vector3<typename Color3<T>::FloatingPointType> toSrgb(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type rgb) {
constexpr const T a = T(0.055); constexpr const T a = T(0.055);
return lerp(rgb*T(12.92), (T(1.0) + a)*pow(rgb, T(1.0)/T(2.4)) - Vector3<T>{a}, rgb > Vector3<T>(T(0.0031308))); return lerp(rgb*T(12.92), (T(1.0) + a)*pow(rgb, T(1.0)/T(2.4)) - Vector3<T>{a}, rgb > Vector3<T>(T(0.0031308)));
} }
template<class T> Vector4<typename Color4<T>::FloatingPointType> toSrgbAlpha(typename std::enable_if<std::is_floating_point<T>::value, const Color4<T>&>::type rgba) { template<class T> Vector4<typename Color4<T>::FloatingPointType> toSrgbAlpha(typename std::enable_if<IsFloatingPoint<T>::value, const Color4<T>&>::type rgba) {
return {toSrgb<T>(rgba.rgb()), rgba.a()}; return {toSrgb<T>(rgba.rgb()), rgba.a()};
} }
template<class T> inline Vector3<typename Color3<T>::FloatingPointType> toSrgb(typename std::enable_if<std::is_integral<T>::value, const Color3<T>&>::type rgb) { template<class T> inline Vector3<typename Color3<T>::FloatingPointType> toSrgb(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type rgb) {
return toSrgb<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(rgb)); return toSrgb<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(rgb));
} }
template<class T> inline Vector4<typename Color4<T>::FloatingPointType> toSrgbAlpha(typename std::enable_if<std::is_integral<T>::value, const Color4<T>&>::type rgba) { template<class T> inline Vector4<typename Color4<T>::FloatingPointType> toSrgbAlpha(typename std::enable_if<IsIntegral<T>::value, const Color4<T>&>::type rgba) {
return {toSrgb<T>(rgba.rgb()), unpack<typename Color3<T>::FloatingPointType>(rgba.a())}; return {toSrgb<T>(rgba.rgb()), unpack<typename Color3<T>::FloatingPointType>(rgba.a())};
} }
template<class T, class Integral> inline Vector3<Integral> toSrgbIntegral(const Color3<T>& rgb) { template<class T, class Integral> inline Vector3<Integral> toSrgbIntegral(const Color3<T>& rgb) {
static_assert(std::is_integral<Integral>::value, "only conversion from different integral type is supported"); static_assert(IsIntegral<Integral>::value, "only conversion from different integral type is supported");
return pack<Vector3<Integral>>(toSrgb<T>(rgb)); return pack<Vector3<Integral>>(toSrgb<T>(rgb));
} }
template<class T, class Integral> inline Vector4<Integral> toSrgbAlphaIntegral(const Color4<T>& rgba) { template<class T, class Integral> inline Vector4<Integral> toSrgbAlphaIntegral(const Color4<T>& rgba) {
static_assert(std::is_integral<Integral>::value, "only conversion from different integral type is supported"); static_assert(IsIntegral<Integral>::value, "only conversion from different integral type is supported");
return pack<Vector4<Integral>>(toSrgbAlpha<T>(rgba)); return pack<Vector4<Integral>>(toSrgbAlpha<T>(rgba));
} }
/* CIE XYZ -> RGB conversion */ /* CIE XYZ -> RGB conversion */
template<class T> typename std::enable_if<std::is_floating_point<T>::value, Color3<T>>::type fromXyz(const Vector3<T>& xyz) { template<class T> typename std::enable_if<IsFloatingPoint<T>::value, Color3<T>>::type fromXyz(const Vector3<T>& xyz) {
/* Taken from https://en.wikipedia.org/wiki/Talk:SRGB#Rounded_vs._Exact, /* Taken from https://en.wikipedia.org/wiki/Talk:SRGB#Rounded_vs._Exact,
the rounded matrices from the main article don't round-trip perfectly */ the rounded matrices from the main article don't round-trip perfectly */
return Matrix3x3<T>{ return Matrix3x3<T>{
@ -177,12 +177,12 @@ template<class T> typename std::enable_if<std::is_floating_point<T>::value, Colo
Vector3<T>{T(-329)/T(214), T(1648619)/T(878810), T(-2585)/T(12673)}, Vector3<T>{T(-329)/T(214), T(1648619)/T(878810), T(-2585)/T(12673)},
Vector3<T>{T(-1974)/T(3959), T(36519)/T(878810), T(705)/T(667)}}*xyz; Vector3<T>{T(-1974)/T(3959), T(36519)/T(878810), T(705)/T(667)}}*xyz;
} }
template<class T> inline typename std::enable_if<std::is_integral<T>::value, Color3<T>>::type fromXyz(const Vector3<typename Color3<T>::FloatingPointType>& xyz) { template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color3<T>>::type fromXyz(const Vector3<typename Color3<T>::FloatingPointType>& xyz) {
return pack<Color3<T>>(fromXyz<typename Color3<T>::FloatingPointType>(xyz)); return pack<Color3<T>>(fromXyz<typename Color3<T>::FloatingPointType>(xyz));
} }
/* RGB -> CIE XYZ conversion */ /* RGB -> CIE XYZ conversion */
template<class T> Vector3<typename Color3<T>::FloatingPointType> toXyz(typename std::enable_if<std::is_floating_point<T>::value, const Color3<T>&>::type rgb) { template<class T> Vector3<typename Color3<T>::FloatingPointType> toXyz(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type rgb) {
/* Taken from https://en.wikipedia.org/wiki/Talk:SRGB#Rounded_vs._Exact, /* Taken from https://en.wikipedia.org/wiki/Talk:SRGB#Rounded_vs._Exact,
the rounded matrices from the main article don't round-trip perfectly */ the rounded matrices from the main article don't round-trip perfectly */
return (Matrix3x3<T>{ return (Matrix3x3<T>{
@ -190,7 +190,7 @@ template<class T> Vector3<typename Color3<T>::FloatingPointType> toXyz(typename
Vector3<T>{T(87881)/T(245763), T(175762)/T(245763), T(87881)/T(737289)}, Vector3<T>{T(87881)/T(245763), T(175762)/T(245763), T(87881)/T(737289)},
Vector3<T>{T(12673)/T(70218), T(12673)/T(175545), T(1001167)/T(1053270)}})*rgb; Vector3<T>{T(12673)/T(70218), T(12673)/T(175545), T(1001167)/T(1053270)}})*rgb;
} }
template<class T> inline Vector3<typename Color3<T>::FloatingPointType> toXyz(typename std::enable_if<std::is_integral<T>::value, const Color3<T>&>::type rgb) { template<class T> inline Vector3<typename Color3<T>::FloatingPointType> toXyz(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type rgb) {
return toXyz<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(rgb)); return toXyz<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(rgb));
} }
@ -202,10 +202,10 @@ template<class T> inline Vector3<typename Color3<T>::FloatingPointType> toXyz(ty
projects created directly using VS (enabled by default since 15.5) but not projects created directly using VS (enabled by default since 15.5) but not
projects using CMake. Not using SFINAE in this case makes it work. Minimal projects using CMake. Not using SFINAE in this case makes it work. Minimal
repro case here: https://twitter.com/czmosra/status/1039446378248896513 */ repro case here: https://twitter.com/czmosra/status/1039446378248896513 */
template<class T> constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type fullChannel() { template<class T> constexpr typename std::enable_if<IsFloatingPoint<T>::value, T>::type fullChannel() {
return T(1); return T(1);
} }
template<class T> constexpr typename std::enable_if<std::is_integral<T>::value, T>::type fullChannel() { template<class T> constexpr typename std::enable_if<IsIntegral<T>::value, T>::type fullChannel() {
return Implementation::bitMax<T>(); return Implementation::bitMax<T>();
} }
#else #else

Loading…
Cancel
Save