tor-browser

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

epf.cc (4969B)


      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 // Edge-preserving smoothing: weighted average based on L1 patch similarity.
      7 
      8 #include "lib/jxl/epf.h"
      9 
     10 #include <algorithm>
     11 #include <cstddef>
     12 #include <cstdint>
     13 #include <cstring>
     14 
     15 #include "lib/jxl/ac_strategy.h"
     16 #include "lib/jxl/base/compiler_specific.h"
     17 #include "lib/jxl/base/rect.h"
     18 #include "lib/jxl/base/status.h"
     19 #include "lib/jxl/dec_cache.h"
     20 #include "lib/jxl/loop_filter.h"
     21 #include "lib/jxl/quantizer.h"
     22 
     23 namespace jxl {
     24 
     25 // Mirror n floats starting at *p and store them before p.
     26 JXL_INLINE void LeftMirror(float* p, size_t n) {
     27  for (size_t i = 0; i < n; i++) {
     28    *(p - 1 - i) = p[i];
     29  }
     30 }
     31 
     32 // Mirror n floats starting at *(p - n) and store them at *p.
     33 JXL_INLINE void RightMirror(float* p, size_t n) {
     34  for (size_t i = 0; i < n; i++) {
     35    p[i] = *(p - 1 - i);
     36  }
     37 }
     38 
     39 Status ComputeSigma(const LoopFilter& lf, const Rect& block_rect,
     40                    PassesDecoderState* state) {
     41  JXL_ENSURE(lf.epf_iters > 0);
     42  const AcStrategyImage& ac_strategy = state->shared->ac_strategy;
     43  const float quant_scale = state->shared->quantizer.Scale();
     44 
     45  const size_t sigma_stride = state->sigma.PixelsPerRow();
     46  const size_t sharpness_stride = state->shared->epf_sharpness.PixelsPerRow();
     47 
     48  for (size_t by = 0; by < block_rect.ysize(); ++by) {
     49    float* JXL_RESTRICT sigma_row = block_rect.Row(&state->sigma, by);
     50    const uint8_t* JXL_RESTRICT sharpness_row =
     51        block_rect.ConstRow(state->shared->epf_sharpness, by);
     52    AcStrategyRow acs_row = ac_strategy.ConstRow(block_rect, by);
     53    const int32_t* const JXL_RESTRICT row_quant =
     54        block_rect.ConstRow(state->shared->raw_quant_field, by);
     55 
     56    for (size_t bx = 0; bx < block_rect.xsize(); bx++) {
     57      AcStrategy acs = acs_row[bx];
     58      size_t llf_x = acs.covered_blocks_x();
     59      if (!acs.IsFirstBlock()) continue;
     60      // quant_scale is smaller for low quality.
     61      // quant_scale is roughly 0.08 / butteraugli score.
     62      //
     63      // row_quant is smaller for low quality.
     64      // row_quant is a quantization multiplier of form 1.0 /
     65      // row_quant[bx]
     66      //
     67      // lf.epf_quant_mul is a parameter in the format
     68      // kInvSigmaNum is a constant
     69      float sigma_quant =
     70          lf.epf_quant_mul / (quant_scale * row_quant[bx] * kInvSigmaNum);
     71      for (size_t iy = 0; iy < acs.covered_blocks_y(); iy++) {
     72        for (size_t ix = 0; ix < acs.covered_blocks_x(); ix++) {
     73          float sigma =
     74              sigma_quant *
     75              lf.epf_sharp_lut[sharpness_row[bx + ix + iy * sharpness_stride]];
     76          // Avoid infinities.
     77          sigma = std::min(-1e-4f, sigma);  // TODO(veluca): remove this.
     78          sigma_row[bx + ix + kSigmaPadding +
     79                    (iy + kSigmaPadding) * sigma_stride] = 1.0f / sigma;
     80        }
     81      }
     82      // TODO(veluca): remove this padding.
     83      // Left padding with mirroring.
     84      if (bx + block_rect.x0() == 0) {
     85        for (size_t iy = 0; iy < acs.covered_blocks_y(); iy++) {
     86          LeftMirror(
     87              sigma_row + kSigmaPadding + (iy + kSigmaPadding) * sigma_stride,
     88              kSigmaBorder);
     89        }
     90      }
     91      // Right padding with mirroring.
     92      if (bx + block_rect.x0() + llf_x ==
     93          state->shared->frame_dim.xsize_blocks) {
     94        for (size_t iy = 0; iy < acs.covered_blocks_y(); iy++) {
     95          RightMirror(sigma_row + kSigmaPadding + bx + llf_x +
     96                          (iy + kSigmaPadding) * sigma_stride,
     97                      kSigmaBorder);
     98        }
     99      }
    100      // Offsets for row copying, in blocks.
    101      size_t offset_before = bx + block_rect.x0() == 0 ? 1 : bx + kSigmaPadding;
    102      size_t offset_after =
    103          bx + block_rect.x0() + llf_x == state->shared->frame_dim.xsize_blocks
    104              ? kSigmaPadding + llf_x + bx + kSigmaBorder
    105              : kSigmaPadding + llf_x + bx;
    106      size_t num = offset_after - offset_before;
    107      // Above
    108      if (by + block_rect.y0() == 0) {
    109        for (size_t iy = 0; iy < kSigmaBorder; iy++) {
    110          memcpy(
    111              sigma_row + offset_before +
    112                  (kSigmaPadding - 1 - iy) * sigma_stride,
    113              sigma_row + offset_before + (kSigmaPadding + iy) * sigma_stride,
    114              num * sizeof(*sigma_row));
    115        }
    116      }
    117      // Below
    118      if (by + block_rect.y0() + acs.covered_blocks_y() ==
    119          state->shared->frame_dim.ysize_blocks) {
    120        for (size_t iy = 0; iy < kSigmaBorder; iy++) {
    121          memcpy(
    122              sigma_row + offset_before +
    123                  sigma_stride * (acs.covered_blocks_y() + kSigmaPadding + iy),
    124              sigma_row + offset_before +
    125                  sigma_stride *
    126                      (acs.covered_blocks_y() + kSigmaPadding - 1 - iy),
    127              num * sizeof(*sigma_row));
    128        }
    129      }
    130    }
    131  }
    132  return true;
    133 }
    134 
    135 }  // namespace jxl