Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f25991f3 authored by Harish Mahendrakar's avatar Harish Mahendrakar Committed by Dichen Zhang
Browse files

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
parent 96de8374
Loading
Loading
Loading
Loading
+29 −1
Original line number Diff line number Diff line
@@ -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 @@ inline Color operator/(const Color& lhs, const float rhs) {
  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 @@ struct ShepardsIDW {
  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 @@ uint8_t encodeRecovery(float y_sdr, float y_hdr, float hdr_ratio);
 * 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.
+8 −2
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ namespace android::recoverymap {
#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 @@ status_t RecoveryMap::applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_
  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 @@ status_t RecoveryMap::applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_
            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);

+5 −2
Original line number Diff line number Diff line
@@ -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 @@ Color applyRecovery(Color e, float recovery, float hdr_ratio) {
  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;

+19 −0
Original line number Diff line number Diff line
@@ -557,6 +557,25 @@ TEST_F(RecoveryMapMathTest, srgbInvOetfLUT) {
    }
}

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());