ConvectionKernels_IndexSelectorHDR.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #pragma once
  2. #ifndef __CVTT_INDEXSELECTORHDR_H__
  3. #define __CVTT_INDEXSELECTORHDR_H__
  4. #include "ConvectionKernels_ParallelMath.h"
  5. #include "ConvectionKernels_IndexSelector.h"
  6. namespace cvtt
  7. {
  8. namespace Internal
  9. {
  10. ParallelMath::SInt16 UnscaleHDRValueSigned(const ParallelMath::SInt16 &v);
  11. ParallelMath::UInt15 UnscaleHDRValueUnsigned(const ParallelMath::UInt16 &v);
  12. template<int TVectorSize>
  13. class IndexSelectorHDR : public IndexSelector<TVectorSize>
  14. {
  15. public:
  16. typedef ParallelMath::UInt15 MUInt15;
  17. typedef ParallelMath::UInt16 MUInt16;
  18. typedef ParallelMath::UInt31 MUInt31;
  19. typedef ParallelMath::SInt16 MSInt16;
  20. typedef ParallelMath::SInt32 MSInt32;
  21. typedef ParallelMath::Float MFloat;
  22. private:
  23. MUInt15 InvertSingle(const MUInt15& anIndex) const
  24. {
  25. MUInt15 inverted = m_maxValueMinusOne - anIndex;
  26. return ParallelMath::Select(m_isInverted, inverted, anIndex);
  27. }
  28. void ReconstructHDRSignedUninverted(const MUInt15 &index, MSInt16* pixel) const
  29. {
  30. MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9));
  31. for (int ch = 0; ch < TVectorSize; ch++)
  32. {
  33. MSInt16 ep0 = ParallelMath::LosslessCast<MSInt16>::Cast(this->m_endPoint[0][ch]);
  34. MSInt16 ep1 = ParallelMath::LosslessCast<MSInt16>::Cast(this->m_endPoint[1][ch]);
  35. MSInt32 pixel32 = ParallelMath::XMultiply((ParallelMath::MakeUInt15(64) - weight), ep0) + ParallelMath::XMultiply(weight, ep1);
  36. pixel32 = ParallelMath::RightShift(pixel32 + ParallelMath::MakeSInt32(32), 6);
  37. pixel[ch] = UnscaleHDRValueSigned(ParallelMath::ToSInt16(pixel32));
  38. }
  39. }
  40. void ReconstructHDRUnsignedUninverted(const MUInt15 &index, MSInt16* pixel) const
  41. {
  42. MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9));
  43. for (int ch = 0; ch < TVectorSize; ch++)
  44. {
  45. MUInt16 ep0 = ParallelMath::LosslessCast<MUInt16>::Cast(this->m_endPoint[0][ch]);
  46. MUInt16 ep1 = ParallelMath::LosslessCast<MUInt16>::Cast(this->m_endPoint[1][ch]);
  47. MUInt31 pixel31 = ParallelMath::XMultiply((ParallelMath::MakeUInt15(64) - weight), ep0) + ParallelMath::XMultiply(weight, ep1);
  48. pixel31 = ParallelMath::RightShift(pixel31 + ParallelMath::MakeUInt31(32), 6);
  49. pixel[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(UnscaleHDRValueUnsigned(ParallelMath::ToUInt16(pixel31)));
  50. }
  51. }
  52. MFloat ErrorForInterpolatorComponent(int index, int ch, const MFloat *pixel) const
  53. {
  54. MFloat diff = pixel[ch] - m_reconstructedInterpolators[index][ch];
  55. return diff * diff;
  56. }
  57. MFloat ErrorForInterpolator(int index, const MFloat *pixel) const
  58. {
  59. MFloat error = ErrorForInterpolatorComponent(index, 0, pixel);
  60. for (int ch = 1; ch < TVectorSize; ch++)
  61. error = error + ErrorForInterpolatorComponent(index, ch, pixel);
  62. return error;
  63. }
  64. public:
  65. void InitHDR(int range, bool isSigned, bool fastIndexing, const float *channelWeights)
  66. {
  67. assert(range <= 16);
  68. m_range = range;
  69. m_isInverted = ParallelMath::MakeBoolInt16(false);
  70. m_maxValueMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>(range - 1));
  71. if (!fastIndexing)
  72. {
  73. for (int i = 0; i < range; i++)
  74. {
  75. MSInt16 recon2CL[TVectorSize];
  76. if (isSigned)
  77. ReconstructHDRSignedUninverted(ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), recon2CL);
  78. else
  79. ReconstructHDRUnsignedUninverted(ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), recon2CL);
  80. for (int ch = 0; ch < TVectorSize; ch++)
  81. m_reconstructedInterpolators[i][ch] = ParallelMath::TwosCLHalfToFloat(recon2CL[ch]) * channelWeights[ch];
  82. }
  83. }
  84. }
  85. void ReconstructHDRSigned(const MUInt15 &index, MSInt16* pixel) const
  86. {
  87. ReconstructHDRSignedUninverted(InvertSingle(index), pixel);
  88. }
  89. void ReconstructHDRUnsigned(const MUInt15 &index, MSInt16* pixel) const
  90. {
  91. ReconstructHDRUnsignedUninverted(InvertSingle(index), pixel);
  92. }
  93. void ConditionalInvert(const ParallelMath::Int16CompFlag &invert)
  94. {
  95. m_isInverted = invert;
  96. }
  97. MUInt15 SelectIndexHDRSlow(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope*) const
  98. {
  99. MUInt15 index = ParallelMath::MakeUInt15(0);
  100. MFloat bestError = ErrorForInterpolator(0, pixel);
  101. for (int i = 1; i < m_range; i++)
  102. {
  103. MFloat error = ErrorForInterpolator(i, pixel);
  104. ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(error, bestError);
  105. ParallelMath::ConditionalSet(index, ParallelMath::FloatFlagToInt16(errorBetter), ParallelMath::MakeUInt15(static_cast<uint16_t>(i)));
  106. bestError = ParallelMath::Min(bestError, error);
  107. }
  108. return InvertSingle(index);
  109. }
  110. MUInt15 SelectIndexHDRFast(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope* rtn) const
  111. {
  112. return InvertSingle(this->SelectIndexLDR(pixel, rtn));
  113. }
  114. private:
  115. MFloat m_reconstructedInterpolators[16][TVectorSize];
  116. ParallelMath::Int16CompFlag m_isInverted;
  117. MUInt15 m_maxValueMinusOne;
  118. int m_range;
  119. };
  120. }
  121. }
  122. #endif