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 #ifndef LIB_JXL_NOISE_DISTRIBUTIONS_H_
7 #define LIB_JXL_NOISE_DISTRIBUTIONS_H_
8
9 // Noise distributions for testing partial_derivatives and robust_statistics.
10
11 #include <stddef.h>
12 #include <stdint.h>
13
14 #include <random> // distributions
15 #include <string>
16
17 #include "lib/jxl/common.h"
18 #include "lib/jxl/image.h"
19
20 namespace jxl {
21
22 // Unmodified input
23 struct NoiseNone {
NameNoiseNone24 std::string Name() const { return "None"; }
25
26 template <class Random>
operatorNoiseNone27 float operator()(const float in, Random* rng) const {
28 return in;
29 }
30 };
31
32 // Salt+pepper
33 class NoiseImpulse {
34 public:
NoiseImpulse(const uint32_t threshold)35 explicit NoiseImpulse(const uint32_t threshold) : threshold_(threshold) {}
Name()36 std::string Name() const { return "Impulse" + ToString(threshold_); }
37
38 // Sets pixels to 0 if rand < threshold or 1 if rand > ~threshold.
39 template <class Random>
operator()40 float operator()(const float in, Random* rng) const {
41 const uint32_t rand = (*rng)();
42 float out = 0.0f;
43 if (rand > ~threshold_) {
44 out = 1.0f;
45 }
46 if (rand > threshold_) {
47 out = in;
48 }
49 return out;
50 }
51
52 private:
53 const uint32_t threshold_;
54 };
55
56 class NoiseUniform {
57 public:
NoiseUniform(const float min,const float max_exclusive)58 NoiseUniform(const float min, const float max_exclusive)
59 : dist_(min, max_exclusive) {}
Name()60 std::string Name() const { return "Uniform" + ToString(dist_.b()); }
61
62 template <class Random>
operator()63 float operator()(const float in, Random* rng) const {
64 return in + dist_(*rng);
65 }
66
67 private:
68 mutable std::uniform_real_distribution<float> dist_;
69 };
70
71 // Additive, zero-mean Gaussian.
72 class NoiseGaussian {
73 public:
NoiseGaussian(const float stddev)74 explicit NoiseGaussian(const float stddev) : dist_(0.0f, stddev) {}
Name()75 std::string Name() const { return "Gaussian" + ToString(dist_.stddev()); }
76
77 template <class Random>
operator()78 float operator()(const float in, Random* rng) const {
79 return in + dist_(*rng);
80 }
81
82 private:
83 mutable std::normal_distribution<float> dist_;
84 };
85
86 // Integer noise is scaled by 1E-3.
87 class NoisePoisson {
88 public:
NoisePoisson(const double mean)89 explicit NoisePoisson(const double mean) : dist_(mean) {}
Name()90 std::string Name() const { return "Poisson" + ToString(dist_.mean()); }
91
92 template <class Random>
operator()93 float operator()(const float in, Random* rng) const {
94 return in + dist_(*rng) * 1E-3f;
95 }
96
97 private:
98 mutable std::poisson_distribution<int> dist_;
99 };
100
101 // Returns the result of applying the randomized "noise" function to each pixel.
102 template <class NoiseType, class Random>
AddNoise(const ImageF & in,const NoiseType & noise,Random * rng)103 ImageF AddNoise(const ImageF& in, const NoiseType& noise, Random* rng) {
104 const size_t xsize = in.xsize();
105 const size_t ysize = in.ysize();
106 ImageF out(xsize, ysize);
107 for (size_t y = 0; y < ysize; ++y) {
108 const float* JXL_RESTRICT in_row = in.ConstRow(y);
109 float* JXL_RESTRICT out_row = out.Row(y);
110 for (size_t x = 0; x < xsize; ++x) {
111 out_row[x] = noise(in_row[x], rng);
112 }
113 }
114 return out;
115 }
116
117 template <class NoiseType, class Random>
AddNoise(const Image3F & in,const NoiseType & noise,Random * rng)118 Image3F AddNoise(const Image3F& in, const NoiseType& noise, Random* rng) {
119 const size_t xsize = in.xsize();
120 const size_t ysize = in.ysize();
121 Image3F out(xsize, ysize);
122 // noise_estimator_test requires this loop order.
123 for (size_t c = 0; c < 3; ++c) {
124 for (size_t y = 0; y < ysize; ++y) {
125 const float* JXL_RESTRICT in_row = in.ConstPlaneRow(c, y);
126 float* JXL_RESTRICT out_row = out.PlaneRow(c, y);
127
128 for (size_t x = 0; x < xsize; ++x) {
129 out_row[x] = noise(in_row[x], rng);
130 }
131 }
132 }
133 return out;
134 }
135
136 } // namespace jxl
137
138 #endif // LIB_JXL_NOISE_DISTRIBUTIONS_H_
139