From patchwork Mon Jul 6 08:01:49 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 27229 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 6887BC3318 for ; Mon, 6 Jul 2026 08:02:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 06F8F66069; Mon, 6 Jul 2026 10:02:37 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ETRrjvWP"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 07AB266031 for ; Mon, 6 Jul 2026 10:02:16 +0200 (CEST) Received: from [192.168.125.177] (mob-109-113-60-81.net.vodafone.it [109.113.60.81]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7C4A93FE8; Mon, 6 Jul 2026 10:01:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1783324888; bh=WEvfaM6MO/uOsVIRRFYs+XFPvBWUs8JbZ1zNEbDqhtg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ETRrjvWPTlPo1XM181ztjhecX29DQYBBmTwgfoRnCCQySmWmaSRHatuDEFxJlA+LB unH7csiZbR49Sm9mWGrjeCuMRqTHDxsh6igGgx+ihkgVX06W9xrrEWOg7ixL5xq3E8 ZfO4A6FSmOesnLAzjveevq23aYqy8R0y4zSpAD1U= From: Jacopo Mondi Date: Mon, 06 Jul 2026 10:01:49 +0200 Subject: [PATCH v3 29/35] ipa: libipa: lsc: Template LscAlgorithm with register format MIME-Version: 1.0 Message-Id: <20260706-libipa-algorithms-v3-29-968757b038bb@ideasonboard.com> References: <20260706-libipa-algorithms-v3-0-968757b038bb@ideasonboard.com> In-Reply-To: <20260706-libipa-algorithms-v3-0-968757b038bb@ideasonboard.com> To: libcamera-devel@lists.libcamera.org, Stefan Klug Cc: Jacopo Mondi X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=23337; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=WEvfaM6MO/uOsVIRRFYs+XFPvBWUs8JbZ1zNEbDqhtg=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBqS2DyJunQgTeZ6lynttiVkuB0bLgDO1dtzP7qo 4tlNCMksViJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaktg8gAKCRByNAaPFqFW PEZwD/9CeRXfVdiLB3FlTRA+Sn+50Wssqo8i7bAjP9F5/V1Yebv3i5UY7SlTau6Nv02ccF2TYbY GZE7/oyl4ygbhwnurterckIPlHTUxs0BI/SCDCdwxShwkEt6s9HgGo4nFl4tVbTx2Y+zEBg1RhX Ek53lSGqY41cYvayKvCesDCfqPqvskliXog8sYrM+furZRpdRqcLiD3pva39tUlSQEq3iFyfOWA UesN0AXZ7xDgn53iPu6gS3q+1nlhOyM9tuCQ24Sg/GSeKnxWIrgJkGLxaC+D5IUHuPbDOahtuuO hHlt4s0uPUFg28LPgfiWWMl+a+H3hRbrx8Utn/L7GRtzGierdXOnqkX8fWqu6zNAcbCAt5MDZAh tMdciATF3O1aHMeagLaLM/28+anFQgHuvBMxM9/aRpQpcGbW9AzCuULwfXvvkg2aLVE7QkL9tQn 0su1eZruu4dnB1QCKwBSh6h9bkkOauKWC4oSGL6bnQX1VfTDjYliuGBZyNUq9ldihWPGxP3tHZs 8T+kKZvVkd8VvciJIsYWi6+RFgnSYEB8ewP67nxkY3aNH1zS2DwsLT9/ESvsAvvJeWVsbXd3yNf +IMF2/W6c22/AmQzwt7u450jNsmMzprqvsskz5w/AjOfY6icxLR9BouHDd3+e882IZLTdp1lM2V cRDaOoigA+azhXw== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The LscPolynomial::samplePolynomial function expands the radial polynomial assuming the RkISP1 Q<2, 10> register format: /* * 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( poly.sampleAtNormalizedPixelPos(xp, yp) * 1024); v = std::clamp(v, 1024, 4095); In order to remove all assumptions about the platform register format template the LscAlgorithm class with the fixed point format of the ISP Lsc engine registers. float sample = static_cast (poly.sampleAtNormalizedPixelPos(xp, yp)); samples.push_back(U(sample).quantized()); In order to template the LscPolynomial class, template the whole class hierarchy including the LscTable class that doesn't need (yet) the template argument but will use it once re-sampling LscTable will be implemented. Split all involved classes (LscAlgorithm, LscTable and LscPolynomial) in two classes: a Lsc*Base class for non-templated function implementations and a Lsc* class for templated functions implementations. Signed-off-by: Jacopo Mondi --- src/ipa/libipa/lsc.cpp | 151 +++++++++++++------------------------- src/ipa/libipa/lsc.h | 81 +++++++++++++++++--- src/ipa/libipa/lsc_base.cpp | 1 + src/ipa/libipa/lsc_base.h | 1 + src/ipa/libipa/lsc_polynomial.cpp | 90 +++++++---------------- src/ipa/libipa/lsc_polynomial.h | 67 +++++++++++++++-- src/ipa/libipa/lsc_table.cpp | 49 +++++++++---- src/ipa/libipa/lsc_table.h | 35 ++++++--- src/ipa/rkisp1/algorithms/lsc.h | 3 +- 9 files changed, 270 insertions(+), 208 deletions(-) diff --git a/src/ipa/libipa/lsc.cpp b/src/ipa/libipa/lsc.cpp index c1207292518a..621c04d354a8 100644 --- a/src/ipa/libipa/lsc.cpp +++ b/src/ipa/libipa/lsc.cpp @@ -7,13 +7,6 @@ #include "lsc.h" -#include - -#include - -#include "lsc_polynomial.h" -#include "lsc_table.h" - /** * \file lsc.h * \brief libipa lsc algorithm @@ -48,9 +41,56 @@ namespace lsc { } /* namespace lsc */ +/** + * \class LscAlgorithmBase + * \brief Base class for LscAlgorithm + * + * Base class for LscAlgorithm for non-templated functions implementation + */ + +/** + * \brief Queue a request to the lsc algorithm + * \param[in] state The lsc active state + * \param[in] context The lsc frame context + * \param[in] controls The list of controls associated with a Request + * + * Queue a new list of \a controls to the lsc algorithm. + * The only supported control is controls::LensShadingCorrectionEnable. + */ +void LscAlgorithmBase::queueRequest(lsc::ActiveState &state, + lsc::FrameContext &context, + const ControlList &controls) +{ + const auto &lscEnable = controls.get(controls::LensShadingCorrectionEnable); + if (lscEnable && *lscEnable != state.enabled) { + state.enabled = *lscEnable; + + LOG(Lsc, Debug) + << (state.enabled ? "Enabling" : "Disabling") << " Lsc"; + + context.update = true; + } + + context.enabled = state.enabled; +} + +/** + * \brief Populate the list of lsc metadata + * \param[in] context The lsc frame context + * \param[in] metadata The list of metadata + * + * Populates the list of \a metadata with controls handled by the LscAlgorithm + * class. The only supported metadata is controls::LensShadingCorrectionEnable. + */ +void LscAlgorithmBase::process(lsc::FrameContext &context, ControlList &metadata) +{ + metadata.set(controls::LensShadingCorrectionEnable, context.enabled); +} + /** * \class LscAlgorithm * \brief libIPA lsc algorithm implementation + * \tparam U The fixedpoint lsc engine register format * * Due to the optical characteristics of the lens, the light intensity received * by the sensor is not uniform. The Lens Shading Correction algorithm applies @@ -200,6 +240,7 @@ namespace lsc { */ /** + * \fn LscAlgorithm::init() * \param[in] tuningData The tuning data * \param[in] controls The IPA list of supported controls * \param[in] descriptor The lsc engine descriptor @@ -209,42 +250,9 @@ namespace lsc { * * \return 0 on success, a negative error code otherwise */ -int LscAlgorithm::init(const ValueNode &tuningData, ControlInfoMap::Map &controls, - const LscDescriptor &descriptor) -{ - polynomial_ = false; - - std::string type = tuningData["type"].get("table"); - if (type == "table") { - impl_ = std::make_unique(); - LOG(Lsc, Debug) << "Using table-based Lsc"; - } else if (type == "polynomial") { - impl_ = std::make_unique(); - polynomial_ = true; - LOG(Lsc, Debug) << "Using polynomial Lsc"; - } else { - LOG(Lsc, Error) << "Unsupported Lsc algorithm '" - << type << "'"; - return -EINVAL; - } - - const ValueNode &yamlSets = tuningData["sets"]; - if (!yamlSets.isList()) { - LOG(Lsc, Error) << "'sets' parameter not found in tuning file"; - return -EINVAL; - } - - int ret = impl_->parseLscData(yamlSets, descriptor); - if (ret) - return ret; - - controls[&controls::LensShadingCorrectionEnable] = - ControlInfo(false, true, true); - - return 0; -} /** + * \fn LscAlgorithm::configure() * \param[in] state The lsc active state * \param[in] analogCrop The current sensor analog crop rectangle * \param[in] xPos List of horizontal positions of the LSC grid nodes @@ -265,67 +273,6 @@ int LscAlgorithm::init(const ValueNode &tuningData, ControlInfoMap::Map &control * * \return 0 on success, a negative error code otherwise */ -int LscAlgorithm::configure(lsc::ActiveState &state, const Rectangle &analogCrop, - const std::vector &xPos, - const std::vector &yPos) -{ - LOG(Lsc, Debug) << "Sample Lsc data for " << analogCrop; - lsc::ComponentsMap lscData = - impl_->sampleForCrop(analogCrop, xPos, yPos); - - /* - * Retain a copy of the components table. - * - * We could avoid a copy here if getComponents() could - * return sets_.data() but I wasn't able to work around the - * compiler refusing it. - */ - lscData_ = lscData; - - sets_.setData(std::move(lscData)); - state.enabled = true; - - return 0; -} - -/** - * \brief Queue a request to the lsc algorithm - * \param[in] state The lsc active state - * \param[in] context The lsc frame context - * \param[in] controls The list of controls associated with a Request - * - * Queue a new list of \a controls to the lsc algorithm. - * The only supported control is controls::LensShadingCorrectionEnable. - */ -void LscAlgorithm::queueRequest(lsc::ActiveState &state, - lsc::FrameContext &context, - const ControlList &controls) -{ - const auto &lscEnable = controls.get(controls::LensShadingCorrectionEnable); - if (lscEnable && *lscEnable != state.enabled) { - state.enabled = *lscEnable; - - LOG(Lsc, Debug) - << (state.enabled ? "Enabling" : "Disabling") << " Lsc"; - - context.update = true; - } - - context.enabled = state.enabled; -} - -/** - * \brief Populate the list of lsc metadata - * \param[in] context The lsc frame context - * \param[in] metadata The list of metadata - * - * Populates the list of \a metadata with controls handled by the LscAlgorithm - * class. The only supported metadata is controls::LensShadingCorrectionEnable. - */ -void LscAlgorithm::process(lsc::FrameContext &context, ControlList &metadata) -{ - metadata.set(controls::LensShadingCorrectionEnable, context.enabled); -} /** * \fn LscAlgorithm::interpolateComponents diff --git a/src/ipa/libipa/lsc.h b/src/ipa/libipa/lsc.h index 9fe8ad67ea33..d48336b169f4 100644 --- a/src/ipa/libipa/lsc.h +++ b/src/ipa/libipa/lsc.h @@ -8,18 +8,25 @@ #pragma once #include +#include #include +#include + +#include #include #include #include "libcamera/internal/value_node.h" #include "interpolator.h" -#include "lsc_base.h" +#include "lsc_polynomial.h" +#include "lsc_table.h" namespace libcamera { +LOG_DECLARE_CATEGORY(Lsc) + namespace ipa { namespace lsc { @@ -35,19 +42,75 @@ struct FrameContext { } /* namespace lsc */ -class LscAlgorithm +class LscAlgorithmBase +{ +public: + void queueRequest(lsc::ActiveState &state, lsc::FrameContext &context, + const ControlList &controls); + void process(lsc::FrameContext &context, ControlList &metadata); +}; + +template +class LscAlgorithm : public LscAlgorithmBase { public: int init(const ValueNode &tuningData, ControlInfoMap::Map &controls, - const LscDescriptor &descriptor); + const LscDescriptor &descriptor) + { + polynomial_ = false; + + std::string type = tuningData["type"].get("table"); + if (type == "table") { + impl_ = std::make_unique>(); + LOG(Lsc, Debug) << "Using table-based Lsc"; + } else if (type == "polynomial") { + impl_ = std::make_unique>(); + polynomial_ = true; + LOG(Lsc, Debug) << "Using polynomial Lsc"; + } else { + LOG(Lsc, Error) << "Unsupported Lsc algorithm '" + << type << "'"; + return -EINVAL; + } + + const ValueNode &yamlSets = tuningData["sets"]; + if (!yamlSets.isList()) { + LOG(Lsc, Error) << "'sets' parameter not found in tuning file"; + return -EINVAL; + } + + int ret = impl_->parseLscData(yamlSets, descriptor); + if (ret) + return ret; + + controls[&controls::LensShadingCorrectionEnable] = + ControlInfo(false, true, true); + + return 0; + } int configure(lsc::ActiveState &state, const Rectangle &analogCrop, const std::vector &xPos, - const std::vector &yPos); - - void queueRequest(lsc::ActiveState &state, lsc::FrameContext &context, - const ControlList &controls); - void process(lsc::FrameContext &context, ControlList &metadata); + const std::vector &yPos) + { + LOG(Lsc, Debug) << "Sample Lsc data for " << analogCrop; + lsc::ComponentsMap lscData = + impl_->sampleForCrop(analogCrop, xPos, yPos); + + /* + * Retain a copy of the components table. + * + * We could avoid a copy here if getComponents() could + * return sets_.data() but I wasn't able to work around the + * compiler refusing it. + */ + lscData_ = lscData; + + sets_.setData(std::move(lscData)); + state.enabled = true; + + return 0; + } const lsc::Components interpolateComponents(unsigned int ct) { @@ -60,7 +123,7 @@ public: } private: - std::unique_ptr impl_; + std::unique_ptr> impl_; Interpolator sets_; lsc::ComponentsMap lscData_; bool polynomial_; diff --git a/src/ipa/libipa/lsc_base.cpp b/src/ipa/libipa/lsc_base.cpp index 7de6ee70e7a0..0eeb99f6881a 100644 --- a/src/ipa/libipa/lsc_base.cpp +++ b/src/ipa/libipa/lsc_base.cpp @@ -86,6 +86,7 @@ void Interpolator:: /** * \class LscImplementation * \brief Pure virtual base class for lsc algorithm implementations + * \tparam U The fixedpoint lsc engine register format * * Defines the interface for the lsc algorithm implementation. */ diff --git a/src/ipa/libipa/lsc_base.h b/src/ipa/libipa/lsc_base.h index 48307455362a..721fd137ef21 100644 --- a/src/ipa/libipa/lsc_base.h +++ b/src/ipa/libipa/lsc_base.h @@ -57,6 +57,7 @@ struct LscDescriptor { Size sensorSize; }; +template class LscImplementation { public: diff --git a/src/ipa/libipa/lsc_polynomial.cpp b/src/ipa/libipa/lsc_polynomial.cpp index 013a4469546e..2b743ed53be7 100644 --- a/src/ipa/libipa/lsc_polynomial.cpp +++ b/src/ipa/libipa/lsc_polynomial.cpp @@ -113,14 +113,10 @@ void Polynomial::setReferenceImageSize(const Size &size) } /* namespace lsc */ /** - * \class LscPolynomial - * \brief Radial Polynomial lsc algorithm implementation + * \class LscPolynomialBase + * \brief Base class for LscPolynomial * - * Polynomial-based lsc algorithm implementation. The LscPolynomial class - * implements lsc support using Polynomial to represent the shading artifacts - * map. - * - * \sa LscImplementation + * Base class for LscPolynomial for non-templated functions. */ /** @@ -132,8 +128,8 @@ void Polynomial::setReferenceImageSize(const Size &size) * * \return 0 on success or a negative error number otherwise */ -int LscPolynomial::parseLscData(const ValueNode &sets, - const LscDescriptor &descriptor) +int LscPolynomialBase::parseLscData(const ValueNode &sets, + const LscDescriptor &descriptor) { for (const auto &set : sets.asList()) { uint32_t ct = set["ct"].get(0); @@ -174,6 +170,27 @@ int LscPolynomial::parseLscData(const ValueNode &sets, } /** + * \var LscPolynomialBase::lscData_ + * \brief The polynomial lsc data + * + * Maps colour temperatures to per-colour radial polynomial definitions. + */ + +/** + * \class LscPolynomial + * \brief Radial Polynomial lsc algorithm implementation + * \tparam U The fixedpoint format used to convert gain values generated by + * polynomial expansion to the register format + * + * Polynomial-based lsc algorithm implementation. The LscPolynomial class + * implements lsc support using Polynomial to represent the shading artifacts + * map. + * + * \sa LscImplementation + */ + +/** + * \fn LscPolynomial::sampleForCrop() * \brief Re-sample the lsc components for \a cropRectangle * \param[in] cropRectangle The sensor analogue crop rectangle * \param[in] xPos List of horizontal positions of the lsc grid nodes @@ -195,62 +212,7 @@ int LscPolynomial::parseLscData(const ValueNode &sets, * [0, 0.0625, 0.125, 0.1875, ... , 1]. It is expected that the first position * is 0 and the last position is 1. */ -lsc::ComponentsMap -LscPolynomial::sampleForCrop(const Rectangle &cropRectangle, - std::vector xPos, std::vector yPos) -{ - - lsc::ComponentsMap components; - - for (const auto &[t, c] : lscData_) { - lsc::Components comp; - - for (const auto &[k, p] : c) { - comp.emplace(std::piecewise_construct, - std::forward_as_tuple(k), - std::forward_as_tuple(samplePolynomial(p, xPos, yPos, - cropRectangle))); - } - components[t] = comp; - } - - return components; -} - -std::vector -LscPolynomial::samplePolynomial(const lsc::Polynomial &poly, - Span xPositions, - Span yPositions, - const Rectangle &cropRectangle) -{ - double m = poly.getM(); - double x0 = cropRectangle.x / m; - double y0 = cropRectangle.y / m; - double w = cropRectangle.width / m; - double h = cropRectangle.height / m; - std::vector samples; - - samples.reserve(xPositions.size() * yPositions.size()); - - for (double y : yPositions) { - 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( - poly.sampleAtNormalizedPixelPos(xp, yp) * - 1024); - v = std::clamp(v, 1024, 4095); - samples.push_back(v); - } - } - return samples; -} } /* namespace ipa */ diff --git a/src/ipa/libipa/lsc_polynomial.h b/src/ipa/libipa/lsc_polynomial.h index 6d19e46a50b7..04d7465b3af0 100644 --- a/src/ipa/libipa/lsc_polynomial.h +++ b/src/ipa/libipa/lsc_polynomial.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -50,26 +51,80 @@ private: } /* namespace lsc */ -class LscPolynomial : public LscImplementation +class LscPolynomialBase { private: using PolynomialComponents = std::map; using PolynomialComponentsMap = std::map; +protected: + int parseLscData(const ValueNode &yamlSets, + const LscDescriptor &descriptor); + + PolynomialComponentsMap lscData_; +}; + +template +class LscPolynomial : public LscPolynomialBase, public LscImplementation +{ public: - int parseLscData(const ValueNode &sets, - const LscDescriptor &descriptor) override; + int parseLscData(const ValueNode &yamlSets, + const LscDescriptor &descriptor) override + { + return LscPolynomialBase::parseLscData(yamlSets, descriptor); + } lsc::ComponentsMap sampleForCrop(const Rectangle &cropRectangle, - std::vector xPos, std::vector yPos) override; + std::vector xPos, std::vector yPos) override + { + lsc::ComponentsMap components; + + for (const auto &[t, c] : lscData_) { + lsc::Components comp; + + for (const auto &[k, p] : c) { + comp.emplace(std::piecewise_construct, + std::forward_as_tuple(k), + std::forward_as_tuple(samplePolynomial(p, xPos, yPos, + cropRectangle))); + } + + components[t] = comp; + } + + return components; + } private: std::vector samplePolynomial(const lsc::Polynomial &poly, Span xPositions, Span yPositions, - const Rectangle &cropRectangle); - PolynomialComponentsMap lscData_; + const Rectangle &cropRectangle) + { + double m = poly.getM(); + double x0 = cropRectangle.x / m; + double y0 = cropRectangle.y / m; + double w = cropRectangle.width / m; + double h = cropRectangle.height / m; + std::vector samples; + + samples.reserve(xPositions.size() * yPositions.size()); + + for (double y : yPositions) { + for (double x : xPositions) { + double xp = x0 + x * w; + double yp = y0 + y * h; + + float sample = static_cast + (poly.sampleAtNormalizedPixelPos(xp, yp)); + + samples.push_back(U(sample).quantized()); + } + } + + return samples; + } }; } /* namespace ipa */ diff --git a/src/ipa/libipa/lsc_table.cpp b/src/ipa/libipa/lsc_table.cpp index 415c1cc0ccd4..bb3c76b12332 100644 --- a/src/ipa/libipa/lsc_table.cpp +++ b/src/ipa/libipa/lsc_table.cpp @@ -14,13 +14,10 @@ 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. + * \class LscTableBase + * \brief Base class for LscTable * - * \sa LscImplementation + * Base class for LscTable for non-templated functions. */ /** @@ -32,8 +29,8 @@ namespace ipa { * * \return 0 on success or a negative error number otherwise */ -int LscTable::parseLscData(const ValueNode &sets, - const LscDescriptor &descriptor) +int LscTableBase::parseLscData(const ValueNode &sets, + const LscDescriptor &descriptor) { for (const auto &set : sets.asList()) { uint32_t ct = set["ct"].get(0); @@ -51,8 +48,8 @@ int LscTable::parseLscData(const ValueNode &sets, return 0; } -int LscTable::parseLscComponent(const ValueNode &yamlSet, - unsigned int ct, const LscDescriptor &descriptor) +int LscTableBase::parseLscComponent(const ValueNode &yamlSet, + unsigned int ct, const LscDescriptor &descriptor) { lsc::Components component; for (auto &k : descriptor.keys) { @@ -82,10 +79,10 @@ int LscTable::parseLscComponent(const ValueNode &yamlSet, return 0; } -std::vector LscTable::parseTable(const ValueNode &tuningData, - const char *prop, - unsigned int numHCells, - unsigned int numVCells) +std::vector LscTableBase::parseTable(const ValueNode &tuningData, + const char *prop, + unsigned int numHCells, + unsigned int numVCells) { unsigned int lscNumSamples = numHCells * numVCells; @@ -102,6 +99,30 @@ std::vector LscTable::parseTable(const ValueNode &tuningData, return table; } +/** + * \var LscTableBase::lscData_ + * \brief The tabular lsc data + * + * Maps colour temperatures to per-colour channel vector of gains + */ + +/** + * \class LscTable + * \brief Table based lsc algorithm implementation + * \tparam U The fixedpoint lsc engine register format + * + * Table based lsc algorithm implementation. The LscTable class implements lsc + * support using tabular lsc data. + * + * \sa LscImplementation + */ + +/** + * \fn LscTable::parseLscData() + * + * \copydoc LscTableBase::parseLscData() + */ + } /* namespace ipa */ } /* namespace libcamera */ diff --git a/src/ipa/libipa/lsc_table.h b/src/ipa/libipa/lsc_table.h index 3fe52afbad7b..65e04b09c3ff 100644 --- a/src/ipa/libipa/lsc_table.h +++ b/src/ipa/libipa/lsc_table.h @@ -23,11 +23,32 @@ LOG_DECLARE_CATEGORY(LscTable) namespace ipa { -class LscTable : public LscImplementation +class LscTableBase +{ +protected: + int parseLscData(const ValueNode &sets, + const LscDescriptor &descriptor); + +private: + int parseLscComponent(const ValueNode &yamlSet, + unsigned int ct, const LscDescriptor &descriptor); + std::vector parseTable(const ValueNode &tuningData, + const char *prop, + unsigned int numHCells, + unsigned int numVCells); +protected: + lsc::ComponentsMap lscData_; +}; + +template +class LscTable : public LscTableBase, public LscImplementation { public: int parseLscData(const ValueNode &sets, - const LscDescriptor &descriptor) override; + const LscDescriptor &descriptor) override + { + return LscTableBase::parseLscData(sets, descriptor); + } lsc::ComponentsMap sampleForCrop([[maybe_unused]] const Rectangle &cropRectangle, @@ -38,16 +59,6 @@ public: << "Tabular LSC data doesn't support resampling"; return lscData_; } - -private: - int parseLscComponent(const ValueNode &yamlSet, - unsigned int ct, const LscDescriptor &descriptor); - std::vector parseTable(const ValueNode &tuningData, - const char *prop, - unsigned int numHCells, - unsigned int numVCells); - - lsc::ComponentsMap lscData_; }; } /* namespace ipa */ diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h index e7d3091a36c5..31156f56cd21 100644 --- a/src/ipa/rkisp1/algorithms/lsc.h +++ b/src/ipa/rkisp1/algorithms/lsc.h @@ -13,6 +13,7 @@ #include "libcamera/internal/value_node.h" +#include "libipa/fixedpoint.h" #include "libipa/lsc.h" #include "algorithm.h" @@ -58,7 +59,7 @@ private: unsigned int lastAppliedCt_; unsigned int lastAppliedQuantizedCt_; - LscAlgorithm lscAlgo_; + LscAlgorithm> lscAlgo_; }; } /* namespace ipa::rkisp1::algorithms */