[v3,17/35] ipa: libipa: lsc_table: Move LscTable from RkISP1
diff mbox series

Message ID 20260706-libipa-algorithms-v3-17-968757b038bb@ideasonboard.com
State New
Headers show
Series
  • ipa: libipa: Introduce libipa algorithms
Related show

Commit Message

Jacopo Mondi July 6, 2026, 8:01 a.m. UTC
Move the LscTableImpl class to libipa from RkISP1.

Rename the class from LscTableImpl to a simpler LscTable.
The class is copied verbatim, only documntation has been added.

The implementation still contains RkISP1 specific data which will be
removed once the class is generalized.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 src/ipa/libipa/lsc_table.cpp      | 95 +++++++++++++++++++++++++++++++++++++++
 src/ipa/libipa/lsc_table.h        | 50 +++++++++++++++++++++
 src/ipa/libipa/meson.build        |  2 +
 src/ipa/rkisp1/algorithms/lsc.cpp | 81 +--------------------------------
 4 files changed, 149 insertions(+), 79 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/libipa/lsc_table.cpp b/src/ipa/libipa/lsc_table.cpp
new file mode 100644
index 000000000000..41a862b92e88
--- /dev/null
+++ b/src/ipa/libipa/lsc_table.cpp
@@ -0,0 +1,95 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2026, Ideas On Board
+ *
+ * Table-based Lsc implementation
+ */
+
+#include "lsc_table.h"
+
+/* \todo Remove RkISP1 from libipa. */
+#include "linux/rkisp1-config.h"
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(LscTable)
+
+namespace ipa {
+
+/**
+ * \class LscTable
+ * \brief Table based lsc algorithm implementation
+ *
+ * Table based lsc algorithm implementation. The LscTable class implements lsc
+ * support using tabular lsc data.
+ *
+ * \sa LscImplementation
+ */
+
+/**
+ * \brief Parse tabular lsc data
+ * \param[in] sets The tuning file content
+ *
+ * Parse the lsc data in tabular form from the \a sets tuning data.
+ *
+ * \return 0 on success or a negative error number otherwise
+ */
+int LscTable::parseLscData(const ValueNode &sets)
+{
+	for (const auto &set : sets.asList()) {
+		uint32_t ct = set["ct"].get<uint32_t>(0);
+
+		if (lscData_.count(ct)) {
+			LOG(LscTable, Error)
+				<< "Multiple sets found for color temperature "
+				<< ct;
+			return -EINVAL;
+		}
+
+		lsc::Components components;
+		components.r = parseTable(set, "r");
+		components.gr = parseTable(set, "gr");
+		components.gb = parseTable(set, "gb");
+		components.b = parseTable(set, "b");
+
+		if (components.r.empty() || components.gr.empty() ||
+		    components.gb.empty() || components.b.empty()) {
+			LOG(LscTable, Error)
+				<< "Set for color temperature " << ct
+				<< " is missing tables";
+			return -EINVAL;
+		}
+
+		lscData_.emplace(ct, std::move(components));
+	}
+
+	if (lscData_.empty()) {
+		LOG(LscTable, Error) << "Failed to load any sets";
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+std::vector<uint16_t> LscTable::parseTable(const ValueNode &tuningData,
+					   const char *prop)
+{
+	static constexpr unsigned int kLscNumSamples =
+		RKISP1_CIF_ISP_LSC_SAMPLES_MAX * RKISP1_CIF_ISP_LSC_SAMPLES_MAX;
+
+	std::vector<uint16_t> table =
+		tuningData[prop].get<std::vector<uint16_t>>().value_or(utils::defopt);
+	if (table.size() != kLscNumSamples) {
+		LOG(LscTable, Error)
+			<< "Invalid '" << prop << "' values: expected "
+			<< kLscNumSamples
+			<< " elements, got " << table.size();
+		return {};
+	}
+
+	return table;
+}
+
+} /* namespace ipa */
+
+} /* namespace libcamera */
diff --git a/src/ipa/libipa/lsc_table.h b/src/ipa/libipa/lsc_table.h
new file mode 100644
index 000000000000..0983b78c3f6b
--- /dev/null
+++ b/src/ipa/libipa/lsc_table.h
@@ -0,0 +1,50 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2026, Ideas On Board
+ *
+ * Table-based Lsc implementation
+ */
+#pragma once
+
+#include <vector>
+
+#include <libcamera/base/log.h>
+#include <libcamera/base/span.h>
+
+#include <libcamera/geometry.h>
+
+#include "libcamera/internal/value_node.h"
+
+#include "lsc_base.h"
+
+namespace libcamera {
+
+LOG_DECLARE_CATEGORY(LscTable)
+
+namespace ipa {
+
+class LscTable : public LscImplementation
+{
+public:
+	int parseLscData(const ValueNode &sets) override;
+
+	lsc::ComponentsMap
+	sampleForCrop([[maybe_unused]] const Rectangle &cropRectangle,
+		      [[maybe_unused]] Span<const double> xSizes,
+		      [[maybe_unused]] Span<const double> ySizes) override
+	{
+		LOG(LscTable, Warning)
+			<< "Tabular LSC data doesn't support resampling";
+		return lscData_;
+	}
+
+private:
+	std::vector<uint16_t> parseTable(const ValueNode &tuningData,
+					 const char *prop);
+
+	lsc::ComponentsMap lscData_;
+};
+
+} /* namespace ipa */
+
+} /* namespace libcamera */
diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build
index 96611e90ee1e..95d398d99fd6 100644
--- a/src/ipa/libipa/meson.build
+++ b/src/ipa/libipa/meson.build
@@ -16,6 +16,7 @@  libipa_headers = files([
     'interpolator.h',
     'lsc_base.h',
     'lsc_polynomial.h',
+    'lsc_table.h',
     'lux.h',
     'module.h',
     'pwl.h',
@@ -39,6 +40,7 @@  libipa_sources = files([
     'interpolator.cpp',
     'lsc_base.cpp',
     'lsc_polynomial.cpp',
+    'lsc_table.cpp',
     'lux.cpp',
     'module.cpp',
     'pwl.cpp',
diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp
index a4ea879aaa83..974534175e06 100644
--- a/src/ipa/rkisp1/algorithms/lsc.cpp
+++ b/src/ipa/rkisp1/algorithms/lsc.cpp
@@ -17,6 +17,7 @@ 
 #include "libcamera/internal/value_node.h"
 
 #include "libipa/lsc_polynomial.h"
+#include "libipa/lsc_table.h"
 #include "linux/rkisp1-config.h"
 
 /**
@@ -33,84 +34,6 @@  namespace {
 
 constexpr int kColourTemperatureQuantization = 10;
 
-class LscTableImpl : public LscImplementation
-{
-public:
-	int parseLscData(const ValueNode &sets) override;
-
-	lsc::ComponentsMap
-	sampleForCrop([[maybe_unused]] const Rectangle &cropRectangle,
-		      [[maybe_unused]] Span<const double> xSizes,
-		      [[maybe_unused]] Span<const double> ySizes) override
-	{
-		LOG(RkISP1Lsc, Warning)
-			<< "Tabular LSC data doesn't support resampling";
-		return lscData_;
-	}
-
-private:
-	std::vector<uint16_t> parseTable(const ValueNode &tuningData,
-					 const char *prop);
-
-	lsc::ComponentsMap lscData_;
-};
-
-int LscTableImpl::parseLscData(const ValueNode &sets)
-{
-	for (const auto &set : sets.asList()) {
-		uint32_t ct = set["ct"].get<uint32_t>(0);
-
-		if (lscData_.count(ct)) {
-			LOG(RkISP1Lsc, Error)
-				<< "Multiple sets found for color temperature "
-				<< ct;
-			return -EINVAL;
-		}
-
-		lsc::Components components;
-		components.r = parseTable(set, "r");
-		components.gr = parseTable(set, "gr");
-		components.gb = parseTable(set, "gb");
-		components.b = parseTable(set, "b");
-
-		if (components.r.empty() || components.gr.empty() ||
-		    components.gb.empty() || components.b.empty()) {
-			LOG(RkISP1Lsc, Error)
-				<< "Set for color temperature " << ct
-				<< " is missing tables";
-			return -EINVAL;
-		}
-
-		lscData_.emplace(ct, std::move(components));
-	}
-
-	if (lscData_.empty()) {
-		LOG(RkISP1Lsc, Error) << "Failed to load any sets";
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-std::vector<uint16_t> LscTableImpl::parseTable(const ValueNode &tuningData,
-						 const char *prop)
-{
-	static constexpr unsigned int kLscNumSamples =
-		RKISP1_CIF_ISP_LSC_SAMPLES_MAX * RKISP1_CIF_ISP_LSC_SAMPLES_MAX;
-
-	std::vector<uint16_t> table =
-		tuningData[prop].get<std::vector<uint16_t>>().value_or(utils::defopt);
-	if (table.size() != kLscNumSamples) {
-		LOG(RkISP1Lsc, Error)
-			<< "Invalid '" << prop << "' values: expected "
-			<< kLscNumSamples
-			<< " elements, got " << table.size();
-		return {};
-	}
-
-	return table;
-}
-
 std::vector<double> parseSizes(const ValueNode &tuningData,
 			       const char *prop)
 {
@@ -190,7 +113,7 @@  int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,
 	std::string type = tuningData["type"].get<std::string>("table");
 	if (type == "table") {
 		LOG(RkISP1Lsc, Debug) << "Loading tabular LSC data.";
-		algo_ = std::make_unique<LscTableImpl>();
+		algo_ = std::make_unique<LscTable>();
 		ret = algo_->parseLscData(sets);
 	} else if (type == "polynomial") {
 		LOG(RkISP1Lsc, Debug) << "Loading polynomial LSC data.";