// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #ifndef LIB_JXL_NOISE_DISTRIBUTIONS_H_ #define LIB_JXL_NOISE_DISTRIBUTIONS_H_ // Noise distributions for testing partial_derivatives and robust_statistics. #include #include #include // distributions #include #include "lib/jxl/common.h" #include "lib/jxl/image.h" namespace jxl { // Unmodified input struct NoiseNone { std::string Name() const { return "None"; } template float operator()(const float in, Random* rng) const { return in; } }; // Salt+pepper class NoiseImpulse { public: explicit NoiseImpulse(const uint32_t threshold) : threshold_(threshold) {} std::string Name() const { return "Impulse" + ToString(threshold_); } // Sets pixels to 0 if rand < threshold or 1 if rand > ~threshold. template float operator()(const float in, Random* rng) const { const uint32_t rand = (*rng)(); float out = 0.0f; if (rand > ~threshold_) { out = 1.0f; } if (rand > threshold_) { out = in; } return out; } private: const uint32_t threshold_; }; class NoiseUniform { public: NoiseUniform(const float min, const float max_exclusive) : dist_(min, max_exclusive) {} std::string Name() const { return "Uniform" + ToString(dist_.b()); } template float operator()(const float in, Random* rng) const { return in + dist_(*rng); } private: mutable std::uniform_real_distribution dist_; }; // Additive, zero-mean Gaussian. class NoiseGaussian { public: explicit NoiseGaussian(const float stddev) : dist_(0.0f, stddev) {} std::string Name() const { return "Gaussian" + ToString(dist_.stddev()); } template float operator()(const float in, Random* rng) const { return in + dist_(*rng); } private: mutable std::normal_distribution dist_; }; // Integer noise is scaled by 1E-3. class NoisePoisson { public: explicit NoisePoisson(const double mean) : dist_(mean) {} std::string Name() const { return "Poisson" + ToString(dist_.mean()); } template float operator()(const float in, Random* rng) const { return in + dist_(*rng) * 1E-3f; } private: mutable std::poisson_distribution dist_; }; // Returns the result of applying the randomized "noise" function to each pixel. template ImageF AddNoise(const ImageF& in, const NoiseType& noise, Random* rng) { const size_t xsize = in.xsize(); const size_t ysize = in.ysize(); ImageF out(xsize, ysize); for (size_t y = 0; y < ysize; ++y) { const float* JXL_RESTRICT in_row = in.ConstRow(y); float* JXL_RESTRICT out_row = out.Row(y); for (size_t x = 0; x < xsize; ++x) { out_row[x] = noise(in_row[x], rng); } } return out; } template Image3F AddNoise(const Image3F& in, const NoiseType& noise, Random* rng) { const size_t xsize = in.xsize(); const size_t ysize = in.ysize(); Image3F out(xsize, ysize); // noise_estimator_test requires this loop order. for (size_t c = 0; c < 3; ++c) { for (size_t y = 0; y < ysize; ++y) { const float* JXL_RESTRICT in_row = in.ConstPlaneRow(c, y); float* JXL_RESTRICT out_row = out.PlaneRow(c, y); for (size_t x = 0; x < xsize; ++x) { out_row[x] = noise(in_row[x], rng); } } } return out; } } // namespace jxl #endif // LIB_JXL_NOISE_DISTRIBUTIONS_H_