[{"id":39706,"web_url":"https://patchwork.libcamera.org/comment/39706/","msgid":"<3b98f495-c541-43ad-aeb6-6337ef8fdd4a@nxsw.ie>","date":"2026-07-15T00:32:10","subject":"Re: [RFC PATCH v7 3/6] ipa: simple: Add LSC algorithm","submitter":{"id":226,"url":"https://patchwork.libcamera.org/api/people/226/","name":"Bryan O'Donoghue","email":"bod.linux@nxsw.ie"},"content":"On 08/07/2026 21:18, Milan Zamazal wrote:\n> From: Xander Pronk <xander.c.pronk@gmail.com>\n> \n> The algorithm is based on the common libipa lens shading correction\n> implementation.  The grid values obtained from the libipa algorithm are\n> passed to debayering in an array to be used as an RGB texture.\n\npassed to the debayer algorithm as an array and used as an RGB(a) ? texture.\n\n> \n> Notes to the implementation:\n\non the\n\n> \n> - The overall idea is to keep things simple, to not make the LSC\n>    computation unnecessarily expensive.\n> \n> - 16 equally spaced grid positions are used for LscAlgorithm; for no\n>    particular reason other than that we already use the same number for\n>    the whole grid sizes.\n> \n> - LscAlgorithm accepts only quantised types.  UQ<2,6> is used, to be\n>    converted to float for debayering.\n> \n> - The limit of 100 to consider a temperature change noticeable is\n>    arbitrary.\n\n100 what ? 100 counts, 100 lumens - what does the 100 represent ?\n\n> \n> Co-developed-by: Rick ten Wolde <rick_libcamera@wolde.info>\n> Signed-off-by: Rick ten Wolde <rick_libcamera@wolde.info>\n> Signed-off-by: Xander Pronk <xander.c.pronk@gmail.com>\n> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n> ---\n>   src/ipa/simple/algorithms/lsc.cpp     | 89 +++++++++++++++++++++++++++\n>   src/ipa/simple/algorithms/lsc.h       | 50 +++++++++++++++\n>   src/ipa/simple/algorithms/meson.build |  1 +\n>   src/ipa/simple/ipa_context.h          |  5 ++\n>   4 files changed, 145 insertions(+)\n>   create mode 100644 src/ipa/simple/algorithms/lsc.cpp\n>   create mode 100644 src/ipa/simple/algorithms/lsc.h\n> \n> diff --git a/src/ipa/simple/algorithms/lsc.cpp b/src/ipa/simple/algorithms/lsc.cpp\n> new file mode 100644\n> index 000000000..815ffb911\n> --- /dev/null\n> +++ b/src/ipa/simple/algorithms/lsc.cpp\n> @@ -0,0 +1,89 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Lens shading correction\n> + */\n> +\n> +#include \"lsc.h\"\n> +\n> +#include <libcamera/base/log.h>\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::soft::algorithms {\n> +\n> +LOG_DEFINE_CATEGORY(IPASoftLsc)\n> +\n> +int Lsc::init(IPAContext &context, const ValueNode &tuningData)\n> +{\n> +\tstatic constexpr unsigned int kGridSize = DebayerParams::kLscGridSize;\n> +\n> +\tfor (unsigned int i = 0; i < kGridSize; i++)\n> +\t\tgridPos_.push_back(static_cast<double>(i) / (kGridSize - 1));\n> +\n> +\treturn lscAlgo_.init(tuningData, context.ctrlMap,\n> +\t\t\t     { .keys = { \"r\", \"g\", \"b\" },\n> +\t\t\t       .numHCells = kGridSize,\n> +\t\t\t       .numVCells = kGridSize,\n> +\t\t\t       .sensorSize = context.sensorInfo.activeAreaSize });\n> +}\n> +\n> +int Lsc::configure(IPAContext &context,\n> +\t\t   [[maybe_unused]] const IPAConfigInfo &configInfo)\n> +{\n> +\treturn lscAlgo_.configure(context.activeState.lsc,\n> +\t\t\t\t  context.sensorInfo.analogCrop,\n> +\t\t\t\t  gridPos_, gridPos_);\n> +}\n> +\n> +void Lsc::prepare([[maybe_unused]] IPAContext &context,\n> +\t\t  [[maybe_unused]] const uint32_t frame,\n> +\t\t  IPAFrameContext &frameContext,\n> +\t\t  DebayerParams *params)\n> +{\n> +\tunsigned int ct = frameContext.awb.colourTemperature;\n> +\n> +\tparams->lscEnabled = frameContext.lsc.enabled;\n> +\n> +\tif (!frameContext.lsc.enabled ||\n> +\t    utils::abs_diff(ct, lastAppliedCt_) < 100)\n> +\t\treturn;\n\nThe 100 should be a define with a meaningful name\n\n> +\n> +\tconst lsc::Components<uint8_t> &set = lscAlgo_.interpolateComponents(ct);\n> +\n> +\tconst auto &red = set.at(\"r\");\n> +\tconst auto &green = set.at(\"g\");\n> +\tconst auto &blue = set.at(\"b\");\n> +\n> +\tDebayerParams::LscLookupTable lut;\n> +\tconstexpr unsigned int gridSize = DebayerParams::kLscGridSize;\n> +\tfor (unsigned int i = 0, j = 0; i < gridSize * gridSize; i++) {\n> +\t\tlut[j++] = red[i] / 64.0;\n> +\t\tlut[j++] = green[i] / 64.0;\n> +\t\tlut[j++] = blue[i] / 64.0;\n> +\t}\n\nDoes the commit log make this / 64 make sense ? Anyway a comment would \nbe appreciated.\n\n> +\tparams->lscLut = lut;\n> +\n> +\tlastAppliedCt_ = ct;\n> +}\n> +\n> +void Lsc::queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n> +\t\t       IPAFrameContext &frameContext, const ControlList &controls)\n> +{\n> +\tlscAlgo_.queueRequest(context.activeState.lsc, frameContext.lsc,\n> +\t\t\t      controls);\n> +}\n> +\n> +void Lsc::process([[maybe_unused]] IPAContext &context,\n> +\t\t  [[maybe_unused]] const uint32_t frame,\n> +\t\t  IPAFrameContext &frameContext,\n> +\t\t  [[maybe_unused]] const SwIspStats *stats,\n> +\t\t  ControlList &metadata)\n> +{\n> +\tlscAlgo_.process(frameContext.lsc, metadata);\n> +}\n> +\n> +REGISTER_IPA_ALGORITHM(Lsc, \"Lsc\")\n> +\n> +} /* namespace ipa::soft::algorithms */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/ipa/simple/algorithms/lsc.h b/src/ipa/simple/algorithms/lsc.h\n> new file mode 100644\n> index 000000000..9418fac39\n> --- /dev/null\n> +++ b/src/ipa/simple/algorithms/lsc.h\n> @@ -0,0 +1,50 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Lens shading correction\n> + */\n> +\n> +#pragma once\n> +\n> +#include <libipa/interpolator.h>\n> +\n> +#include \"libipa/fixedpoint.h\"\n> +#include \"libipa/lsc.h\"\n> +\n> +#include \"algorithm.h\"\n> +#include \"ipa_context.h\"\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::soft::algorithms {\n> +\n> +class Lsc : public Algorithm\n> +{\n> +public:\n> +\tLsc() = default;\n> +\t~Lsc() = default;\n> +\n> +\tint init(IPAContext &context, const ValueNode &tuningData) override;\n> +\tint configure(IPAContext &context,\n> +\t\t      const IPAConfigInfo &configInfo) override;\n> +\tvoid queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n> +\t\t\t  IPAFrameContext &frameContext, const ControlList &controls) override;\n> +\tvoid prepare(IPAContext &context,\n> +\t\t     const uint32_t frame,\n> +\t\t     IPAFrameContext &frameContext,\n> +\t\t     DebayerParams *params) override;\n> +\tvoid process([[maybe_unused]] IPAContext &context,\n> +\t\t     [[maybe_unused]] const uint32_t frame,\n> +\t\t     IPAFrameContext &frameContext,\n> +\t\t     [[maybe_unused]] const SwIspStats *stats,\n> +\t\t     ControlList &metadata) override;\n> +\n> +private:\n> +\tLscAlgorithm<UQ<2, 6>> lscAlgo_;\n> +\tstd::vector<double> gridPos_;\n> +\n> +\tunsigned int lastAppliedCt_ = 0;\n> +};\n> +\n> +} /* namespace ipa::soft::algorithms */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build\n> index 73c637220..c9f6e5590 100644\n> --- a/src/ipa/simple/algorithms/meson.build\n> +++ b/src/ipa/simple/algorithms/meson.build\n> @@ -6,4 +6,5 @@ soft_simple_ipa_algorithms = files([\n>       'agc.cpp',\n>       'blc.cpp',\n>       'ccm.cpp',\n> +    'lsc.cpp',\n>   ])\n> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n> index ff312ae8f..23c2cfd0a 100644\n> --- a/src/ipa/simple/ipa_context.h\n> +++ b/src/ipa/simple/ipa_context.h\n> @@ -19,6 +19,7 @@\n>   #include <libipa/awb.h>\n>   #include <libipa/ccm.h>\n>   #include <libipa/fc_queue.h>\n> +#include \"libipa/lsc.h\"\n> \n>   #include \"core_ipa_interface.h\"\n> \n> @@ -61,6 +62,8 @@ struct IPAActiveState {\n>   \t\tstd::optional<float> contrast;\n>   \t\tstd::optional<float> saturation;\n>   \t} knobs;\n> +\n> +\tipa::lsc::ActiveState lsc;\n>   };\n> \n>   struct IPAFrameContext : public FrameContext {\n> @@ -75,6 +78,7 @@ struct IPAFrameContext : public FrameContext {\n>   \tfloat gamma;\n>   \tstd::optional<float> contrast;\n>   \tstd::optional<float> saturation;\n> +\tipa::lsc::FrameContext lsc;\n>   };\n> \n>   struct IPAContext {\n> @@ -89,6 +93,7 @@ struct IPAContext {\n>   \tFCQueue<IPAFrameContext> frameContexts;\n>   \tControlInfoMap::Map ctrlMap;\n>   \tbool ccmEnabled = false;\n> +\tipa::lsc::ActiveState lsc;\n>   };\n> \n>   } /* namespace ipa::soft */\n> --\n> 2.55.0\n> \n\nCode seems fine but, I think it should be more self-describing - \ncomments I mean.\n\n---\nbod","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 3CF21C3301\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 15 Jul 2026 00:32:17 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 74A0566156;\n\tWed, 15 Jul 2026 02:32:16 +0200 (CEST)","from sea.source.kernel.org (sea.source.kernel.org [172.234.252.31])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5018766152\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 15 Jul 2026 02:32:15 +0200 (CEST)","from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18])\n\tby sea.source.kernel.org (Postfix) with ESMTP id 5131640747;\n\tWed, 15 Jul 2026 00:32:13 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id F12F31F000E9;\n\tWed, 15 Jul 2026 00:32:11 +0000 (UTC)"],"Message-ID":"<3b98f495-c541-43ad-aeb6-6337ef8fdd4a@nxsw.ie>","Date":"Wed, 15 Jul 2026 01:32:10 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [RFC PATCH v7 3/6] ipa: simple: Add LSC algorithm","To":"Milan Zamazal <mzamazal@redhat.com>, libcamera-devel@lists.libcamera.org","Cc":"Xander Pronk <xander.c.pronk@gmail.com>,\n\tHans de Goede <johannes.goede@oss.qualcomm.com>,\n\tLaurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tRick ten Wolde <rick_libcamera@wolde.info>","References":"<20260708201816.299983-1-mzamazal@redhat.com>\n\t<EttAFRlyBPwEQ-_7Kwkbu3TWHW-JGt3TZjpD-eb4qsEF9SaO4gj42N_ugJfHDattqSyLIfA82elSgdDJVX-XdQ==@protonmail.internalid>\n\t<20260708201816.299983-4-mzamazal@redhat.com>","From":"Bryan O'Donoghue <bod.linux@nxsw.ie>","Content-Language":"en-GB","In-Reply-To":"<20260708201816.299983-4-mzamazal@redhat.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","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>"}},{"id":39712,"web_url":"https://patchwork.libcamera.org/comment/39712/","msgid":"<85v7agmzav.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","date":"2026-07-15T08:28:56","subject":"Re: [RFC PATCH v7 3/6] ipa: simple: Add LSC algorithm","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Bryan O'Donoghue <bod.linux@nxsw.ie> writes:\n\n> On 08/07/2026 21:18, Milan Zamazal wrote:\n>> From: Xander Pronk <xander.c.pronk@gmail.com>\n>> The algorithm is based on the common libipa lens shading correction\n>> implementation.  The grid values obtained from the libipa algorithm are\n>> passed to debayering in an array to be used as an RGB texture.\n>\n> passed to the debayer algorithm as an array and used as an \n\nOK\n\n> RGB(a) ? texture.\n\nIt's an RGB texture, no alpha correction.\n\n>> Notes to the implementation:\n>\n> on the\n\nOK\n\n>> - The overall idea is to keep things simple, to not make the LSC\n>>    computation unnecessarily expensive.\n>> - 16 equally spaced grid positions are used for LscAlgorithm; for no\n>>    particular reason other than that we already use the same number for\n>>    the whole grid sizes.\n>> - LscAlgorithm accepts only quantised types.  UQ<2,6> is used, to be\n>>    converted to float for debayering.\n>> - The limit of 100 to consider a temperature change noticeable is\n>>    arbitrary.\n>\n> 100 what ? 100 counts, 100 lumens - what does the 100 represent ?\n\nDegrees, will add.\n\n>> Co-developed-by: Rick ten Wolde <rick_libcamera@wolde.info>\n>> Signed-off-by: Rick ten Wolde <rick_libcamera@wolde.info>\n>> Signed-off-by: Xander Pronk <xander.c.pronk@gmail.com>\n>> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n>> ---\n>>   src/ipa/simple/algorithms/lsc.cpp     | 89 +++++++++++++++++++++++++++\n>>   src/ipa/simple/algorithms/lsc.h       | 50 +++++++++++++++\n>>   src/ipa/simple/algorithms/meson.build |  1 +\n>>   src/ipa/simple/ipa_context.h          |  5 ++\n>>   4 files changed, 145 insertions(+)\n>>   create mode 100644 src/ipa/simple/algorithms/lsc.cpp\n>>   create mode 100644 src/ipa/simple/algorithms/lsc.h\n>> diff --git a/src/ipa/simple/algorithms/lsc.cpp b/src/ipa/simple/algorithms/lsc.cpp\n>> new file mode 100644\n>> index 000000000..815ffb911\n>> --- /dev/null\n>> +++ b/src/ipa/simple/algorithms/lsc.cpp\n>> @@ -0,0 +1,89 @@\n>> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n>> +/*\n>> + * Lens shading correction\n>> + */\n>> +\n>> +#include \"lsc.h\"\n>> +\n>> +#include <libcamera/base/log.h>\n>> +\n>> +namespace libcamera {\n>> +\n>> +namespace ipa::soft::algorithms {\n>> +\n>> +LOG_DEFINE_CATEGORY(IPASoftLsc)\n>> +\n>> +int Lsc::init(IPAContext &context, const ValueNode &tuningData)\n>> +{\n>> +\tstatic constexpr unsigned int kGridSize = DebayerParams::kLscGridSize;\n>> +\n>> +\tfor (unsigned int i = 0; i < kGridSize; i++)\n>> +\t\tgridPos_.push_back(static_cast<double>(i) / (kGridSize - 1));\n>> +\n>> +\treturn lscAlgo_.init(tuningData, context.ctrlMap,\n>> +\t\t\t     { .keys = { \"r\", \"g\", \"b\" },\n>> +\t\t\t       .numHCells = kGridSize,\n>> +\t\t\t       .numVCells = kGridSize,\n>> +\t\t\t       .sensorSize = context.sensorInfo.activeAreaSize });\n>> +}\n>> +\n>> +int Lsc::configure(IPAContext &context,\n>> +\t\t   [[maybe_unused]] const IPAConfigInfo &configInfo)\n>> +{\n>> +\treturn lscAlgo_.configure(context.activeState.lsc,\n>> +\t\t\t\t  context.sensorInfo.analogCrop,\n>> +\t\t\t\t  gridPos_, gridPos_);\n>> +}\n>> +\n>> +void Lsc::prepare([[maybe_unused]] IPAContext &context,\n>> +\t\t  [[maybe_unused]] const uint32_t frame,\n>> +\t\t  IPAFrameContext &frameContext,\n>> +\t\t  DebayerParams *params)\n>> +{\n>> +\tunsigned int ct = frameContext.awb.colourTemperature;\n>> +\n>> +\tparams->lscEnabled = frameContext.lsc.enabled;\n>> +\n>> +\tif (!frameContext.lsc.enabled ||\n>> +\t    utils::abs_diff(ct, lastAppliedCt_) < 100)\n>> +\t\treturn;\n>\n> The 100 should be a define with a meaningful name\n\nOK\n\n>> +\n>> +\tconst lsc::Components<uint8_t> &set = lscAlgo_.interpolateComponents(ct);\n>> +\n>> +\tconst auto &red = set.at(\"r\");\n>> +\tconst auto &green = set.at(\"g\");\n>> +\tconst auto &blue = set.at(\"b\");\n>> +\n>> +\tDebayerParams::LscLookupTable lut;\n>> +\tconstexpr unsigned int gridSize = DebayerParams::kLscGridSize;\n>> +\tfor (unsigned int i = 0, j = 0; i < gridSize * gridSize; i++) {\n>> +\t\tlut[j++] = red[i] / 64.0;\n>> +\t\tlut[j++] = green[i] / 64.0;\n>> +\t\tlut[j++] = blue[i] / 64.0;\n>> +\t}\n>\n> Does the commit log make this / 64 make sense ? Anyway a comment would be appreciated.\n\nI'll add a source code comment.\n\n>> +\tparams->lscLut = lut;\n>> +\n>> +\tlastAppliedCt_ = ct;\n>> +}\n>> +\n>> +void Lsc::queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n>> +\t\t       IPAFrameContext &frameContext, const ControlList &controls)\n>> +{\n>> +\tlscAlgo_.queueRequest(context.activeState.lsc, frameContext.lsc,\n>> +\t\t\t      controls);\n>> +}\n>> +\n>> +void Lsc::process([[maybe_unused]] IPAContext &context,\n>> +\t\t  [[maybe_unused]] const uint32_t frame,\n>> +\t\t  IPAFrameContext &frameContext,\n>> +\t\t  [[maybe_unused]] const SwIspStats *stats,\n>> +\t\t  ControlList &metadata)\n>> +{\n>> +\tlscAlgo_.process(frameContext.lsc, metadata);\n>> +}\n>> +\n>> +REGISTER_IPA_ALGORITHM(Lsc, \"Lsc\")\n>> +\n>> +} /* namespace ipa::soft::algorithms */\n>> +\n>> +} /* namespace libcamera */\n>> diff --git a/src/ipa/simple/algorithms/lsc.h b/src/ipa/simple/algorithms/lsc.h\n>> new file mode 100644\n>> index 000000000..9418fac39\n>> --- /dev/null\n>> +++ b/src/ipa/simple/algorithms/lsc.h\n>> @@ -0,0 +1,50 @@\n>> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n>> +/*\n>> + * Lens shading correction\n>> + */\n>> +\n>> +#pragma once\n>> +\n>> +#include <libipa/interpolator.h>\n>> +\n>> +#include \"libipa/fixedpoint.h\"\n>> +#include \"libipa/lsc.h\"\n>> +\n>> +#include \"algorithm.h\"\n>> +#include \"ipa_context.h\"\n>> +\n>> +namespace libcamera {\n>> +\n>> +namespace ipa::soft::algorithms {\n>> +\n>> +class Lsc : public Algorithm\n>> +{\n>> +public:\n>> +\tLsc() = default;\n>> +\t~Lsc() = default;\n>> +\n>> +\tint init(IPAContext &context, const ValueNode &tuningData) override;\n>> +\tint configure(IPAContext &context,\n>> +\t\t      const IPAConfigInfo &configInfo) override;\n>> +\tvoid queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n>> +\t\t\t  IPAFrameContext &frameContext, const ControlList &controls) override;\n>> +\tvoid prepare(IPAContext &context,\n>> +\t\t     const uint32_t frame,\n>> +\t\t     IPAFrameContext &frameContext,\n>> +\t\t     DebayerParams *params) override;\n>> +\tvoid process([[maybe_unused]] IPAContext &context,\n>> +\t\t     [[maybe_unused]] const uint32_t frame,\n>> +\t\t     IPAFrameContext &frameContext,\n>> +\t\t     [[maybe_unused]] const SwIspStats *stats,\n>> +\t\t     ControlList &metadata) override;\n>> +\n>> +private:\n>> +\tLscAlgorithm<UQ<2, 6>> lscAlgo_;\n>> +\tstd::vector<double> gridPos_;\n>> +\n>> +\tunsigned int lastAppliedCt_ = 0;\n>> +};\n>> +\n>> +} /* namespace ipa::soft::algorithms */\n>> +\n>> +} /* namespace libcamera */\n>> diff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build\n>> index 73c637220..c9f6e5590 100644\n>> --- a/src/ipa/simple/algorithms/meson.build\n>> +++ b/src/ipa/simple/algorithms/meson.build\n>> @@ -6,4 +6,5 @@ soft_simple_ipa_algorithms = files([\n>>       'agc.cpp',\n>>       'blc.cpp',\n>>       'ccm.cpp',\n>> +    'lsc.cpp',\n>>   ])\n>> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n>> index ff312ae8f..23c2cfd0a 100644\n>> --- a/src/ipa/simple/ipa_context.h\n>> +++ b/src/ipa/simple/ipa_context.h\n>> @@ -19,6 +19,7 @@\n>>   #include <libipa/awb.h>\n>>   #include <libipa/ccm.h>\n>>   #include <libipa/fc_queue.h>\n>> +#include \"libipa/lsc.h\"\n>>   #include \"core_ipa_interface.h\"\n>> @@ -61,6 +62,8 @@ struct IPAActiveState {\n>>   \t\tstd::optional<float> contrast;\n>>   \t\tstd::optional<float> saturation;\n>>   \t} knobs;\n>> +\n>> +\tipa::lsc::ActiveState lsc;\n>>   };\n>>   struct IPAFrameContext : public FrameContext {\n>> @@ -75,6 +78,7 @@ struct IPAFrameContext : public FrameContext {\n>>   \tfloat gamma;\n>>   \tstd::optional<float> contrast;\n>>   \tstd::optional<float> saturation;\n>> +\tipa::lsc::FrameContext lsc;\n>>   };\n>>   struct IPAContext {\n>> @@ -89,6 +93,7 @@ struct IPAContext {\n>>   \tFCQueue<IPAFrameContext> frameContexts;\n>>   \tControlInfoMap::Map ctrlMap;\n>>   \tbool ccmEnabled = false;\n>> +\tipa::lsc::ActiveState lsc;\n>>   };\n>>   } /* namespace ipa::soft */\n>> --\n>> 2.55.0\n>> \n>\n> Code seems fine but, I think it should be more self-describing - comments I mean.\n>\n> ---\n> bod","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 0E312C3301\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 15 Jul 2026 08:29:05 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1A96266163;\n\tWed, 15 Jul 2026 10:29:04 +0200 (CEST)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3786F6614E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 15 Jul 2026 10:29:02 +0200 (CEST)","from mail-wm1-f72.google.com (mail-wm1-f72.google.com\n\t[209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-601-yez21cobNj-YnE-RLAQwVQ-1; Wed, 15 Jul 2026 04:28:59 -0400","by mail-wm1-f72.google.com with SMTP id\n\t5b1f17b1804b1-492488f8583so75028895e9.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 15 Jul 2026 01:28:59 -0700 (PDT)","from mzamazal-thinkpadp1gen7.tpbc.csb\n\t(ip-77-48-47-4.net.vodafone.cz. [77.48.47.4])\n\tby smtp.gmail.com with ESMTPSA id\n\t5b1f17b1804b1-4950a2e98b0sm231629345e9.8.2026.07.15.01.28.56\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 15 Jul 2026 01:28:57 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"i1XFDX8M\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1784104141;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=nR4Xq8bYE9AB109pnLdfGM7xdp7l6BPsjjbt1XQ6aVI=;\n\tb=i1XFDX8MZ01+lK4h7Z5/dcR9PDqToapJ2Ia+mZEGuG+hlVVPtRtcsrckZ/EXhxoWnqzBo6\n\tbNgQVxSc4LeKIrpKrjYz+RLPkeI/KYRnkbgr7QR2T4fl3pX2vjRMOC9GHZ7Q5DFRQOjVlC\n\tjpnIWjgY+dpTYyFE+eiN6E2AS/DJ4U4=","X-MC-Unique":"yez21cobNj-YnE-RLAQwVQ-1","X-Mimecast-MFC-AGG-ID":"yez21cobNj-YnE-RLAQwVQ_1784104138","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1784104138; x=1784708938;\n\th=content-type:mime-version:user-agent:message-id:date:references\n\t:in-reply-to:subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to\n\t:cc:subject:date:message-id:reply-to:content-type;\n\tbh=nR4Xq8bYE9AB109pnLdfGM7xdp7l6BPsjjbt1XQ6aVI=;\n\tb=VV5JAiAYHICpV/IKUCPNEKXO9H1xlf2MrPZiIVN6+kdvOQ4/t00g4+prWxQJFciSbp\n\tjquowm7AzfvMpKL5HEV+X+eciigpDUjVFVPcjj1iPXJX/P/Z3CDG/qd3AMT/gsM8BYXN\n\twOAxHGGY1HqxjMy1GgbUIjUM6/6Gd9gEhPeinKd+Lh7z8qQV5fg25SDJnhGjTxBRe7CB\n\tBQyIxdNxFvANoITrvb3GRjoWpdpcaqDezKPlks9BdJKmnF+cKU2xeYh7uleeqJ9SAMo3\n\tZ+BgZaQmVEVYAVqiujoE8I16X7ikU3WxWWFJPcD7KgPVTV7AJuWOiCFJfZgTXo9cW5Yx\n\ttNWA==","X-Gm-Message-State":"AOJu0YxXEEm2pSgpXO4S6WXtL4O5JePkzqsnJBwWIxFTCzgU1d8dnmqN\n\tRWzoKoyRvLbSed3gARpvX0EtqKPiySe69hFj0qy2SIUaajxx2goz7L8Tx/4uXymiFYr4uqDcChX\n\tH0r/oAle/E9aCQ4sM/FVoUqgQcXgaN8E51bSgthu+dYm01ld/ipdi+aCRmjIi97e/jkOY5d3laT\n\tQ=","X-Gm-Gg":"AfdE7cmHaDbQ7kB7hSU4ByzJEV5/btxIxlK8EAYZBFTu+sR9epy/1Pg9OmP9MnDjfw9\n\thaesTNqIhpQsyN9bICtBm9wM7ahQ+DWndhb9xnr7fzjm1jV8TvliWiP6Qw6Z6KUV3/M11BAB0qr\n\t1pCf/hkY8CRFxTZlGru4T9pfA2PP/4CBXgGFUZZcKF3GjAk/wUiq3fFi0bJs/tnHpE9QqTObtag\n\tH5l72Dkc5v0yDjI39/JzGMdDUktlSHkZZqSvtB44DLwK4/Zf9+VxWeDE5S6GufarbeXt8xgHZGX\n\t57UyikKFvswPCKvw8VvN2+g0uYFbOwhK3ySiJsTWrYC4NM6zaIfZYA9uVUTfWz5dkpQ3juZkrgk\n\tsaDaSInWRClCRb2gvt4HJwO2XXs5KC6g1doRJSKEyX8JU6D67Ag7S2x+217NkLLSv","X-Received":["by 2002:a05:600d:6451:20b0:493:c0c1:3930 with SMTP id\n\t5b1f17b1804b1-495389ce059mr44960375e9.1.1784104138320; \n\tWed, 15 Jul 2026 01:28:58 -0700 (PDT)","by 2002:a05:600d:6451:20b0:493:c0c1:3930 with SMTP id\n\t5b1f17b1804b1-495389ce059mr44960145e9.1.1784104137806; \n\tWed, 15 Jul 2026 01:28:57 -0700 (PDT)"],"From":"Milan Zamazal <mzamazal@redhat.com>","To":"Bryan O'Donoghue <bod.linux@nxsw.ie>","Cc":"libcamera-devel@lists.libcamera.org,  Xander Pronk\n\t<xander.c.pronk@gmail.com>,  Hans de Goede\n\t<johannes.goede@oss.qualcomm.com>,  Laurent Pinchart\n\t<laurent.pinchart@ideasonboard.com>,  Rick ten Wolde\n\t<rick_libcamera@wolde.info>","Subject":"Re: [RFC PATCH v7 3/6] ipa: simple: Add LSC algorithm","In-Reply-To":"<3b98f495-c541-43ad-aeb6-6337ef8fdd4a@nxsw.ie> (Bryan\n\tO'Donoghue's message of \"Wed, 15 Jul 2026 01:32:10 +0100\")","References":"<20260708201816.299983-1-mzamazal@redhat.com>\n\t<EttAFRlyBPwEQ-_7Kwkbu3TWHW-JGt3TZjpD-eb4qsEF9SaO4gj42N_ugJfHDattqSyLIfA82elSgdDJVX-XdQ==@protonmail.internalid>\n\t<20260708201816.299983-4-mzamazal@redhat.com>\n\t<3b98f495-c541-43ad-aeb6-6337ef8fdd4a@nxsw.ie>","Date":"Wed, 15 Jul 2026 10:28:56 +0200","Message-ID":"<85v7agmzav.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"cH9CEUSyP0xqhcHEghY9M4mlJDUrXEuGLuptZ69kZx4_1784104138","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","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>"}}]