[16/19] libcamera: software_isp: Use floating point for color parameters
diff mbox series

Message ID 20240626072100.55497-17-mzamazal@redhat.com
State Superseded
Headers show
Series
  • Software ISP refactoring
Related show

Commit Message

Milan Zamazal June 26, 2024, 7:20 a.m. UTC
It's more natural to represent color gains and black level as floating
point numbers rather than using a particular pixel-related
representation.

double is used rather than float because it's a more common floating
point type in libcamera algorithms.  Otherwise there is no obvious
reason to select one over the other here.

The constructed color tables still use integer representation for
efficiency.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
---
 src/ipa/simple/algorithms/blc.cpp    |  8 ++++----
 src/ipa/simple/algorithms/colors.cpp | 26 ++++++++++++++------------
 src/ipa/simple/ipa_context.h         |  8 ++++----
 3 files changed, 22 insertions(+), 20 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/simple/algorithms/blc.cpp b/src/ipa/simple/algorithms/blc.cpp
index e216138d..82c89dbb 100644
--- a/src/ipa/simple/algorithms/blc.cpp
+++ b/src/ipa/simple/algorithms/blc.cpp
@@ -26,7 +26,7 @@  int BlackLevel::init(IPAContext &context,
 {
 	context.configuration.black.set = false;
 	context.configuration.black.changed = true;
-	context.configuration.black.level = 255;
+	context.configuration.black.level = 1.0;
 	return 0;
 }
 
@@ -51,16 +51,16 @@  void BlackLevel::process(IPAContext &context,
 	const unsigned int total =
 		std::accumulate(begin(histogram), end(histogram), 0);
 	const unsigned int pixelThreshold = ignoredPercentage_ * total;
-	const unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;
 	const unsigned int currentBlackIdx =
-		context.configuration.black.level / histogramRatio;
+		context.configuration.black.level * SwIspStats::kYHistogramSize;
 
 	for (unsigned int i = 0, seen = 0;
 	     i < currentBlackIdx && i < SwIspStats::kYHistogramSize;
 	     i++) {
 		seen += histogram[i];
 		if (seen >= pixelThreshold) {
-			context.configuration.black.level = i * histogramRatio;
+			context.configuration.black.level =
+				static_cast<double>(i) / SwIspStats::kYHistogramSize;
 			context.configuration.black.changed = true;
 			LOG(IPASoftBL, Debug)
 				<< "Auto-set black level: "
diff --git a/src/ipa/simple/algorithms/colors.cpp b/src/ipa/simple/algorithms/colors.cpp
index d4ab409c..726835d9 100644
--- a/src/ipa/simple/algorithms/colors.cpp
+++ b/src/ipa/simple/algorithms/colors.cpp
@@ -36,7 +36,7 @@  int Colors::init(IPAContext &context,
 	updateGammaTable(context);
 
 	auto &gains = context.activeState.gains;
-	gains.red = gains.green = gains.blue = 256;
+	gains.red = gains.green = gains.blue = 1.0;
 
 	return 0;
 }
@@ -45,7 +45,7 @@  void Colors::updateGammaTable(IPAContext &context)
 {
 	auto &gammaTable = context.activeState.gammaTable;
 	const unsigned int blackIndex =
-		context.configuration.black.level * IPAActiveState::kGammaLookupSize / 256;
+		context.configuration.black.level * IPAActiveState::kGammaLookupSize;
 	std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, 0);
 	const float divisor = kGammaLookupSize - blackIndex - 1.0;
 	for (unsigned int i = blackIndex; i < kGammaLookupSize; i++)
@@ -65,15 +65,18 @@  void Colors::prepare(IPAContext &context,
 	auto &gains = context.activeState.gains;
 	auto &gammaTable = context.activeState.gammaTable;
 	for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {
-		constexpr unsigned int div =
-			static_cast<double>(DebayerParams::kRGBLookupSize) * 256 / kGammaLookupSize;
+		constexpr double div =
+			static_cast<double>(DebayerParams::kRGBLookupSize) / kGammaLookupSize;
 		/* Apply gamma after gain! */
 		unsigned int idx;
-		idx = std::min({ i * gains.red / div, kGammaLookupSize - 1 });
+		idx = std::min({ static_cast<unsigned int>(i * gains.red / div),
+				 kGammaLookupSize - 1 });
 		params->red[i] = gammaTable[idx];
-		idx = std::min({ i * gains.green / div, kGammaLookupSize - 1 });
+		idx = std::min({ static_cast<unsigned int>(i * gains.green / div),
+				 kGammaLookupSize - 1 });
 		params->green[i] = gammaTable[idx];
-		idx = std::min({ i * gains.blue / div, kGammaLookupSize - 1 });
+		idx = std::min({ static_cast<unsigned int>(i * gains.blue / div),
+				 kGammaLookupSize - 1 });
 		params->blue[i] = gammaTable[idx];
 	}
 }
@@ -85,7 +88,7 @@  void Colors::process(IPAContext &context,
 		     [[maybe_unused]] ControlList &metadata)
 {
 	const SwIspStats::Histogram &histogram = stats->yHistogram;
-	const uint8_t blackLevel = context.configuration.black.level;
+	const double blackLevel = context.configuration.black.level;
 
 	/*
 	 * Black level must be subtracted to get the correct AWB ratios, they
@@ -102,12 +105,11 @@  void Colors::process(IPAContext &context,
 	/*
 	 * Calculate red and blue gains for AWB.
 	 * Clamp max gain at 4.0, this also avoids 0 division.
-	 * Gain: 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.
 	 */
 	auto &gains = context.activeState.gains;
-	gains.red = sumR <= sumG / 4 ? 1024 : 256 * sumG / sumR;
-	gains.blue = sumB <= sumG / 4 ? 1024 : 256 * sumG / sumB;
-	/* Green gain is fixed to 256 */
+	gains.red = sumR <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumR;
+	gains.blue = sumB <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumB;
+	/* Green gain is fixed to 1.0 */
 
 	LOG(IPASoftColors, Debug) << "gain R/B " << gains.red << "/" << gains.blue;
 }
diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
index 991a45b1..3e0d9b51 100644
--- a/src/ipa/simple/ipa_context.h
+++ b/src/ipa/simple/ipa_context.h
@@ -20,7 +20,7 @@  namespace ipa::soft {
 struct IPASessionConfiguration {
 	float gamma;
 	struct {
-		uint8_t level;
+		double level;
 		bool set;
 		bool changed;
 	} black;
@@ -28,9 +28,9 @@  struct IPASessionConfiguration {
 
 struct IPAActiveState {
 	struct {
-		unsigned int red;
-		unsigned int green;
-		unsigned int blue;
+		double red;
+		double green;
+		double blue;
 	} gains;
 	static constexpr unsigned int kGammaLookupSize = 1024;
 	std::array<double, kGammaLookupSize> gammaTable;