libjxl

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

dec_noise.cc (4219B)


      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/jxl/dec_noise.h"
      7 
      8 #include <stdint.h>
      9 #include <stdlib.h>
     10 
     11 #include <algorithm>
     12 #include <numeric>
     13 #include <utility>
     14 
     15 #undef HWY_TARGET_INCLUDE
     16 #define HWY_TARGET_INCLUDE "lib/jxl/dec_noise.cc"
     17 #include <hwy/foreach_target.h>
     18 #include <hwy/highway.h>
     19 
     20 #include "lib/jxl/base/compiler_specific.h"
     21 #include "lib/jxl/chroma_from_luma.h"
     22 #include "lib/jxl/image_ops.h"
     23 #include "lib/jxl/sanitizers.h"
     24 #include "lib/jxl/xorshift128plus-inl.h"
     25 HWY_BEFORE_NAMESPACE();
     26 namespace jxl {
     27 namespace HWY_NAMESPACE {
     28 
     29 // These templates are not found via ADL.
     30 using hwy::HWY_NAMESPACE::Or;
     31 using hwy::HWY_NAMESPACE::ShiftRight;
     32 using hwy::HWY_NAMESPACE::Vec;
     33 
     34 using D = HWY_CAPPED(float, kBlockDim);
     35 using DI = hwy::HWY_NAMESPACE::Rebind<int, D>;
     36 using DI8 = hwy::HWY_NAMESPACE::Repartition<uint8_t, D>;
     37 
     38 // Converts one vector's worth of random bits to floats in [1, 2).
     39 // NOTE: as the convolution kernel sums to 0, it doesn't matter if inputs are in
     40 // [0, 1) or in [1, 2).
     41 void BitsToFloat(const uint32_t* JXL_RESTRICT random_bits,
     42                  float* JXL_RESTRICT floats) {
     43   const HWY_FULL(float) df;
     44   const HWY_FULL(uint32_t) du;
     45 
     46   const auto bits = Load(du, random_bits);
     47   // 1.0 + 23 random mantissa bits = [1, 2)
     48   const auto rand12 = BitCast(df, Or(ShiftRight<9>(bits), Set(du, 0x3F800000)));
     49   Store(rand12, df, floats);
     50 }
     51 
     52 void RandomImage(Xorshift128Plus* rng, const Rect& rect,
     53                  ImageF* JXL_RESTRICT noise) {
     54   const size_t xsize = rect.xsize();
     55   const size_t ysize = rect.ysize();
     56 
     57   // May exceed the vector size, hence we have two loops over x below.
     58   constexpr size_t kFloatsPerBatch =
     59       Xorshift128Plus::N * sizeof(uint64_t) / sizeof(float);
     60   HWY_ALIGN uint64_t batch[Xorshift128Plus::N] = {};
     61 
     62   const HWY_FULL(float) df;
     63   const size_t N = Lanes(df);
     64 
     65   for (size_t y = 0; y < ysize; ++y) {
     66     float* JXL_RESTRICT row = rect.Row(noise, y);
     67 
     68     size_t x = 0;
     69     // Only entire batches (avoids exceeding the image padding).
     70     for (; x + kFloatsPerBatch < xsize; x += kFloatsPerBatch) {
     71       rng->Fill(batch);
     72       for (size_t i = 0; i < kFloatsPerBatch; i += Lanes(df)) {
     73         BitsToFloat(reinterpret_cast<const uint32_t*>(batch) + i, row + x + i);
     74       }
     75     }
     76 
     77     // Any remaining pixels, rounded up to vectors (safe due to padding).
     78     rng->Fill(batch);
     79     size_t batch_pos = 0;  // < kFloatsPerBatch
     80     for (; x < xsize; x += N) {
     81       BitsToFloat(reinterpret_cast<const uint32_t*>(batch) + batch_pos,
     82                   row + x);
     83       batch_pos += N;
     84     }
     85   }
     86 }
     87 void Random3Planes(size_t visible_frame_index, size_t nonvisible_frame_index,
     88                    size_t x0, size_t y0, const std::pair<ImageF*, Rect>& plane0,
     89                    const std::pair<ImageF*, Rect>& plane1,
     90                    const std::pair<ImageF*, Rect>& plane2) {
     91   HWY_ALIGN Xorshift128Plus rng(visible_frame_index, nonvisible_frame_index, x0,
     92                                 y0);
     93   RandomImage(&rng, plane0.second, plane0.first);
     94   RandomImage(&rng, plane1.second, plane1.first);
     95   RandomImage(&rng, plane2.second, plane2.first);
     96 }
     97 
     98 // NOLINTNEXTLINE(google-readability-namespace-comments)
     99 }  // namespace HWY_NAMESPACE
    100 }  // namespace jxl
    101 HWY_AFTER_NAMESPACE();
    102 
    103 #if HWY_ONCE
    104 namespace jxl {
    105 
    106 HWY_EXPORT(Random3Planes);
    107 void Random3Planes(size_t visible_frame_index, size_t nonvisible_frame_index,
    108                    size_t x0, size_t y0, const std::pair<ImageF*, Rect>& plane0,
    109                    const std::pair<ImageF*, Rect>& plane1,
    110                    const std::pair<ImageF*, Rect>& plane2) {
    111   HWY_DYNAMIC_DISPATCH(Random3Planes)
    112   (visible_frame_index, nonvisible_frame_index, x0, y0, plane0, plane1, plane2);
    113 }
    114 
    115 void DecodeFloatParam(float precision, float* val, BitReader* br) {
    116   const int absval_quant = br->ReadFixedBits<10>();
    117   *val = absval_quant / precision;
    118 }
    119 
    120 Status DecodeNoise(BitReader* br, NoiseParams* noise_params) {
    121   for (float& i : noise_params->lut) {
    122     DecodeFloatParam(kNoisePrecision, &i, br);
    123   }
    124   return true;
    125 }
    126 
    127 }  // namespace jxl
    128 #endif  // HWY_ONCE