From patchwork Wed Jul 8 15:51:00 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 27327 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 2AAE4C3330 for ; Wed, 8 Jul 2026 15:51:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BF2B566112; Wed, 8 Jul 2026 17:51:44 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="NjuNL8iH"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D83BB660A7 for ; Wed, 8 Jul 2026 17:51:17 +0200 (CEST) Received: from [192.168.1.182] (93-46-82-201.ip106.fastwebnet.it [93.46.82.201]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id EFCD93FB2; Wed, 8 Jul 2026 17:50:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1783525828; bh=Xx5zJIB1zkJdCGevazKOxH+Pfpu5Y2Nin5HQC5SwJro=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=NjuNL8iHPORAO0SZhRMeWNOWX6qktSnsPdu6M4Auffn9SdkXt3FhLuT8TsqwJEu4r X8VjqTRLSdpQnIfCso06fgAZR1x3B1FPzn5KdVB6KrKcqmRtZfEqGqWEyliiGEHxmQ 0RNFPMq0namsx2LPg5mS46sAIaU5ah6vyyEY2GYg= From: Jacopo Mondi Date: Wed, 08 Jul 2026 17:51:00 +0200 Subject: [PATCH v5 18/36] ipa: libipa: lsc_table: Move LscTable from RkISP1 MIME-Version: 1.0 Message-Id: <20260708-libipa-algorithms-v5-18-0759d0359f52@ideasonboard.com> References: <20260708-libipa-algorithms-v5-0-0759d0359f52@ideasonboard.com> In-Reply-To: <20260708-libipa-algorithms-v5-0-0759d0359f52@ideasonboard.com> To: libcamera-devel@lists.libcamera.org, Stefan Klug Cc: Jacopo Mondi , Kieran Bingham X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=8313; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=Xx5zJIB1zkJdCGevazKOxH+Pfpu5Y2Nin5HQC5SwJro=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBqTnHm2lXJhzaCYOtMDp/oPJJ1zKVenT5DTBlc8 PwYIj2viFSJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCak5x5gAKCRByNAaPFqFW PJ3/EACnPXG35lF1d+9gE1cBshVPUwHJEEeHBdr0AwGq7kxx21zNF+4hNN/LIV8Fiv75GqxkkDp wed3LU3Xg9PWkxcSg9Ia6CubCtd2nR1meT4laDm7KSFElSl7ZWmuSkSQb2Ozpit7o+dySmdHJwe qwGuAkfPi4pTFfvuWUg4p1TuX3/GnbTvnWqziuDsPaW2iKghy8kwoLwnbqlVsH6iYjHnKTguLHS Ket3qr5dkqVKzBkEKx6vk1os8wwJ+XpXAusnAhxBmvJvL9ts5e+XKBPlLXxEIKIEqdaYwXJ0fpS 5ZVeHv3zfTEUKf3eI+JjsR1eBHYTu7ri7BIpX5VUy/1jPignUNSBxh+HOq+Pn6smrqgJt9kNRDq zsGn1mSIhEz6L8RRP62hUzPj3+Y+JaaVEqSqBmkH+rs+do7l5jImaJb4sbkSEgu8z/pUdtXfb+D S8znAoA7ksY41LLk72h752jkVo5/5Vi0fMfksn2hDlmVaXp0pBbuFjmmdtxyiGRdidFEHzS2Dus Rx8CqIeXHV2KaYzhacudYqQTzWppDwEFOdW+p0v+C252fLAiK0/6LVy4RLUitr2KF06Z6GQsj+6 g1YlqAS1pV//wMTgROw2MvqMRACl4vQRF0OsKnqrTsOTaseQpn3sENr8PWynvg9br/06UZdNx4b 683e+k1ncNSMrFg== 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" 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 Reviewed-by: Kieran Bingham --- 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(-) diff --git a/src/ipa/libipa/lsc_table.cpp b/src/ipa/libipa/lsc_table.cpp new file mode 100644 index 000000000000..47dff156963a --- /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(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 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 table = + tuningData[prop].get>().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 + +#include +#include + +#include + +#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 xSizes, + [[maybe_unused]] Span ySizes) override + { + LOG(LscTable, Warning) + << "Tabular LSC data doesn't support resampling"; + return lscData_; + } + +private: + std::vector 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 b161798763cb..f32c46084dd1 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 xSizes, - [[maybe_unused]] Span ySizes) override - { - LOG(RkISP1Lsc, Warning) - << "Tabular LSC data doesn't support resampling"; - return lscData_; - } - -private: - std::vector 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(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 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 table = - tuningData[prop].get>().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 parseSizes(const ValueNode &tuningData, const char *prop) { @@ -190,7 +113,7 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context, std::string type = tuningData["type"].get("table"); if (type == "table") { LOG(RkISP1Lsc, Debug) << "Loading tabular LSC data."; - algo_ = std::make_unique(); + algo_ = std::make_unique(); ret = algo_->parseLscData(sets); } else if (type == "polynomial") { LOG(RkISP1Lsc, Debug) << "Loading polynomial LSC data.";