jpegrecoverymap: use lookup for applyRecovery
Bug: 261877699
Test: push files from tests/data to /sdcard/Documents and then \
atest libjpegdecoder_test libjpegencoder_test libjpegrecoverymap_test
Change-Id: I1fe0650d53042985839185e31a7300f0fc33dd06
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymapmath.h b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymapmath.h
index f14fafc..0695bb7 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymapmath.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymapmath.h
@@ -17,12 +17,15 @@
#ifndef ANDROID_JPEGRECOVERYMAP_RECOVERYMAPMATH_H
#define ANDROID_JPEGRECOVERYMAP_RECOVERYMAPMATH_H
+#include <cmath>
#include <stdint.h>
#include <jpegrecoverymap/recoverymap.h>
namespace android::recoverymap {
+#define CLIP3(x, min, max) ((x) < (min)) ? (min) : ((x) > (max)) ? (max) : (x)
+
////////////////////////////////////////////////////////////////////////////////
// Framework
@@ -112,6 +115,31 @@
return temp /= rhs;
}
+constexpr size_t kRecoveryFactorPrecision = 10;
+constexpr size_t kRecoveryFactorNumEntries = 1 << kRecoveryFactorPrecision;
+struct RecoveryLUT {
+ RecoveryLUT(float hdrRatio) {
+ float increment = 2.0 / kRecoveryFactorNumEntries;
+ float value = -1.0f;
+ for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++, value += increment) {
+ mRecoveryTable[idx] = pow(hdrRatio, value);
+ }
+ }
+
+ ~RecoveryLUT() {
+ }
+
+ float getRecoveryFactor(float recovery) {
+ uint32_t value = static_cast<uint32_t>(((recovery + 1.0f) / 2.0f) * kRecoveryFactorNumEntries);
+ //TODO() : Remove once conversion modules have appropriate clamping in place
+ value = CLIP3(value, 0, kRecoveryFactorNumEntries - 1);
+ return mRecoveryTable[value];
+ }
+
+private:
+ float mRecoveryTable[kRecoveryFactorNumEntries];
+};
+
struct ShepardsIDW {
ShepardsIDW(int mapScaleFactor) : mMapScaleFactor{mapScaleFactor} {
const int size = mMapScaleFactor * mMapScaleFactor * 4;
@@ -158,7 +186,6 @@
void fillShepardsIDW(float *weights, int incR, int incB);
};
-
////////////////////////////////////////////////////////////////////////////////
// sRGB transformations
// NOTE: sRGB has the same color primaries as BT.709, but different transfer
@@ -306,6 +333,7 @@
* value, with the given hdr ratio, to the given sdr input in the range [0, 1].
*/
Color applyRecovery(Color e, float recovery, float hdr_ratio);
+Color applyRecoveryLUT(Color e, float recovery, RecoveryLUT& recoveryLUT);
/*
* Helper for sampling from YUV 420 images.
diff --git a/libs/jpegrecoverymap/recoverymap.cpp b/libs/jpegrecoverymap/recoverymap.cpp
index a898f1e..ef5498c 100644
--- a/libs/jpegrecoverymap/recoverymap.cpp
+++ b/libs/jpegrecoverymap/recoverymap.cpp
@@ -46,6 +46,7 @@
#define USE_PQ_OETF_LUT 1
#define USE_HLG_INVOETF_LUT 1
#define USE_PQ_INVOETF_LUT 1
+#define USE_APPLY_RECOVERY_LUT 1
#define JPEGR_CHECK(x) \
{ \
@@ -909,10 +910,12 @@
dest->width = uncompressed_yuv_420_image->width;
dest->height = uncompressed_yuv_420_image->height;
ShepardsIDW idwTable(kMapDimensionScaleFactor);
+ RecoveryLUT recoveryLUT(metadata->rangeScalingFactor);
JobQueue jobQueue;
std::function<void()> applyRecMap = [uncompressed_yuv_420_image, uncompressed_recovery_map,
- metadata, dest, &jobQueue, &idwTable]() -> void {
+ metadata, dest, &jobQueue, &idwTable,
+ &recoveryLUT]() -> void {
const float hdr_ratio = metadata->rangeScalingFactor;
size_t width = uncompressed_yuv_420_image->width;
size_t height = uncompressed_yuv_420_image->height;
@@ -964,8 +967,11 @@
recovery = sampleMap(uncompressed_recovery_map, map_scale_factor, x, y,
idwTable);
}
+#if USE_APPLY_RECOVERY_LUT
+ Color rgb_hdr = applyRecoveryLUT(rgb_sdr, recovery, recoveryLUT);
+#else
Color rgb_hdr = applyRecovery(rgb_sdr, recovery, hdr_ratio);
-
+#endif
Color rgb_gamma_hdr = hdrOetf(rgb_hdr / metadata->rangeScalingFactor);
uint32_t rgba1010102 = colorToRgba1010102(rgb_gamma_hdr);
diff --git a/libs/jpegrecoverymap/recoverymapmath.cpp b/libs/jpegrecoverymap/recoverymapmath.cpp
index 64fa44b..4f21ac6 100644
--- a/libs/jpegrecoverymap/recoverymapmath.cpp
+++ b/libs/jpegrecoverymap/recoverymapmath.cpp
@@ -20,8 +20,6 @@
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;
@@ -481,6 +479,11 @@
return e * recoveryFactor;
}
+Color applyRecoveryLUT(Color e, float recovery, RecoveryLUT& recoveryLUT) {
+ float recoveryFactor = recoveryLUT.getRecoveryFactor(recovery);
+ return e * recoveryFactor;
+}
+
Color getYuv420Pixel(jr_uncompressed_ptr image, size_t x, size_t y) {
size_t pixel_count = image->width * image->height;
diff --git a/libs/jpegrecoverymap/tests/recoverymapmath_test.cpp b/libs/jpegrecoverymap/tests/recoverymapmath_test.cpp
index 0d0e4fc..1d522d1 100644
--- a/libs/jpegrecoverymap/tests/recoverymapmath_test.cpp
+++ b/libs/jpegrecoverymap/tests/recoverymapmath_test.cpp
@@ -557,6 +557,25 @@
}
}
+TEST_F(RecoveryMapMathTest, applyRecoveryLUT) {
+ float increment = 2.0 / kRecoveryFactorNumEntries;
+ for (float hdrRatio = 1.0f; hdrRatio <= 10.0f; hdrRatio += 1.0f) {
+ RecoveryLUT recoveryLUT(hdrRatio);
+ for (float value = -1.0f; value <= -1.0f; value += increment) {
+ EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), value, hdrRatio),
+ applyRecoveryLUT(RgbBlack(), value, recoveryLUT));
+ EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), value, hdrRatio),
+ applyRecoveryLUT(RgbWhite(), value, recoveryLUT));
+ EXPECT_RGB_NEAR(applyRecovery(RgbRed(), value, hdrRatio),
+ applyRecoveryLUT(RgbRed(), value, recoveryLUT));
+ EXPECT_RGB_NEAR(applyRecovery(RgbGreen(), value, hdrRatio),
+ applyRecoveryLUT(RgbGreen(), value, recoveryLUT));
+ EXPECT_RGB_NEAR(applyRecovery(RgbBlue(), value, hdrRatio),
+ applyRecoveryLUT(RgbBlue(), value, recoveryLUT));
+ }
+ }
+}
+
TEST_F(RecoveryMapMathTest, PqTransferFunctionRoundtrip) {
EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(0.0f)), 0.0f);
EXPECT_NEAR(pqInvOetf(pqOetf(0.01f)), 0.01f, ComparisonEpsilon());