summaryrefslogtreecommitdiff
path: root/include/meson.build
blob: 2ac9a3a049f2041f13de46c7721304142889c1d4 (plain)
1
2
3
4
5
6
# SPDX-License-Identifier: CC0-1.0

libcamera_include_dir = 'libcamera'

subdir('android')
subdir('libcamera')
='#n20'>20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2024, Red Hat Inc.
 *
 * black level handling
 */

#include "black_level.h"

#include <numeric>

#include <libcamera/base/log.h>

namespace libcamera {

LOG_DEFINE_CATEGORY(IPASoftBL)

/**
 * \class BlackLevel
 * \brief Object providing black point level for software ISP
 *
 * Black level can be provided in hardware tuning files or, if no tuning file is
 * available for the given hardware, guessed automatically, with less accuracy.
 * As tuning files are not yet implemented for software ISP, BlackLevel
 * currently provides only guessed black levels.
 *
 * This class serves for tracking black level as a property of the underlying
 * hardware, not as means of enhancing a particular scene or image.
 *
 * The class is supposed to be instantiated for the given camera stream.
 * The black level can be retrieved using BlackLevel::get() method. It is
 * initially 0 and may change when updated using BlackLevel::update() method.
 */

BlackLevel::BlackLevel()
	: blackLevel_(255), blackLevelSet_(false)
{
}

/**
 * \brief Return the current black level
 *
 * \return The black level, in the range from 0 (minimum) to 255 (maximum).
 * If the black level couldn't be determined yet, return 0.
 */
uint8_t BlackLevel::get() const
{
	return blackLevelSet_ ? blackLevel_ : 0;
}

/**
 * \brief Update black level from the provided histogram
 * \param[in] yHistogram The histogram to be used for updating black level
 *
 * The black level is property of the given hardware, not image. It is updated
 * only if it has not been yet set or if it is lower than the lowest value seen
 * so far.
 */
void BlackLevel::update(SwIspStats::Histogram &yHistogram)
{
	/*
	 * The constant is selected to be "good enough", not overly conservative or
	 * aggressive. There is no magic about the given value.
	 */
	constexpr float ignoredPercentage_ = 0.02;
	const unsigned int total =
		std::accumulate(begin(yHistogram), end(yHistogram), 0);
	const unsigned int pixelThreshold = ignoredPercentage_ * total;
	const unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;
	const unsigned int currentBlackIdx = blackLevel_ / histogramRatio;

	for (unsigned int i = 0, seen = 0;
	     i < currentBlackIdx && i < SwIspStats::kYHistogramSize;
	     i++) {
		seen += yHistogram[i];
		if (seen >= pixelThreshold) {
			blackLevel_ = i * histogramRatio;
			blackLevelSet_ = true;
			LOG(IPASoftBL, Debug)
				<< "Auto-set black level: "
				<< i << "/" << SwIspStats::kYHistogramSize
				<< " (" << 100 * (seen - yHistogram[i]) / total << "% below, "
				<< 100 * seen / total << "% at or below)";
			break;
		}
	};
}
} /* namespace libcamera */