From patchwork Mon Jul 6 08:01:43 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 27223 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 54070C330A for ; Mon, 6 Jul 2026 08:02:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C6AA566063; Mon, 6 Jul 2026 10:02:30 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ovdmCUrc"; 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 7F6D56602D for ; Mon, 6 Jul 2026 10:02:12 +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 EA2D73FC2; Mon, 6 Jul 2026 10:01:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1783324884; bh=gU7UoVQjDoxjMvS0BE4xv1ojYvnjxU9I7ZQIqWCiBUY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ovdmCUrcccbkaaf2ZfMEPE7mbK3Ah4smWggu44dJHo5coa/tQJKQsuAoEgfS+I+Dw IJn+VB9TfJr/IB+MKRpqAnNrtpd3nkRZJXyfv62acujnKkKKjP+CMSa752MKhZWeSF 6XA5tX3tky7i1m3MrtMFBRZSVJzJ51Crj5KKBmuQ= From: Jacopo Mondi Date: Mon, 06 Jul 2026 10:01:43 +0200 Subject: [PATCH v3 23/35] ipa: libipa: lsc: Move sizesListToPositions() back to rkisp1 MIME-Version: 1.0 Message-Id: <20260706-libipa-algorithms-v3-23-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=9808; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=gU7UoVQjDoxjMvS0BE4xv1ojYvnjxU9I7ZQIqWCiBUY=; b=owEBbAKT/ZANAwAKAXI0Bo8WoVY8AcsmYgBqS2Dx6AsDYWVTbQexLPVjWZDH5248IuMXw2nrC q6sgtermP2JAjIEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaktg8QAKCRByNAaPFqFW PGmLD/imCuPIfH6JVeojG7QO2zVjLe532Fyxpceb5UKj5QfEAs3VQ3KEpGA6UWER2nnmioLHfZw rWgc6NiVo1cDAI1Ur2EEN+Pe8DonTrbvCDpQQzzrpgtmpUphw+06Y+IbmPOAnvLhJSjRTRslmKG DPsifetT7EdZH1bgWVvuJy7BlZGWe8dWd2859mSgGSB+M4+UQU1ceF4wZ9jxKkHBwmPhC9qtS7H 5PsyvXYGIyYr+aDcOaFppTlb1Ol4RRrZW86bAFjkWDCNNZ9iREoipzjkc0eWP4ImEwbu0T534TV xF+HnywwGyQ12kb9UkUKWp2OSj00qRuAYvQkj306PQYiuiBS2Nhi5aZxlXStwNU0FFXvUtszqad jCD7TXjpdqc+xG+oxBrOQP4+AymQrDPAUDgzdjUHHGFELn8b4i7DtavEg3crnQViLZmepXTGTxK xZoFvQ79ewRfdPcbyfh8SD4aZ711rLFrn2h0yVNp728NkDu4IZGw9+ZGaa9CF58vUpKCLktWlEu GuN1Wm+IKJ73+cXCYDcwwWwt2BK6+04wCFzjmWGEWPH1n8xoCh22/fr+ZVgHq11Hdt4K4Dgs3LK 5gIV5qyWST0KpCZhTeDeXLluQ1v9kEGUcKKaYpiBc9q5p+vOB3GmI1GdsSAm/nbDGPb7BCRmOwg VFyVXs+PUqrLV 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::sampleForCrop() function is designed to receive a list of segment sizes and translates it to a list of grid vertexes internally with the sizesListToPositions() function. As the sizesListToPositions() implementation is RkISP1-specific, move it back to the RkISP1 IPA and change the prototype of the sampleForCrop() function to accept a vector of grid vertexes instead of a span of segment sizes. Signed-off-by: Jacopo Mondi --- src/ipa/libipa/lsc_base.cpp | 6 +++--- src/ipa/libipa/lsc_base.h | 3 +-- src/ipa/libipa/lsc_polynomial.cpp | 38 ++++---------------------------------- src/ipa/libipa/lsc_polynomial.h | 4 +--- src/ipa/libipa/lsc_table.h | 4 ++-- src/ipa/rkisp1/algorithms/lsc.cpp | 32 +++++++++++++++++++++++++++++++- src/ipa/rkisp1/algorithms/lsc.h | 3 +++ 7 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/ipa/libipa/lsc_base.cpp b/src/ipa/libipa/lsc_base.cpp index b055249c066a..7b0216b689c4 100644 --- a/src/ipa/libipa/lsc_base.cpp +++ b/src/ipa/libipa/lsc_base.cpp @@ -88,8 +88,8 @@ void Interpolator:: * \fn LscImplementation::sampleForCrop * \brief Re-sample the lsc components for \a cropRectangle * \param[in] cropRectangle The sensor analogue crop rectangle - * \param[in] xSizes List of horizontal positions of the lsc grid nodes - * \param[in] ySizes List of vertical positions of the lsc grid nodes + * \param[in] xPos List of horizontal positions of the lsc grid nodes + * \param[in] yPos List of vertical positions of the lsc grid nodes * * Lsc tables have to be re-sampled every time a new sensor configuration is * used, as each streaming session might use a different sensor crop rectangle @@ -98,7 +98,7 @@ void Interpolator:: * \a cropRectangle represents the size of the frame on which the Lsc tables * have to be re-sampled on. * - * \a xSizes and \a ySizes represent the position of the grid nodes vertexes in + * \a xPos and \a yPos represent the position of the grid nodes vertexes in * the [0, 1] interval. In example an equally spaced grid of 16 nodes will have * each segment of size 0.0625 and the list of nodes position will be * [0, 0.0625, 0.125, 0.1875, ... , 1]. It is expected that the first position diff --git a/src/ipa/libipa/lsc_base.h b/src/ipa/libipa/lsc_base.h index 51cc35888209..8d1843a5d4fd 100644 --- a/src/ipa/libipa/lsc_base.h +++ b/src/ipa/libipa/lsc_base.h @@ -65,8 +65,7 @@ public: virtual lsc::ComponentsMap sampleForCrop(const Rectangle &cropRectangle, - Span xSizes, - Span ySizes) = 0; + std::vector xPos, std::vector yPos); }; } /* namespace ipa */ diff --git a/src/ipa/libipa/lsc_polynomial.cpp b/src/ipa/libipa/lsc_polynomial.cpp index 5c4ffc98797e..f39122963019 100644 --- a/src/ipa/libipa/lsc_polynomial.cpp +++ b/src/ipa/libipa/lsc_polynomial.cpp @@ -184,8 +184,8 @@ int LscPolynomial::parseLscData(const ValueNode &sets) /** * \brief Re-sample the lsc components for \a cropRectangle * \param[in] cropRectangle The sensor analogue crop rectangle - * \param[in] xSizes List of horizontal positions of the lsc grid nodes - * \param[in] ySizes List of vertical positions of the lsc grid nodes + * \param[in] xPos List of horizontal positions of the lsc grid nodes + * \param[in] yPos List of vertical positions of the lsc grid nodes * * Lsc tables have to be re-sampled every time a new sensor configuration is * used, as each streaming session might use a different sensor crop rectangle. @@ -197,7 +197,7 @@ int LscPolynomial::parseLscData(const ValueNode &sets) * \a cropRectangle represents the size of the frame on which the Lsc tables * have to be re-sampled on. * - * \a xSizes and \a ySizes represent the position of the grid nodes vertexes in + * \a xPos and \a yPos represent the position of the grid nodes vertexes in * the [0, 1] interval. In example an equally spaced grid of 16 nodes will have * each segment of size 0.0625 and the list of nodes position will be * [0, 0.0625, 0.125, 0.1875, ... , 1]. It is expected that the first position @@ -205,11 +205,8 @@ int LscPolynomial::parseLscData(const ValueNode &sets) */ lsc::ComponentsMap LscPolynomial::sampleForCrop(const Rectangle &cropRectangle, - Span xSizes, - Span ySizes) + std::vector xPos, std::vector yPos) { - std::vector xPos = sizesListToPositions(xSizes); - std::vector yPos = sizesListToPositions(ySizes); lsc::ComponentsMap components; @@ -259,33 +256,6 @@ LscPolynomial::samplePolynomial(const lsc::Polynomial &poly, return samples; } -/* - * The rkisp1 LSC grid spacing is defined by the cell sizes on the top-left - * quadrant of the grid. This is then mirrored in hardware to the other - * quadrants. See parseSizes() for further details. For easier handling, this - * function converts the cell sizes of half the grid to a list of position of - * the whole grid (on one axis). Example: - * - * input: | 0.2 | 0.3 | - * output: 0.0 0.2 0.5 0.8 1.0 - */ -std::vector -LscPolynomial::sizesListToPositions(Span sizes) -{ - const int half = sizes.size(); - std::vector positions(half * 2 + 1); - double x = 0.0; - - positions[half] = 0.5; - for (int i = 1; i <= half; i++) { - x += sizes[half - i]; - positions[half - i] = 0.5 - x; - positions[half + i] = 0.5 + x; - } - - return positions; -} - } /* namespace ipa */ #ifndef __DOXYGEN__ diff --git a/src/ipa/libipa/lsc_polynomial.h b/src/ipa/libipa/lsc_polynomial.h index 17c2c34499f0..d2276ecc6f6b 100644 --- a/src/ipa/libipa/lsc_polynomial.h +++ b/src/ipa/libipa/lsc_polynomial.h @@ -71,11 +71,9 @@ public: lsc::ComponentsMap sampleForCrop(const Rectangle &cropRectangle, - Span xSizes, - Span ySizes) override; + std::vector xPos, std::vector yPos) override; private: - std::vector sizesListToPositions(Span sizes); std::vector samplePolynomial(const lsc::Polynomial &poly, Span xPositions, Span yPositions, diff --git a/src/ipa/libipa/lsc_table.h b/src/ipa/libipa/lsc_table.h index 0983b78c3f6b..67c7464ea5b6 100644 --- a/src/ipa/libipa/lsc_table.h +++ b/src/ipa/libipa/lsc_table.h @@ -30,8 +30,8 @@ public: lsc::ComponentsMap sampleForCrop([[maybe_unused]] const Rectangle &cropRectangle, - [[maybe_unused]] Span xSizes, - [[maybe_unused]] Span ySizes) override + [[maybe_unused]] std::vector xPos, + [[maybe_unused]] std::vector yPos) override { LOG(LscTable, Warning) << "Tabular LSC data doesn't support resampling"; diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index 0312ce2f8bb1..f393f101b740 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -70,6 +70,9 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context, if (xSize_.empty() || ySize_.empty()) return -EINVAL; + xPos_ = sizesListToPositions(xSize_); + yPos_ = sizesListToPositions(ySize_); + /* Get all defined sets to apply. */ const ValueNode &sets = tuningData["sets"]; if (!sets.isList()) { @@ -138,6 +141,33 @@ std::vector LensShadingCorrection::parseSizes(const ValueNode &tuningDat return sizes; } +/* + * The rkisp1 LSC grid spacing is defined by the cell sizes on the top-left + * quadrant of the grid. This is then mirrored in hardware to the other + * quadrants. See parseSizes() for further details. For easier handling, this + * function converts the cell sizes of half the grid to a list of position of + * the whole grid (on one axis). Example: + * + * input: | 0.2 | 0.3 | + * output: 0.0 0.2 0.5 0.8 1.0 + */ +std::vector +LensShadingCorrection::sizesListToPositions(Span sizes) +{ + const int half = sizes.size(); + std::vector positions(half * 2 + 1); + double x = 0.0; + + positions[half] = 0.5; + for (int i = 1; i <= half; i++) { + x += sizes[half - i]; + positions[half - i] = 0.5 - x; + positions[half + i] = 0.5 + x; + } + + return positions; +} + /** * \copydoc libcamera::ipa::Algorithm::configure */ @@ -171,7 +201,7 @@ int LensShadingCorrection::configure(IPAContext &context, LOG(RkISP1Lsc, Debug) << "Sample LSC data for " << configInfo.analogCrop; lsc::ComponentsMap shadingData = algo_->sampleForCrop(configInfo.analogCrop, - xSize_, ySize_); + xPos_, yPos_); sets_.setData(std::move(shadingData)); context.activeState.lsc.enabled = true; diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h index ee037353bbe4..06aa7a5f133c 100644 --- a/src/ipa/rkisp1/algorithms/lsc.h +++ b/src/ipa/rkisp1/algorithms/lsc.h @@ -41,9 +41,12 @@ private: void copyTable(rkisp1_cif_isp_lsc_config &config, const lsc::Components &set0); std::vector parseSizes(const ValueNode &tuningData, const char *prop); + std::vector sizesListToPositions(Span sizes); std::vector xSize_; std::vector ySize_; + std::vector xPos_; + std::vector yPos_; uint16_t xGrad_[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE]; uint16_t yGrad_[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE]; uint16_t xSizes_[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE];