From patchwork Tue Oct 14 07:52:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24617 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 65522BF415 for ; Tue, 14 Oct 2025 07:53:02 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1759960580; Tue, 14 Oct 2025 09:53:02 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="nAj7EOVQ"; 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 5D9AF60316 for ; Tue, 14 Oct 2025 09:53:01 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 13D13C73; Tue, 14 Oct 2025 09:51:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428283; bh=NY4t52LW7OV3tZg/BUnq/jRegL5QfDM5Iu0/WOHoxt4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nAj7EOVQFLsHlc0dL2hUZQOhFFSXSy3IcVVoDTdc+oPj3V26IEGzrRI/B5gLEV+kl NAFqCYhg3OWvPGeWIASVGePxlgCM5yULv72uCPY8jvFl+QcM4MWnCn0By0AWHUa+hy 5b8CCxWG0mmDgnT3UODrOXh5om8szcqsRT8jYHqY= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 01/12] ipa: rkisp1: lsc: Drop unused member variable Date: Tue, 14 Oct 2025 09:52:23 +0200 Message-ID: <20251014075252.2876485-2-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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 Components::ct member is not used anywhere. Drop it. Signed-off-by: Stefan Klug Reviewed-by: Barnabás Pőcze --- src/ipa/rkisp1/algorithms/lsc.cpp | 2 -- src/ipa/rkisp1/algorithms/lsc.h | 1 - 2 files changed, 3 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index e7301bfec863..ab0ada4eed46 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -113,7 +113,6 @@ public: return -EINVAL; } - set.ct = ct; pr->setReferenceImageSize(sensorSize_); pgr->setReferenceImageSize(sensorSize_); pgb->setReferenceImageSize(sensorSize_); @@ -221,7 +220,6 @@ public: LensShadingCorrection::Components &set = lscData[ct]; - set.ct = ct; set.r = parseTable(yamlSet, "r"); set.gr = parseTable(yamlSet, "gr"); set.gb = parseTable(yamlSet, "gb"); diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h index 5a0824e36dd5..0e3745d5589c 100644 --- a/src/ipa/rkisp1/algorithms/lsc.h +++ b/src/ipa/rkisp1/algorithms/lsc.h @@ -30,7 +30,6 @@ public: RkISP1Params *params) override; struct Components { - uint32_t ct; std::vector r; std::vector gr; std::vector gb; From patchwork Tue Oct 14 07:52:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24618 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 43179BF415 for ; Tue, 14 Oct 2025 07:53:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E6D25605D4; Tue, 14 Oct 2025 09:53:05 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="vsWInhWZ"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 56B1260316 for ; Tue, 14 Oct 2025 09:53:04 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 23C5CC73; Tue, 14 Oct 2025 09:51:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428286; bh=9/T1Ds6PeIVNp1j6ta4M8wTuGk5o/qdncfeLZwe0O7E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vsWInhWZxJzcK+TmPVJDaGnv0Wcynsr2ensRmvGX3exDYmQyi9KwQ/uzO5zekut57 cBcmGJV/xHMxcTw64mjeLr0/1SGUWj2CqZZKBGKXUZCyGrb8wotPn7eN6bSKRLvkPW pVjFNUIC5Es0Z/UcYwFa2xmwrfwc1PSzctILYbfg= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 02/12] ipa: rkisp1: lsc: Drop unused function declaration Date: Tue, 14 Oct 2025 09:52:24 +0200 Message-ID: <20251014075252.2876485-3-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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 interpolateTable() function is not implemented anywhere. Drop the declaration. Signed-off-by: Stefan Klug Reviewed-by: Barnabás Pőcze --- src/ipa/rkisp1/algorithms/lsc.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h index 0e3745d5589c..7b68dda1a0d4 100644 --- a/src/ipa/rkisp1/algorithms/lsc.h +++ b/src/ipa/rkisp1/algorithms/lsc.h @@ -39,9 +39,6 @@ public: private: void setParameters(rkisp1_cif_isp_lsc_config &config); void copyTable(rkisp1_cif_isp_lsc_config &config, const Components &set0); - void interpolateTable(rkisp1_cif_isp_lsc_config &config, - const Components &set0, const Components &set1, - const uint32_t ct); ipa::Interpolator sets_; std::vector xSize_; From patchwork Tue Oct 14 07:52:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24619 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 D6862BF415 for ; Tue, 14 Oct 2025 07:53:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 872D7605B5; Tue, 14 Oct 2025 09:53:10 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="BZzqNSh2"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 098A06052F for ; Tue, 14 Oct 2025 09:53:08 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id CD7D1E70; Tue, 14 Oct 2025 09:51:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428289; bh=nk2bk2sb1dSQ4EJf68a+JRQex4nzNHtjgDhl74bB8B4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BZzqNSh2kPlK+rRjzD25krsNJjX3hTiI6SdH5pOi8IoRPAfP/Delc27QsXtwQNWhi UucJ9a9yq+0Ypt+BkOasmYHHbBczpGyjRNslJnUAH2Bj94iTEEvmhtVqp1IyEjrE7O HTB0Qfyu2qDUooQZlUI/z4gSAa9GH3z2nf79fER8= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 03/12] ipa: rkisp1: lsc: Replace assert with ASSERT Date: Tue, 14 Oct 2025 09:52:25 +0200 Message-ID: <20251014075252.2876485-4-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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" Replace assert() by ASSERT() and drop a set of unnecessary curly braces. Those were noticed in the former review but after the series was applied. Fix them now. Signed-off-by: Stefan Klug Reviewed-by: Barnabás Pőcze --- src/ipa/rkisp1/algorithms/lsc.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index ab0ada4eed46..c581e6441853 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -33,11 +33,10 @@ template void interpolateVector(const std::vector &a, const std::vector &b, std::vector &dest, double lambda) { - assert(a.size() == b.size()); + ASSERT(a.size() == b.size()); dest.resize(a.size()); - for (size_t i = 0; i < a.size(); i++) { + for (size_t i = 0; i < a.size(); i++) dest[i] = a[i] * (1.0 - lambda) + b[i] * lambda; - } } template<> @@ -167,8 +166,8 @@ private: double h = cropRectangle_.height / m; std::vector res; - assert(xSizes_.size() * 2 + 1 == k); - assert(ySizes_.size() * 2 + 1 == k); + ASSERT(xSizes_.size() * 2 + 1 == k); + ASSERT(ySizes_.size() * 2 + 1 == k); res.reserve(k * k); From patchwork Tue Oct 14 07:52:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24620 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 8FEF1BF415 for ; Tue, 14 Oct 2025 07:53:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 415DD605D7; Tue, 14 Oct 2025 09:53:12 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="cea6rgnK"; 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 046A4605D0 for ; Tue, 14 Oct 2025 09:53:11 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id ABDBC741; Tue, 14 Oct 2025 09:51:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428292; bh=9iKWzfrp5sGrmZ68X330iYb6beiyYZPZMkiEhz3X12Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cea6rgnKXAmQDRmpNFYDA4IdKxnMqtr/NhMGZQ/6nvh+seJ/h4IGs7wKMtQHraE5P 1ddow34OxvUVXhm+0D3hq9+8LkLk85oBYhU1SSdlFnlP5zKLOxn+xwpU+EMz4f8hmo UbIgRwUeiGCwPVz5CuUSGxpNn42qQ3RGQlMe75iY= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 04/12] ipa: rkisp1: lsc: Rename res to positions Date: Tue, 14 Oct 2025 09:52:26 +0200 Message-ID: <20251014075252.2876485-5-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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" Rename the res variable to positions which better describes the intent. This was commented in review after being merged. While at it, improve the documentation a bit. Signed-off-by: Stefan Klug --- src/ipa/rkisp1/algorithms/lsc.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index c581e6441853..bb58386ae646 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -132,9 +132,11 @@ public: private: /* - * The lsc grid has custom spacing defined on half the range (see - * parseSizes() for details). For easier handling this function converts - * the spaces vector to positions and mirrors them. E.g.: + * The rkisp1 LSC grid spacing is defined by the cell sizes on the first + * half of the grid. This is then mirrored in hardware to the other + * half. 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 @@ -142,17 +144,17 @@ private: std::vector sizesListToPositions(const std::vector &sizes) { const int half = sizes.size(); - std::vector res(half * 2 + 1); + std::vector positions(half * 2 + 1); double x = 0.0; - res[half] = 0.5; + positions[half] = 0.5; for (int i = 1; i <= half; i++) { x += sizes[half - i]; - res[half - i] = 0.5 - x; - res[half + i] = 0.5 + x; + positions[half - i] = 0.5 - x; + positions[half + i] = 0.5 + x; } - return res; + return positions; } std::vector samplePolynomial(const LscPolynomial &poly) From patchwork Tue Oct 14 07:52:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24621 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 BE27EBF415 for ; Tue, 14 Oct 2025 07:53:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 315CD605D0; Tue, 14 Oct 2025 09:53:14 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="mdnGsEWH"; 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 80A876052F for ; Tue, 14 Oct 2025 09:53:13 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 529AAC73; Tue, 14 Oct 2025 09:51:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428295; bh=dg6CvKFqBV5VDXoxIZfPMXvTEHeS9+it41urpZy1QOc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mdnGsEWHbCAbK+0oTy6/eyEns2TGI80c1Mt28pECMircG1XfSQUzUlCXtVfe55GWp g/C4uPxLoOv9atVb45nHrSb0bPz9kahYxdYM+K/Kqsc5Ia9/knMzYRi2hhXoh/Kt85 nhIyq6bu/UrzEY2HQUvFbXQi605Fx8hg9wsf4oMc= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 05/12] ipa: rkisp1: lsc: Rename res to ret Date: Tue, 14 Oct 2025 09:52:27 +0200 Message-ID: <20251014075252.2876485-6-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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" Rename res to ret as that is used in libcamera for return codes. Signed-off-by: Stefan Klug --- src/ipa/rkisp1/algorithms/lsc.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index bb58386ae646..e4938dbd657c 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -320,28 +320,29 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context, return -EINVAL; } + int ret = 0; std::map lscData; - int res = 0; + std::string type = tuningData["type"].get("table"); if (type == "table") { LOG(RkISP1Lsc, Debug) << "Loading tabular LSC data."; auto loader = LscTableLoader(); - res = loader.parseLscData(yamlSets, lscData); + ret = loader.parseLscData(yamlSets, lscData); } else if (type == "polynomial") { LOG(RkISP1Lsc, Debug) << "Loading polynomial LSC data."; auto loader = LscPolynomialLoader(context.sensorInfo.activeAreaSize, context.sensorInfo.analogCrop, xSize_, ySize_); - res = loader.parseLscData(yamlSets, lscData); + ret = loader.parseLscData(yamlSets, lscData); } else { LOG(RkISP1Lsc, Error) << "Unsupported LSC data type '" << type << "'"; - res = -EINVAL; + ret = -EINVAL; } - if (res) - return res; + if (ret) + return ret; sets_.setData(std::move(lscData)); From patchwork Tue Oct 14 07:52:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24622 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 A6735BF415 for ; Tue, 14 Oct 2025 07:53:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5D7F1605D7; Tue, 14 Oct 2025 09:53:18 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Y5VqH4Gt"; 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 E34146052F for ; Tue, 14 Oct 2025 09:53:16 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id AE836741; Tue, 14 Oct 2025 09:51:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428298; bh=Or5s/Vj6mdT0Vr3n+H+YktJqaQ/C57C4uaOKClLD6OI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y5VqH4GtsN97YsZVA9DYzfsQZHnS+4D4PX91LSPYgOC+6GIwiKqWrv6zuGHwtiApp tgV7CHJeCDW+zAhi9UMqvz+RktvvkpIdo2FbZf4hsWl5+7lRLGtsTXIGf1K/Axvrsv DuYZ1oNqWP/qUGcqnDGP6MvkoaQbzdiTnUHKFs+M= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 06/12] ipa: rkisp1: lsc: Rename res to samples Date: Tue, 14 Oct 2025 09:52:28 +0200 Message-ID: <20251014075252.2876485-7-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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" Rename res to samples to better describe the intent. This was noted in review after the series was merged. Signed-off-by: Stefan Klug Reviewed-by: Barnabás Pőcze --- src/ipa/rkisp1/algorithms/lsc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index e4938dbd657c..e46943f4bae0 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -166,12 +166,12 @@ private: double y0 = cropRectangle_.y / m; double w = cropRectangle_.width / m; double h = cropRectangle_.height / m; - std::vector res; + std::vector samples; ASSERT(xSizes_.size() * 2 + 1 == k); ASSERT(ySizes_.size() * 2 + 1 == k); - res.reserve(k * k); + samples.reserve(k * k); std::vector xPos(sizesListToPositions(xSizes_)); std::vector yPos(sizesListToPositions(ySizes_)); @@ -189,10 +189,10 @@ private: poly.sampleAtNormalizedPixelPos(xp, yp) * 1024); v = std::min(std::max(v, 1024), 4095); - res.push_back(v); + samples.push_back(v); } } - return res; + return samples; } Size sensorSize_; From patchwork Tue Oct 14 07:52:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24623 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 83084BF415 for ; Tue, 14 Oct 2025 07:53:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 26D33605E5; Tue, 14 Oct 2025 09:53:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="uIr13y69"; 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 A6B476052F for ; Tue, 14 Oct 2025 09:53:19 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 75C94C73; Tue, 14 Oct 2025 09:51:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428301; bh=/rju20fUx+t7fLoumYtsmjDtj7B8b7bm7Sk9WU1/3yM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uIr13y692kUX04fqMAps+Wr9b9+GG5PuxqoEdfrgj3RI8Yq5ZgM9WP+dsbP35WW0F 4c5osqkNW9rc3kYhQGQOk0pDHkL/XmJh3lIIjT/u24iDeIsdPKZlv3qpQXZ4GxXx39 lG7mT2juUuotNni0R9iIMDEvWXOAr1LEMF8c32nI= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 07/12] ipa: rksip1: lsc: Move function definitions out of class Date: Tue, 14 Oct 2025 09:52:29 +0200 Message-ID: <20251014075252.2876485-8-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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 function definitions out of the related classes. This was noted in review after the series was already merged. After trying it out I must admit that it really improves readability and reduces the indentation level by one. Signed-off-by: Stefan Klug --- Note: This patch contains no functional changes. `git diff --ignore-space-change` helps in verifying that. --- src/ipa/rkisp1/algorithms/lsc.cpp | 314 ++++++++++++++++-------------- 1 file changed, 163 insertions(+), 151 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index e46943f4bae0..0c1bb470c346 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -85,184 +85,196 @@ public: } int parseLscData(const YamlObject &yamlSets, - std::map &lscData) - { - const auto &sets = yamlSets.asList(); - for (const auto &yamlSet : sets) { - std::optional pr, pgr, pgb, pb; - uint32_t ct = yamlSet["ct"].get(0); - - if (lscData.count(ct)) { - LOG(RkISP1Lsc, Error) - << "Multiple sets found for " - << "color temperature " << ct; - return -EINVAL; - } - - LensShadingCorrection::Components &set = lscData[ct]; - pr = yamlSet["r"].get(); - pgr = yamlSet["gr"].get(); - pgb = yamlSet["gb"].get(); - pb = yamlSet["b"].get(); - - if (!(pr || pgr || pgb || pb)) { - LOG(RkISP1Lsc, Error) - << "Failed to parse polynomial for " - << "colour temperature " << ct; - return -EINVAL; - } - - pr->setReferenceImageSize(sensorSize_); - pgr->setReferenceImageSize(sensorSize_); - pgb->setReferenceImageSize(sensorSize_); - pb->setReferenceImageSize(sensorSize_); - set.r = samplePolynomial(*pr); - set.gr = samplePolynomial(*pgr); - set.gb = samplePolynomial(*pgb); - set.b = samplePolynomial(*pb); + std::map &lscData); + +private: + std::vector sizesListToPositions(const std::vector &sizes); + std::vector samplePolynomial(const LscPolynomial &poly); + + Size sensorSize_; + Rectangle cropRectangle_; + const std::vector &xSizes_; + const std::vector &ySizes_; +}; + +int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets, + std::map &lscData) +{ + const auto &sets = yamlSets.asList(); + for (const auto &yamlSet : sets) { + std::optional pr, pgr, pgb, pb; + uint32_t ct = yamlSet["ct"].get(0); + + if (lscData.count(ct)) { + LOG(RkISP1Lsc, Error) + << "Multiple sets found for " + << "color temperature " << ct; + return -EINVAL; } - if (lscData.empty()) { - LOG(RkISP1Lsc, Error) << "Failed to load any sets"; + LensShadingCorrection::Components &set = lscData[ct]; + pr = yamlSet["r"].get(); + pgr = yamlSet["gr"].get(); + pgb = yamlSet["gb"].get(); + pb = yamlSet["b"].get(); + + if (!(pr || pgr || pgb || pb)) { + LOG(RkISP1Lsc, Error) + << "Failed to parse polynomial for " + << "colour temperature " << ct; return -EINVAL; } - return 0; + pr->setReferenceImageSize(sensorSize_); + pgr->setReferenceImageSize(sensorSize_); + pgb->setReferenceImageSize(sensorSize_); + pb->setReferenceImageSize(sensorSize_); + set.r = samplePolynomial(*pr); + set.gr = samplePolynomial(*pgr); + set.gb = samplePolynomial(*pgb); + set.b = samplePolynomial(*pb); } -private: - /* - * The rkisp1 LSC grid spacing is defined by the cell sizes on the first - * half of the grid. This is then mirrored in hardware to the other - * half. 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 sizesListToPositions(const std::vector &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; - } + if (lscData.empty()) { + LOG(RkISP1Lsc, Error) << "Failed to load any sets"; + return -EINVAL; + } - return positions; + return 0; +} + +/* + * The rkisp1 LSC grid spacing is defined by the cell sizes on the first half of + * the grid. This is then mirrored in hardware to the other half. 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 LscPolynomialLoader::sizesListToPositions(const std::vector &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; } - std::vector samplePolynomial(const LscPolynomial &poly) - { - constexpr int k = RKISP1_CIF_ISP_LSC_SAMPLES_MAX; - - 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; - - ASSERT(xSizes_.size() * 2 + 1 == k); - ASSERT(ySizes_.size() * 2 + 1 == k); - - samples.reserve(k * k); - - std::vector xPos(sizesListToPositions(xSizes_)); - std::vector yPos(sizesListToPositions(ySizes_)); - - for (int y = 0; y < k; y++) { - for (int x = 0; x < k; x++) { - double xp = x0 + xPos[x] * w; - double yp = y0 + yPos[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::min(std::max(v, 1024), 4095); - samples.push_back(v); - } + return positions; +} + +std::vector LscPolynomialLoader::samplePolynomial(const LscPolynomial &poly) +{ + constexpr int k = RKISP1_CIF_ISP_LSC_SAMPLES_MAX; + + 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; + + ASSERT(xSizes_.size() * 2 + 1 == k); + ASSERT(ySizes_.size() * 2 + 1 == k); + + samples.reserve(k * k); + + std::vector xPos(sizesListToPositions(xSizes_)); + std::vector yPos(sizesListToPositions(ySizes_)); + + for (int y = 0; y < k; y++) { + for (int x = 0; x < k; x++) { + double xp = x0 + xPos[x] * w; + double yp = y0 + yPos[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::min(std::max(v, 1024), 4095); + samples.push_back(v); } - return samples; } - - Size sensorSize_; - Rectangle cropRectangle_; - const std::vector &xSizes_; - const std::vector &ySizes_; -}; + return samples; +} class LscTableLoader { public: int parseLscData(const YamlObject &yamlSets, - std::map &lscData) - { - const auto &sets = yamlSets.asList(); - - for (const auto &yamlSet : sets) { - uint32_t ct = yamlSet["ct"].get(0); - - if (lscData.count(ct)) { - LOG(RkISP1Lsc, Error) - << "Multiple sets found for color temperature " - << ct; - return -EINVAL; - } - - LensShadingCorrection::Components &set = lscData[ct]; - - set.r = parseTable(yamlSet, "r"); - set.gr = parseTable(yamlSet, "gr"); - set.gb = parseTable(yamlSet, "gb"); - set.b = parseTable(yamlSet, "b"); - - if (set.r.empty() || set.gr.empty() || - set.gb.empty() || set.b.empty()) { - LOG(RkISP1Lsc, Error) - << "Set for color temperature " << ct - << " is missing tables"; - return -EINVAL; - } - } + std::map &lscData); + +private: + std::vector parseTable(const YamlObject &tuningData, + const char *prop); +}; + +int LscTableLoader::parseLscData(const YamlObject &yamlSets, + std::map &lscData) +{ + const auto &sets = yamlSets.asList(); + + for (const auto &yamlSet : sets) { + uint32_t ct = yamlSet["ct"].get(0); - if (lscData.empty()) { - LOG(RkISP1Lsc, Error) << "Failed to load any sets"; + if (lscData.count(ct)) { + LOG(RkISP1Lsc, Error) + << "Multiple sets found for color temperature " + << ct; return -EINVAL; } - return 0; - } + LensShadingCorrection::Components &set = lscData[ct]; -private: - std::vector parseTable(const YamlObject &tuningData, - const char *prop) - { - static constexpr unsigned int kLscNumSamples = - RKISP1_CIF_ISP_LSC_SAMPLES_MAX * RKISP1_CIF_ISP_LSC_SAMPLES_MAX; + set.r = parseTable(yamlSet, "r"); + set.gr = parseTable(yamlSet, "gr"); + set.gb = parseTable(yamlSet, "gb"); + set.b = parseTable(yamlSet, "b"); - std::vector table = - tuningData[prop].getList().value_or(std::vector{}); - if (table.size() != kLscNumSamples) { + if (set.r.empty() || set.gr.empty() || + set.gb.empty() || set.b.empty()) { LOG(RkISP1Lsc, Error) - << "Invalid '" << prop << "' values: expected " - << kLscNumSamples - << " elements, got " << table.size(); - return {}; + << "Set for color temperature " << ct + << " is missing tables"; + return -EINVAL; } + } - return table; + if (lscData.empty()) { + LOG(RkISP1Lsc, Error) << "Failed to load any sets"; + return -EINVAL; } -}; + + return 0; +} + +std::vector LscTableLoader::parseTable(const YamlObject &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].getList().value_or(std::vector{}); + if (table.size() != kLscNumSamples) { + LOG(RkISP1Lsc, Error) + << "Invalid '" << prop << "' values: expected " + << kLscNumSamples + << " elements, got " << table.size(); + return {}; + } + + return table; +} static std::vector parseSizes(const YamlObject &tuningData, const char *prop) From patchwork Tue Oct 14 07:52:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24624 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 0F537BF415 for ; Tue, 14 Oct 2025 07:53:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B499F605DD; Tue, 14 Oct 2025 09:53:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="PHGBvyCp"; 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 D300E605D0 for ; Tue, 14 Oct 2025 09:53:22 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id A9082741; Tue, 14 Oct 2025 09:51:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428304; bh=pqB0nGkdsqNB9H6pqQ6rULwqSv30iPl+tcON4T3/W48=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PHGBvyCpMiLOF1ciUd4HxKjziFbjAsVeLd6GbUHChiR6Vpf6PqJas+tlcTFXXasgJ CzGgACpBeGnklZIDEubH3EQySyOUKpVwzx05rzc/9PqTcef3iIxUYBqwXKgMQXbwT1 aXYh294pam7mg7fy4YS7+hGvzH/eYlIIfZ0Dp9sM= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 08/12] ipa: rkisp1: lsc: Pass sampling positions into samplePolynomial Date: Tue, 14 Oct 2025 09:52:30 +0200 Message-ID: <20251014075252.2876485-9-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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" There is no need to recalculate the sampling positions over and over. Pass them as parameter into the sampling function. The vectors are still kept inside the loop as this is also a preparatory change for the upcoming refactoring. Signed-off-by: Stefan Klug Reviewed-by: Barnabás Pőcze --- src/ipa/rkisp1/algorithms/lsc.cpp | 37 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index 0c1bb470c346..2fbc8bd1b242 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -89,7 +89,9 @@ public: private: std::vector sizesListToPositions(const std::vector &sizes); - std::vector samplePolynomial(const LscPolynomial &poly); + std::vector samplePolynomial(const LscPolynomial &poly, + const std::vector &xPositions, + const std::vector &yPositions); Size sensorSize_; Rectangle cropRectangle_; @@ -129,10 +131,13 @@ int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets, pgr->setReferenceImageSize(sensorSize_); pgb->setReferenceImageSize(sensorSize_); pb->setReferenceImageSize(sensorSize_); - set.r = samplePolynomial(*pr); - set.gr = samplePolynomial(*pgr); - set.gb = samplePolynomial(*pgb); - set.b = samplePolynomial(*pb); + + std::vector xPos(sizesListToPositions(xSizes_)); + std::vector yPos(sizesListToPositions(ySizes_)); + set.r = samplePolynomial(*pr, xPos, yPos); + set.gr = samplePolynomial(*pgr, xPos, yPos); + set.gb = samplePolynomial(*pgb, xPos, yPos); + set.b = samplePolynomial(*pb, xPos, yPos); } if (lscData.empty()) { @@ -169,10 +174,10 @@ std::vector LscPolynomialLoader::sizesListToPositions(const std::vector< return positions; } -std::vector LscPolynomialLoader::samplePolynomial(const LscPolynomial &poly) +std::vector LscPolynomialLoader::samplePolynomial(const LscPolynomial &poly, + const std::vector &xPositions, + const std::vector &yPositions) { - constexpr int k = RKISP1_CIF_ISP_LSC_SAMPLES_MAX; - double m = poly.getM(); double x0 = cropRectangle_.x / m; double y0 = cropRectangle_.y / m; @@ -180,18 +185,12 @@ std::vector LscPolynomialLoader::samplePolynomial(const LscPolynomial double h = cropRectangle_.height / m; std::vector samples; - ASSERT(xSizes_.size() * 2 + 1 == k); - ASSERT(ySizes_.size() * 2 + 1 == k); - - samples.reserve(k * k); - - std::vector xPos(sizesListToPositions(xSizes_)); - std::vector yPos(sizesListToPositions(ySizes_)); + samples.reserve(xPositions.size() * yPositions.size()); - for (int y = 0; y < k; y++) { - for (int x = 0; x < k; x++) { - double xp = x0 + xPos[x] * w; - double yp = y0 + yPos[y] * h; + 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 From patchwork Tue Oct 14 07:52:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24625 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 9AAD7BF415 for ; Tue, 14 Oct 2025 07:53:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 503BC605E6; Tue, 14 Oct 2025 09:53:26 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="f3RAHuR/"; 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 3347C605E6 for ; Tue, 14 Oct 2025 09:53:25 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id ED5C6741; Tue, 14 Oct 2025 09:51:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428307; bh=wbAH6rM15jLZHDvo20itwrBqufMWQudO9JpuIDDPktw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=f3RAHuR/lcTsFV2GewoGJbcxcBnpdCFs0YxXkpbEK/EmUQpxyFVKhmpbbBtdLfN5a H+z7X6bO8HXeL6jeRvneku8ZWnfkmPkge2uTuZYsaust8Pd8bfJWcngBWo1zWmvd3h D6WLRJUzDh2YU8g1dvN3WUvWHP/AbQHQ0/HzaDxo= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 09/12] ipa: rkisp1: lsc: Pass crop rectangle as parameter Date: Tue, 14 Oct 2025 09:52:31 +0200 Message-ID: <20251014075252.2876485-10-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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" In preparation for the upcoming rework, pass the crop rectangle as parameter to samplePolynomial(). This patch contains no functional change. Signed-off-by: Stefan Klug Reviewed-by: Barnabás Pőcze --- src/ipa/rkisp1/algorithms/lsc.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index 2fbc8bd1b242..29cd7efd83ef 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -91,7 +91,8 @@ private: std::vector sizesListToPositions(const std::vector &sizes); std::vector samplePolynomial(const LscPolynomial &poly, const std::vector &xPositions, - const std::vector &yPositions); + const std::vector &yPositions, + const Rectangle &cropRectangle); Size sensorSize_; Rectangle cropRectangle_; @@ -134,10 +135,10 @@ int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets, std::vector xPos(sizesListToPositions(xSizes_)); std::vector yPos(sizesListToPositions(ySizes_)); - set.r = samplePolynomial(*pr, xPos, yPos); - set.gr = samplePolynomial(*pgr, xPos, yPos); - set.gb = samplePolynomial(*pgb, xPos, yPos); - set.b = samplePolynomial(*pb, xPos, yPos); + set.r = samplePolynomial(*pr, xPos, yPos, cropRectangle_); + set.gr = samplePolynomial(*pgr, xPos, yPos, cropRectangle_); + set.gb = samplePolynomial(*pgb, xPos, yPos, cropRectangle_); + set.b = samplePolynomial(*pb, xPos, yPos, cropRectangle_); } if (lscData.empty()) { @@ -176,13 +177,14 @@ std::vector LscPolynomialLoader::sizesListToPositions(const std::vector< std::vector LscPolynomialLoader::samplePolynomial(const LscPolynomial &poly, const std::vector &xPositions, - const std::vector &yPositions) + const std::vector &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; + 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()); From patchwork Tue Oct 14 07:52:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24626 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 65919BF415 for ; Tue, 14 Oct 2025 07:53:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 16407605ED; Tue, 14 Oct 2025 09:53:29 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="uwYJZXXQ"; 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 BDFF3605D0 for ; Tue, 14 Oct 2025 09:53:27 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 8CC3CC73; Tue, 14 Oct 2025 09:51:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428309; bh=cMre7HJg244MUXqGL2X0oASmhIDQ++HGk2yYZJ+FtKM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uwYJZXXQSdML2v/kAdCfl4QoiW1ZqABXqIB54lsMElsmUzhZAQrH3HbM3hqK2ue+t UvbCk8yPi20L06Z7SmlDIFByCpmgIGU9I6k5VRMQm8pPViFp63x5hSZpruhpiMhyye vVcVHQhvSZr0NXYM/mSg9JQCujF1guxIfw7hI1Rc= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 10/12] ipa: rkisp1: lsc: Resample polynomial lens shading tables at configure time Date: Tue, 14 Oct 2025 09:52:32 +0200 Message-ID: <20251014075252.2876485-11-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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 lens shading correction is always applied based on the sensor crop bounds. This leads to incorrect lens shading correction for analog crops that do not cover the whole sensor. To fix that, we need to adapt the lens shading table for the selected analog crop at configure time. Introduce an abstract ShadingDescriptor class that holds the lens shading information that can then be sampled at configure time for a specific crop rectangle. Resampling for a specific crop is only implemented for polynomial lsc data. For tabular data, a warning is logged and the unmodified table is returned. This matches the current functionality for tabular data and is a huge improvement for polynomial data. Signed-off-by: Stefan Klug --- src/ipa/rkisp1/algorithms/lsc.cpp | 230 +++++++++++++++++++----------- src/ipa/rkisp1/algorithms/lsc.h | 14 ++ 2 files changed, 157 insertions(+), 87 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index 29cd7efd83ef..68cf35064182 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -70,38 +70,124 @@ namespace ipa::rkisp1::algorithms { LOG_DEFINE_CATEGORY(RkISP1Lsc) -class LscPolynomialLoader +class LscPolynomialShadingDescriptor : public LensShadingCorrection::ShadingDescriptor { public: - LscPolynomialLoader(const Size &sensorSize, - const Rectangle &cropRectangle, - const std::vector &xSizes, - const std::vector &ySizes) - : sensorSize_(sensorSize), - cropRectangle_(cropRectangle), - xSizes_(xSizes), - ySizes_(ySizes) + LscPolynomialShadingDescriptor(const LscPolynomial &pr, const LscPolynomial &pgr, + const LscPolynomial &pgb, const LscPolynomial &pb) + : pr_(pr), pgr_(pgr), pgb_(pgb), pb_(pb) { } - int parseLscData(const YamlObject &yamlSets, - std::map &lscData); + void sampleForCrop(const Rectangle &cropRectangle, + const std::vector &xSizes, + const std::vector &ySizes, + LensShadingCorrection::Components &components) override; private: - std::vector sizesListToPositions(const std::vector &sizes); std::vector samplePolynomial(const LscPolynomial &poly, const std::vector &xPositions, const std::vector &yPositions, const Rectangle &cropRectangle); + std::vector sizesListToPositions(const std::vector &sizes); + + LscPolynomial pr_; + LscPolynomial pgr_; + LscPolynomial pgb_; + LscPolynomial pb_; +}; + +void LscPolynomialShadingDescriptor::sampleForCrop(const Rectangle &cropRectangle, + const std::vector &xSizes, + const std::vector &ySizes, + LensShadingCorrection::Components &components) +{ + std::vector xPos = sizesListToPositions(xSizes); + std::vector yPos = sizesListToPositions(ySizes); + components.r = samplePolynomial(pr_, xPos, yPos, cropRectangle); + components.gr = samplePolynomial(pgr_, xPos, yPos, cropRectangle); + components.gb = samplePolynomial(pgb_, xPos, yPos, cropRectangle); + components.b = samplePolynomial(pb_, xPos, yPos, cropRectangle); +} + +std::vector +LscPolynomialShadingDescriptor::samplePolynomial(const LscPolynomial &poly, + const std::vector &xPositions, + const std::vector &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::min(std::max(v, 1024), 4095); + samples.push_back(v); + } + } + return samples; +} + +/* + * The rkisp1 LSC grid spacing is defined by the cell sizes on the first half of + * the grid. This is then mirrored in hardware to the other half. 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 +LscPolynomialShadingDescriptor::sizesListToPositions(const std::vector &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; +} + +class LscPolynomialLoader +{ +public: + LscPolynomialLoader(const Size &sensorSize) : sensorSize_(sensorSize) + { + } + + int parseLscData(const YamlObject &yamlSets, + LensShadingCorrection::ShadingDescriptorMap &lscData); + +private: Size sensorSize_; - Rectangle cropRectangle_; - const std::vector &xSizes_; - const std::vector &ySizes_; }; int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets, - std::map &lscData) + LensShadingCorrection::ShadingDescriptorMap &lscData) { const auto &sets = yamlSets.asList(); for (const auto &yamlSet : sets) { @@ -115,7 +201,6 @@ int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets, return -EINVAL; } - LensShadingCorrection::Components &set = lscData[ct]; pr = yamlSet["r"].get(); pgr = yamlSet["gr"].get(); pgb = yamlSet["gb"].get(); @@ -133,12 +218,9 @@ int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets, pgb->setReferenceImageSize(sensorSize_); pb->setReferenceImageSize(sensorSize_); - std::vector xPos(sizesListToPositions(xSizes_)); - std::vector yPos(sizesListToPositions(ySizes_)); - set.r = samplePolynomial(*pr, xPos, yPos, cropRectangle_); - set.gr = samplePolynomial(*pgr, xPos, yPos, cropRectangle_); - set.gb = samplePolynomial(*pgb, xPos, yPos, cropRectangle_); - set.b = samplePolynomial(*pb, xPos, yPos, cropRectangle_); + lscData.emplace( + ct, std::make_unique( + *pr, *pgr, *pgb, *pb)); } if (lscData.empty()) { @@ -149,70 +231,33 @@ int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets, return 0; } -/* - * The rkisp1 LSC grid spacing is defined by the cell sizes on the first half of - * the grid. This is then mirrored in hardware to the other half. 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 LscPolynomialLoader::sizesListToPositions(const std::vector &sizes) +class LscTableShadingDescriptor : public LensShadingCorrection::ShadingDescriptor { - 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; +public: + LscTableShadingDescriptor(LensShadingCorrection::Components components) + : lscData_(std::move(components)) + { } - return positions; -} - -std::vector LscPolynomialLoader::samplePolynomial(const LscPolynomial &poly, - const std::vector &xPositions, - const std::vector &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::min(std::max(v, 1024), 4095); - samples.push_back(v); - } + void sampleForCrop([[maybe_unused]] const Rectangle &cropRectangle, + [[maybe_unused]] const std::vector &xSizes, + [[maybe_unused]] const std::vector &ySizes, + LensShadingCorrection::Components &components) + { + LOG(RkISP1Lsc, Warning) + << "Tabular LSC data doesn't support resampling."; + components = lscData_; } - return samples; -} + +private: + LensShadingCorrection::Components lscData_; +}; class LscTableLoader { public: int parseLscData(const YamlObject &yamlSets, - std::map &lscData); + LensShadingCorrection::ShadingDescriptorMap &lscData); private: std::vector parseTable(const YamlObject &tuningData, @@ -220,7 +265,7 @@ private: }; int LscTableLoader::parseLscData(const YamlObject &yamlSets, - std::map &lscData) + LensShadingCorrection::ShadingDescriptorMap &lscData) { const auto &sets = yamlSets.asList(); @@ -234,8 +279,7 @@ int LscTableLoader::parseLscData(const YamlObject &yamlSets, return -EINVAL; } - LensShadingCorrection::Components &set = lscData[ct]; - + LensShadingCorrection::Components set; set.r = parseTable(yamlSet, "r"); set.gr = parseTable(yamlSet, "gr"); set.gb = parseTable(yamlSet, "gb"); @@ -248,6 +292,9 @@ int LscTableLoader::parseLscData(const YamlObject &yamlSets, << " is missing tables"; return -EINVAL; } + + lscData.emplace( + ct, std::make_unique(std::move(set))); } if (lscData.empty()) { @@ -334,7 +381,7 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context, } int ret = 0; - std::map lscData; + std::map> lscData; std::string type = tuningData["type"].get("table"); if (type == "table") { @@ -343,10 +390,11 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context, ret = loader.parseLscData(yamlSets, lscData); } else if (type == "polynomial") { LOG(RkISP1Lsc, Debug) << "Loading polynomial LSC data."; - auto loader = LscPolynomialLoader(context.sensorInfo.activeAreaSize, - context.sensorInfo.analogCrop, - xSize_, - ySize_); + /* + * \todo: Most likely the reference frame should be native_size. + * Let's wait how the internal discussions progress. + */ + auto loader = LscPolynomialLoader(context.sensorInfo.activeAreaSize); ret = loader.parseLscData(yamlSets, lscData); } else { LOG(RkISP1Lsc, Error) << "Unsupported LSC data type '" @@ -357,7 +405,7 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context, if (ret) return ret; - sets_.setData(std::move(lscData)); + shadingDescriptors_.swap(lscData); return 0; } @@ -393,6 +441,14 @@ int LensShadingCorrection::configure(IPAContext &context, yGrad_[i] = std::round(32768 / ySizes_[i]); } + LOG(RkISP1Lsc, Debug) << "Sample LSC data for " << configInfo.analogCrop; + std::map shadingData; + for (auto const &[t, descriptor] : shadingDescriptors_) + descriptor->sampleForCrop(configInfo.analogCrop, xSize_, ySize_, + shadingData[t]); + + sets_.setData(std::move(shadingData)); + context.configuration.lsc.enabled = true; return 0; } diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h index 7b68dda1a0d4..43fee337931f 100644 --- a/src/ipa/rkisp1/algorithms/lsc.h +++ b/src/ipa/rkisp1/algorithms/lsc.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include "libipa/interpolator.h" @@ -36,10 +37,23 @@ public: std::vector b; }; + class ShadingDescriptor + { + public: + virtual ~ShadingDescriptor() = default; + virtual void sampleForCrop(const Rectangle &cropRectangle, + const std::vector &xSizes, + const std::vector &ySizes, + Components &components) = 0; + }; + + using ShadingDescriptorMap = std::map>; + private: void setParameters(rkisp1_cif_isp_lsc_config &config); void copyTable(rkisp1_cif_isp_lsc_config &config, const Components &set0); + std::map> shadingDescriptors_; ipa::Interpolator sets_; std::vector xSize_; std::vector ySize_; From patchwork Tue Oct 14 07:52:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24627 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 E2A33BF415 for ; Tue, 14 Oct 2025 07:53:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A6500605EA; Tue, 14 Oct 2025 09:53:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="rNjLIFZq"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A5CE4605DD for ; Tue, 14 Oct 2025 09:53:31 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 2712CC73; Tue, 14 Oct 2025 09:51:53 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428313; bh=2Hc+TYFyl1w104gmWwZ01Zd68dWJEywjDmfnavqXN/o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rNjLIFZqm/dSwQr5v7l8DuI5Myiwu+zpuQhxwFAQTas140NCh7UergAMIfa7eJ3hF MJOyFEV2cXkQKfUakOccAA7jlTjpbqACVjqTCYLfwhRxsnckCa5tpL1aYfLey6Vg8m mJskxWNaDKWyrejWqfDifTlfNFKBm6CR3hFvlqeU= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Jacopo Mondi Subject: [PATCH v1 11/12] libcamera: control_ids: Introduce LensShadingEnable Date: Tue, 14 Oct 2025 09:52:33 +0200 Message-ID: <20251014075252.2876485-12-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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" Introduce a control to enable and disable LSC and replace the draft android control. Signed-off-by: Jacopo Mondi Signed-off-by: Stefan Klug --- src/android/camera_capabilities.cpp | 4 ++-- src/libcamera/control_ids_core.yaml | 6 ++++++ src/libcamera/control_ids_draft.yaml | 14 -------------- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp index b161bc6b3ed6..6fbd83695dfc 100644 --- a/src/android/camera_capabilities.cpp +++ b/src/android/camera_capabilities.cpp @@ -1223,10 +1223,10 @@ int CameraCapabilities::initializeStaticMetadata() { std::vector data; data.reserve(2); - const auto &infoMap = controlsInfo.find(&controls::draft::LensShadingMapMode); + const auto &infoMap = controlsInfo.find(&controls::LensShadingEnable); if (infoMap != controlsInfo.end()) { for (const auto &value : infoMap->second.values()) - data.push_back(value.get()); + data.push_back(value.get()); } else { data.push_back(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF); } diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml index f781865859ac..9244b7eddb77 100644 --- a/src/libcamera/control_ids_core.yaml +++ b/src/libcamera/control_ids_core.yaml @@ -1346,4 +1346,10 @@ controls: reduces the WdrExposureValue until the amount of pixels that are close to saturation is lower than this value. + - LensShadingEnable: + type: bool + direction: inout + description: | + Enable or disable the lens shading algorithm. + ... diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml index 03309eeac34f..14026de46ad6 100644 --- a/src/libcamera/control_ids_draft.yaml +++ b/src/libcamera/control_ids_draft.yaml @@ -110,20 +110,6 @@ controls: row and the start of exposure of the last row. Currently identical to ANDROID_SENSOR_ROLLING_SHUTTER_SKEW - - LensShadingMapMode: - type: int32_t - direction: inout - description: | - Control to report if the lens shading map is available. Currently - identical to ANDROID_STATISTICS_LENS_SHADING_MAP_MODE. - enum: - - name: LensShadingMapModeOff - value: 0 - description: No lens shading map mode is available. - - name: LensShadingMapModeOn - value: 1 - description: The lens shading map mode is available. - - PipelineDepth: type: int32_t direction: out From patchwork Tue Oct 14 07:52:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24628 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 91477BF415 for ; Tue, 14 Oct 2025 07:53:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 462D9605EF; Tue, 14 Oct 2025 09:53:36 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="HdsK6f2g"; 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 BD60E605DD for ; Tue, 14 Oct 2025 09:53:34 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:61fb:8e55:ff1e:be62]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 84CF8C73; Tue, 14 Oct 2025 09:51:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760428316; bh=mBl3sCmfidcqdXPeszxfzmjPP031maQ+jUPB6OKVpBc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HdsK6f2gG9jBTzUxj/2Yqh7LVmmHDiQyW5f4nETwSL6WUJzV3TtTQE4iP4fYMn0Fh TFxHsrm8Uc7ccUMMhseq37+IylMnSn6kP/hOzMj/j8/rcQ3U/tcHJaU0RNbHX75ZZq +iRHgXsNw+i2xw03WpxBenmiYClDt2JdMBepwGTc= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v1 12/12] ipa: rkisp1: Add LensShadingEnable control Date: Tue, 14 Oct 2025 09:52:34 +0200 Message-ID: <20251014075252.2876485-13-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> References: <20251014075252.2876485-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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" Implement the LensShadingEnable control for rkisp1. Signed-off-by: Stefan Klug --- src/ipa/rkisp1/algorithms/dpf.cpp | 2 +- src/ipa/rkisp1/algorithms/lsc.cpp | 41 ++++++++++++++++++++++++++--- src/ipa/rkisp1/algorithms/lsc.h | 3 +++ src/ipa/rkisp1/ipa_context.h | 12 ++++++--- src/libcamera/control_ids_core.yaml | 3 +++ 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp index cb6095daeeed..79cb4829fdbb 100644 --- a/src/ipa/rkisp1/algorithms/dpf.cpp +++ b/src/ipa/rkisp1/algorithms/dpf.cpp @@ -229,7 +229,7 @@ void Dpf::prepare(IPAContext &context, const uint32_t frame, *config = config_; const auto &awb = context.configuration.awb; - const auto &lsc = context.configuration.lsc; + const auto &lsc = context.activeState.lsc; auto &mode = config->gain.mode; diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index 68cf35064182..ddb7154a0211 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -366,6 +366,8 @@ LensShadingCorrection::LensShadingCorrection() int LensShadingCorrection::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) { + context.ctrlMap[&controls::LensShadingEnable] = ControlInfo(false, true, true); + xSize_ = parseSizes(tuningData, "x-size"); ySize_ = parseSizes(tuningData, "y-size"); @@ -449,7 +451,7 @@ int LensShadingCorrection::configure(IPAContext &context, sets_.setData(std::move(shadingData)); - context.configuration.lsc.enabled = true; + context.activeState.lsc.enabled = true; return 0; } @@ -470,6 +472,27 @@ void LensShadingCorrection::copyTable(rkisp1_cif_isp_lsc_config &config, std::copy(set.b.begin(), set.b.end(), &config.b_data_tbl[0][0]); } +/** + * \copydoc libcamera::ipa::Algorithm::queueRequest + */ +void LensShadingCorrection::queueRequest(IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) +{ + auto &lsc = context.activeState.lsc; + + const auto &lscEnable = controls.get(controls::LensShadingEnable); + if (lscEnable && *lscEnable != lsc.enabled) { + lsc.enabled = *lscEnable; + + LOG(RkISP1Lsc, Debug) + << (*lscEnable ? "Enabling" : "Disabling") << " Lsc"; + + frameContext.lsc.update = true; + } +} + /** * \copydoc libcamera::ipa::Algorithm::prepare */ @@ -479,16 +502,26 @@ void LensShadingCorrection::prepare([[maybe_unused]] IPAContext &context, RkISP1Params *params) { uint32_t ct = frameContext.awb.temperatureK; - if (std::abs(static_cast(ct) - static_cast(lastAppliedCt_)) < + + if (!frameContext.lsc.update && !context.activeState.lsc.enabled) + return; + + if (!frameContext.lsc.update && + std::abs(static_cast(ct) - static_cast(lastAppliedCt_)) < kColourTemperatureChangeThreshhold) return; + unsigned int quantizedCt; const Components &set = sets_.getInterpolated(ct, &quantizedCt); - if (lastAppliedQuantizedCt_ == quantizedCt) + if (!frameContext.lsc.update && lastAppliedQuantizedCt_ == quantizedCt) return; auto config = params->block(); - config.setEnabled(true); + config.setEnabled(context.activeState.lsc.enabled); + + if (!context.activeState.lsc.enabled) + return; + setParameters(*config); copyTable(*config, set); diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h index 43fee337931f..a3d8042130c0 100644 --- a/src/ipa/rkisp1/algorithms/lsc.h +++ b/src/ipa/rkisp1/algorithms/lsc.h @@ -29,6 +29,9 @@ public: void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, RkISP1Params *params) override; + void queueRequest(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) override; struct Components { std::vector r; diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index f85a130d9c23..5ec87ae4e5a3 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -55,10 +55,6 @@ struct IPASessionConfiguration { bool supported; } compress; - struct { - bool enabled; - } lsc; - struct { utils::Duration minExposureTime; utils::Duration maxExposureTime; @@ -139,6 +135,10 @@ struct IPAActiveState { double gain; double strength; } wdr; + + struct { + bool enabled; + } lsc; }; struct IPAFrameContext : public FrameContext { @@ -214,6 +214,10 @@ struct IPAFrameContext : public FrameContext { double strength; double gain; } wdr; + + struct { + bool update; + } lsc; }; struct IPAContext { diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml index 9244b7eddb77..3b062df64bf5 100644 --- a/src/libcamera/control_ids_core.yaml +++ b/src/libcamera/control_ids_core.yaml @@ -1352,4 +1352,7 @@ controls: description: | Enable or disable the lens shading algorithm. + This control is only available when there are valid lens shading + correction parameters available in the tuning file. + ...