1 #ifndef PIXELOPERATIONS_HH
2 #define PIXELOPERATIONS_HH
16 , blendMask(calcBlendMask())
51 [[nodiscard]]
inline Pixel calcBlendMask()
const
56 return ~(rBit | gBit | bBit);
68 const Pixel blendMask;
89 [[nodiscard]]
inline int getRloss()
const {
return 0; }
90 [[nodiscard]]
inline int getGloss()
const {
return 0; }
91 [[nodiscard]]
inline int getBloss()
const {
return 0; }
92 [[nodiscard]]
inline int getAloss()
const {
return 0; }
94 [[nodiscard]]
inline unsigned getBlendMask()
const {
return 0xFEFEFEFE; }
114 static PixelFormat format(16,
122 [[nodiscard]]
inline int getRmask()
const {
return 0x001F; }
123 [[nodiscard]]
inline int getGmask()
const {
return 0x07E0; }
124 [[nodiscard]]
inline int getBmask()
const {
return 0xF800; }
125 [[nodiscard]]
inline int getAmask()
const {
return 0x0000; }
126 [[nodiscard]]
inline int getRshift()
const {
return 0; }
127 [[nodiscard]]
inline int getGshift()
const {
return 5; }
128 [[nodiscard]]
inline int getBshift()
const {
return 11; }
129 [[nodiscard]]
inline int getAshift()
const {
return 0; }
130 [[nodiscard]]
inline int getRloss()
const {
return 3; }
131 [[nodiscard]]
inline int getGloss()
const {
return 2; }
132 [[nodiscard]]
inline int getBloss()
const {
return 3; }
133 [[nodiscard]]
inline int getAloss()
const {
return 8; }
135 [[nodiscard]]
inline uint16_t
getBlendMask()
const {
return 0xF7DE; }
184 [[nodiscard]]
inline Pixel combine(
unsigned r,
unsigned g,
unsigned b)
const;
197 template<
unsigned w1,
unsigned w2>
199 template<
unsigned w1,
unsigned w2,
unsigned w3>
201 template<
unsigned w1,
unsigned w2,
unsigned w3,
unsigned w4>
203 template<
unsigned w1,
unsigned w2,
unsigned w3,
204 unsigned w4,
unsigned w5,
unsigned w6>
208 template<
unsigned w1,
unsigned w2>
210 template<
unsigned w1,
unsigned w2,
unsigned w3>
212 template<
unsigned w1,
unsigned w2,
unsigned w3,
unsigned w4>
214 template<
unsigned w1,
unsigned w2,
unsigned w3,
215 unsigned w4,
unsigned w5,
unsigned w6>
250 template<
typename Pixel>
256 template<
typename Pixel>
259 if constexpr (
sizeof(
Pixel) == 4) {
260 return (p >> getRshift()) & 0xFF;
262 return (p & getRmask()) >> getRshift();
265 template<
typename Pixel>
268 if constexpr (
sizeof(
Pixel) == 4) {
269 return (p >> getGshift()) & 0xFF;
271 return (p & getGmask()) >> getGshift();
274 template<
typename Pixel>
277 if constexpr (
sizeof(
Pixel) == 4) {
278 return (p >> getBshift()) & 0xFF;
280 return (p & getBmask()) >> getBshift();
283 template<
typename Pixel>
286 if constexpr (
sizeof(
Pixel) == 4) {
287 return (p >> getAshift()) & 0xFF;
294 template<
typename Pixel>
297 if constexpr (
sizeof(
Pixel) == 4) {
298 return alpha(p) == 255;
303 template<
typename Pixel>
306 if constexpr (
sizeof(
Pixel) == 4) {
307 return alpha(p) == 0;
313 template<
typename Pixel>
316 if constexpr (
sizeof(
Pixel) == 4) {
317 return (p >> getRshift()) & 0xFF;
319 return ((p >> getRshift()) << getRloss()) & 0xFF;
322 template<
typename Pixel>
325 if constexpr (
sizeof(
Pixel) == 4) {
326 return (p >> getGshift()) & 0xFF;
328 return ((p >> getGshift()) << getGloss()) & 0xFF;
331 template<
typename Pixel>
334 if constexpr (
sizeof(
Pixel) == 4) {
335 return (p >> getBshift()) & 0xFF;
337 return ((p >> getBshift()) << getBloss()) & 0xFF;
341 template<
typename Pixel>
343 unsigned r,
unsigned g,
unsigned b)
const
345 return Pixel((r << getRshift()) |
350 template<
typename Pixel>
352 unsigned r,
unsigned g,
unsigned b)
const
354 if constexpr (
sizeof(
Pixel) == 4) {
355 return Pixel((r << getRshift()) |
359 return Pixel(((r >> getRloss()) << getRshift()) |
360 ((
g >> getGloss()) << getGshift()) |
361 ((b >> getBloss()) << getBshift()));
365 template<
typename Pixel>
368 if constexpr (
sizeof(
Pixel) == 4) {
371 return 255 >> getRloss();
374 template<
typename Pixel>
377 if constexpr (
sizeof(
Pixel) == 4) {
380 return 255 >> getGloss();
383 template<
typename Pixel>
386 if constexpr (
sizeof(
Pixel) == 4) {
389 return 255 >> getBloss();
393 template<
typename Pixel>
399 return (p1 & p2) + (((p1 ^ p2) & getBlendMask()) >> 1);
401 template<
typename Pixel>
406 return (p1 | p2) - (((p1 ^ p2) & getBlendMask()) >> 1);
409 template<
typename Pixel>
410 template<
unsigned w1,
unsigned w2>
413 constexpr
unsigned total = w1 + w2;
414 if constexpr (w1 == 0) {
416 }
else if constexpr (w1 > w2) {
417 return blend<w2, w1>(p2, p1);
419 }
else if constexpr (w1 == w2) {
421 return avgDown(p1, p2);
422 }
else if constexpr ((3 * w1) == w2) {
424 Pixel p11 = avgDown(p1, p2);
425 return avgUp(p11, p2);
426 }
else if constexpr ((7 * w1) == w2) {
428 Pixel p11 = avgDown(p1, p2);
429 Pixel p13 = avgDown(p11, p2);
430 return avgUp(p13, p2);
431 }
else if constexpr ((5 * w1) == (3 * w2)) {
433 Pixel p11 = avgUp (p1, p2);
434 Pixel p13 = avgDown(p11, p2);
435 return avgDown(p11, p13);
441 constexpr
unsigned newTotal = IS_RGB565 ? 64 : 256;
442 constexpr
unsigned ww1 = (2 * w1 * newTotal + total) / (2 * total);
443 constexpr
unsigned ww2 = 256 - ww1;
444 return blend<ww1, ww2>(p1, p2);
446 }
else if constexpr (
sizeof(
Pixel) == 4) {
448 unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
449 (p2 & 0x00FF00FF) * w2
450 ) >> l2) & 0x00FF00FF;
451 unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
452 ((p2 & 0xFF00FF00) >> l2) * w2
456 }
else if constexpr (IS_RGB565) {
457 if constexpr (total > 64) {
461 constexpr
unsigned DIV64 = (total > 64) ? 64 : 1;
462 constexpr
unsigned factor = total / DIV64;
463 constexpr
unsigned round = factor / 2;
464 constexpr
unsigned ww1 = (w1 + round) / factor;
465 constexpr
unsigned ww2 = 64 - ww1;
466 return blend<ww1, ww2>(p1, p2);
469 unsigned c1 = (((unsigned(p1) & 0xF81F) * w1) +
470 ((unsigned(p2) & 0xF81F) * w2)) & (0xF81F << l2);
471 unsigned c2 = (((unsigned(p1) & 0x07E0) * w1) +
472 ((unsigned(p2) & 0x07E0) * w2)) & (0x07E0 << l2);
473 return (c1 | c2) >> l2;
478 unsigned r = (red (p1) * w1 + red (p2) * w2) / total;
479 unsigned g = (green(p1) * w1 + green(p2) * w2) / total;
480 unsigned b = (blue (p1) * w1 + blue (p2) * w2) / total;
485 template<
typename Pixel>
486 template<
unsigned w1,
unsigned w2,
unsigned w3>
489 constexpr
unsigned total = w1 + w2 +
w3;
492 unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
493 (p2 & 0x00FF00FF) * w2 +
494 (
p3 & 0x00FF00FF) *
w3) >> l2) & 0x00FF00FF;
495 unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
496 ((p2 & 0xFF00FF00) >> l2) * w2 +
497 ((
p3 & 0xFF00FF00) >> l2) *
w3) & 0xFF00FF00;
500 unsigned r = (red (p1) * w1 + red (p2) * w2 + red (
p3) *
w3) / total;
501 unsigned g = (green(p1) * w1 + green(p2) * w2 + green(
p3) *
w3) / total;
502 unsigned b = (blue (p1) * w1 + blue (p2) * w2 + blue (
p3) *
w3) / total;
507 template<
typename Pixel>
508 template<
unsigned w1,
unsigned w2,
unsigned w3,
unsigned w4>
512 constexpr
unsigned total = w1 + w2 +
w3 +
w4;
515 unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
516 (p2 & 0x00FF00FF) * w2 +
517 (
p3 & 0x00FF00FF) *
w3 +
518 (
p4 & 0x00FF00FF) *
w4) >> l2) & 0x00FF00FF;
519 unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
520 ((p2 & 0xFF00FF00) >> l2) * w2 +
521 ((
p3 & 0xFF00FF00) >> l2) *
w3 +
522 ((
p4 & 0xFF00FF00) >> l2) *
w4) & 0xFF00FF00;
525 unsigned r = (red (p1) * w1 + red (p2) * w2 +
526 red (
p3) *
w3 + red (
p4) *
w4) / total;
527 unsigned g = (green(p1) * w1 + green(p2) * w2 +
528 green(
p3) *
w3 + green(
p4) *
w4) / total;
529 unsigned b = (blue (p1) * w1 + blue (p2) * w2 +
530 blue (
p3) *
w3 + blue (
p4) *
w4) / total;
535 template<
typename Pixel>
536 template<
unsigned w1,
unsigned w2,
unsigned w3,
537 unsigned w4,
unsigned w5,
unsigned w6>
541 constexpr
unsigned total = w1 + w2 +
w3 +
w4 + w5 + w6;
544 unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
545 (p2 & 0x00FF00FF) * w2 +
546 (
p3 & 0x00FF00FF) *
w3 +
547 (
p4 & 0x00FF00FF) *
w4 +
548 (p5 & 0x00FF00FF) * w5 +
549 (p6 & 0x00FF00FF) * w6) >> l2) & 0x00FF00FF;
550 unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
551 ((p2 & 0xFF00FF00) >> l2) * w2 +
552 ((
p3 & 0xFF00FF00) >> l2) *
w3 +
553 ((
p4 & 0xFF00FF00) >> l2) *
w4 +
554 ((p5 & 0xFF00FF00) >> l2) * w5 +
555 ((p6 & 0xFF00FF00) >> l2) * w6) & 0xFF00FF00;
558 unsigned r = (red (p1) * w1 + red (p2) * w2 +
560 red (p5) * w5 + red (p6) * w6) / total;
561 unsigned g = (green(p1) * w1 + green(p2) * w2 +
563 green(p5) * w5 + green(p6) * w6) / total;
564 unsigned b = (blue (p1) * w1 + blue (p2) * w2 +
566 blue (p5) * w5 + blue (p6) * w6) / total;
572 template<
typename Pixel>
573 template<
unsigned w1,
unsigned w2>
576 return blend<w1, w2>(p[0], p[1]);
579 template<
typename Pixel>
580 template<
unsigned w1,
unsigned w2,
unsigned w3>
583 return blend<w1, w2, w3>(p[0], p[1], p[2]);
586 template<
typename Pixel>
587 template<
unsigned w1,
unsigned w2,
unsigned w3,
unsigned w4>
590 return blend<w1, w2, w3, w4>(p[0], p[1], p[2], p[3]);
593 template<
typename Pixel>
594 template<
unsigned w1,
unsigned w2,
unsigned w3,
595 unsigned w4,
unsigned w5,
unsigned w6>
598 return blend<w1, w2, w3, w4, w5, w6>(p[0], p[1], p[2], p[3], p[4], p[5]);
601 template<
typename Pixel>
604 if constexpr (
sizeof(
Pixel) == 4) {
605 return ((((p & 0x00FF00FF) *
x) & 0xFF00FF00) >> 8)
606 | ((((p >> 8) & 0x00FF00FF) *
x) & 0xFF00FF00);
612 template<
typename Pixel>
615 if constexpr (
sizeof(
Pixel) == 4) {
616 unsigned rb1 = (p1 >> 0) & 0x00FF00FF;
617 unsigned ag1 = (p1 >> 8) & 0x00FF00FF;
618 unsigned rb2 = (p2 >> 0) & 0x00FF00FF;
619 unsigned ag2 = (p2 >> 8) & 0x00FF00FF;
624 unsigned trb = ((rb2 - rb1) *
x) >> 8;
625 unsigned tag = ((ag2 - ag1) *
x) >> 0;
627 unsigned rb = ((trb + rb1) << 0) & 0x00FF00FF;
628 unsigned ag = (tag + (ag1 << 8)) & 0xFF00FF00;
632 }
else if constexpr (IS_RGB565) {
633 unsigned rb1 = p1 & 0xF81F;
634 unsigned rb2 = p2 & 0xF81F;
635 unsigned g1 = p1 & 0x07E0;
636 unsigned g2 = p2 & 0x07E0;
639 unsigned trb = ((rb2 - rb1) *
x) >> 6;
640 unsigned tg = ((g2 - g1 ) *
x) >> 6;
642 unsigned rb = (trb + rb1) & 0xF81F;
643 unsigned g = (tg + g1 ) & 0x07E0;
648 int r1 = red(p1), r2 = red(p2);
649 int g1 = green(p1), g2 = green(p2);
650 int b1 = blue(p1), b2 = blue(p2);
653 int r = ((r2 - r1) *
x) / 256 + r1;
654 int g = ((g2 - g1) *
x) / 256 + g1;
655 int b = ((b2 - b1) *
x) / 256 + b1;
661 template<
typename Pixel>
664 if constexpr (
sizeof(
Pixel) == 2) {
666 return (p1 == 0x0001) ? p2 : p1;
668 unsigned a = alpha(p1);
671 return lerp(p2, p1, a);
PixelOpBase(const PixelFormat &format_)
const PixelFormat & getPixelFormat() const
unsigned getBlendMask() const
const PixelFormat & getPixelFormat() const
static constexpr bool IS_RGB565
Return true if it's statically known that the pixelformat has a 5-6-5 format (not specified which com...
PixelOpBase(const PixelFormat &format_)
Pixel getBlendMask() const
Returns a constant that is useful to calculate the average of two pixel values.
Pixel blend(Pixel p1, Pixel p2, Pixel p3, Pixel p4) const
static Pixel multiply(Pixel p, unsigned x)
Perform a component wise multiplication of a pixel with an 8-bit fractional value: result = (pixel * ...
unsigned getMaxRed() const
Get maximum component value.
unsigned blue256(Pixel p) const
Pixel blend(Pixel p1, Pixel p2, Pixel p3, Pixel p4, Pixel p5, Pixel p6) const
unsigned blue(Pixel p) const
unsigned getMaxGreen() const
Pixel blend4(const Pixel *p) const
Pixel blend(Pixel p1, Pixel p2) const
Blend the given colors into a single color.
Pixel blend2(const Pixel *p) const
unsigned getMaxBlue() const
Pixel blend(Pixel p1, Pixel p2, Pixel p3) const
unsigned red256(Pixel p) const
Same as above, but result is scaled to [0..255].
bool isFullyTransparent(Pixel p) const
unsigned alpha(Pixel p) const
Pixel blend3(const Pixel *p) const
unsigned green256(Pixel p) const
Pixel combine256(unsigned r, unsigned g, unsigned b) const
Pixel combine(unsigned r, unsigned g, unsigned b) const
Combine RGB components to a pixel.
Pixel blend6(const Pixel *p) const
unsigned red(Pixel p) const
Extract RGB components.
PixelOperations(const PixelFormat &format)
Pixel lerp(Pixel p1, Pixel p2, unsigned x) const
Perform linear interpolation between two pixels.
bool isFullyOpaque(Pixel p) const
unsigned green(Pixel p) const
Pixel alphaBlend(Pixel p1, Pixel p2) const
Perform alpha blending of two pixels.
mat4 p4(vec4(1, 2, 3, 4), vec4(3, 4, 5, 6), vec4(5, 0, 7, 8), vec4(7, 8, 9, 0))
mat3 p3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 0, 9))
constexpr T log2p1(T x) noexcept
Returns the number of bits needed to store the value 'x', that is: for x==0 : 0 for x!...
constexpr bool ispow2(T x) noexcept
Is the given number an integral power of two? That is, does it have exactly one 1-bit in binary repre...
KeyCode combine(KeyCode key, KeyCode modifier)
Convenience method to create key combinations (hides ugly casts).
This file implemented 3 utility functions:
constexpr KeyMatrixPosition x
Keyboard bindings.