// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include "SaturationCeiling.h" #include #include namespace saturation_ceiling { namespace { int Bin(int64_t value) { return static_cast(std::floor(std::log2(static_cast(value) / FLOOR) * BINS_PER_OCTAVE)); } int64_t LowerEdge(int bin) { return static_cast(std::ceil(FLOOR * std::exp2(static_cast(bin) / BINS_PER_OCTAVE))); } } // namespace void Add(Histogram &h, int64_t value) { if (value < FLOOR) return; const int b = Bin(value); if (b < N_BINS) h[b]++; } void Add(Histogram &h, const std::vector &values, const std::vector &mask) { for (size_t i = 0; i < values.size(); i++) if (i >= mask.size() || mask[i] == 0) Add(h, values[i]); } std::optional Ceiling(const Histogram &h) { for (int b = WINDOW; b < N_BINS; b++) { const uint64_t below = *std::max_element(h.begin() + b - WINDOW, h.begin() + b); if (h[b] >= MIN_PIXELS && static_cast(h[b]) > RISE * static_cast(below)) return LowerEdge(b); } return std::nullopt; } } // namespace saturation_ceiling