[v6,27/31] ipa: libipa: lsc: Quantize lsc gains in IPA
diff mbox series

Message ID 20260720-libipa-algorithms-v6-27-ececb73f97cb@ideasonboard.com
State New
Headers show
Series
  • ipa: libipa: Introduce libipa algorithms
Related show

Commit Message

Jacopo Mondi July 20, 2026, 2:59 p.m. UTC
The libIPA Lsc algorithm currently assumes the register format of
the RkISP1 platform (16 bits Q2.10 format), as that's where the
implementation has been derived from.

Move the register quantization to the plaltform IPA and use 'floats'
as the exchange format for the table-based and polynomial-based
LSC implementations.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 src/ipa/libipa/lsc_base.h         |  2 +-
 src/ipa/libipa/lsc_polynomial.cpp | 17 +++++------------
 src/ipa/libipa/lsc_polynomial.h   |  8 ++++----
 src/ipa/libipa/lsc_table.cpp      |  6 +++---
 src/ipa/libipa/lsc_table.h        |  2 +-
 src/ipa/rkisp1/algorithms/lsc.cpp | 34 ++++++++++++++++++++++++++--------
 6 files changed, 40 insertions(+), 29 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/libipa/lsc_base.h b/src/ipa/libipa/lsc_base.h
index b0b9b3b0712d..386cac55be34 100644
--- a/src/ipa/libipa/lsc_base.h
+++ b/src/ipa/libipa/lsc_base.h
@@ -26,7 +26,7 @@  namespace ipa {
 
 namespace lsc {
 
-using Components = std::map<std::string, std::vector<uint16_t>>;
+using Components = std::map<std::string, std::vector<float>>;
 using ComponentsMap = std::map<unsigned int, Components>;
 
 } /* namespace lsc */
diff --git a/src/ipa/libipa/lsc_polynomial.cpp b/src/ipa/libipa/lsc_polynomial.cpp
index c61c85fbf2b2..e31a63e06cc8 100644
--- a/src/ipa/libipa/lsc_polynomial.cpp
+++ b/src/ipa/libipa/lsc_polynomial.cpp
@@ -218,7 +218,7 @@  LscPolynomial::sampleForCrop(const Rectangle &cropRectangle,
 	return components;
 }
 
-std::vector<uint16_t>
+std::vector<float>
 LscPolynomial::samplePolynomial(const lsc::Polynomial &poly,
 				Span<const double> xPositions,
 				Span<const double> yPositions,
@@ -229,7 +229,7 @@  LscPolynomial::samplePolynomial(const lsc::Polynomial &poly,
 	double y0 = cropRectangle.y / m;
 	double w = cropRectangle.width / m;
 	double h = cropRectangle.height / m;
-	std::vector<uint16_t> samples;
+	std::vector<float> samples;
 
 	samples.reserve(xPositions.size() * yPositions.size());
 
@@ -237,16 +237,9 @@  LscPolynomial::samplePolynomial(const lsc::Polynomial &poly,
 		for (double x : xPositions) {
 			double xp = x0 + x * w;
 			double yp = y0 + y * h;
-			/*
-			 * The hardware uses 2.10 fixed point format and limits
-			 * the legal values to [1..3.999]. Scale and clamp the
-			 * sampled value accordingly.
-			 */
-			int v = static_cast<int>(
-				poly.sampleAtNormalizedPixelPos(xp, yp) *
-				1024);
-			v = std::clamp(v, 1024, 4095);
-			samples.push_back(v);
+
+			samples.push_back(static_cast<float>
+					 (poly.sampleAtNormalizedPixelPos(xp, yp)));
 		}
 	}
 	return samples;
diff --git a/src/ipa/libipa/lsc_polynomial.h b/src/ipa/libipa/lsc_polynomial.h
index 6d19e46a50b7..8d526531075b 100644
--- a/src/ipa/libipa/lsc_polynomial.h
+++ b/src/ipa/libipa/lsc_polynomial.h
@@ -65,10 +65,10 @@  public:
 		      std::vector<double> xPos, std::vector<double> yPos) override;
 
 private:
-	std::vector<uint16_t> samplePolynomial(const lsc::Polynomial &poly,
-					       Span<const double> xPositions,
-					       Span<const double> yPositions,
-					       const Rectangle &cropRectangle);
+	std::vector<float> samplePolynomial(const lsc::Polynomial &poly,
+					    Span<const double> xPositions,
+					    Span<const double> yPositions,
+					    const Rectangle &cropRectangle);
 	PolynomialComponentsMap lscData_;
 };
 
diff --git a/src/ipa/libipa/lsc_table.cpp b/src/ipa/libipa/lsc_table.cpp
index 92e24bc5160a..33f6182de1bd 100644
--- a/src/ipa/libipa/lsc_table.cpp
+++ b/src/ipa/libipa/lsc_table.cpp
@@ -82,15 +82,15 @@  int LscTable::parseLscComponent(const ValueNode &yamlSet,
 	return 0;
 }
 
-std::vector<uint16_t> LscTable::parseTable(const ValueNode &tuningData,
+std::vector<float> LscTable::parseTable(const ValueNode &tuningData,
 					   const char *prop,
 					   unsigned int numHSamples,
 					   unsigned int numVSamples)
 {
 	unsigned int lscNumSamples = numHSamples * numVSamples;
 
-	std::vector<uint16_t> table =
-		tuningData[prop].get<std::vector<uint16_t>>().value_or(utils::defopt);
+	std::vector<float> table =
+		tuningData[prop].get<std::vector<float>>().value_or(utils::defopt);
 	if (table.size() != lscNumSamples) {
 		LOG(LscTable, Error)
 			<< "Invalid '" << prop << "' values: expected "
diff --git a/src/ipa/libipa/lsc_table.h b/src/ipa/libipa/lsc_table.h
index a33208761c15..6d9b0c692b7f 100644
--- a/src/ipa/libipa/lsc_table.h
+++ b/src/ipa/libipa/lsc_table.h
@@ -42,7 +42,7 @@  public:
 private:
 	int parseLscComponent(const ValueNode &yamlSet,
 			      unsigned int ct, const LscDescriptor &descriptor);
-	std::vector<uint16_t> parseTable(const ValueNode &tuningData,
+	std::vector<float> parseTable(const ValueNode &tuningData,
 					 const char *prop,
 					 unsigned int numHSamples,
 					 unsigned int numVSamples);
diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp
index 7a95bfcfb93a..dba1a01118ee 100644
--- a/src/ipa/rkisp1/algorithms/lsc.cpp
+++ b/src/ipa/rkisp1/algorithms/lsc.cpp
@@ -177,14 +177,32 @@  void LensShadingCorrection::setParameters(rkisp1_cif_isp_lsc_config &config)
 void LensShadingCorrection::copyTable(rkisp1_cif_isp_lsc_config &config,
 				      const lsc::Components &set)
 {
-	const auto &r = set.at("r");
-	std::copy(r.begin(), r.end(), &config.r_data_tbl[0][0]);
-	const auto &gr = set.at("gr");
-	std::copy(gr.begin(), gr.end(), &config.gr_data_tbl[0][0]);
-	const auto &gb = set.at("gb");
-	std::copy(gb.begin(), gb.end(), &config.gb_data_tbl[0][0]);
-	const auto &b = set.at("b");
-	std::copy(b.begin(), b.end(), &config.b_data_tbl[0][0]);
+	/*
+	 * The hardware uses 2.10 fixed point format and limits the legal values
+	 * to [1..3.999]. Scale and clamp the sampled values accordingly.
+	 */
+	std::vector<uint16_t> regs;
+	regs.reserve(RKISP1_CIF_ISP_LSC_SAMPLES_MAX *
+		     RKISP1_CIF_ISP_LSC_SAMPLES_MAX);
+
+	for (const float &f : set.at("r"))
+		regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095));
+	std::copy(regs.begin(), regs.end(), &config.r_data_tbl[0][0]);
+
+	regs = {};
+	for (const float &f : set.at("gr"))
+		regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095));
+	std::copy(regs.begin(), regs.end(), &config.gr_data_tbl[0][0]);
+
+	regs = {};
+	for (const float &f : set.at("gb"))
+		regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095));
+	std::copy(regs.begin(), regs.end(), &config.gb_data_tbl[0][0]);
+
+	regs = {};
+	for (const float &f : set.at("b"))
+		regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095));
+	std::copy(regs.begin(), regs.end(), &config.b_data_tbl[0][0]);
 }
 
 /**