All Classes Files Functions Variables Typedefs Pages
ColorCore.hpp
Go to the documentation of this file.
1 #pragma once
2 
12 #include <cstddef>
13 #include <cstdint>
14 #include <cstring>
15 #include <limits>
16 #include <stdexcept>
17 #include <string>
18 
19 namespace lumina {
20 
21 // forward declare half float type (see util/half.hpp)
22 class half;
23 
24 template <class T, class U>
25 inline T clamp(U v)
26 {
27  if(v > std::numeric_limits<T>::max())
28  return std::numeric_limits<T>::max();
29  else if(v < std::numeric_limits<T>::min())
30  return std::numeric_limits<T>::min();
31  else
32  return static_cast<T>(v);
33 }
34 
35 
36 namespace internal {
37 
38 
39 
40 
41 template <typename T, typename Enable = void> struct ColorTraits;
42 
43 // specialization for floating point
44 template <typename T>
45 struct ColorTraits<T,
46  typename std::enable_if<std::is_floating_point<T>::value,
47  void>::type> {
48  static constexpr bool isFloatingPoint = true;
49  static constexpr T maxColor = 1.f;
50 };
51 
52 // specialization for integral types
53 template <typename T>
54 struct ColorTraits<T,
55  typename std::enable_if<std::is_integral<T>::value,
56  void>::type> {
57  static constexpr bool isFloatingPoint = false;
58  static constexpr T maxColor = std::numeric_limits<T>::max();
59 };
60 
61 
62 
63 
64 
65 
66 template <typename T, bool Alpha>
67 struct ColorImpl;
68 
69 template <typename T>
70 struct ColorImpl<T, true> {
71  union {
72  struct {
73  T r, g, b, a;
74  };
75  T data[4];
76  };
77 
78  ColorImpl(T r, T g, T b, T a = ColorTraits<T>::maxColor)
79  : r(r), g(g), b(b), a(a) {}
80  ColorImpl() : r(T(0)), g(T(0)), b(T(0)), a(ColorTraits<T>::maxColor) {}
81 };
82 
83 template <typename T>
84 struct ColorImpl<T, false> {
85  union {
86  struct {
87  T r, g, b;
88  };
89  T data[3];
90  };
91 
92  ColorImpl(T r, T g, T b) : r(r), g(g), b(b) {}
93  ColorImpl() : r(T(0)), g(T(0)), b(T(0)) {}
94 };
95 
96 }
97 
98 template <typename T, bool A = false>
99 struct Color : public internal::ColorImpl<T, A> {
101  using type = T;
102  static constexpr bool alpha = A;
103  static constexpr int size = (A ? 4 * sizeof(T) : 3 * sizeof(T));
104 
105 
106  bool operator==(Color<T, A> other) {
107  bool same = true;
108  for(int i = 0; i < sizeof(this->data)/sizeof(this->data[0]); ++i) {
109  same = same && (this->data[i] == other.data[i]);
110  }
111  return same;
112  }
113 
114  bool operator!=(Color<T, A> other) {
115  return !(*this == other);
116  }
117 
118  T& operator[](std::size_t index) {
119  if(index >= 4)
120  throw std::out_of_range("Invalid subscript");
121  return this->data[index];
122  }
123 
124  T operator[](std::size_t index) const {
125  if(index >= 4)
126  throw std::out_of_range("Invalid subscript");
127  return this->data[index];
128  }
129 };
130 
131 
132 
133 using Color8 = Color<uint8_t>;
135 using Color16 = Color<uint16_t>;
137 using Color32 = Color<uint32_t>;
139 using Color32f = Color<float>;
141 using Color16f = Color<half>;
143 
144 
151 // template <typename Tout, typename Enable = void>
152 // Tout makeColor(float r, float g, float b, float a = 1.f);
153 
154 template <typename Tout>
155 typename std::enable_if<std::is_integral<typename Tout::type>::value,
156  Tout>::type
157 makeColor(float r, float g, float b, float a = 1.f) {
159  g * internal::ColorTraits<typename Tout::type>::maxColor,
160  b * internal::ColorTraits<typename Tout::type>::maxColor,
161  a * internal::ColorTraits<typename Tout::type>::maxColor);
162 }
163 template <typename Tout>
164 typename std::enable_if<std::is_floating_point<typename Tout::type>::value,
165  Tout>::type
166 makeColor(float r, float g, float b, float a = 1.f) {
167  return Tout(r, g, b, a);
168 }
169 
174 template <typename T>
175 float colorProportion(T v) {
176  return (v / static_cast<float>(internal::ColorTraits<T>::maxColor));
177 }
178 
179 template <typename Tout, typename Tin>
180 Tout convertChannelType(Tin in) {
181  return colorProportion(in) * internal::ColorTraits<Tout>::maxColor;
182 }
183 
191 template <typename Tdst, typename Tsrc>
192 typename std::enable_if<Tdst::A, Tdst>::type color_cast(Color<Tsrc, true> in) {
193  return Tdst(convertChannelType<typename Tdst::type>(in.r),
194  convertChannelType<typename Tdst::type>(in.g),
195  convertChannelType<typename Tdst::type>(in.b),
196  convertChannelType<typename Tdst::type>(in.a));
197 }
198 template <typename Tdst, typename Tsrc>
199 typename std::enable_if<!Tdst::A, Tdst>::type color_cast(Color<Tsrc, true> in) {
200  return Tdst(convertChannelType<typename Tdst::type>(in.r),
201  convertChannelType<typename Tdst::type>(in.g),
202  convertChannelType<typename Tdst::type>(in.b));
203 }
204 template <typename Tdst, typename Tsrc>
205 Tdst color_cast(Color<Tsrc, false> in) {
206  return Tdst(convertChannelType<typename Tdst::type>(in.r),
207  convertChannelType<typename Tdst::type>(in.g),
208  convertChannelType<typename Tdst::type>(in.b));
209 }
210 
211 
218 template <typename T>
219 Color<T, true> blendAdditive(Color<T, true> lh, Color<T, true> rh) {
220  float lha = lh.a / 255.f;
221  float rha = rh.a / 255.f;
222 
223  // The float result is implicit casted to T and will clamped automatic.
224  return Color<T, true>(lh.r * lha + rh.r * rha,
225  lh.g * lha + rh.g * rha,
226  lh.b * lha + rh.b * rha,
227  lh.a + rh.a);
228 }
229 
237 template <typename T>
238 Color<T, true> blendAlpha(Color<T, true> lh, Color<T, true> rh) {
239  float alpha = rh.a / 255.f;
240  float ainv = 1 - alpha;
241 
242  // The float result is implicit casted to T and will clamped automatic.
243  return Color<T, true>(lh.r * ainv + rh.r * alpha,
244  lh.g * ainv + rh.g * alpha,
245  lh.b * ainv + rh.b * alpha,
246  lh.a * ainv + rh.a * alpha);
247 }
248 
249 // /**
250 // * @brief Blends two colors with specific weight values
251 // * @details Each color is weighted by the given alpha parameter. Won't exceed
252 // * standard color range.
253 // */
254 // template <typename T>
255 // LColor<T> weightedBlend(LColor<T> lh,
256 // float lhAlpha,
257 // LColor<T> rh,
258 // float rhAlpha) {
259 // // normalize weight values
260 // if(lhAlpha < 0.f)
261 // lhAlpha = 0.f;
262 // if(rhAlpha < 0.f)
263 // rhAlpha = 0.f;
264 
265 // float sum = lhAlpha + rhAlpha;
266 // if(sum > 1.f) {
267 // lhAlpha /= sum;
268 // rhAlpha /= sum;
269 // }
270 
271 // return LColor<T>(lh.r * lhAlpha + rh.r * rhAlpha,
272 // lh.g * lhAlpha + rh.g * rhAlpha,
273 // lh.b * lhAlpha + rh.b * rhAlpha,
274 // lh.a * lhAlpha + rh.a * rhAlpha);
275 // }
276 
277 
278 
279 
280 
281 
282 
283 
284 
285 } // namespace lumina
Definition: ColorCore.hpp:99
Definition: ColorCore.hpp:41
Definition: ColorCore.hpp:67