Patch Detail
Show a patch.
GET /api/1.1/patches/27209/?format=api
{ "id": 27209, "url": "https://patchwork.libcamera.org/api/1.1/patches/27209/?format=api", "web_url": "https://patchwork.libcamera.org/patch/27209/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260706-libipa-algorithms-v3-9-968757b038bb@ideasonboard.com>", "date": "2026-07-06T08:01:29", "name": "[v3,09/35] ipa: rkisp1: lsc: Re-architecture Lsc support", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "04a3f4f0f86d6bb981c72c6b06be15939bdf47d6", "submitter": { "id": 143, "url": "https://patchwork.libcamera.org/api/1.1/people/143/?format=api", "name": "Jacopo Mondi", "email": "jacopo.mondi@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/27209/mbox/", "series": [ { "id": 6038, "url": "https://patchwork.libcamera.org/api/1.1/series/6038/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=6038", "date": "2026-07-06T08:01:20", "name": "ipa: libipa: Introduce libipa algorithms", "version": 3, "mbox": "https://patchwork.libcamera.org/series/6038/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/27209/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/27209/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 26C17C3308\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 6 Jul 2026 08:02:13 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A83C266035;\n\tMon, 6 Jul 2026 10:02:12 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id AA58E65FF1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 6 Jul 2026 10:02:03 +0200 (CEST)", "from [192.168.125.177] (mob-109-113-60-81.net.vodafone.it\n\t[109.113.60.81])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 4F68A1D17;\n\tMon, 6 Jul 2026 10:01:15 +0200 (CEST)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"ZWvb4mp3\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1783324875;\n\tbh=+zh1/KZ1jgRGtmTQ5vykJHqeNYyq/krkRSwJSU9o9yo=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=ZWvb4mp3J8+RNckHT69WRODlW98QK4tAF8ORszFzQKeiyQyJ8z1MqSsfzHtysDFK3\n\tq50PqouIh3BF0vTU/MArQSgrlmj/kSvsu0QtSQAyYyVllaV23kaZpTTci4/EJWl8qB\n\tRxsjZ7yFNKDw/yEcEIfOkFMKd0ksdaRkzzMhNt/4=", "From": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>", "Date": "Mon, 06 Jul 2026 10:01:29 +0200", "Subject": "[PATCH v3 09/35] ipa: rkisp1: lsc: Re-architecture Lsc support", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "7bit", "Message-Id": "<20260706-libipa-algorithms-v3-9-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, \n\tStefan Klug <stefan.klug@ideasonboard.com>", "Cc": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>", "X-Mailer": "b4 0.14.3", "X-Developer-Signature": "v=1; a=openpgp-sha256; l=15591;\n\ti=jacopo.mondi@ideasonboard.com; h=from:subject:message-id;\n\tbh=+zh1/KZ1jgRGtmTQ5vykJHqeNYyq/krkRSwJSU9o9yo=;\n\tb=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBqS2DwZaTAE3zju3/ivFXXa0VqqbkOH/tJwDnDB\n\tXIh71deS/OJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaktg8AAKCRByNAaPFqFW\n\tPOLMD/9YNhNPRsuVh4LE09XXCUeuiQTgeMGA2sn0WnYwqftnFv5qfAQuq5mI25h75h3idwsoX90\n\tutxJAyg66Wm5eWBLAEVqcG8NvmOzvj7gJDdeiPjgEm7iyzZpa051rcg/v2P0lRUzmAFrtm1O9t1\n\t8JbWp5EuScR4ZpvK0BC8eEM0cX2wH9wyNf9S1LB1r96iSAhcqZ9RoM6jPXf8gtj1CZXTgCgogWi\n\tZWFog+nfTcUtsNHzIYpUcQ2FMv0S1miuaDl+Oq1bVvOZXRPTMuhtQ8aLEBsUWcxsyQwG9zZE+K6\n\tF8SPu2QrJ/FjwXYk5bR5srCfc/J1yDga7ZNcTENzqWCvG4vhCngKfTDiewC0WVtdnGFquULSS3Y\n\tWqpBEGUmduptOTdyAZVfgsQ+KSLg9vN2/gPsyW6FYFGRFrlBNb43eJTDPMxLsjodsmTThGOqN4a\n\tO70Y4sYhTTNF8OsXBK98ctWrKY0H8sNty40x7MCdgT8P3Rl2Nbo2ppnmdZCCUafBBoyrSIxqqWq\n\tgkDXOHVQvqRKXZMyTm5paaH167IvOxAXX2YNkUEc10sSTwz0A/EXzJGWW8iaIu3qxWXhJ2d9s10\n\twBKjd5nr5DLnGjQPe3/HOfQUXXaQpba0dTNPmxg7aIWEPUUuzzcemWsv0e55k5cy8C0EMNBl4uJ\n\txqeMKUDNyru8R6w==", "X-Developer-Key": "i=jacopo.mondi@ideasonboard.com; a=openpgp;\n\tfpr=72392EDC88144A65C701EA9BA5826A2587AD026B", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "The RkISP1 LSC implementation is realized by the following components:\n\n- 2 \"tuning file\" parser classes:\n\n - LscPolynomialLoader\n - LscTableLoader\n\n which implement the \"parseLscData\" function that loads from tuning\n file a polynomial representation of the lsc gains or a table of gains\n respectively.\n\n- A hierachy of \"ShadingDescriptors\"\n - LscPolynomialShadingDescriptor\n - LscTableShadingDescriptor\n\n that implement the \"sampleForCrop\" interface which expands a\n polynomial to a list of gains for the LscPolynomialShadingDescriptor\n and simply return the data parsed from tuning file for\n LscTableShadingDescriptor.\n\nUnify the two functionalities in a single class hierarchy whose\ninterface is defined by the LscImplementation pure virtual class\nimplemented by LscPolynomialImpl and LscTableImpl.\n\nThe LensShadingCorrection algorithm class instantiates the correct\nsub-class and uses the file parsing and table expansion functionalities\nby implementing the composition pattern.\n\nSigned-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n---\n src/ipa/rkisp1/algorithms/lsc.cpp | 247 +++++++++++++++++---------------------\n src/ipa/rkisp1/algorithms/lsc.h | 49 ++++----\n 2 files changed, 141 insertions(+), 155 deletions(-)", "diff": "diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp\nindex faf88effde01..92001319279e 100644\n--- a/src/ipa/rkisp1/algorithms/lsc.cpp\n+++ b/src/ipa/rkisp1/algorithms/lsc.cpp\n@@ -54,17 +54,6 @@ void Interpolator<rkisp1::algorithms::LensShadingCorrection::Components>::\n \n namespace ipa::rkisp1::algorithms {\n \n-/**\n- * \\class LensShadingCorrection\n- * \\brief RkISP1 Lens Shading Correction control\n- *\n- * Due to the optical characteristics of the lens, the light intensity received\n- * by the sensor is not uniform.\n- *\n- * The Lens Shading Correction algorithm applies multipliers to all pixels to\n- * compensate for the lens shading effect. The coefficients are specified in a\n- * downscaled table in the tuning data.\n- */\n \n LOG_DEFINE_CATEGORY(RkISP1Lsc)\n \n@@ -72,54 +61,110 @@ namespace {\n \n constexpr int kColourTemperatureQuantization = 10;\n \n-class LscPolynomialShadingDescriptor : public LensShadingCorrection::ShadingDescriptor\n+class LscPolynomialImpl : public LscImplementation\n {\n+private:\n+\tstruct PolynomialComponents {\n+\t\tLscPolynomial pr;\n+\t\tLscPolynomial pgr;\n+\t\tLscPolynomial pgb;\n+\t\tLscPolynomial pb;\n+\t};\n+\tusing PolynomialComponentsMap = std::map<unsigned int, PolynomialComponents>;\n+\n public:\n-\tLscPolynomialShadingDescriptor(const LscPolynomial &pr, const LscPolynomial &pgr,\n-\t\t\t\t const LscPolynomial &pgb, const LscPolynomial &pb)\n-\t\t: pr_(pr), pgr_(pgr), pgb_(pgb), pb_(pb)\n+\tLscPolynomialImpl(const Size &sensorSize)\n+\t\t: sensorSize_(sensorSize)\n \t{\n \t}\n \n-\tLensShadingCorrection::Components sampleForCrop(const Rectangle &cropRectangle,\n-\t\t\t\t\t\t\tSpan<const double> xSizes,\n-\t\t\t\t\t\t\tSpan<const double> ySizes) override;\n+\tint parseLscData(const ValueNode &sets) override;\n+\n+\tLensShadingCorrection::ComponentsMap\n+\tsampleForCrop(const Rectangle &cropRectangle,\n+\t\t Span<const double> xSizes,\n+\t\t Span<const double> ySizes) override;\n \n private:\n+\tstd::vector<double> sizesListToPositions(Span<const double> sizes);\n \tstd::vector<uint16_t> samplePolynomial(const LscPolynomial &poly,\n \t\t\t\t\t Span<const double> xPositions,\n \t\t\t\t\t Span<const double> yPositions,\n \t\t\t\t\t const Rectangle &cropRectangle);\n+\tPolynomialComponentsMap lscData_;\n+\tSize sensorSize_;\n+};\n \n-\tstd::vector<double> sizesListToPositions(Span<const double> sizes);\n+int LscPolynomialImpl::parseLscData(const ValueNode &sets)\n+{\n+\tfor (const auto &set : sets.asList()) {\n+\t\tstd::optional<LscPolynomial> pr, pgr, pgb, pb;\n+\t\tuint32_t ct = set[\"ct\"].get<uint32_t>(0);\n \n-\tLscPolynomial pr_;\n-\tLscPolynomial pgr_;\n-\tLscPolynomial pgb_;\n-\tLscPolynomial pb_;\n-};\n+\t\tif (lscData_.count(ct)) {\n+\t\t\tLOG(RkISP1Lsc, Error)\n+\t\t\t\t<< \"Multiple sets found for \"\n+\t\t\t\t<< \"color temperature \" << ct;\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tpr = set[\"r\"].get<LscPolynomial>();\n+\t\tpgr = set[\"gr\"].get<LscPolynomial>();\n+\t\tpgb = set[\"gb\"].get<LscPolynomial>();\n+\t\tpb = set[\"b\"].get<LscPolynomial>();\n+\n+\t\tif (!(pr || pgr || pgb || pb)) {\n+\t\t\tLOG(RkISP1Lsc, Error)\n+\t\t\t\t<< \"Failed to parse polynomial for \"\n+\t\t\t\t<< \"colour temperature \" << ct;\n+\t\t\treturn -EINVAL;\n+\t\t}\n \n-LensShadingCorrection::Components\n-LscPolynomialShadingDescriptor::sampleForCrop(const Rectangle &cropRectangle,\n-\t\t\t\t\t Span<const double> xSizes,\n-\t\t\t\t\t Span<const double> ySizes)\n+\t\tpr->setReferenceImageSize(sensorSize_);\n+\t\tpgr->setReferenceImageSize(sensorSize_);\n+\t\tpgb->setReferenceImageSize(sensorSize_);\n+\t\tpb->setReferenceImageSize(sensorSize_);\n+\n+\t\tlscData_.emplace(std::piecewise_construct,\n+\t\t\t\t std::forward_as_tuple(ct),\n+\t\t\t\t std::forward_as_tuple(PolynomialComponents{ *pr, *pgr, *pgb, *pb }));\n+\t}\n+\n+\tif (lscData_.empty()) {\n+\t\tLOG(RkISP1Lsc, Error) << \"Failed to load any sets\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+LensShadingCorrection::ComponentsMap\n+LscPolynomialImpl::sampleForCrop(const Rectangle &cropRectangle,\n+\t\t\t\t Span<const double> xSizes,\n+\t\t\t\t Span<const double> ySizes)\n {\n \tstd::vector<double> xPos = sizesListToPositions(xSizes);\n \tstd::vector<double> yPos = sizesListToPositions(ySizes);\n \n-\treturn {\n-\t\t.r = samplePolynomial(pr_, xPos, yPos, cropRectangle),\n-\t\t.gr = samplePolynomial(pgr_, xPos, yPos, cropRectangle),\n-\t\t.gb = samplePolynomial(pgb_, xPos, yPos, cropRectangle),\n-\t\t.b = samplePolynomial(pb_, xPos, yPos, cropRectangle)\n-\t};\n+\tLensShadingCorrection::ComponentsMap components;\n+\n+\tfor (const auto &[k, p] : lscData_) {\n+\t\tcomponents[k] = {\n+\t\t\tsamplePolynomial(p.pr, xPos, yPos, cropRectangle),\n+\t\t\tsamplePolynomial(p.pgr, xPos, yPos, cropRectangle),\n+\t\t\tsamplePolynomial(p.pgb, xPos, yPos, cropRectangle),\n+\t\t\tsamplePolynomial(p.pb, xPos, yPos, cropRectangle)\n+\t\t};\n+\t}\n+\n+\treturn components;\n }\n \n std::vector<uint16_t>\n-LscPolynomialShadingDescriptor::samplePolynomial(const LscPolynomial &poly,\n-\t\t\t\t\t\t Span<const double> xPositions,\n-\t\t\t\t\t\t Span<const double> yPositions,\n-\t\t\t\t\t\t const Rectangle &cropRectangle)\n+LscPolynomialImpl::samplePolynomial(const LscPolynomial &poly,\n+\t\t\t\t Span<const double> xPositions,\n+\t\t\t\t Span<const double> yPositions,\n+\t\t\t\t const Rectangle &cropRectangle)\n {\n \tdouble m = poly.getM();\n \tdouble x0 = cropRectangle.x / m;\n@@ -160,7 +205,7 @@ LscPolynomialShadingDescriptor::samplePolynomial(const LscPolynomial &poly,\n * output: 0.0 0.2 0.5 0.8 1.0\n */\n std::vector<double>\n-LscPolynomialShadingDescriptor::sizesListToPositions(Span<const double> sizes)\n+LscPolynomialImpl::sizesListToPositions(Span<const double> sizes)\n {\n \tconst int half = sizes.size();\n \tstd::vector<double> positions(half * 2 + 1);\n@@ -176,74 +221,12 @@ LscPolynomialShadingDescriptor::sizesListToPositions(Span<const double> sizes)\n \treturn positions;\n }\n \n-class LscPolynomialLoader\n+class LscTableImpl : public LscImplementation\n {\n public:\n-\tLscPolynomialLoader(const Size &sensorSize)\n-\t\t: sensorSize_(sensorSize)\n-\t{\n-\t}\n-\n-\tint parseLscData(const ValueNode &sets,\n-\t\t\t LensShadingCorrection::ShadingDescriptorMap &lscData);\n+\tint parseLscData(const ValueNode &sets) override;\n \n-private:\n-\tSize sensorSize_;\n-};\n-\n-int LscPolynomialLoader::parseLscData(const ValueNode &sets,\n-\t\t\t\t LensShadingCorrection::ShadingDescriptorMap &lscData)\n-{\n-\tfor (const auto &set : sets.asList()) {\n-\t\tstd::optional<LscPolynomial> pr, pgr, pgb, pb;\n-\t\tuint32_t ct = set[\"ct\"].get<uint32_t>(0);\n-\n-\t\tif (lscData.count(ct)) {\n-\t\t\tLOG(RkISP1Lsc, Error)\n-\t\t\t\t<< \"Multiple sets found for \"\n-\t\t\t\t<< \"color temperature \" << ct;\n-\t\t\treturn -EINVAL;\n-\t\t}\n-\n-\t\tpr = set[\"r\"].get<LscPolynomial>();\n-\t\tpgr = set[\"gr\"].get<LscPolynomial>();\n-\t\tpgb = set[\"gb\"].get<LscPolynomial>();\n-\t\tpb = set[\"b\"].get<LscPolynomial>();\n-\n-\t\tif (!(pr || pgr || pgb || pb)) {\n-\t\t\tLOG(RkISP1Lsc, Error)\n-\t\t\t\t<< \"Failed to parse polynomial for \"\n-\t\t\t\t<< \"colour temperature \" << ct;\n-\t\t\treturn -EINVAL;\n-\t\t}\n-\n-\t\tpr->setReferenceImageSize(sensorSize_);\n-\t\tpgr->setReferenceImageSize(sensorSize_);\n-\t\tpgb->setReferenceImageSize(sensorSize_);\n-\t\tpb->setReferenceImageSize(sensorSize_);\n-\n-\t\tlscData.emplace(\n-\t\t\tct, std::make_unique<LscPolynomialShadingDescriptor>(\n-\t\t\t\t *pr, *pgr, *pgb, *pb));\n-\t}\n-\n-\tif (lscData.empty()) {\n-\t\tLOG(RkISP1Lsc, Error) << \"Failed to load any sets\";\n-\t\treturn -EINVAL;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-class LscTableShadingDescriptor : public LensShadingCorrection::ShadingDescriptor\n-{\n-public:\n-\tLscTableShadingDescriptor(LensShadingCorrection::Components components)\n-\t\t: lscData_(std::move(components))\n-\t{\n-\t}\n-\n-\tLensShadingCorrection::Components\n+\tLensShadingCorrection::ComponentsMap\n \tsampleForCrop([[maybe_unused]] const Rectangle &cropRectangle,\n \t\t [[maybe_unused]] Span<const double> xSizes,\n \t\t [[maybe_unused]] Span<const double> ySizes) override\n@@ -253,28 +236,19 @@ public:\n \t\treturn lscData_;\n \t}\n \n-private:\n-\tLensShadingCorrection::Components lscData_;\n-};\n-\n-class LscTableLoader\n-{\n-public:\n-\tint parseLscData(const ValueNode &sets,\n-\t\t\t LensShadingCorrection::ShadingDescriptorMap &lscData);\n-\n private:\n \tstd::vector<uint16_t> parseTable(const ValueNode &tuningData,\n \t\t\t\t\t const char *prop);\n+\n+\tLensShadingCorrection::ComponentsMap lscData_;\n };\n \n-int LscTableLoader::parseLscData(const ValueNode &sets,\n-\t\t\t\t LensShadingCorrection::ShadingDescriptorMap &lscData)\n+int LscTableImpl::parseLscData(const ValueNode &sets)\n {\n \tfor (const auto &set : sets.asList()) {\n \t\tuint32_t ct = set[\"ct\"].get<uint32_t>(0);\n \n-\t\tif (lscData.count(ct)) {\n+\t\tif (lscData_.count(ct)) {\n \t\t\tLOG(RkISP1Lsc, Error)\n \t\t\t\t<< \"Multiple sets found for color temperature \"\n \t\t\t\t<< ct;\n@@ -295,11 +269,10 @@ int LscTableLoader::parseLscData(const ValueNode &sets,\n \t\t\treturn -EINVAL;\n \t\t}\n \n-\t\tlscData.emplace(\n-\t\t\tct, std::make_unique<LscTableShadingDescriptor>(std::move(components)));\n+\t\tlscData_.emplace(ct, std::move(components));\n \t}\n \n-\tif (lscData.empty()) {\n+\tif (lscData_.empty()) {\n \t\tLOG(RkISP1Lsc, Error) << \"Failed to load any sets\";\n \t\treturn -EINVAL;\n \t}\n@@ -307,7 +280,7 @@ int LscTableLoader::parseLscData(const ValueNode &sets,\n \treturn 0;\n }\n \n-std::vector<uint16_t> LscTableLoader::parseTable(const ValueNode &tuningData,\n+std::vector<uint16_t> LscTableImpl::parseTable(const ValueNode &tuningData,\n \t\t\t\t\t\t const char *prop)\n {\n \tstatic constexpr unsigned int kLscNumSamples =\n@@ -363,6 +336,18 @@ unsigned int quantize(unsigned int value, unsigned int step)\n \n } /* namespace */\n \n+/**\n+ * \\class LensShadingCorrection\n+ * \\brief RkISP1 Lens Shading Correction control\n+ *\n+ * Due to the optical characteristics of the lens, the light intensity received\n+ * by the sensor is not uniform.\n+ *\n+ * The Lens Shading Correction algorithm applies multipliers to all pixels to\n+ * compensate for the lens shading effect. The coefficients are specified in a\n+ * downscaled table in the tuning data.\n+ */\n+\n LensShadingCorrection::LensShadingCorrection()\n \t: lastAppliedCt_(0), lastAppliedQuantizedCt_(0)\n {\n@@ -388,22 +373,21 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,\n \t\treturn -EINVAL;\n \t}\n \n-\tShadingDescriptorMap lscData;\n-\tint ret = 0;\n+\tint ret;\n \n \tstd::string type = tuningData[\"type\"].get<std::string>(\"table\");\n \tif (type == \"table\") {\n \t\tLOG(RkISP1Lsc, Debug) << \"Loading tabular LSC data.\";\n-\t\tauto loader = LscTableLoader();\n-\t\tret = loader.parseLscData(sets, lscData);\n+\t\talgo_ = std::make_unique<LscTableImpl>();\n+\t\tret = algo_->parseLscData(sets);\n \t} else if (type == \"polynomial\") {\n \t\tLOG(RkISP1Lsc, Debug) << \"Loading polynomial LSC data.\";\n \t\t/*\n \t\t * \\todo: Most likely the reference frame should be native_size.\n \t\t * Let's wait how the internal discussions progress.\n \t\t */\n-\t\tauto loader = LscPolynomialLoader(context.sensorInfo.activeAreaSize);\n-\t\tret = loader.parseLscData(sets, lscData);\n+\t\talgo_ = std::make_unique<LscPolynomialImpl>(context.sensorInfo.activeAreaSize);\n+\t\tret = algo_->parseLscData(sets);\n \t} else {\n \t\tLOG(RkISP1Lsc, Error) << \"Unsupported LSC data type '\"\n \t\t\t\t << type << \"'\";\n@@ -416,8 +400,6 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,\n \tcontext.ctrlMap[&controls::LensShadingCorrectionEnable] =\n \t\tControlInfo(false, true, true);\n \n-\tshadingDescriptors_ = std::move(lscData);\n-\n \treturn 0;\n }\n \n@@ -453,11 +435,8 @@ int LensShadingCorrection::configure(IPAContext &context,\n \t}\n \n \tLOG(RkISP1Lsc, Debug) << \"Sample LSC data for \" << configInfo.analogCrop;\n-\tstd::map<unsigned int, LensShadingCorrection::Components> shadingData;\n-\tfor (const auto &[t, descriptor] : shadingDescriptors_)\n-\t\tshadingData[t] = descriptor->sampleForCrop(configInfo.analogCrop,\n-\t\t\t\t\t\t\t xSize_, ySize_);\n-\n+\tComponentsMap shadingData = algo_->sampleForCrop(configInfo.analogCrop,\n+\t\t\t\t\t\t\t xSize_, ySize_);\n \tsets_.setData(std::move(shadingData));\n \n \tcontext.activeState.lsc.enabled = true;\ndiff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h\nindex 0a256e225327..3463531f2ab2 100644\n--- a/src/ipa/rkisp1/algorithms/lsc.h\n+++ b/src/ipa/rkisp1/algorithms/lsc.h\n@@ -18,9 +18,20 @@ namespace libcamera {\n \n namespace ipa::rkisp1::algorithms {\n \n+class LscImplementation;\n+\n class LensShadingCorrection : public Algorithm\n {\n public:\n+\tstruct Components {\n+\t\tstd::vector<uint16_t> r;\n+\t\tstd::vector<uint16_t> gr;\n+\t\tstd::vector<uint16_t> gb;\n+\t\tstd::vector<uint16_t> b;\n+\t};\n+\n+\tusing ComponentsMap = std::map<unsigned int, Components>;\n+\n \tLensShadingCorrection();\n \t~LensShadingCorrection() = default;\n \n@@ -36,31 +47,10 @@ public:\n \t\t IPAFrameContext &frameContext,\n \t\t const rkisp1_stat_buffer *stats,\n \t\t ControlList &metadata) override;\n-\n-\tstruct Components {\n-\t\tstd::vector<uint16_t> r;\n-\t\tstd::vector<uint16_t> gr;\n-\t\tstd::vector<uint16_t> gb;\n-\t\tstd::vector<uint16_t> b;\n-\t};\n-\n-\tclass ShadingDescriptor\n-\t{\n-\tpublic:\n-\t\tvirtual ~ShadingDescriptor() = default;\n-\t\tvirtual Components sampleForCrop(const Rectangle &cropRectangle,\n-\t\t\t\t\t\t Span<const double> xSizes,\n-\t\t\t\t\t\t Span<const double> ySizes) = 0;\n-\t};\n-\n-\tusing ShadingDescriptorMap = std::map<unsigned int, std::unique_ptr<ShadingDescriptor>>;\n-\n private:\n \tvoid setParameters(rkisp1_cif_isp_lsc_config &config);\n \tvoid copyTable(rkisp1_cif_isp_lsc_config &config, const Components &set0);\n \n-\tShadingDescriptorMap shadingDescriptors_;\n-\tipa::Interpolator<Components> sets_;\n \tstd::vector<double> xSize_;\n \tstd::vector<double> ySize_;\n \tuint16_t xGrad_[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE];\n@@ -70,6 +60,23 @@ private:\n \n \tunsigned int lastAppliedCt_;\n \tunsigned int lastAppliedQuantizedCt_;\n+\n+\tipa::Interpolator<Components> sets_;\n+\n+\tstd::unique_ptr<LscImplementation> algo_;\n+};\n+\n+class LscImplementation\n+{\n+public:\n+\tvirtual ~LscImplementation() {}\n+\n+\tvirtual int parseLscData(const ValueNode &sets) = 0;\n+\n+\tvirtual LensShadingCorrection::ComponentsMap\n+\tsampleForCrop(const Rectangle &cropRectangle,\n+\t\t Span<const double> xSizes,\n+\t\t Span<const double> ySizes) = 0;\n };\n \n } /* namespace ipa::rkisp1::algorithms */\n", "prefixes": [ "v3", "09/35" ] }