openMSX
PixelOperations.hh
Go to the documentation of this file.
1 #ifndef PIXELOPERATIONS_HH
2 #define PIXELOPERATIONS_HH
3 
4 #include "unreachable.hh"
5 #include "build-info.hh"
6 #include <SDL.h>
7 
8 namespace openmsx {
9 
10 template<typename Pixel> class PixelOpBase
11 {
12 public:
13  explicit PixelOpBase(const SDL_PixelFormat& format_)
14  : format(format_)
15  , blendMask(calcBlendMask())
16  {
17  }
18 
19  const SDL_PixelFormat& getSDLPixelFormat() const { return format; }
20 
21  inline int getRmask() const { return format.Rmask; }
22  inline int getGmask() const { return format.Gmask; }
23  inline int getBmask() const { return format.Bmask; }
24  inline int getAmask() const { return format.Amask; }
25  inline int getRshift() const { return format.Rshift; }
26  inline int getGshift() const { return format.Gshift; }
27  inline int getBshift() const { return format.Bshift; }
28  inline int getAshift() const { return format.Ashift; }
29  inline int getRloss() const { return format.Rloss; }
30  inline int getGloss() const { return format.Gloss; }
31  inline int getBloss() const { return format.Bloss; }
32  inline int getAloss() const { return format.Aloss; }
33 
41  inline Pixel getBlendMask() const { return blendMask; }
42 
47  static const bool IS_RGB565 = false;
48 
49 private:
50  inline Pixel calcBlendMask() const
51  {
52  int rBit = ~(getRmask() << 1) & getRmask();
53  int gBit = ~(getGmask() << 1) & getGmask();
54  int bBit = ~(getBmask() << 1) & getBmask();
55  return ~(rBit | gBit | bBit);
56  }
57 
58  const SDL_PixelFormat& format;
59 
66  const Pixel blendMask;
67 };
68 
69 // Specialization for 32bpp
70 // No need to store 'blendMask' in a member variable.
71 template<> class PixelOpBase<unsigned>
72 {
73 public:
74  explicit PixelOpBase(const SDL_PixelFormat& format_)
75  : format(format_) {}
76 
77  const SDL_PixelFormat& getSDLPixelFormat() const { return format; }
78 
79  inline int getRmask() const { return format.Rmask; }
80  inline int getGmask() const { return format.Gmask; }
81  inline int getBmask() const { return format.Bmask; }
82  inline int getAmask() const { return format.Amask; }
83  inline int getRshift() const { return format.Rshift; }
84  inline int getGshift() const { return format.Gshift; }
85  inline int getBshift() const { return format.Bshift; }
86  inline int getAshift() const { return format.Ashift; }
87  inline int getRloss() const { return 0; }
88  inline int getGloss() const { return 0; }
89  inline int getBloss() const { return 0; }
90  inline int getAloss() const { return 0; }
91 
92  inline unsigned getBlendMask() const { return 0xFEFEFEFE; }
93 
94  static const bool IS_RGB565 = false;
95 
96 private:
97  const SDL_PixelFormat& format;
98 };
99 
100 
101 #if PLATFORM_DINGUX
102 // Specialization for dingoo (16bpp)
103 // We know the exact pixel format for this platform. No need for any
104 // members in this class. All values can also be compile-time constant.
105 template<> class PixelOpBase<unsigned short>
106 {
107 public:
108  explicit PixelOpBase(const SDL_PixelFormat& /*format*/) {}
109 
110  const SDL_PixelFormat& getSDLPixelFormat() const
111  {
112  static SDL_PixelFormat format;
113  format.palette = nullptr;
114  format.BitsPerPixel = 16;
115  format.BytesPerPixel = 2;
116  format.Rloss = 3;
117  format.Gloss = 2;
118  format.Bloss = 3;
119  format.Aloss = 8;
120  format.Rshift = 0;
121  format.Gshift = 5;
122  format.Bshift = 11;
123  format.Ashift = 0;
124  format.Rmask = 0x001F;
125  format.Gmask = 0x07E0;
126  format.Bmask = 0xF800;
127  format.Amask = 0x0000;
128  return format;
129  }
130 
131  inline int getRmask() const { return 0x001F; }
132  inline int getGmask() const { return 0x07E0; }
133  inline int getBmask() const { return 0xF800; }
134  inline int getAmask() const { return 0x0000; }
135  inline int getRshift() const { return 0; }
136  inline int getGshift() const { return 5; }
137  inline int getBshift() const { return 11; }
138  inline int getAshift() const { return 0; }
139  inline int getRloss() const { return 3; }
140  inline int getGloss() const { return 2; }
141  inline int getBloss() const { return 3; }
142  inline int getAloss() const { return 8; }
143 
144  inline unsigned short getBlendMask() const { return 0xF7DE; }
145 
146  static const bool IS_RGB565 = true;
147 };
148 #endif
149 
150 
151 
152 template<typename Pixel> class PixelOperations : public PixelOpBase<Pixel>
153 {
154 public:
170 
171  explicit PixelOperations(const SDL_PixelFormat& format);
172 
175  inline unsigned red(Pixel p) const;
176  inline unsigned green(Pixel p) const;
177  inline unsigned blue(Pixel p) const;
178  inline unsigned alpha(Pixel p) const;
179 
180  // alpha is maximum
181  inline bool isFullyOpaque(Pixel p) const;
182  // alpha is minimum
183  inline bool isFullyTransparent(Pixel p) const;
184 
187  inline unsigned red256(Pixel p) const;
188  inline unsigned green256(Pixel p) const;
189  inline unsigned blue256(Pixel p) const;
190 
193  inline Pixel combine(unsigned r, unsigned g, unsigned b) const;
194  inline Pixel combine256(unsigned r, unsigned g, unsigned b) const;
195 
198  inline unsigned getMaxRed() const;
199  inline unsigned getMaxGreen() const;
200  inline unsigned getMaxBlue() const;
201 
206  template <unsigned w1, unsigned w2>
207  inline Pixel blend(Pixel p1, Pixel p2) const;
208  template <unsigned w1, unsigned w2, unsigned w3>
209  inline Pixel blend(Pixel p1, Pixel p2, Pixel p3) const;
210  template <unsigned w1, unsigned w2, unsigned w3, unsigned w4>
211  inline Pixel blend(Pixel p1, Pixel p2, Pixel p3, Pixel p4) const;
212  template <unsigned w1, unsigned w2, unsigned w3,
213  unsigned w4, unsigned w5, unsigned w6>
214  inline Pixel blend(Pixel p1, Pixel p2, Pixel p3,
215  Pixel p4, Pixel p5, Pixel p6) const;
216 
217  template <unsigned w1, unsigned w2>
218  inline Pixel blend2(const Pixel* p) const;
219  template <unsigned w1, unsigned w2, unsigned w3>
220  inline Pixel blend3(const Pixel* p) const;
221  template <unsigned w1, unsigned w2, unsigned w3, unsigned w4>
222  inline Pixel blend4(const Pixel* p) const;
223  template <unsigned w1, unsigned w2, unsigned w3,
224  unsigned w4, unsigned w5, unsigned w6>
225  inline Pixel blend6(const Pixel* p) const;
226 
235  static inline Pixel multiply(Pixel p, unsigned x);
236 
245  inline Pixel lerp(Pixel p1, Pixel p2, unsigned x) const;
246 
251  inline Pixel alphaBlend(Pixel p1, Pixel p2) const;
252 
253 private:
254  inline Pixel avgDown(Pixel p1, Pixel p2) const;
255  inline Pixel avgUp (Pixel p1, Pixel p2) const;
256 };
257 
258 
259 template <typename Pixel>
260 PixelOperations<Pixel>::PixelOperations(const SDL_PixelFormat& format_)
261  : PixelOpBase<Pixel>(format_)
262 {
263 }
264 
265 template <typename Pixel>
266 inline unsigned PixelOperations<Pixel>::red(Pixel p) const
267 {
268  if (sizeof(Pixel) == 4) {
269  return (p >> getRshift()) & 0xFF;
270  } else {
271  return (p & getRmask()) >> getRshift();
272  }
273 }
274 template <typename Pixel>
275 inline unsigned PixelOperations<Pixel>::green(Pixel p) const
276 {
277  if (sizeof(Pixel) == 4) {
278  return (p >> getGshift()) & 0xFF;
279  } else {
280  return (p & getGmask()) >> getGshift();
281  }
282 }
283 template <typename Pixel>
284 inline unsigned PixelOperations<Pixel>::blue(Pixel p) const
285 {
286  if (sizeof(Pixel) == 4) {
287  return (p >> getBshift()) & 0xFF;
288  } else {
289  return (p & getBmask()) >> getBshift();
290  }
291 }
292 template <typename Pixel>
293 inline unsigned PixelOperations<Pixel>::alpha(Pixel p) const
294 {
295  if (sizeof(Pixel) == 4) {
296  return (p >> getAshift()) & 0xFF;
297  } else {
298  UNREACHABLE; return 0;
299  //return (p & getAmask()) >> getAshift();
300  }
301 }
302 
303 template <typename Pixel>
305 {
306  if (sizeof(Pixel) == 4) {
307  return alpha(p) == 255;
308  } else {
309  return p != 0x0001;
310  }
311 }
312 template <typename Pixel>
314 {
315  if (sizeof(Pixel) == 4) {
316  return alpha(p) == 0;
317  } else {
318  return p == 0x0001;
319  }
320 }
321 
322 template <typename Pixel>
323 inline unsigned PixelOperations<Pixel>::red256(Pixel p) const
324 {
325  if (sizeof(Pixel) == 4) {
326  return (p >> getRshift()) & 0xFF;
327  } else {
328  return ((p >> getRshift()) << getRloss()) & 0xFF;
329  }
330 }
331 template <typename Pixel>
332 inline unsigned PixelOperations<Pixel>::green256(Pixel p) const
333 {
334  if (sizeof(Pixel) == 4) {
335  return (p >> getGshift()) & 0xFF;
336  } else {
337  return ((p >> getGshift()) << getGloss()) & 0xFF;
338  }
339 }
340 template <typename Pixel>
341 inline unsigned PixelOperations<Pixel>::blue256(Pixel p) const
342 {
343  if (sizeof(Pixel) == 4) {
344  return (p >> getBshift()) & 0xFF;
345  } else {
346  return ((p >> getBshift()) << getBloss()) & 0xFF;
347  }
348 }
349 
350 template <typename Pixel>
352  unsigned r, unsigned g, unsigned b) const
353 {
354  return Pixel((r << getRshift()) |
355  (g << getGshift()) |
356  (b << getBshift()));
357 }
358 
359 template <typename Pixel>
361  unsigned r, unsigned g, unsigned b) const
362 {
363  if (sizeof(Pixel) == 4) {
364  return Pixel((r << getRshift()) |
365  (g << getGshift()) |
366  (b << getBshift()));
367  } else {
368  return Pixel(((r >> getRloss()) << getRshift()) |
369  ((g >> getGloss()) << getGshift()) |
370  ((b >> getBloss()) << getBshift()));
371  }
372 }
373 
374 template <typename Pixel>
375 inline unsigned PixelOperations<Pixel>::getMaxRed() const
376 {
377  if (sizeof(Pixel) == 4) {
378  return 255;
379  } else {
380  return 255 >> getRloss();
381  }
382 }
383 template <typename Pixel>
384 inline unsigned PixelOperations<Pixel>::getMaxGreen() const
385 {
386  if (sizeof(Pixel) == 4) {
387  return 255;
388  } else {
389  return 255 >> getGloss();
390  }
391 }
392 template <typename Pixel>
393 inline unsigned PixelOperations<Pixel>::getMaxBlue() const
394 {
395  if (sizeof(Pixel) == 4) {
396  return 255;
397  } else {
398  return 255 >> getBloss();
399  }
400 }
401 
402 template<unsigned N> struct IsPow2 {
403  static const bool result = ((N & 1) == 0) && IsPow2<N / 2>::result;
404  static const unsigned log2 = 1 + IsPow2<N / 2>::log2;
405 };
406 template<> struct IsPow2<1> {
407  static const bool result = true;
408  static const unsigned log2 = 0;
409 };
410 
411 
412 template<typename Pixel>
414 {
415  // Average can be calculated as:
416  // floor((x + y) / 2.0) = (x & y) + (x ^ y) / 2
417  // see "Average of Integers" on http://aggregate.org/MAGIC/
418  return (p1 & p2) + (((p1 ^ p2) & getBlendMask()) >> 1);
419 }
420 template<typename Pixel>
421 inline Pixel PixelOperations<Pixel>::avgUp(Pixel p1, Pixel p2) const
422 {
423  // Similar to above, but rounds up
424  // ceil((x + y) / 2.0) = (x | y) - (x ^ y) / 2
425  return (p1 | p2) - (((p1 ^ p2) & getBlendMask()) >> 1);
426 }
427 
428 template<typename Pixel>
429 template<unsigned w1, unsigned w2>
431 {
432  static const unsigned total = w1 + w2;
433  if (w1 == 0) {
434  return p2;
435  } else if (w1 > w2) {
436  return blend<w2, w1>(p2, p1);
437 
438  } else if (w1 == w2) {
439  // <1,1>
440  return avgDown(p1, p2);
441  } else if ((3 * w1) == w2) {
442  // <1,3>
443  Pixel p11 = avgDown(p1, p2);
444  return avgUp(p11, p2);
445  } else if ((7 * w1) == w2) {
446  // <1,7>
447  Pixel p11 = avgDown(p1, p2);
448  Pixel p13 = avgDown(p11, p2);
449  return avgUp(p13, p2);
450  } else if ((5 * w1) == (3 * w2)) {
451  // <3,5> mix rounding up/down to get a more accurate result
452  Pixel p11 = avgUp (p1, p2);
453  Pixel p13 = avgDown(p11, p2);
454  return avgDown(p11, p13);
455 
456  } else if (!IsPow2<total>::result) {
457  // approximate with weights that sum to 256 (or 64)
458  // e.g. approximate <1,2> as <85,171> (or <21,43>)
459  // ww1 = round(256 * w1 / total) ww2 = 256 - ww1
460  static const unsigned newTotal = IS_RGB565 ? 64 : 256;
461  static const unsigned ww1 = (2 * w1 * newTotal + total) / (2 * total);
462  static const unsigned ww2 = 256 - ww1;
463  return blend<ww1, ww2>(p1, p2);
464 
465  } else if (sizeof(Pixel) == 4) {
466  unsigned l2 = IsPow2<total>::log2;
467  unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
468  (p2 & 0x00FF00FF) * w2
469  ) >> l2) & 0x00FF00FF;
470  unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
471  ((p2 & 0xFF00FF00) >> l2) * w2
472  ) & 0xFF00FF00;
473  return c1 | c2;
474 
475  } else if (IS_RGB565) {
476  if (total > 64) {
477  // reduce to maximum 6-bit
478  // note: DIV64 only exists to work around a
479  // division by zero in dead code
480  static const unsigned DIV64 = (total > 64) ? 64 : 1;
481  static const unsigned factor = total / DIV64;
482  static const unsigned round = factor / 2;
483  static const unsigned ww1 = (w1 + round) / factor;
484  static const unsigned ww2 = 64 - ww1;
485  return blend<ww1, ww2>(p1, p2);
486  } else {
487  unsigned l2 = IsPow2<total>::log2;
488  unsigned c1 = (((unsigned(p1) & 0xF81F) * w1) +
489  ((unsigned(p2) & 0xF81F) * w2)) & (0xF81F << l2);
490  unsigned c2 = (((unsigned(p1) & 0x07E0) * w1) +
491  ((unsigned(p2) & 0x07E0) * w2)) & (0x07E0 << l2);
492  return (c1 | c2) >> l2;
493  }
494 
495  } else {
496  // generic version
497  unsigned r = (red (p1) * w1 + red (p2) * w2) / total;
498  unsigned g = (green(p1) * w1 + green(p2) * w2) / total;
499  unsigned b = (blue (p1) * w1 + blue (p2) * w2) / total;
500  return combine(r, g, b);
501  }
502 }
503 
504 template <typename Pixel>
505 template <unsigned w1, unsigned w2, unsigned w3>
507 {
508  static const unsigned total = w1 + w2 + w3;
509  if ((sizeof(Pixel) == 4) && IsPow2<total>::result) {
510  unsigned l2 = IsPow2<total>::log2;
511  unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
512  (p2 & 0x00FF00FF) * w2 +
513  (p3 & 0x00FF00FF) * w3) >> l2) & 0x00FF00FF;
514  unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
515  ((p2 & 0xFF00FF00) >> l2) * w2 +
516  ((p3 & 0xFF00FF00) >> l2) * w3) & 0xFF00FF00;
517  return c1 | c2;
518  } else {
519  unsigned r = (red (p1) * w1 + red (p2) * w2 + red (p3) * w3) / total;
520  unsigned g = (green(p1) * w1 + green(p2) * w2 + green(p3) * w3) / total;
521  unsigned b = (blue (p1) * w1 + blue (p2) * w2 + blue (p3) * w3) / total;
522  return combine(r, g, b);
523  }
524 }
525 
526 template <typename Pixel>
527 template <unsigned w1, unsigned w2, unsigned w3, unsigned w4>
529  Pixel p1, Pixel p2, Pixel p3, Pixel p4) const
530 {
531  static const unsigned total = w1 + w2 + w3 + w4;
532  if ((sizeof(Pixel) == 4) && IsPow2<total>::result) {
533  unsigned l2 = IsPow2<total>::log2;
534  unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
535  (p2 & 0x00FF00FF) * w2 +
536  (p3 & 0x00FF00FF) * w3 +
537  (p4 & 0x00FF00FF) * w4) >> l2) & 0x00FF00FF;
538  unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
539  ((p2 & 0xFF00FF00) >> l2) * w2 +
540  ((p3 & 0xFF00FF00) >> l2) * w3 +
541  ((p4 & 0xFF00FF00) >> l2) * w4) & 0xFF00FF00;
542  return c1 | c2;
543  } else {
544  unsigned r = (red (p1) * w1 + red (p2) * w2 +
545  red (p3) * w3 + red (p4) * w4) / total;
546  unsigned g = (green(p1) * w1 + green(p2) * w2 +
547  green(p3) * w3 + green(p4) * w4) / total;
548  unsigned b = (blue (p1) * w1 + blue (p2) * w2 +
549  blue (p3) * w3 + blue (p4) * w4) / total;
550  return combine(r, g, b);
551  }
552 }
553 
554 template <typename Pixel>
555 template <unsigned w1, unsigned w2, unsigned w3,
556  unsigned w4, unsigned w5, unsigned w6>
558  Pixel p1, Pixel p2, Pixel p3, Pixel p4, Pixel p5, Pixel p6) const
559 {
560  static const unsigned total = w1 + w2 + w3 + w4 + w5 + w6;
561  if ((sizeof(Pixel) == 4) && IsPow2<total>::result) {
562  unsigned l2 = IsPow2<total>::log2;
563  unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
564  (p2 & 0x00FF00FF) * w2 +
565  (p3 & 0x00FF00FF) * w3 +
566  (p4 & 0x00FF00FF) * w4 +
567  (p5 & 0x00FF00FF) * w5 +
568  (p6 & 0x00FF00FF) * w6) >> l2) & 0x00FF00FF;
569  unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
570  ((p2 & 0xFF00FF00) >> l2) * w2 +
571  ((p3 & 0xFF00FF00) >> l2) * w3 +
572  ((p4 & 0xFF00FF00) >> l2) * w4 +
573  ((p5 & 0xFF00FF00) >> l2) * w5 +
574  ((p6 & 0xFF00FF00) >> l2) * w6) & 0xFF00FF00;
575  return c1 | c2;
576  } else {
577  unsigned r = (red (p1) * w1 + red (p2) * w2 +
578  red (p3) * w3 + red (p4) * w4 +
579  red (p5) * w5 + red (p6) * w6) / total;
580  unsigned g = (green(p1) * w1 + green(p2) * w2 +
581  green(p3) * w3 + green(p4) * w4 +
582  green(p5) * w5 + green(p6) * w6) / total;
583  unsigned b = (blue (p1) * w1 + blue (p2) * w2 +
584  blue (p3) * w3 + blue (p4) * w4 +
585  blue (p5) * w5 + blue (p6) * w6) / total;
586  return combine(r, g, b);
587  }
588 }
589 
590 
591 template <typename Pixel>
592 template <unsigned w1, unsigned w2>
594 {
595  return blend<w1, w2>(p[0], p[1]);
596 }
597 
598 template <typename Pixel>
599 template <unsigned w1, unsigned w2, unsigned w3>
601 {
602  return blend<w1, w2, w3>(p[0], p[1], p[2]);
603 }
604 
605 template <typename Pixel>
606 template <unsigned w1, unsigned w2, unsigned w3, unsigned w4>
608 {
609  return blend<w1, w2, w3, w4>(p[0], p[1], p[2], p[3]);
610 }
611 
612 template <typename Pixel>
613 template <unsigned w1, unsigned w2, unsigned w3,
614  unsigned w4, unsigned w5, unsigned w6>
616 {
617  return blend<w1, w2, w3, w4, w5, w6>(p[0], p[1], p[2], p[3], p[4], p[5]);
618 }
619 
620 template <typename Pixel>
622 {
623  if (sizeof(Pixel) == 4) {
624  return ((((p & 0x00FF00FF) * x) & 0xFF00FF00) >> 8)
625  | ((((p >> 8) & 0x00FF00FF) * x) & 0xFF00FF00);
626  } else {
627  UNREACHABLE; return 0;
628  }
629 }
630 
631 template <typename Pixel>
632 inline Pixel PixelOperations<Pixel>::lerp(Pixel p1, Pixel p2, unsigned x) const
633 {
634  if (sizeof(Pixel) == 4) { // 32 bpp
635  unsigned rb1 = (p1 >> 0) & 0x00FF00FF;
636  unsigned ag1 = (p1 >> 8) & 0x00FF00FF;
637  unsigned rb2 = (p2 >> 0) & 0x00FF00FF;
638  unsigned ag2 = (p2 >> 8) & 0x00FF00FF;
639 
640  // Note: the subtraction for the lower component can 'borrow' from
641  // the higher component. Though in the full calculation this error
642  // magically cancels out.
643  unsigned trb = ((rb2 - rb1) * x) >> 8;
644  unsigned tag = ((ag2 - ag1) * x) >> 0;
645 
646  unsigned rb = ((trb + rb1) << 0) & 0x00FF00FF;
647  unsigned ag = (tag + (ag1 << 8)) & 0xFF00FF00;
648 
649  return rb | ag;
650 
651  } else if (IS_RGB565) {
652  unsigned rb1 = p1 & 0xF81F;
653  unsigned rb2 = p2 & 0xF81F;
654  unsigned g1 = p1 & 0x07E0;
655  unsigned g2 = p2 & 0x07E0;
656 
657  x >>= 2;
658  unsigned trb = ((rb2 - rb1) * x) >> 6;
659  unsigned tg = ((g2 - g1 ) * x) >> 6;
660 
661  unsigned rb = (trb + rb1) & 0xF81F;
662  unsigned g = (tg + g1 ) & 0x07E0;
663 
664  return rb | g;
665 
666  } else {
667  int r1 = red(p1), r2 = red(p2);
668  int g1 = green(p1), g2 = green(p2);
669  int b1 = blue(p1), b2 = blue(p2);
670 
671  // note: '/ 256' is not the same as '>> 8' for signed numbers
672  int r = ((r2 - r1) * x) / 256 + r1;
673  int g = ((g2 - g1) * x) / 256 + g1;
674  int b = ((b2 - b1) * x) / 256 + b1;
675 
676  return combine(r, g, b);
677  }
678 }
679 
680 template <typename Pixel>
682 {
683  if (sizeof(Pixel) == 2) {
684  // TODO keep magic value in sync with OutputSurface::getKeyColor()
685  return (p1 == 0x0001) ? p2 : p1;
686  } else {
687  unsigned a = alpha(p1);
688  // Note: 'a' is [0..255], while lerp() expects [0..256].
689  // We ignore this small error.
690  return lerp(p2, p1, a);
691  }
692 }
693 
694 } // namespace openmsx
695 
696 #endif
KeyCode combine(KeyCode key, KeyCode modifier)
Convenience method to create key combinations (hides ugly casts).
Definition: Keys.hh:317
unsigned green256(Pixel p) const
Pixel blend6(const Pixel *p) const
unsigned getMaxGreen() const
Pixel combine256(unsigned r, unsigned g, unsigned b) const
const SDL_PixelFormat & getSDLPixelFormat() const
Pixel combine(unsigned r, unsigned g, unsigned b) const
Combine RGB components to a pixel.
unsigned getMaxRed() const
Get maximum component value.
unsigned red256(Pixel p) const
Same as above, but result is scaled to [0..255].
const SDL_PixelFormat & getSDLPixelFormat() const
unsigned getMaxBlue() const
bool isFullyTransparent(Pixel p) const
PixelOpBase(const SDL_PixelFormat &format_)
unsigned Pixel
static const bool result
unsigned alpha(Pixel p) const
Pixel blend(Pixel p1, Pixel p2) const
Blend the given colors into a single color.
unsigned blue256(Pixel p) const
unsigned blue(Pixel p) const
PixelOperations(const SDL_PixelFormat &format)
unsigned red(Pixel p) const
Extract RGB componts.
Pixel lerp(Pixel p1, Pixel p2, unsigned x) const
Perform linear interpolation between two pixels.
Pixel blend2(const Pixel *p) const
static Pixel multiply(Pixel p, unsigned x)
Perform a component wise multiplication of a pixel with an 8-bit fractional value: result = (pixel * ...
Pixel getBlendMask() const
Returns a constant that is useful to calculate the average of two pixel values.
Pixel alphaBlend(Pixel p1, Pixel p2) const
Perform alpha blending of two pixels.
unsigned green(Pixel p) const
bool isFullyOpaque(Pixel p) const
static const unsigned log2
void format(SectorAccessibleDisk &disk, bool dos1)
Format the given disk (= a single partition).
PixelOpBase(const SDL_PixelFormat &format_)
Pixel blend4(const Pixel *p) const
static const bool IS_RGB565
Return true if it's statically known that the pixelformat has a 5-6-5 format (not specified wihich co...
Pixel blend3(const Pixel *p) const
#define UNREACHABLE
Definition: unreachable.hh:56