libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

tone_mapping.cc (4644B)


      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 float rec2020_luminances[3] = {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   return RunOnPool(
     48       pool, 0, ib->ysize(), ThreadPool::NoInit,
     49       [&](const uint32_t y, size_t /* thread */) {
     50         float* const JXL_RESTRICT row_r = ib->color()->PlaneRow(0, y);
     51         float* const JXL_RESTRICT row_g = ib->color()->PlaneRow(1, y);
     52         float* const JXL_RESTRICT row_b = ib->color()->PlaneRow(2, y);
     53         for (size_t x = 0; x < ib->xsize(); x += Lanes(df)) {
     54           V red = Load(df, row_r + x);
     55           V green = Load(df, row_g + x);
     56           V blue = Load(df, row_b + x);
     57           tone_mapper.ToneMap(&red, &green, &blue);
     58           Store(red, df, row_r + x);
     59           Store(green, df, row_g + x);
     60           Store(blue, df, row_b + x);
     61         }
     62       },
     63       "ToneMap");
     64 }
     65 
     66 Status GamutMapFrame(ImageBundle* const ib, float preserve_saturation,
     67                      ThreadPool* const pool) {
     68   HWY_FULL(float) df;
     69   using V = decltype(Zero(df));
     70 
     71   ColorEncoding linear_rec2020;
     72   linear_rec2020.SetColorSpace(ColorSpace::kRGB);
     73   JXL_RETURN_IF_ERROR(linear_rec2020.SetPrimariesType(Primaries::k2100));
     74   JXL_RETURN_IF_ERROR(linear_rec2020.SetWhitePointType(WhitePoint::kD65));
     75   linear_rec2020.Tf().SetTransferFunction(TransferFunction::kLinear);
     76   JXL_RETURN_IF_ERROR(linear_rec2020.CreateICC());
     77   JXL_RETURN_IF_ERROR(
     78       ib->TransformTo(linear_rec2020, *JxlGetDefaultCms(), pool));
     79 
     80   JXL_RETURN_IF_ERROR(RunOnPool(
     81       pool, 0, ib->ysize(), ThreadPool::NoInit,
     82       [&](const uint32_t y, size_t /* thread*/) {
     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,
     91                    preserve_saturation);
     92           Store(red, df, row_r + x);
     93           Store(green, df, row_g + x);
     94           Store(blue, df, row_b + x);
     95         }
     96       },
     97       "GamutMap"));
     98 
     99   return true;
    100 }
    101 
    102 // NOLINTNEXTLINE(google-readability-namespace-comments)
    103 }  // namespace HWY_NAMESPACE
    104 }  // namespace jxl
    105 HWY_AFTER_NAMESPACE();
    106 
    107 #if HWY_ONCE
    108 namespace jxl {
    109 
    110 namespace {
    111 HWY_EXPORT(ToneMapFrame);
    112 HWY_EXPORT(GamutMapFrame);
    113 }  // namespace
    114 
    115 Status ToneMapTo(const std::pair<float, float> display_nits,
    116                  CodecInOut* const io, ThreadPool* const pool) {
    117   const auto tone_map_frame = HWY_DYNAMIC_DISPATCH(ToneMapFrame);
    118   for (ImageBundle& ib : io->frames) {
    119     JXL_RETURN_IF_ERROR(tone_map_frame(display_nits, &ib, pool));
    120   }
    121   io->metadata.m.SetIntensityTarget(display_nits.second);
    122   return true;
    123 }
    124 
    125 Status GamutMap(CodecInOut* const io, float preserve_saturation,
    126                 ThreadPool* const pool) {
    127   const auto gamut_map_frame = HWY_DYNAMIC_DISPATCH(GamutMapFrame);
    128   for (ImageBundle& ib : io->frames) {
    129     JXL_RETURN_IF_ERROR(gamut_map_frame(&ib, preserve_saturation, pool));
    130   }
    131   return true;
    132 }
    133 
    134 }  // namespace jxl
    135 #endif