[RFC,v2,09/13] libcamera: ipa: simple: Make gamma adjustable
diff mbox series

Message ID 20251120104548.80268-10-mzamazal@redhat.com
State New
Headers show
Series
  • Simple pipeline IPA cleanup
Related show

Commit Message

Milan Zamazal Nov. 20, 2025, 10:45 a.m. UTC
The gamma value is fixed in software ISP.  Let's make it adjustable,
similarly to contrast and saturation.

The default gamma value is changed from 1/2.0 to a more common value
1/2.2, which is used in GPU ISP.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
---
 src/ipa/simple/algorithms/adjust.cpp | 8 ++++++++
 src/ipa/simple/algorithms/adjust.h   | 2 ++
 src/ipa/simple/algorithms/lut.cpp    | 9 ++++++---
 src/ipa/simple/ipa_context.h         | 3 +++
 4 files changed, 19 insertions(+), 3 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/simple/algorithms/adjust.cpp b/src/ipa/simple/algorithms/adjust.cpp
index 49fa98c9d..600fd3c7b 100644
--- a/src/ipa/simple/algorithms/adjust.cpp
+++ b/src/ipa/simple/algorithms/adjust.cpp
@@ -23,6 +23,7 @@  LOG_DEFINE_CATEGORY(IPASoftAdjust)
 
 int Adjust::init(IPAContext &context, [[maybe_unused]] const YamlObject &tuningData)
 {
+	context.ctrlMap[&controls::Gamma] = ControlInfo(0.1f, 10.0f, kDefaultGamma);
 	context.ctrlMap[&controls::Contrast] = ControlInfo(0.0f, 2.0f, 1.0f);
 	if (context.ccmEnabled)
 		context.ctrlMap[&controls::Saturation] = ControlInfo(0.0f, 2.0f, 1.0f);
@@ -32,6 +33,7 @@  int Adjust::init(IPAContext &context, [[maybe_unused]] const YamlObject &tuningD
 int Adjust::configure(IPAContext &context,
 		      [[maybe_unused]] const IPAConfigInfo &configInfo)
 {
+	context.activeState.knobs.gamma = std::optional<double>();
 	context.activeState.knobs.contrast = std::optional<double>();
 	context.activeState.knobs.saturation = std::optional<double>();
 
@@ -43,6 +45,12 @@  void Adjust::queueRequest(typename Module::Context &context,
 			  [[maybe_unused]] typename Module::FrameContext &frameContext,
 			  const ControlList &controls)
 {
+	const auto &gamma = controls.get(controls::Gamma);
+	if (gamma.has_value()) {
+		context.activeState.knobs.gamma = gamma;
+		LOG(IPASoftAdjust, Debug) << "Setting gamma to " << gamma.value();
+	}
+
 	const auto &contrast = controls.get(controls::Contrast);
 	if (contrast.has_value()) {
 		context.activeState.knobs.contrast = contrast;
diff --git a/src/ipa/simple/algorithms/adjust.h b/src/ipa/simple/algorithms/adjust.h
index c4baa2503..190d2079f 100644
--- a/src/ipa/simple/algorithms/adjust.h
+++ b/src/ipa/simple/algorithms/adjust.h
@@ -19,6 +19,8 @@  namespace libcamera {
 
 namespace ipa::soft::algorithms {
 
+const float kDefaultGamma = 2.2f;
+
 class Adjust : public Algorithm
 {
 public:
diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp
index a4cb14673..a17a24c9e 100644
--- a/src/ipa/simple/algorithms/lut.cpp
+++ b/src/ipa/simple/algorithms/lut.cpp
@@ -18,6 +18,8 @@ 
 
 #include "simple/ipa_context.h"
 
+#include "adjust.h"
+
 namespace libcamera {
 
 LOG_DEFINE_CATEGORY(IPASoftLut)
@@ -27,8 +29,6 @@  namespace ipa::soft::algorithms {
 int Lut::configure(IPAContext &context,
 		   [[maybe_unused]] const IPAConfigInfo &configInfo)
 {
-	/* Gamma value is fixed */
-	context.configuration.gamma = 0.5;
 	updateGammaTable(context);
 
 	return 0;
@@ -39,6 +39,8 @@  void Lut::updateGammaTable(IPAContext &context)
 	auto &gammaTable = context.activeState.gamma.gammaTable;
 	const auto blackLevel = context.activeState.blc.level;
 	const unsigned int blackIndex = blackLevel * gammaTable.size() / 256;
+	const auto gamma =
+		1.0 / context.activeState.knobs.gamma.value_or(kDefaultGamma);
 	const auto contrast = context.activeState.knobs.contrast.value_or(1.0);
 
 	const float divisor = gammaTable.size() - blackIndex - 1.0;
@@ -52,7 +54,7 @@  void Lut::updateGammaTable(IPAContext &context)
 		else
 			normalized = 1.0 - 0.5 * std::pow((1.0 - normalized) / 0.5, contrastExp);
 		gammaTable[i] = UINT8_MAX *
-				std::pow(normalized, context.configuration.gamma);
+				std::pow(normalized, gamma);
 	}
 	/*
 	 * Due to CCM operations, the table lookup may reach indices below the black
@@ -63,6 +65,7 @@  void Lut::updateGammaTable(IPAContext &context)
 	std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex,
 		  gammaTable[blackIndex]);
 
+	context.activeState.gamma.gamma = gamma;
 	context.activeState.gamma.blackLevel = blackLevel;
 	context.activeState.gamma.contrast = contrast;
 }
diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
index c69d59780..8f56c25bf 100644
--- a/src/ipa/simple/ipa_context.h
+++ b/src/ipa/simple/ipa_context.h
@@ -57,6 +57,7 @@  struct IPAActiveState {
 	struct {
 		std::array<double, kGammaLookupSize> gammaTable;
 		uint8_t blackLevel;
+		float gamma;
 		double contrast;
 	} gamma;
 
@@ -65,6 +66,7 @@  struct IPAActiveState {
 	bool matrixChanged = false;
 
 	struct {
+		std::optional<float> gamma;
 		/* 0..2 range, 1.0 = normal */
 		std::optional<double> contrast;
 		std::optional<float> saturation;
@@ -84,6 +86,7 @@  struct IPAFrameContext : public FrameContext {
 		double blue;
 	} gains;
 
+	std::optional<float> gamma;
 	std::optional<double> contrast;
 	std::optional<float> saturation;
 };