Show a patch.

GET /api/patches/25703/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 25703,
    "url": "https://patchwork.libcamera.org/api/patches/25703/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/25703/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/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": "<20260108-sklug-lsc-resampling-v2-dev-v2-13-e682ec4b9893@ideasonboard.com>",
    "date": "2026-01-08T16:05:56",
    "name": "[v2,13/15] ipa: rkisp1: lsc: Resample polynomial lens shading tables at configure time",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "727913d25dbe88bbf3f36656d2c42e94c08f0bd2",
    "submitter": {
        "id": 184,
        "url": "https://patchwork.libcamera.org/api/people/184/?format=api",
        "name": "Stefan Klug",
        "email": "stefan.klug@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/25703/mbox/",
    "series": [
        {
            "id": 5697,
            "url": "https://patchwork.libcamera.org/api/series/5697/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5697",
            "date": "2026-01-08T16:05:43",
            "name": "Add resampling support for polynomial LSC data",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/5697/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/25703/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/25703/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 53488BE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  8 Jan 2026 16:07:06 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 0496461FDE;\n\tThu,  8 Jan 2026 17:07:06 +0100 (CET)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id BBBD961FC5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  8 Jan 2026 17:07:04 +0100 (CET)",
            "from ideasonboard.com (unknown\n\t[IPv6:2a00:6020:448c:6c00:90af:8957:b721:10d4])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 1BF5326D2; \n\tThu,  8 Jan 2026 17:06:42 +0100 (CET)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"HmkYpdcH\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1767888402;\n\tbh=rsFrVOVU+1EDCj1TbjsOHC9KGpb7qZR65YvDwV3jm6I=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=HmkYpdcHA9gxx6Eu9ZEn49ghGLVmznibieWa/nV+eT8ub4Wb5wd6bKqLFZkB9xR/l\n\tiEpFvHqVWt9ntyA8BIqxlbQZTuwPtlwhXu1eeOMa7MilZp5OHzX4xe6WWN/xekcM5h\n\tAsPXEmSSuTPlBdI5UIdNqUuL/soQJb/OdjQI90k0=",
        "From": "Stefan Klug <stefan.klug@ideasonboard.com>",
        "Date": "Thu, 08 Jan 2026 17:05:56 +0100",
        "Subject": "[PATCH v2 13/15] ipa: rkisp1: lsc: Resample polynomial lens\n\tshading tables at configure time",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20260108-sklug-lsc-resampling-v2-dev-v2-13-e682ec4b9893@ideasonboard.com>",
        "References": "<20260108-sklug-lsc-resampling-v2-dev-v2-0-e682ec4b9893@ideasonboard.com>",
        "In-Reply-To": "<20260108-sklug-lsc-resampling-v2-dev-v2-0-e682ec4b9893@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Stefan Klug <stefan.klug@ideasonboard.com>",
        "X-Mailer": "b4 0.14.2",
        "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 lens shading correction is always applied based on the sensor crop\nbounds. This leads to incorrect lens shading correction for analog crops\nthat do not cover the whole sensor.\n\nTo fix that, we need to adapt the lens shading table for the selected\nanalog crop at configure time. Introduce an abstract ShadingDescriptor\nclass that holds the lens shading information that can then be sampled\nat configure time for a specific crop rectangle.\n\nResampling for a specific crop is only implemented for polynomial lsc\ndata. For tabular data, a warning is logged and the unmodified table is\nreturned. This matches the current functionality for tabular data and is\na huge improvement for polynomial data.\n\nSigned-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n\n---\n\nChanges in v2:\n- Replaced \"auto const\" by \"const auto\"\n- Replaces some vector parameters by Spans\n- Changed sampleForCrop to return the components\n- Replaced min/max by clamp\n- Replaced map.swap() by move assignment\n---\n src/ipa/rkisp1/algorithms/lsc.cpp | 233 ++++++++++++++++++++++++--------------\n src/ipa/rkisp1/algorithms/lsc.h   |  13 +++\n 2 files changed, 159 insertions(+), 87 deletions(-)",
    "diff": "diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp\nindex a5855f8a0a67a6b5ad95635454f3716d07c86e6f..698f07b85bfa5d3de0c454087bf8e0874d85add7 100644\n--- a/src/ipa/rkisp1/algorithms/lsc.cpp\n+++ b/src/ipa/rkisp1/algorithms/lsc.cpp\n@@ -72,38 +72,127 @@ namespace {\n \n constexpr int kColourTemperatureChangeThreshhold = 10;\n \n-class LscPolynomialLoader\n+class LscPolynomialShadingDescriptor : public LensShadingCorrection::ShadingDescriptor\n {\n public:\n-\tLscPolynomialLoader(const Size &sensorSize,\n-\t\t\t    const Rectangle &cropRectangle,\n-\t\t\t    const std::vector<double> &xSizes,\n-\t\t\t    const std::vector<double> &ySizes)\n-\t\t: sensorSize_(sensorSize),\n-\t\t  cropRectangle_(cropRectangle),\n-\t\t  xSizes_(xSizes),\n-\t\t  ySizes_(ySizes)\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 \t{\n \t}\n \n-\tint parseLscData(const YamlObject &yamlSets,\n-\t\t\t std::map<unsigned int, LensShadingCorrection::Components> &lscData);\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 \n private:\n-\tstd::vector<double> sizesListToPositions(const std::vector<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 \n+\tstd::vector<double> sizesListToPositions(Span<const double> sizes);\n+\n+\tLscPolynomial pr_;\n+\tLscPolynomial pgr_;\n+\tLscPolynomial pgb_;\n+\tLscPolynomial pb_;\n+};\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+{\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+}\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+{\n+\tdouble m = poly.getM();\n+\tdouble x0 = cropRectangle.x / m;\n+\tdouble y0 = cropRectangle.y / m;\n+\tdouble w = cropRectangle.width / m;\n+\tdouble h = cropRectangle.height / m;\n+\tstd::vector<uint16_t> samples;\n+\n+\tsamples.reserve(xPositions.size() * yPositions.size());\n+\n+\tfor (double y : yPositions) {\n+\t\tfor (double x : xPositions) {\n+\t\t\tdouble xp = x0 + x * w;\n+\t\t\tdouble yp = y0 + y * h;\n+\t\t\t/*\n+\t\t\t * The hardware uses 2.10 fixed point format and limits\n+\t\t\t * the legal values to [1..3.999]. Scale and clamp the\n+\t\t\t * sampled value accordingly.\n+\t\t\t */\n+\t\t\tint v = static_cast<int>(\n+\t\t\t\tpoly.sampleAtNormalizedPixelPos(xp, yp) *\n+\t\t\t\t1024);\n+\t\t\tv = std::clamp(v, 1024, 4095);\n+\t\t\tsamples.push_back(v);\n+\t\t}\n+\t}\n+\treturn samples;\n+}\n+\n+/*\n+ * The rkisp1 LSC grid spacing is defined by the cell sizes on the first half of\n+ * the grid. This is then mirrored in hardware to the other half. See\n+ * parseSizes() for further details. For easier handling, this function converts\n+ * the cell sizes of half the grid to a list of position of the whole grid (on\n+ * one axis). Example:\n+ *\n+ * input:   | 0.2 | 0.3 |\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+{\n+\tconst int half = sizes.size();\n+\tstd::vector<double> positions(half * 2 + 1);\n+\tdouble x = 0.0;\n+\n+\tpositions[half] = 0.5;\n+\tfor (int i = 1; i <= half; i++) {\n+\t\tx += sizes[half - i];\n+\t\tpositions[half - i] = 0.5 - x;\n+\t\tpositions[half + i] = 0.5 + x;\n+\t}\n+\n+\treturn positions;\n+}\n+\n+class LscPolynomialLoader\n+{\n+public:\n+\tLscPolynomialLoader(const Size &sensorSize)\n+\t\t: sensorSize_(sensorSize)\n+\t{\n+\t}\n+\n+\tint parseLscData(const YamlObject &yamlSets,\n+\t\t\t LensShadingCorrection::ShadingDescriptorMap &lscData);\n+\n+private:\n \tSize sensorSize_;\n-\tRectangle cropRectangle_;\n-\tconst std::vector<double> &xSizes_;\n-\tconst std::vector<double> &ySizes_;\n };\n \n int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets,\n-\t\t\t\t      std::map<unsigned int, LensShadingCorrection::Components> &lscData)\n+\t\t\t\t      LensShadingCorrection::ShadingDescriptorMap &lscData)\n {\n \tconst auto &sets = yamlSets.asList();\n \tfor (const auto &yamlSet : sets) {\n@@ -117,7 +206,6 @@ int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets,\n \t\t\treturn -EINVAL;\n \t\t}\n \n-\t\tLensShadingCorrection::Components &set = lscData[ct];\n \t\tpr = yamlSet[\"r\"].get<LscPolynomial>();\n \t\tpgr = yamlSet[\"gr\"].get<LscPolynomial>();\n \t\tpgb = yamlSet[\"gb\"].get<LscPolynomial>();\n@@ -135,12 +223,9 @@ int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets,\n \t\tpgb->setReferenceImageSize(sensorSize_);\n \t\tpb->setReferenceImageSize(sensorSize_);\n \n-\t\tstd::vector<double> xPos = sizesListToPositions(xSizes_);\n-\t\tstd::vector<double> yPos = sizesListToPositions(ySizes_);\n-\t\tset.r = samplePolynomial(*pr, xPos, yPos, cropRectangle_);\n-\t\tset.gr = samplePolynomial(*pgr, xPos, yPos, cropRectangle_);\n-\t\tset.gb = samplePolynomial(*pgb, xPos, yPos, cropRectangle_);\n-\t\tset.b = samplePolynomial(*pb, xPos, yPos, cropRectangle_);\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@@ -151,70 +236,33 @@ int LscPolynomialLoader::parseLscData(const YamlObject &yamlSets,\n \treturn 0;\n }\n \n-/*\n- * The rkisp1 LSC grid spacing is defined by the cell sizes on the first half of\n- * the grid. This is then mirrored in hardware to the other half. See\n- * parseSizes() for further details. For easier handling, this function converts\n- * the cell sizes of half the grid to a list of position of the whole grid (on\n- * one axis). Example:\n- *\n- * input:   | 0.2 | 0.3 |\n- * output: 0.0   0.2   0.5   0.8   1.0\n- */\n-std::vector<double> LscPolynomialLoader::sizesListToPositions(const std::vector<double> &sizes)\n+class LscTableShadingDescriptor : public LensShadingCorrection::ShadingDescriptor\n {\n-\tconst int half = sizes.size();\n-\tstd::vector<double> positions(half * 2 + 1);\n-\tdouble x = 0.0;\n-\n-\tpositions[half] = 0.5;\n-\tfor (int i = 1; i <= half; i++) {\n-\t\tx += sizes[half - i];\n-\t\tpositions[half - i] = 0.5 - x;\n-\t\tpositions[half + i] = 0.5 + x;\n+public:\n+\tLscTableShadingDescriptor(LensShadingCorrection::Components components)\n+\t\t: lscData_(std::move(components))\n+\t{\n \t}\n \n-\treturn positions;\n-}\n-\n-std::vector<uint16_t> LscPolynomialLoader::samplePolynomial(const LscPolynomial &poly,\n-\t\t\t\t\t\t\t    Span<const double> xPositions,\n-\t\t\t\t\t\t\t    Span<const double> yPositions,\n-\t\t\t\t\t\t\t    const Rectangle &cropRectangle)\n-{\n-\tdouble m = poly.getM();\n-\tdouble x0 = cropRectangle.x / m;\n-\tdouble y0 = cropRectangle.y / m;\n-\tdouble w = cropRectangle.width / m;\n-\tdouble h = cropRectangle.height / m;\n-\tstd::vector<uint16_t> samples;\n-\n-\tsamples.reserve(xPositions.size() * yPositions.size());\n-\n-\tfor (double y : yPositions) {\n-\t\tfor (double x : xPositions) {\n-\t\t\tdouble xp = x0 + x * w;\n-\t\t\tdouble yp = y0 + y * h;\n-\t\t\t/*\n-\t\t\t * The hardware uses 2.10 fixed point format and limits\n-\t\t\t * the legal values to [1..3.999]. Scale and clamp the\n-\t\t\t * sampled value accordingly.\n-\t\t\t */\n-\t\t\tint v = static_cast<int>(\n-\t\t\t\tpoly.sampleAtNormalizedPixelPos(xp, yp) *\n-\t\t\t\t1024);\n-\t\t\tv = std::min(std::max(v, 1024), 4095);\n-\t\t\tsamples.push_back(v);\n-\t\t}\n+\tLensShadingCorrection::Components\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)\n+\t{\n+\t\tLOG(RkISP1Lsc, Warning)\n+\t\t\t<< \"Tabular LSC data doesn't support resampling.\";\n+\t\treturn lscData_;\n \t}\n-\treturn samples;\n-}\n+\n+private:\n+\tLensShadingCorrection::Components lscData_;\n+};\n \n class LscTableLoader\n {\n public:\n \tint parseLscData(const YamlObject &yamlSets,\n-\t\t\t std::map<unsigned int, LensShadingCorrection::Components> &lscData);\n+\t\t\t LensShadingCorrection::ShadingDescriptorMap &lscData);\n \n private:\n \tstd::vector<uint16_t> parseTable(const YamlObject &tuningData,\n@@ -222,7 +270,7 @@ private:\n };\n \n int LscTableLoader::parseLscData(const YamlObject &yamlSets,\n-\t\t\t\t std::map<unsigned int, LensShadingCorrection::Components> &lscData)\n+\t\t\t\t LensShadingCorrection::ShadingDescriptorMap &lscData)\n {\n \tconst auto &sets = yamlSets.asList();\n \n@@ -236,8 +284,7 @@ int LscTableLoader::parseLscData(const YamlObject &yamlSets,\n \t\t\treturn -EINVAL;\n \t\t}\n \n-\t\tLensShadingCorrection::Components &set = lscData[ct];\n-\n+\t\tLensShadingCorrection::Components set;\n \t\tset.r = parseTable(yamlSet, \"r\");\n \t\tset.gr = parseTable(yamlSet, \"gr\");\n \t\tset.gb = parseTable(yamlSet, \"gb\");\n@@ -250,6 +297,9 @@ int LscTableLoader::parseLscData(const YamlObject &yamlSets,\n \t\t\t\t<< \" is missing tables\";\n \t\t\treturn -EINVAL;\n \t\t}\n+\n+\t\tlscData.emplace(\n+\t\t\tct, std::make_unique<LscTableShadingDescriptor>(std::move(set)));\n \t}\n \n \tif (lscData.empty()) {\n@@ -341,7 +391,7 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,\n \t\treturn -EINVAL;\n \t}\n \n-\tstd::map<unsigned int, Components> lscData;\n+\tShadingDescriptorMap lscData;\n \tint ret = 0;\n \n \tstd::string type = tuningData[\"type\"].get<std::string>(\"table\");\n@@ -351,10 +401,11 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,\n \t\tret = loader.parseLscData(yamlSets, lscData);\n \t} else if (type == \"polynomial\") {\n \t\tLOG(RkISP1Lsc, Debug) << \"Loading polynomial LSC data.\";\n-\t\tauto loader = LscPolynomialLoader(context.sensorInfo.activeAreaSize,\n-\t\t\t\t\t\t  context.sensorInfo.analogCrop,\n-\t\t\t\t\t\t  xSize_,\n-\t\t\t\t\t\t  ySize_);\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(yamlSets, lscData);\n \t} else {\n \t\tLOG(RkISP1Lsc, Error) << \"Unsupported LSC data type '\"\n@@ -365,7 +416,7 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,\n \tif (ret)\n \t\treturn ret;\n \n-\tsets_.setData(std::move(lscData));\n+\tshadingDescriptors_ = std::move(lscData);\n \n \treturn 0;\n }\n@@ -401,6 +452,14 @@ int LensShadingCorrection::configure(IPAContext &context,\n \t\tyGrad_[i] = std::round(32768 / ySizes_[i]);\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+\tsets_.setData(std::move(shadingData));\n+\n \tcontext.configuration.lsc.enabled = true;\n \treturn 0;\n }\ndiff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h\nindex 7b68dda1a0d4257c345e0f1b77aa498f8183c92f..3097740a6cb2ce9063a4ba087856987a489b0ab6 100644\n--- a/src/ipa/rkisp1/algorithms/lsc.h\n+++ b/src/ipa/rkisp1/algorithms/lsc.h\n@@ -8,6 +8,7 @@\n #pragma once\n \n #include <map>\n+#include <memory>\n \n #include \"libipa/interpolator.h\"\n \n@@ -36,10 +37,22 @@ public:\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",
    "prefixes": [
        "v2",
        "13/15"
    ]
}