transfer_function.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // ======================================================================== //
  2. // Copyright 2009-2019 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "image.h"
  18. #include "node.h"
  19. namespace oidn {
  20. __forceinline float luminance(float r, float g, float b)
  21. {
  22. return 0.212671f * r + 0.715160f * g + 0.072169f * b;
  23. }
  24. // Color transfer function base class
  25. class TransferFunction
  26. {
  27. public:
  28. virtual ~TransferFunction() = default;
  29. virtual float forward(float y) const = 0;
  30. virtual float inverse(float x) const = 0;
  31. };
  32. // HDR transfer function base class
  33. class HDRTransferFunction : public TransferFunction
  34. {
  35. protected:
  36. static constexpr float yMax = 65504.f;
  37. float exposure;
  38. float rcpExposure;
  39. public:
  40. HDRTransferFunction(float exposure = 1.f)
  41. {
  42. setExposure(exposure);
  43. }
  44. void setExposure(float exposure)
  45. {
  46. this->exposure = exposure;
  47. this->rcpExposure = (exposure != 0.f) ? (1.f / exposure) : 0.f;
  48. }
  49. };
  50. // Linear transfer function (LDR)
  51. class LinearTransferFunction : public TransferFunction
  52. {
  53. public:
  54. __forceinline float forward(float y) const override
  55. {
  56. return min(y, 1.f);
  57. }
  58. __forceinline float inverse(float x) const override
  59. {
  60. return min(x, 1.f);
  61. }
  62. };
  63. // 2.2 gamma transfer function (LDR)
  64. class GammaTransferFunction : public TransferFunction
  65. {
  66. public:
  67. __forceinline float forward(float y) const override
  68. {
  69. return min(pow(y, 1.f/2.2f), 1.f);
  70. }
  71. __forceinline float inverse(float x) const override
  72. {
  73. return min(pow(x, 2.2f), 1.f);
  74. }
  75. };
  76. // Logarithmic transfer function (HDR)
  77. // Compresses [0..65504] to [0..1]
  78. class LogTransferFunction : public HDRTransferFunction
  79. {
  80. private:
  81. static const float xScale;
  82. public:
  83. LogTransferFunction(float exposure = 1.f)
  84. : HDRTransferFunction(exposure)
  85. {
  86. }
  87. __forceinline float forward(float y) const override
  88. {
  89. return log(y * exposure + 1.f) * xScale;
  90. }
  91. __forceinline float inverse(float x) const override
  92. {
  93. return (exp(x * (1.f/xScale)) - 1.f) * rcpExposure;
  94. }
  95. };
  96. // PQX transfer function (HDR)
  97. // Compresses [0..65504] to [0..1]
  98. class PQXTransferFunction : public HDRTransferFunction
  99. {
  100. private:
  101. static constexpr float m1 = 2610.f / 4096.f / 4.f;
  102. static constexpr float m2 = 2523.f / 4096.f * 128.f;
  103. static constexpr float c1 = 3424.f / 4096.f;
  104. static constexpr float c2 = 2413.f / 4096.f * 32.f;
  105. static constexpr float c3 = 2392.f / 4096.f * 32.f;
  106. static constexpr float a = 3711.f / 4096.f / 8.f;
  107. static constexpr float yScale = 100.f / 10000.f;
  108. static const float xScale;
  109. public:
  110. PQXTransferFunction(float exposure = 1.f)
  111. : HDRTransferFunction(exposure)
  112. {
  113. }
  114. __forceinline float forward(float y) const override
  115. {
  116. return pqxForward(y * exposure * yScale) * xScale;
  117. }
  118. __forceinline float inverse(float x) const override
  119. {
  120. return pqxInverse(x * (1.f/xScale)) * (1.f/yScale) * rcpExposure;
  121. }
  122. private:
  123. static __forceinline float pqForward(float y)
  124. {
  125. const float yp = pow(y, m1);
  126. return pow((c1 + c2 * yp) * rcp(1.f + c3 * yp), m2);
  127. }
  128. static __forceinline float pqxForward(float y)
  129. {
  130. if (y <= 1.f)
  131. return pqForward(y);
  132. else
  133. return a * log(y) + 1.f;
  134. }
  135. static __forceinline float pqInverse(float x)
  136. {
  137. const float xp = pow(x, 1.f/m2);
  138. return pow(max((xp - c1) * rcp(c2 - c3 * xp), 0.f), 1.f/m1);
  139. }
  140. static __forceinline float pqxInverse(float x)
  141. {
  142. if (x <= 1.f)
  143. return pqInverse(x);
  144. else
  145. return exp((x - 1.f) * (1.f/a));
  146. }
  147. };
  148. // Autoexposure node
  149. class AutoexposureNode : public Node
  150. {
  151. private:
  152. Image color;
  153. std::shared_ptr<HDRTransferFunction> transferFunc;
  154. public:
  155. AutoexposureNode(const Image& color,
  156. const std::shared_ptr<HDRTransferFunction>& transferFunc)
  157. : color(color),
  158. transferFunc(transferFunc)
  159. {}
  160. void execute(stream& sm) override
  161. {
  162. const float exposure = autoexposure(color);
  163. //printf("exposure = %f\n", exposure);
  164. transferFunc->setExposure(exposure);
  165. }
  166. private:
  167. static float autoexposure(const Image& color);
  168. };
  169. } // namespace oidn