15 using Uint8 = std::uint8_t;
19 min(Uint8 lhs, Uint8 rhs)
21 return (lhs < rhs) ? lhs : rhs;
26 max(Uint8 lhs, Uint8 rhs)
28 return (lhs > rhs) ? lhs : rhs;
41 if(i < 0) {
return 0; }
42 else if(i > 255) {
return 255; }
43 else {
return static_cast<Uint8
>(
i); }
54 Uint8 channel_blend_normal(Uint8 top, Uint8)
60 Uint8 channel_blend_lighten(Uint8 top, Uint8 bottom)
62 return (bottom > top) ? bottom : top;
66 Uint8 channel_blend_darken(Uint8 top, Uint8 bottom)
68 return (bottom > top) ? top : bottom;
72 Uint8 channel_blend_multiply(Uint8 top, Uint8 bottom)
74 return c_u8(
static_cast<float>(
static_cast<int>(top) *
static_cast<int>(bottom)) / 255.0f);
78 Uint8 channel_blend_average(Uint8 top, Uint8 bottom)
80 return c_u8(
static_cast<float>(
static_cast<int>(top) +
static_cast<int>(bottom)) / 2.0f);
84 Uint8 channel_blend_add(Uint8 top, Uint8 bottom)
86 const auto sum =
static_cast<int>(top) +
static_cast<int>(bottom);
91 Uint8 channel_blend_subtract(Uint8 top, Uint8 bottom)
93 return c_u8(
static_cast<int>(top) +
static_cast<int>(bottom) - 255);
97 Uint8 channel_blend_difference(Uint8 top, Uint8 bottom)
99 return c_u8(
static_cast<int>(top) -
static_cast<int>(bottom));
103 Uint8 channel_blend_negation(Uint8 top, Uint8 bottom)
105 return 255 -
abs(255 - top - bottom);
109 Uint8 channel_blend_screen(Uint8 top, Uint8 bottom)
111 return 255 - (((255 - top) * (255 - bottom)) >> 8);
115 Uint8 channel_blend_exclusion(Uint8 top, Uint8 bottom)
117 return top + bottom - 2 * top * bottom / 255;
121 Uint8 channel_blend_overlay(Uint8 top, Uint8 bottom)
125 return 2 * top * bottom / 255;
129 return 255 - 2 * (255 - top) * (255 - bottom) / 255;
134 Uint8 channel_blend_soft_light(Uint8 top, Uint8 bottom)
136 const int magic = (top>>1)+64;
140 const auto r = 2.0f *
c_int_to_float(magic) *
static_cast<float>(bottom) / 255.0f;
145 const auto r = 2.0f * (255.0f-
c_int_to_float(magic)) *
static_cast<float>(255-bottom) / 255.0f;
146 return c_u8(255.0f - r);
151 Uint8 channel_blend_hard_light(Uint8 top, Uint8 bottom)
153 const auto swapped_top = bottom;
154 const auto swapped_bottom = top;
155 return channel_blend_overlay(swapped_top, swapped_bottom);
159 Uint8 channel_blend_color_dodge(Uint8 top, Uint8 bottom)
167 return min(255, ((top << 8 ) / (255 - bottom)));
172 Uint8 channel_blend_color_burn(Uint8 top, Uint8 bottom)
180 return max(0, (255 - ((255 - top) << 8 ) / bottom));
185 Uint8 channel_blend_linear_dodge(Uint8 top, Uint8 bottom)
187 return channel_blend_add(top, bottom);
191 Uint8 channel_blend_linear_burn(Uint8 top, Uint8 bottom)
193 return channel_blend_subtract(top, bottom);
197 Uint8 channel_blend_linear_light(Uint8 top, Uint8 bottom)
201 return channel_blend_linear_burn(top, (2 * bottom));
205 return channel_blend_linear_dodge(top, (2 * (bottom - 128)));
210 Uint8 channel_blend_vivid_light(Uint8 top, Uint8 bottom)
214 return channel_blend_color_burn(top, (2 * bottom));
218 return channel_blend_color_dodge(top, (2 * (bottom - 128)));
223 Uint8 channel_blend_pin_light(Uint8 top, Uint8 bottom)
227 return channel_blend_darken(top, (2 * bottom));
231 return channel_blend_lighten(top, (2 * (bottom - 128)));
236 Uint8 channel_blend_hard_mix(Uint8 top, Uint8 bottom)
238 if(channel_blend_vivid_light(top, bottom) < 128)
249 Uint8 channel_blend_reflect(Uint8 top, Uint8 bottom)
257 return min(255, (top * top / (255 - bottom)));
262 Uint8 channel_blend_glow(Uint8 top, Uint8 bottom)
264 const auto swapped_top = bottom;
265 const auto swapped_bottom = top;
266 return channel_blend_reflect(swapped_top, swapped_bottom);
270 Uint8 channel_blend_phoenix(Uint8 top, Uint8 bottom)
272 return min(top,bottom) -
max(top,bottom) + 255;
280 channel_blend_alpha(Uint8 top, Uint8 bottom,
float factor)
282 return c_u8(factor *
static_cast<float>(top) + (1.0f - factor) *
static_cast<float>(bottom));
286 template<
typename TF>
288 channel_blend_alpha_f(Uint8 top, Uint8 bottom,
float factor, TF f)
290 return channel_blend_alpha(
f(top, bottom), bottom, factor);
294 template<
typename TBlendFunction>
296 blend(
const Rgbi& top,
const Rgbi& bottom, TBlendFunction blend_function)
300 blend_function(top.r, bottom.r),
301 blend_function(top.g, bottom.g),
302 blend_function(top.b, bottom.b),
307 template<
typename TBlendFunction>
309 blend(
const Rgb& top,
const Rgb& bottom, TBlendFunction blend_function)
317 alpha_blend(T lhs, T rhs,
float a)
319 return static_cast<T
>(lhs * (1-
a) + rhs * a);
323 template<
typename TBlendFunction>
329 TBlendFunction blend_function
332 const auto factor =
static_cast<float>(top.a)/255.0f;
333 const auto ff = [&](Uint8 a_top, Uint8 a_bottom)
335 return channel_blend_alpha_f
350 alpha_blend(top.a, bottom.a, 1-factor)
355 template<
typename TBlendFunction>
357 blend(
const Rgba& top,
const Rgba& bottom, TBlendFunction blend_function)
365 color_blend(
BlendMode mode,
const C& top,
const C& bottom)
395 DIE(
"unhandled blend case");
Rgb blend(const Rgb &top, const Rgb &bottom, BlendMode mode)
Rgbai to_rgbai(const Rgba &c)
Rgbi to_rgbi(const Rgb &c)
constexpr int c_float_to_int(float f)
Rgb to_rgb(const Rgbi &c)
constexpr float abs(float r)
constexpr float c_int_to_float(int i)
size2f min(const size2f lhs, const size2f rhs)
Rgba to_rgba(const Rgbai &c)
size2f max(const size2f lhs, const size2f rhs)