156 行
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. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <lol/main.h>
  14. /*
  15. * Image merge operations: merge, min/max, overlay, screen, multiply,
  16. * divide, add, sub, difference
  17. */
  18. namespace lol
  19. {
  20. enum class MergeMode
  21. {
  22. Mix,
  23. Min,
  24. Max,
  25. Overlay,
  26. Screen,
  27. Divide,
  28. Multiply,
  29. Add,
  30. Sub,
  31. Difference,
  32. };
  33. template<PixelFormat FORMAT, MergeMode MODE>
  34. static Image GenericMerge(Image &src1, Image &src2, float alpha)
  35. {
  36. typedef typename PixelType<FORMAT>::type pixel_t;
  37. ASSERT(src1.GetSize() == src2.GetSize());
  38. int const count = src1.GetSize().x * src2.GetSize().y;
  39. Image dst(src1.GetSize());
  40. pixel_t const *src1p = src1.Lock<FORMAT>();
  41. pixel_t const *src2p = src2.Lock<FORMAT>();
  42. pixel_t *dstp = dst.Lock<FORMAT>();
  43. for (int n = 0; n < count; ++n)
  44. {
  45. if (MODE == MergeMode::Mix)
  46. dstp[n] = lol::mix(src1p[n], src2p[n], alpha);
  47. else if (MODE == MergeMode::Min)
  48. dstp[n] = lol::min(src1p[n], src2p[n]);
  49. else if (MODE == MergeMode::Max)
  50. dstp[n] = lol::max(src1p[n], src2p[n]);
  51. else if (MODE == MergeMode::Overlay)
  52. dstp[n] = src1p[n] * (src1p[n] + 2.f * src2p[n]
  53. * (pixel_t(1.f) - src1p[n]));
  54. else if (MODE == MergeMode::Screen)
  55. dstp[n] = src1p[n] + src2p[n] - src1p[n] * src2p[n];
  56. else if (MODE == MergeMode::Divide)
  57. dstp[n] = src1p[n] / (lol::max(src1p[n], src2p[n]) + pixel_t(1e-8f));
  58. else if (MODE == MergeMode::Multiply)
  59. dstp[n] = src1p[n] * src2p[n];
  60. else if (MODE == MergeMode::Add)
  61. dstp[n] = lol::min(src1p[n] + src2p[n], pixel_t(1.f));
  62. else if (MODE == MergeMode::Sub)
  63. dstp[n] = lol::max(src1p[n] - src2p[n], pixel_t(0.f));
  64. else if (MODE == MergeMode::Difference)
  65. dstp[n] = lol::abs(src1p[n] - src2p[n]);
  66. }
  67. src1.Unlock(src1p);
  68. src2.Unlock(src2p);
  69. dst.Unlock(dstp);
  70. return dst;
  71. }
  72. template<MergeMode MODE>
  73. static Image GenericMerge(Image &src1, Image &src2, float alpha)
  74. {
  75. bool gray1 = src1.GetFormat() == PixelFormat::Y_8
  76. || src1.GetFormat() == PixelFormat::Y_F32;
  77. bool gray2 = src2.GetFormat() == PixelFormat::Y_8
  78. || src2.GetFormat() == PixelFormat::Y_F32;
  79. if (gray1 && gray2)
  80. return GenericMerge<PixelFormat::Y_F32, MODE>(src1, src2, alpha);
  81. else
  82. return GenericMerge<PixelFormat::RGBA_F32, MODE>(src1, src2, alpha);
  83. }
  84. Image Image::Merge(Image &src1, Image &src2, float alpha)
  85. {
  86. return GenericMerge<MergeMode::Mix>(src1, src2, alpha);
  87. }
  88. Image Image::Mean(Image &src1, Image &src2)
  89. {
  90. return GenericMerge<MergeMode::Mix>(src1, src2, 0.5f);
  91. }
  92. Image Image::Min(Image &src1, Image &src2)
  93. {
  94. return GenericMerge<MergeMode::Min>(src1, src2, 0.0f);
  95. }
  96. Image Image::Max(Image &src1, Image &src2)
  97. {
  98. return GenericMerge<MergeMode::Max>(src1, src2, 0.0f);
  99. }
  100. Image Image::Overlay(Image &src1, Image &src2)
  101. {
  102. return GenericMerge<MergeMode::Overlay>(src1, src2, 0.0f);
  103. }
  104. Image Image::Screen(Image &src1, Image &src2)
  105. {
  106. return GenericMerge<MergeMode::Screen>(src1, src2, 0.0f);
  107. }
  108. Image Image::Divide(Image &src1, Image &src2)
  109. {
  110. return GenericMerge<MergeMode::Divide>(src1, src2, 0.0f);
  111. }
  112. Image Image::Multiply(Image &src1, Image &src2)
  113. {
  114. return GenericMerge<MergeMode::Multiply>(src1, src2, 0.0f);
  115. }
  116. Image Image::Add(Image &src1, Image &src2)
  117. {
  118. return GenericMerge<MergeMode::Add>(src1, src2, 0.0f);
  119. }
  120. Image Image::Sub(Image &src1, Image &src2)
  121. {
  122. return GenericMerge<MergeMode::Sub>(src1, src2, 0.0f);
  123. }
  124. Image Image::Difference(Image &src1, Image &src2)
  125. {
  126. return GenericMerge<MergeMode::Difference>(src1, src2, 0.0f);
  127. }
  128. } /* namespace lol */