You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

152 lines
4.0 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #include <lol/engine-internal.h>
  11. /*
  12. * Image merge operations: merge, min/max, overlay, screen, multiply,
  13. * divide, add, sub, difference
  14. */
  15. namespace lol
  16. {
  17. enum class MergeMode
  18. {
  19. Mix,
  20. Min,
  21. Max,
  22. Overlay,
  23. Screen,
  24. Divide,
  25. Multiply,
  26. Add,
  27. Sub,
  28. Difference,
  29. };
  30. template<PixelFormat FORMAT, MergeMode MODE>
  31. static Image GenericMerge(Image &src1, Image &src2, float alpha)
  32. {
  33. typedef typename PixelType<FORMAT>::type pixel_t;
  34. ASSERT(src1.GetSize() == src2.GetSize());
  35. int const count = src1.GetSize().x * src2.GetSize().y;
  36. Image dst(src1.GetSize());
  37. pixel_t const *src1p = src1.Lock<FORMAT>();
  38. pixel_t const *src2p = src2.Lock<FORMAT>();
  39. pixel_t *dstp = dst.Lock<FORMAT>();
  40. for (int n = 0; n < count; ++n)
  41. {
  42. if (MODE == MergeMode::Mix)
  43. dstp[n] = lol::mix(src1p[n], src2p[n], alpha);
  44. else if (MODE == MergeMode::Min)
  45. dstp[n] = lol::min(src1p[n], src2p[n]);
  46. else if (MODE == MergeMode::Max)
  47. dstp[n] = lol::max(src1p[n], src2p[n]);
  48. else if (MODE == MergeMode::Overlay)
  49. dstp[n] = src1p[n] * (src1p[n] + 2.f * src2p[n]
  50. * (pixel_t(1.f) - src1p[n]));
  51. else if (MODE == MergeMode::Screen)
  52. dstp[n] = src1p[n] + src2p[n] - src1p[n] * src2p[n];
  53. else if (MODE == MergeMode::Divide)
  54. dstp[n] = src1p[n] / (lol::max(src1p[n], src2p[n]) + pixel_t(1e-8f));
  55. else if (MODE == MergeMode::Multiply)
  56. dstp[n] = src1p[n] * src2p[n];
  57. else if (MODE == MergeMode::Add)
  58. dstp[n] = lol::min(src1p[n] + src2p[n], pixel_t(1.f));
  59. else if (MODE == MergeMode::Sub)
  60. dstp[n] = lol::max(src1p[n] - src2p[n], pixel_t(0.f));
  61. else if (MODE == MergeMode::Difference)
  62. dstp[n] = lol::abs(src1p[n] - src2p[n]);
  63. }
  64. src1.Unlock(src1p);
  65. src2.Unlock(src2p);
  66. dst.Unlock(dstp);
  67. return dst;
  68. }
  69. template<MergeMode MODE>
  70. static Image GenericMerge(Image &src1, Image &src2, float alpha)
  71. {
  72. bool gray1 = src1.GetFormat() == PixelFormat::Y_8
  73. || src1.GetFormat() == PixelFormat::Y_F32;
  74. bool gray2 = src2.GetFormat() == PixelFormat::Y_8
  75. || src2.GetFormat() == PixelFormat::Y_F32;
  76. if (gray1 && gray2)
  77. return GenericMerge<PixelFormat::Y_F32, MODE>(src1, src2, alpha);
  78. else
  79. return GenericMerge<PixelFormat::RGBA_F32, MODE>(src1, src2, alpha);
  80. }
  81. Image Image::Merge(Image &src1, Image &src2, float alpha)
  82. {
  83. return GenericMerge<MergeMode::Mix>(src1, src2, alpha);
  84. }
  85. Image Image::Mean(Image &src1, Image &src2)
  86. {
  87. return GenericMerge<MergeMode::Mix>(src1, src2, 0.5f);
  88. }
  89. Image Image::Min(Image &src1, Image &src2)
  90. {
  91. return GenericMerge<MergeMode::Min>(src1, src2, 0.0f);
  92. }
  93. Image Image::Max(Image &src1, Image &src2)
  94. {
  95. return GenericMerge<MergeMode::Max>(src1, src2, 0.0f);
  96. }
  97. Image Image::Overlay(Image &src1, Image &src2)
  98. {
  99. return GenericMerge<MergeMode::Overlay>(src1, src2, 0.0f);
  100. }
  101. Image Image::Screen(Image &src1, Image &src2)
  102. {
  103. return GenericMerge<MergeMode::Screen>(src1, src2, 0.0f);
  104. }
  105. Image Image::Divide(Image &src1, Image &src2)
  106. {
  107. return GenericMerge<MergeMode::Divide>(src1, src2, 0.0f);
  108. }
  109. Image Image::Multiply(Image &src1, Image &src2)
  110. {
  111. return GenericMerge<MergeMode::Multiply>(src1, src2, 0.0f);
  112. }
  113. Image Image::Add(Image &src1, Image &src2)
  114. {
  115. return GenericMerge<MergeMode::Add>(src1, src2, 0.0f);
  116. }
  117. Image Image::Sub(Image &src1, Image &src2)
  118. {
  119. return GenericMerge<MergeMode::Sub>(src1, src2, 0.0f);
  120. }
  121. Image Image::Difference(Image &src1, Image &src2)
  122. {
  123. return GenericMerge<MergeMode::Difference>(src1, src2, 0.0f);
  124. }
  125. } /* namespace lol */