blend.hpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #pragma once
  2. namespace nall {
  3. auto image::impose(blend mode, unsigned targetX, unsigned targetY, image source, unsigned sourceX, unsigned sourceY, unsigned sourceWidth, unsigned sourceHeight) -> void {
  4. source.transform(_endian, _depth, _alpha.mask(), _red.mask(), _green.mask(), _blue.mask());
  5. for(unsigned y = 0; y < sourceHeight; y++) {
  6. const uint8_t* sp = source._data + source.pitch() * (sourceY + y) + source.stride() * sourceX;
  7. uint8_t* dp = _data + pitch() * (targetY + y) + stride() * targetX;
  8. for(unsigned x = 0; x < sourceWidth; x++) {
  9. uint64_t sourceColor = source.read(sp);
  10. uint64_t targetColor = read(dp);
  11. int64_t sa = (sourceColor & _alpha.mask()) >> _alpha.shift();
  12. int64_t sr = (sourceColor & _red.mask() ) >> _red.shift();
  13. int64_t sg = (sourceColor & _green.mask()) >> _green.shift();
  14. int64_t sb = (sourceColor & _blue.mask() ) >> _blue.shift();
  15. int64_t da = (targetColor & _alpha.mask()) >> _alpha.shift();
  16. int64_t dr = (targetColor & _red.mask() ) >> _red.shift();
  17. int64_t dg = (targetColor & _green.mask()) >> _green.shift();
  18. int64_t db = (targetColor & _blue.mask() ) >> _blue.shift();
  19. uint64_t a, r, g, b;
  20. switch(mode) {
  21. case blend::add:
  22. a = max(sa, da);
  23. r = min(_red.mask() >> _red.shift(), ((sr * sa) >> _alpha.depth()) + ((dr * da) >> _alpha.depth()));
  24. g = min(_green.mask() >> _green.shift(), ((sg * sa) >> _alpha.depth()) + ((dg * da) >> _alpha.depth()));
  25. b = min(_blue.mask() >> _blue.shift(), ((sb * sa) >> _alpha.depth()) + ((db * da) >> _alpha.depth()));
  26. break;
  27. case blend::sourceAlpha:
  28. a = max(sa, da);
  29. r = dr + (((sr - dr) * sa) >> _alpha.depth());
  30. g = dg + (((sg - dg) * sa) >> _alpha.depth());
  31. b = db + (((sb - db) * sa) >> _alpha.depth());
  32. break;
  33. case blend::sourceColor:
  34. a = sa;
  35. r = sr;
  36. g = sg;
  37. b = sb;
  38. break;
  39. case blend::targetAlpha:
  40. a = max(sa, da);
  41. r = sr + (((dr - sr) * da) >> _alpha.depth());
  42. g = sg + (((dg - sg) * da) >> _alpha.depth());
  43. b = sb + (((db - sb) * da) >> _alpha.depth());
  44. break;
  45. case blend::targetColor:
  46. a = da;
  47. r = dr;
  48. g = dg;
  49. b = db;
  50. break;
  51. }
  52. write(dp, (a << _alpha.shift()) | (r << _red.shift()) | (g << _green.shift()) | (b << _blue.shift()));
  53. sp += source.stride();
  54. dp += stride();
  55. }
  56. }
  57. }
  58. }