diff options
author | 2022-12-14 09:37:27 -0800 | |
---|---|---|
committer | 2023-01-19 02:05:50 +0000 | |
commit | 555a06b6146d8f695a7655eb7fc17b8bb01a8af9 (patch) | |
tree | b5e3fc2c34e7c5b185ddac87788dd230e6ee1f7d /libs/jpegrecoverymap/recoverymapmath.cpp | |
parent | 1107ff3272027f7a9a9924f7da9be2ecd5e616f7 (diff) |
jpegrecoverymap: Added LUT implementations for various OETF and InvOETF functions
Instead of computing these for each pixel, these are computed once
at 10-bit precision (index from 0 to 1023) and are used to speed up
the computations.
Bug: 261877699
Test: push files from tests/data to /sdcard/Documents and then \
atest libjpegdecoder_test libjpegencoder_test libjpegrecoverymap_test
Change-Id: Ifd98a96a78bc38879a77d86ebab137a4efc8fa20
Diffstat (limited to 'libs/jpegrecoverymap/recoverymapmath.cpp')
-rw-r--r-- | libs/jpegrecoverymap/recoverymapmath.cpp | 132 |
1 files changed, 131 insertions, 1 deletions
diff --git a/libs/jpegrecoverymap/recoverymapmath.cpp b/libs/jpegrecoverymap/recoverymapmath.cpp index 7d29a3706e..64fa44b152 100644 --- a/libs/jpegrecoverymap/recoverymapmath.cpp +++ b/libs/jpegrecoverymap/recoverymapmath.cpp @@ -15,11 +15,76 @@ */ #include <cmath> - +#include <vector> #include <jpegrecoverymap/recoverymapmath.h> namespace android::recoverymap { +#define CLIP3(x, min, max) ((x) < (min)) ? (min) : ((x) > (max)) ? (max) : (x) + +constexpr size_t kPqOETFPrecision = 10; +constexpr size_t kPqOETFNumEntries = 1 << kPqOETFPrecision; + +static const std::vector<float> kPqOETF = [] { + std::vector<float> result; + float increment = 1.0 / kPqOETFNumEntries; + float value = 0.0f; + for (int idx = 0; idx < kPqOETFNumEntries; idx++, value += increment) { + result.push_back(pqOetf(value)); + } + return result; +}(); + +constexpr size_t kPqInvOETFPrecision = 10; +constexpr size_t kPqInvOETFNumEntries = 1 << kPqInvOETFPrecision; + +static const std::vector<float> kPqInvOETF = [] { + std::vector<float> result; + float increment = 1.0 / kPqInvOETFNumEntries; + float value = 0.0f; + for (int idx = 0; idx < kPqInvOETFNumEntries; idx++, value += increment) { + result.push_back(pqInvOetf(value)); + } + return result; +}(); + +constexpr size_t kHlgOETFPrecision = 10; +constexpr size_t kHlgOETFNumEntries = 1 << kHlgOETFPrecision; + +static const std::vector<float> kHlgOETF = [] { + std::vector<float> result; + float increment = 1.0 / kHlgOETFNumEntries; + float value = 0.0f; + for (int idx = 0; idx < kHlgOETFNumEntries; idx++, value += increment) { + result.push_back(hlgOetf(value)); + } + return result; +}(); + +constexpr size_t kHlgInvOETFPrecision = 10; +constexpr size_t kHlgInvOETFNumEntries = 1 << kHlgInvOETFPrecision; + +static const std::vector<float> kHlgInvOETF = [] { + std::vector<float> result; + float increment = 1.0 / kHlgInvOETFNumEntries; + float value = 0.0f; + for (int idx = 0; idx < kHlgInvOETFNumEntries; idx++, value += increment) { + result.push_back(hlgInvOetf(value)); + } + return result; +}(); + +constexpr size_t kSRGBInvOETFPrecision = 10; +constexpr size_t kSRGBInvOETFNumEntries = 1 << kSRGBInvOETFPrecision; +static const std::vector<float> kSRGBInvOETF = [] { + std::vector<float> result; + float increment = 1.0 / kSRGBInvOETFNumEntries; + float value = 0.0f; + for (int idx = 0; idx < kSRGBInvOETFNumEntries; idx++, value += increment) { + result.push_back(srgbInvOetf(value)); + } + return result; +}(); // Use Shepard's method for inverse distance weighting. For more information: // en.wikipedia.org/wiki/Inverse_distance_weighting#Shepard's_method @@ -117,6 +182,19 @@ Color srgbInvOetf(Color e_gamma) { srgbInvOetf(e_gamma.b) }}}; } +// See IEC 61966-2-1, Equations F.5 and F.6. +float srgbInvOetfLUT(float e_gamma) { + uint32_t value = static_cast<uint32_t>(e_gamma * kSRGBInvOETFNumEntries); + //TODO() : Remove once conversion modules have appropriate clamping in place + value = CLIP3(value, 0, kSRGBInvOETFNumEntries - 1); + return kSRGBInvOETF[value]; +} + +Color srgbInvOetfLUT(Color e_gamma) { + return {{{ srgbInvOetfLUT(e_gamma.r), + srgbInvOetfLUT(e_gamma.g), + srgbInvOetfLUT(e_gamma.b) }}}; +} //////////////////////////////////////////////////////////////////////////////// // Display-P3 transformations @@ -194,6 +272,18 @@ Color hlgOetf(Color e) { return {{{ hlgOetf(e.r), hlgOetf(e.g), hlgOetf(e.b) }}}; } +float hlgOetfLUT(float e) { + uint32_t value = static_cast<uint32_t>(e * kHlgOETFNumEntries); + //TODO() : Remove once conversion modules have appropriate clamping in place + value = CLIP3(value, 0, kHlgOETFNumEntries - 1); + + return kHlgOETF[value]; +} + +Color hlgOetfLUT(Color e) { + return {{{ hlgOetfLUT(e.r), hlgOetfLUT(e.g), hlgOetfLUT(e.b) }}}; +} + // See ITU-R BT.2100-2, Table 5, HLG Reference EOTF. float hlgInvOetf(float e_gamma) { if (e_gamma <= 0.5f) { @@ -209,6 +299,20 @@ Color hlgInvOetf(Color e_gamma) { hlgInvOetf(e_gamma.b) }}}; } +float hlgInvOetfLUT(float e_gamma) { + uint32_t value = static_cast<uint32_t>(e_gamma * kHlgInvOETFNumEntries); + //TODO() : Remove once conversion modules have appropriate clamping in place + value = CLIP3(value, 0, kHlgInvOETFNumEntries - 1); + + return kHlgInvOETF[value]; +} + +Color hlgInvOetfLUT(Color e_gamma) { + return {{{ hlgInvOetfLUT(e_gamma.r), + hlgInvOetfLUT(e_gamma.g), + hlgInvOetfLUT(e_gamma.b) }}}; +} + // See ITU-R BT.2100-2, Table 4, Reference PQ OETF. static const float kPqM1 = 2610.0f / 16384.0f, kPqM2 = 2523.0f / 4096.0f * 128.0f; static const float kPqC1 = 3424.0f / 4096.0f, kPqC2 = 2413.0f / 4096.0f * 32.0f, @@ -224,6 +328,18 @@ Color pqOetf(Color e) { return {{{ pqOetf(e.r), pqOetf(e.g), pqOetf(e.b) }}}; } +float pqOetfLUT(float e) { + uint32_t value = static_cast<uint32_t>(e * kPqOETFNumEntries); + //TODO() : Remove once conversion modules have appropriate clamping in place + value = CLIP3(value, 0, kPqOETFNumEntries - 1); + + return kPqOETF[value]; +} + +Color pqOetfLUT(Color e) { + return {{{ pqOetfLUT(e.r), pqOetfLUT(e.g), pqOetfLUT(e.b) }}}; +} + // Derived from the inverse of the Reference PQ OETF. static const float kPqInvA = 128.0f, kPqInvB = 107.0f, kPqInvC = 2413.0f, kPqInvD = 2392.0f, kPqInvE = 6.2773946361f, kPqInvF = 0.0126833f; @@ -244,6 +360,20 @@ Color pqInvOetf(Color e_gamma) { pqInvOetf(e_gamma.b) }}}; } +float pqInvOetfLUT(float e_gamma) { + uint32_t value = static_cast<uint32_t>(e_gamma * kPqInvOETFNumEntries); + //TODO() : Remove once conversion modules have appropriate clamping in place + value = CLIP3(value, 0, kPqInvOETFNumEntries - 1); + + return kPqInvOETF[value]; +} + +Color pqInvOetfLUT(Color e_gamma) { + return {{{ pqInvOetfLUT(e_gamma.r), + pqInvOetfLUT(e_gamma.g), + pqInvOetfLUT(e_gamma.b) }}}; +} + //////////////////////////////////////////////////////////////////////////////// // Color conversions |