tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

tone_mapping.cc (4738B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #include "lib/extras/tone_mapping.h"
      7 
      8 #undef HWY_TARGET_INCLUDE
      9 #define HWY_TARGET_INCLUDE "lib/extras/tone_mapping.cc"
     10 #include <jxl/cms.h>
     11 
     12 #include <hwy/foreach_target.h>
     13 #include <hwy/highway.h>
     14 
     15 #include "lib/jxl/cms/tone_mapping-inl.h"
     16 #include "lib/jxl/image_bundle.h"
     17 
     18 HWY_BEFORE_NAMESPACE();
     19 namespace jxl {
     20 namespace HWY_NAMESPACE {
     21 
     22 static constexpr Vector3 rec2020_luminances{0.2627f, 0.6780f, 0.0593f};
     23 
     24 Status ToneMapFrame(const std::pair<float, float> display_nits,
     25                    ImageBundle* const ib, ThreadPool* const pool) {
     26  // Perform tone mapping as described in Report ITU-R BT.2390-8, section 5.4
     27  // (pp. 23-25).
     28  // https://www.itu.int/pub/R-REP-BT.2390-8-2020
     29 
     30  HWY_FULL(float) df;
     31  using V = decltype(Zero(df));
     32 
     33  ColorEncoding linear_rec2020;
     34  linear_rec2020.SetColorSpace(ColorSpace::kRGB);
     35  JXL_RETURN_IF_ERROR(linear_rec2020.SetPrimariesType(Primaries::k2100));
     36  JXL_RETURN_IF_ERROR(linear_rec2020.SetWhitePointType(WhitePoint::kD65));
     37  linear_rec2020.Tf().SetTransferFunction(TransferFunction::kLinear);
     38  JXL_RETURN_IF_ERROR(linear_rec2020.CreateICC());
     39  JXL_RETURN_IF_ERROR(
     40      ib->TransformTo(linear_rec2020, *JxlGetDefaultCms(), pool));
     41 
     42  Rec2408ToneMapper<decltype(df)> tone_mapper(
     43      {ib->metadata()->tone_mapping.min_nits,
     44       ib->metadata()->IntensityTarget()},
     45      display_nits, rec2020_luminances);
     46 
     47  const auto process_row = [&](const uint32_t y,
     48                               size_t /* thread */) -> Status {
     49    float* const JXL_RESTRICT row_r = ib->color()->PlaneRow(0, y);
     50    float* const JXL_RESTRICT row_g = ib->color()->PlaneRow(1, y);
     51    float* const JXL_RESTRICT row_b = ib->color()->PlaneRow(2, y);
     52    for (size_t x = 0; x < ib->xsize(); x += Lanes(df)) {
     53      V red = Load(df, row_r + x);
     54      V green = Load(df, row_g + x);
     55      V blue = Load(df, row_b + x);
     56      tone_mapper.ToneMap(&red, &green, &blue);
     57      Store(red, df, row_r + x);
     58      Store(green, df, row_g + x);
     59      Store(blue, df, row_b + x);
     60    }
     61    return true;
     62  };
     63  JXL_RETURN_IF_ERROR(RunOnPool(pool, 0, ib->ysize(), ThreadPool::NoInit,
     64                                process_row, "ToneMap"));
     65  return true;
     66 }
     67 
     68 Status GamutMapFrame(ImageBundle* const ib, float preserve_saturation,
     69                     ThreadPool* const pool) {
     70  HWY_FULL(float) df;
     71  using V = decltype(Zero(df));
     72 
     73  ColorEncoding linear_rec2020;
     74  linear_rec2020.SetColorSpace(ColorSpace::kRGB);
     75  JXL_RETURN_IF_ERROR(linear_rec2020.SetPrimariesType(Primaries::k2100));
     76  JXL_RETURN_IF_ERROR(linear_rec2020.SetWhitePointType(WhitePoint::kD65));
     77  linear_rec2020.Tf().SetTransferFunction(TransferFunction::kLinear);
     78  JXL_RETURN_IF_ERROR(linear_rec2020.CreateICC());
     79  JXL_RETURN_IF_ERROR(
     80      ib->TransformTo(linear_rec2020, *JxlGetDefaultCms(), pool));
     81 
     82  const auto process_row = [&](const uint32_t y, size_t /* thread*/) -> Status {
     83    float* const JXL_RESTRICT row_r = ib->color()->PlaneRow(0, y);
     84    float* const JXL_RESTRICT row_g = ib->color()->PlaneRow(1, y);
     85    float* const JXL_RESTRICT row_b = ib->color()->PlaneRow(2, y);
     86    for (size_t x = 0; x < ib->xsize(); x += Lanes(df)) {
     87      V red = Load(df, row_r + x);
     88      V green = Load(df, row_g + x);
     89      V blue = Load(df, row_b + x);
     90      GamutMap(&red, &green, &blue, rec2020_luminances, preserve_saturation);
     91      Store(red, df, row_r + x);
     92      Store(green, df, row_g + x);
     93      Store(blue, df, row_b + x);
     94    }
     95    return true;
     96  };
     97 
     98  JXL_RETURN_IF_ERROR(RunOnPool(pool, 0, ib->ysize(), ThreadPool::NoInit,
     99                                process_row, "GamutMap"));
    100 
    101  return true;
    102 }
    103 
    104 // NOLINTNEXTLINE(google-readability-namespace-comments)
    105 }  // namespace HWY_NAMESPACE
    106 }  // namespace jxl
    107 HWY_AFTER_NAMESPACE();
    108 
    109 #if HWY_ONCE
    110 namespace jxl {
    111 
    112 namespace {
    113 HWY_EXPORT(ToneMapFrame);
    114 HWY_EXPORT(GamutMapFrame);
    115 }  // namespace
    116 
    117 Status ToneMapTo(const std::pair<float, float> display_nits,
    118                 CodecInOut* const io, ThreadPool* const pool) {
    119  const auto tone_map_frame = HWY_DYNAMIC_DISPATCH(ToneMapFrame);
    120  for (ImageBundle& ib : io->frames) {
    121    JXL_RETURN_IF_ERROR(tone_map_frame(display_nits, &ib, pool));
    122  }
    123  io->metadata.m.SetIntensityTarget(display_nits.second);
    124  return true;
    125 }
    126 
    127 Status GamutMap(CodecInOut* const io, float preserve_saturation,
    128                ThreadPool* const pool) {
    129  const auto gamut_map_frame = HWY_DYNAMIC_DISPATCH(GamutMapFrame);
    130  for (ImageBundle& ib : io->frames) {
    131    JXL_RETURN_IF_ERROR(gamut_map_frame(&ib, preserve_saturation, pool));
    132  }
    133  return true;
    134 }
    135 
    136 }  // namespace jxl
    137 #endif