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