[RFC,v2,36/43] ipa: simple: agc: Adjust histogram for black level
diff mbox series

Message ID 20260723154327.1357866-37-barnabas.pocze@ideasonboard.com
State New
Headers show
Series
  • ipa: libipa: agc rework
Related show

Commit Message

Barnabás Pőcze July 23, 2026, 3:43 p.m. UTC
Instead of providing the black separately, adjust the luminance histogram
according to the current black level. This changes the behaviour slightly
as previously everything under the black level was ignored, and only the
remaining part was split into the 5 bins, but now the full histogram is
split into the 5 bins.

TODO: or should the previous behaviour be preserved and a smaller histogram be used without adjustments?
TODO: is it `i < blackLevelHistIdx` or `i <= blackLevelHistIdx` ???

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
---
 src/ipa/simple/algorithms/agc.cpp | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp
index cc33b269bf..199b444f5a 100644
--- a/src/ipa/simple/algorithms/agc.cpp
+++ b/src/ipa/simple/algorithms/agc.cpp
@@ -11,6 +11,7 @@ 
 #include <cmath>
 #include <optional>
 #include <stdint.h>
+#include <utility>
 
 #include <libcamera/base/log.h>
 
@@ -66,19 +67,15 @@  static constexpr float kExpMaxStep = 0.15;
 
 namespace {
 
-std::optional<float> calculateMSV(const Histogram &histogram, uint8_t blackLevel)
+std::optional<float> calculateMSV(const Histogram &histogram)
 {
 	/*
 	 * Calculate Mean Sample Value (MSV) according to formula from:
 	 * https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf
 	 */
-	const unsigned int blackLevelHistIdx =
-		blackLevel * histogram.bins() / 256;
-	const unsigned int histogramSize =
-		histogram.bins() - blackLevelHistIdx;
-	const unsigned int yHistValsPerBin = histogramSize / kExposureBinsCount;
+	const unsigned int yHistValsPerBin = histogram.bins() / kExposureBinsCount;
 	const unsigned int yHistValsPerBinMod =
-		histogramSize / (histogramSize % kExposureBinsCount + 1);
+		histogram.bins() / (histogram.bins() % kExposureBinsCount + 1);
 	int exposureBins[kExposureBinsCount] = {};
 	unsigned int denom = 0;
 	unsigned int num = 0;
@@ -86,9 +83,9 @@  std::optional<float> calculateMSV(const Histogram &histogram, uint8_t blackLevel
 	if (yHistValsPerBin == 0)
 		return {};
 
-	for (unsigned int i = 0; i < histogramSize; i++) {
+	for (unsigned int i = 0; i < histogram.bins(); i++) {
 		unsigned int idx = (i - (i / yHistValsPerBinMod)) / yHistValsPerBin;
-		exposureBins[idx] += histogram[blackLevelHistIdx + i];
+		exposureBins[idx] += histogram[i];
 	}
 
 	for (unsigned int i = 0; i < kExposureBinsCount; i++) {
@@ -193,7 +190,14 @@  void Agc::process(IPAContext &context,
 		return;
 	}
 
-	auto exposureMSV = calculateMSV({ stats->yHistogram }, context.activeState.blc.level);
+	auto histogram = stats->yHistogram;
+	const unsigned int blackLevelHistIdx =
+		context.activeState.blc.level * std::size(histogram) / 256;
+
+	for (unsigned int i = 1; i < blackLevelHistIdx; i++)
+		histogram[0] += std::exchange(histogram[i], 0);
+
+	auto exposureMSV = calculateMSV({ histogram });
 	if (!exposureMSV) {
 		LOG(IPASoftExposure, Debug)
 			<< "Not adjusting exposure due to insufficient histogram data";