[{"id":29807,"web_url":"https://patchwork.libcamera.org/comment/29807/","msgid":"<171802422442.1489778.16080166471221566518@ping.linuxembedded.co.uk>","date":"2024-06-10T12:57:04","subject":"Re: [PATCH v6 3/3] ipa: rkisp1: algorithms: Add crosstalk algorithm","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Paul Elder (2024-06-07 09:09:06)\n> Add an algorithm module to the rkisp1 IPA for crosstalk correction.\n> \n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> \n> ---\n> No change in v6\n> \n> Changes in v5:\n> - clean up documentation\n> - coalesce parseYaml into init\n> \n> Changes in v4:\n> - remove stray semicolons\n> - use the new matrix interpolator readYaml\n> - use the new matrix operator[] getter\n> \n> Changes in v3:\n> - read ccm offsets from tuning data, and write these offsets to the\n>   parameters buffer\n> - make parseYaml return void, as it should fill in default data if\n>   unable to read, thus never failing\n> \n> Changes in v2:\n> - rename ctk to ccm\n> - reset the matrix interpolator to identity matrix if failed to read\n>   from tuning file\n> ---\n>  src/ipa/rkisp1/algorithms/ccm.cpp     | 109 ++++++++++++++++++++++++++\n>  src/ipa/rkisp1/algorithms/ccm.h       |  44 +++++++++++\n>  src/ipa/rkisp1/algorithms/meson.build |   1 +\n>  3 files changed, 154 insertions(+)\n>  create mode 100644 src/ipa/rkisp1/algorithms/ccm.cpp\n>  create mode 100644 src/ipa/rkisp1/algorithms/ccm.h\n> \n> diff --git a/src/ipa/rkisp1/algorithms/ccm.cpp b/src/ipa/rkisp1/algorithms/ccm.cpp\n> new file mode 100644\n> index 000000000..7ae013601\n> --- /dev/null\n> +++ b/src/ipa/rkisp1/algorithms/ccm.cpp\n> @@ -0,0 +1,109 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2024, Ideas On Board\n> + *\n> + * RkISP1 Color Correction Matrix control algorithm\n> + */\n> +\n> +#include \"ccm.h\"\n> +\n> +#include <algorithm>\n> +#include <chrono>\n> +#include <cmath>\n> +#include <tuple>\n> +#include <vector>\n> +\n> +#include <libcamera/base/log.h>\n> +#include <libcamera/base/utils.h>\n> +\n> +#include <libcamera/ipa/core_ipa_interface.h>\n> +\n> +#include \"libcamera/internal/yaml_parser.h\"\n> +\n> +#include \"../utils.h\"\n> +#include \"libipa/matrix_interpolator.h\"\n> +\n> +/**\n> + * \\file ccm.h\n> + */\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::rkisp1::algorithms {\n> +\n> +/**\n> + * \\class Ccm\n> + * \\brief A color correction matrix algorithm\n> + */\n> +\n> +LOG_DEFINE_CATEGORY(RkISP1Ccm)\n> +\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::init\n> + */\n> +int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)\n> +{\n> +       int ret = ccm_.readYaml(tuningData[\"ccms\"], \"ct\", \"ccm\");\n> +       if (ret < 0) {\n> +               LOG(RkISP1Ccm, Warning)\n> +                       << \"Failed to parse 'ccm' \"\n> +                       << \"parameter from tuning file; falling back to unit matrix\";\n> +               ccm_.reset();\n> +       }\n> +\n> +       ret = offsets_.readYaml(tuningData[\"ccms\"], \"ct\", \"offsets\");\n> +       if (ret < 0) {\n> +               LOG(RkISP1Ccm, Warning)\n> +                       << \"Failed to parse 'offsets' \"\n> +                       << \"parameter from tuning file; falling back to zero offsets\";\n> +               offsets_.reset();\n> +       }\n\nIf both ccm_ and offsets_ are both a Matrix Interpolator - how do they\nfall back to different defaults?\n\nI would certainly /expect/ offsets to default to 0, and CCM to default\nto Identity/Unit matrix ... but I don't think that's what the above is\ndoing ? Or did I miss something?\n\n> +\n> +       return 0;\n> +}\n> +\n> +void Ccm::setParameters(rkisp1_params_cfg *params,\n> +                       const Matrix<double, 3, 3> &matrix,\n> +                       const Matrix<int16_t, 3, 1> &offsets)\n> +{\n> +       struct rkisp1_cif_isp_ctk_config &config = params->others.ctk_config;\n> +\n> +       /*\n> +        * 4 bit integer and 7 bit fractional, ranging from -8 (0x400) to\n> +        * +7.992 (0x3FF)\n> +        */\n> +       for (unsigned int i = 0; i < 3; i++)\n> +               for (unsigned int j = 0; j < 3; j++)\n> +                       config.coeff[i][j] =\n> +                               utils::floatingToFixedPoint<4, 7, uint16_t, double>(matrix[i][j]);\n> +\n> +       for (unsigned int i = 0; i < 3; i++)\n> +               config.ct_offset[i] = offsets[i][0] & 0xFFF;\n> +\n> +       LOG(RkISP1Ccm, Debug) << \"Setting matrix \" << matrix;\n> +       LOG(RkISP1Ccm, Debug) << \"Setting offsets \" << offsets;\n> +\n> +       params->module_en_update |= RKISP1_CIF_ISP_MODULE_CTK;\n> +       params->module_ens |= RKISP1_CIF_ISP_MODULE_CTK;\n> +       params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_CTK;\n> +}\n> +\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::prepare\n> + */\n> +void Ccm::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n> +                 [[maybe_unused]] IPAFrameContext &frameContext,\n> +                 rkisp1_params_cfg *params)\n> +{\n> +       uint32_t ct = context.activeState.awb.temperatureK;\n\nI think I would anticipate that the Ccm would remember the current ct\nin a class private and only perform the below if it's changed.\n\nPerhaps with a customisable delta value to filter how often this gets\nupdated.\n\n\n\n> +       Matrix<double, 3, 3> ccm = ccm_.get(ct);\n> +       Matrix<int16_t, 3, 1> offsets = offsets_.get(ct);\n> +\n> +       setParameters(params, ccm, offsets);\n\nI think we should report the CCM back in the metadata.\n\n\nThis probably means we should store the Ccm into the frameContext (ccm\nsection should be added), and then during process() we set the metadata:\n\n\n\tmetadata.set(controls::ColourCorrectionMatrix, frameContext.ccm);\n\n\nThe control reports:\n\n  - ColourCorrectionMatrix:\n      type: float\n      description: |\n        The 3x3 matrix that converts camera RGB to sRGB within the\n        imaging pipeline. This should describe the matrix that is used\n        after pixels have been white-balanced, but before any gamma\n        transformation. The 3x3 matrix is stored in conventional reading\n        order in an array of 9 floating point values.\n\n      size: [3,3]\n\n\nCan we confirm the control description matches the actions in the\nRKISP1?\n\n\n\n\n> +}\n> +\n> +REGISTER_IPA_ALGORITHM(Ccm, \"Ccm\")\n> +\n> +} /* namespace ipa::rkisp1::algorithms */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/ipa/rkisp1/algorithms/ccm.h b/src/ipa/rkisp1/algorithms/ccm.h\n> new file mode 100644\n> index 000000000..35c2cf83c\n> --- /dev/null\n> +++ b/src/ipa/rkisp1/algorithms/ccm.h\n> @@ -0,0 +1,44 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2024, Ideas On Board\n> + *\n> + * RkISP1 Color Correction Matrix control algorithm\n> + */\n> +\n> +#pragma once\n> +\n> +#include <linux/rkisp1-config.h>\n> +\n> +#include \"libipa/matrix.h\"\n> +#include \"libipa/matrix_interpolator.h\"\n> +\n> +#include \"algorithm.h\"\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::rkisp1::algorithms {\n> +\n> +class Ccm : public Algorithm\n> +{\n> +public:\n> +       Ccm() {}\n> +       ~Ccm() = default;\n> +\n> +       int init(IPAContext &context, const YamlObject &tuningData) override;\n> +       void prepare(IPAContext &context, const uint32_t frame,\n> +                    IPAFrameContext &frameContext,\n> +                    rkisp1_params_cfg *params) override;\n> +\n> +private:\n> +       void parseYaml(const YamlObject &tuningData);\n> +       void setParameters(rkisp1_params_cfg *params,\n> +                          const Matrix<double, 3, 3> &matrix,\n> +                          const Matrix<int16_t, 3, 1> &offsets);\n> +\n> +       MatrixInterpolator<double, 3, 3> ccm_;\n> +       MatrixInterpolator<int16_t, 3, 1> offsets_;\n> +};\n> +\n> +} /* namespace ipa::rkisp1::algorithms */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build\n> index 93a483292..16de71332 100644\n> --- a/src/ipa/rkisp1/algorithms/meson.build\n> +++ b/src/ipa/rkisp1/algorithms/meson.build\n> @@ -4,6 +4,7 @@ rkisp1_ipa_algorithms = files([\n>      'agc.cpp',\n>      'awb.cpp',\n>      'blc.cpp',\n> +    'ccm.cpp',\n>      'cproc.cpp',\n>      'dpcc.cpp',\n>      'dpf.cpp',\n> -- \n> 2.39.2\n>","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 64739C31E9\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 10 Jun 2024 12:57:10 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9F00D634D5;\n\tMon, 10 Jun 2024 14:57:09 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4A0DC634D5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 10 Jun 2024 14:57:07 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 37268230;\n\tMon, 10 Jun 2024 14:56:55 +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=\"I+ZO3gMJ\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1718024215;\n\tbh=0HeIyMvPL4GIi2MVI6f2uzOwLNVjIavI0A+wqcxSWaQ=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=I+ZO3gMJpMrHJ3nE+hStjE71DZh13cS2Mt02t99OHJ/dpUNR2gfycMZWLIRy6WhCL\n\tMYdfww+3L7ikuP6yWVAsn2tb4T3r4NPmSuILwfE3Ui8oSxM9/cvf6kd65yogn1yEIT\n\tPriYpsMMocGXpIjRl3v8pgQ6ZC2L8QhPIfLWXFB0=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20240607080906.2684579-4-paul.elder@ideasonboard.com>","References":"<20240607080906.2684579-1-paul.elder@ideasonboard.com>\n\t<20240607080906.2684579-4-paul.elder@ideasonboard.com>","Subject":"Re: [PATCH v6 3/3] ipa: rkisp1: algorithms: Add crosstalk algorithm","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Paul Elder <paul.elder@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>","To":"Paul Elder <paul.elder@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Mon, 10 Jun 2024 13:57:04 +0100","Message-ID":"<171802422442.1489778.16080166471221566518@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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":29824,"web_url":"https://patchwork.libcamera.org/comment/29824/","msgid":"<ZmgQh1FgqS6ch1Pa@pyrite.rasen.tech>","date":"2024-06-11T08:53:27","subject":"Re: [PATCH v6 3/3] ipa: rkisp1: algorithms: Add crosstalk algorithm","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"On Mon, Jun 10, 2024 at 01:57:04PM +0100, Kieran Bingham wrote:\n> Quoting Paul Elder (2024-06-07 09:09:06)\n> > Add an algorithm module to the rkisp1 IPA for crosstalk correction.\n> > \n> > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> > Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> > \n> > ---\n> > No change in v6\n> > \n> > Changes in v5:\n> > - clean up documentation\n> > - coalesce parseYaml into init\n> > \n> > Changes in v4:\n> > - remove stray semicolons\n> > - use the new matrix interpolator readYaml\n> > - use the new matrix operator[] getter\n> > \n> > Changes in v3:\n> > - read ccm offsets from tuning data, and write these offsets to the\n> >   parameters buffer\n> > - make parseYaml return void, as it should fill in default data if\n> >   unable to read, thus never failing\n> > \n> > Changes in v2:\n> > - rename ctk to ccm\n> > - reset the matrix interpolator to identity matrix if failed to read\n> >   from tuning file\n> > ---\n> >  src/ipa/rkisp1/algorithms/ccm.cpp     | 109 ++++++++++++++++++++++++++\n> >  src/ipa/rkisp1/algorithms/ccm.h       |  44 +++++++++++\n> >  src/ipa/rkisp1/algorithms/meson.build |   1 +\n> >  3 files changed, 154 insertions(+)\n> >  create mode 100644 src/ipa/rkisp1/algorithms/ccm.cpp\n> >  create mode 100644 src/ipa/rkisp1/algorithms/ccm.h\n> > \n> > diff --git a/src/ipa/rkisp1/algorithms/ccm.cpp b/src/ipa/rkisp1/algorithms/ccm.cpp\n> > new file mode 100644\n> > index 000000000..7ae013601\n> > --- /dev/null\n> > +++ b/src/ipa/rkisp1/algorithms/ccm.cpp\n> > @@ -0,0 +1,109 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2024, Ideas On Board\n> > + *\n> > + * RkISP1 Color Correction Matrix control algorithm\n> > + */\n> > +\n> > +#include \"ccm.h\"\n> > +\n> > +#include <algorithm>\n> > +#include <chrono>\n> > +#include <cmath>\n> > +#include <tuple>\n> > +#include <vector>\n> > +\n> > +#include <libcamera/base/log.h>\n> > +#include <libcamera/base/utils.h>\n> > +\n> > +#include <libcamera/ipa/core_ipa_interface.h>\n> > +\n> > +#include \"libcamera/internal/yaml_parser.h\"\n> > +\n> > +#include \"../utils.h\"\n> > +#include \"libipa/matrix_interpolator.h\"\n> > +\n> > +/**\n> > + * \\file ccm.h\n> > + */\n> > +\n> > +namespace libcamera {\n> > +\n> > +namespace ipa::rkisp1::algorithms {\n> > +\n> > +/**\n> > + * \\class Ccm\n> > + * \\brief A color correction matrix algorithm\n> > + */\n> > +\n> > +LOG_DEFINE_CATEGORY(RkISP1Ccm)\n> > +\n> > +/**\n> > + * \\copydoc libcamera::ipa::Algorithm::init\n> > + */\n> > +int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)\n> > +{\n> > +       int ret = ccm_.readYaml(tuningData[\"ccms\"], \"ct\", \"ccm\");\n> > +       if (ret < 0) {\n> > +               LOG(RkISP1Ccm, Warning)\n> > +                       << \"Failed to parse 'ccm' \"\n> > +                       << \"parameter from tuning file; falling back to unit matrix\";\n> > +               ccm_.reset();\n> > +       }\n> > +\n> > +       ret = offsets_.readYaml(tuningData[\"ccms\"], \"ct\", \"offsets\");\n> > +       if (ret < 0) {\n> > +               LOG(RkISP1Ccm, Warning)\n> > +                       << \"Failed to parse 'offsets' \"\n> > +                       << \"parameter from tuning file; falling back to zero offsets\";\n> > +               offsets_.reset();\n> > +       }\n> \n> If both ccm_ and offsets_ are both a Matrix Interpolator - how do they\n> fall back to different defaults?\n> \n> I would certainly /expect/ offsets to default to 0, and CCM to default\n> to Identity/Unit matrix ... but I don't think that's what the above is\n> doing ? Or did I miss something?\n> \n> > +\n> > +       return 0;\n> > +}\n> > +\n> > +void Ccm::setParameters(rkisp1_params_cfg *params,\n> > +                       const Matrix<double, 3, 3> &matrix,\n> > +                       const Matrix<int16_t, 3, 1> &offsets)\n> > +{\n> > +       struct rkisp1_cif_isp_ctk_config &config = params->others.ctk_config;\n> > +\n> > +       /*\n> > +        * 4 bit integer and 7 bit fractional, ranging from -8 (0x400) to\n> > +        * +7.992 (0x3FF)\n> > +        */\n> > +       for (unsigned int i = 0; i < 3; i++)\n> > +               for (unsigned int j = 0; j < 3; j++)\n> > +                       config.coeff[i][j] =\n> > +                               utils::floatingToFixedPoint<4, 7, uint16_t, double>(matrix[i][j]);\n> > +\n> > +       for (unsigned int i = 0; i < 3; i++)\n> > +               config.ct_offset[i] = offsets[i][0] & 0xFFF;\n> > +\n> > +       LOG(RkISP1Ccm, Debug) << \"Setting matrix \" << matrix;\n> > +       LOG(RkISP1Ccm, Debug) << \"Setting offsets \" << offsets;\n> > +\n> > +       params->module_en_update |= RKISP1_CIF_ISP_MODULE_CTK;\n> > +       params->module_ens |= RKISP1_CIF_ISP_MODULE_CTK;\n> > +       params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_CTK;\n> > +}\n> > +\n> > +/**\n> > + * \\copydoc libcamera::ipa::Algorithm::prepare\n> > + */\n> > +void Ccm::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n> > +                 [[maybe_unused]] IPAFrameContext &frameContext,\n> > +                 rkisp1_params_cfg *params)\n> > +{\n> > +       uint32_t ct = context.activeState.awb.temperatureK;\n> \n> I think I would anticipate that the Ccm would remember the current ct\n> in a class private and only perform the below if it's changed.\n\nAh yeah ok.\n\n> \n> Perhaps with a customisable delta value to filter how often this gets\n> updated.\n\nI'd avoid this since it's an integer so we don't have to worry about\nfloat comparisons, plus we'd have a fun time if the ct changes barely\nless than delta but monotonically and suddently ct is super different\nbut never changed because it always changed by ct - 1 every frame.\n\n> \n> \n> \n> > +       Matrix<double, 3, 3> ccm = ccm_.get(ct);\n> > +       Matrix<int16_t, 3, 1> offsets = offsets_.get(ct);\n> > +\n> > +       setParameters(params, ccm, offsets);\n> \n> I think we should report the CCM back in the metadata.\n\nIndeed.\n\n\nThanks,\n\nPaul\n\n> \n> \n> This probably means we should store the Ccm into the frameContext (ccm\n> section should be added), and then during process() we set the metadata:\n> \n> \n> \tmetadata.set(controls::ColourCorrectionMatrix, frameContext.ccm);\n> \n> \n> The control reports:\n> \n>   - ColourCorrectionMatrix:\n>       type: float\n>       description: |\n>         The 3x3 matrix that converts camera RGB to sRGB within the\n>         imaging pipeline. This should describe the matrix that is used\n>         after pixels have been white-balanced, but before any gamma\n>         transformation. The 3x3 matrix is stored in conventional reading\n>         order in an array of 9 floating point values.\n> \n>       size: [3,3]\n> \n> \n> Can we confirm the control description matches the actions in the\n> RKISP1?\n> \n> \n> \n> \n> > +}\n> > +\n> > +REGISTER_IPA_ALGORITHM(Ccm, \"Ccm\")\n> > +\n> > +} /* namespace ipa::rkisp1::algorithms */\n> > +\n> > +} /* namespace libcamera */\n> > diff --git a/src/ipa/rkisp1/algorithms/ccm.h b/src/ipa/rkisp1/algorithms/ccm.h\n> > new file mode 100644\n> > index 000000000..35c2cf83c\n> > --- /dev/null\n> > +++ b/src/ipa/rkisp1/algorithms/ccm.h\n> > @@ -0,0 +1,44 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2024, Ideas On Board\n> > + *\n> > + * RkISP1 Color Correction Matrix control algorithm\n> > + */\n> > +\n> > +#pragma once\n> > +\n> > +#include <linux/rkisp1-config.h>\n> > +\n> > +#include \"libipa/matrix.h\"\n> > +#include \"libipa/matrix_interpolator.h\"\n> > +\n> > +#include \"algorithm.h\"\n> > +\n> > +namespace libcamera {\n> > +\n> > +namespace ipa::rkisp1::algorithms {\n> > +\n> > +class Ccm : public Algorithm\n> > +{\n> > +public:\n> > +       Ccm() {}\n> > +       ~Ccm() = default;\n> > +\n> > +       int init(IPAContext &context, const YamlObject &tuningData) override;\n> > +       void prepare(IPAContext &context, const uint32_t frame,\n> > +                    IPAFrameContext &frameContext,\n> > +                    rkisp1_params_cfg *params) override;\n> > +\n> > +private:\n> > +       void parseYaml(const YamlObject &tuningData);\n> > +       void setParameters(rkisp1_params_cfg *params,\n> > +                          const Matrix<double, 3, 3> &matrix,\n> > +                          const Matrix<int16_t, 3, 1> &offsets);\n> > +\n> > +       MatrixInterpolator<double, 3, 3> ccm_;\n> > +       MatrixInterpolator<int16_t, 3, 1> offsets_;\n> > +};\n> > +\n> > +} /* namespace ipa::rkisp1::algorithms */\n> > +\n> > +} /* namespace libcamera */\n> > diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build\n> > index 93a483292..16de71332 100644\n> > --- a/src/ipa/rkisp1/algorithms/meson.build\n> > +++ b/src/ipa/rkisp1/algorithms/meson.build\n> > @@ -4,6 +4,7 @@ rkisp1_ipa_algorithms = files([\n> >      'agc.cpp',\n> >      'awb.cpp',\n> >      'blc.cpp',\n> > +    'ccm.cpp',\n> >      'cproc.cpp',\n> >      'dpcc.cpp',\n> >      'dpf.cpp',\n> > -- \n> > 2.39.2\n> >","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 C28F5BD87C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 11 Jun 2024 08:53:37 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A67B965463;\n\tTue, 11 Jun 2024 10:53:36 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7EB39634D3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 11 Jun 2024 10:53:34 +0200 (CEST)","from pyrite.rasen.tech (h175-177-049-156.catv02.itscom.jp\n\t[175.177.49.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id AB97029A;\n\tTue, 11 Jun 2024 10:53:20 +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=\"PQqr0iv8\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1718096001;\n\tbh=jG9yvuOHLNwetJZJolxKrKAE6+1Cqw97xUqCAORUNAE=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=PQqr0iv83SlmlB6cU6TeKoeR9d1VkYF7WCfIZ5WbciQoXARSzoFHS/NBBtrrulzP5\n\tzk70EPtDXUiWQ3eerwyDHZhZjggcoT0zy+wuWMHJ1rM6+NhRDYsukGj4FacDWEJnCf\n\tJOyaDxgBE+09yM9THKG8nFAM8o5Duprt/+F7ofnk=","Date":"Tue, 11 Jun 2024 17:53:27 +0900","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org,\n\tStefan Klug <stefan.klug@ideasonboard.com>","Subject":"Re: [PATCH v6 3/3] ipa: rkisp1: algorithms: Add crosstalk algorithm","Message-ID":"<ZmgQh1FgqS6ch1Pa@pyrite.rasen.tech>","References":"<20240607080906.2684579-1-paul.elder@ideasonboard.com>\n\t<20240607080906.2684579-4-paul.elder@ideasonboard.com>\n\t<171802422442.1489778.16080166471221566518@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<171802422442.1489778.16080166471221566518@ping.linuxembedded.co.uk>","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>"}}]