[{"id":29646,"web_url":"https://patchwork.libcamera.org/comment/29646/","msgid":"<20240529003400.GC11144@pendragon.ideasonboard.com>","date":"2024-05-29T00:34:00","subject":"Re: [PATCH v4 5/5] libcamera: software_isp: Pass color lookup tables\n\tas floats","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Milan,\n\nThank you for the patch.\n\nOn Tue, May 28, 2024 at 06:11:26PM +0200, Milan Zamazal wrote:\n> The color lookup tables are passed from stats processing to debayering\n> for direct use as 8-bit color output values.  Let's pass the values as\n> 0.0..1.0 floats to make the gains color bit width independent.\n> \n> Completes software ISP TODO #4.\n\nThe implementation looks good, and this indeed covers TODO #4. The\nconversion of the tables from float to integer takes a big more CPU\ntime, which is reasonable, but it got me thinking.\n\nTODO #4 was recorded at a time where the IPA module computed gain\nvalues, and the ISP computed the look up tables. The gains were\nhigher-level parameters. I thought it would be good to not hardcode in\ntheir representation what was an internal implementation feature of the\nISP, as that would allow changing the ISP implementation later without\nimpacting the IPA module.\n\nNow that the look up tables are computed in the IPA module, the IPA and\nISP are more tightly coupled. Do you think it's still useful to abstract\nthe internal representation of the table entries from the IPA module, or\nwould that just consume more CPU cycles without offering any benefit for\nlater evolutions of the ISP ? I'm thinking in particular about future\nwork on a GPU-based implementation of the soft ISP. Do you foresee that\nwe would use the same IPA module, or a different one ?\n\nIf you think it's useful we can merge this patch, otherwise we could\ndrop the patch and drop TODO #4.\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n> Reviewed-by: Andrei Konovalov <andrey.konovalov.ynk@gmail.com>\n> ---\n>  .../internal/software_isp/debayer_params.h     |  2 +-\n>  src/ipa/simple/soft_simple.cpp                 |  5 ++---\n>  src/libcamera/software_isp/TODO                | 13 -------------\n>  src/libcamera/software_isp/debayer.cpp         |  6 +++---\n>  src/libcamera/software_isp/debayer_cpu.cpp     | 18 +++++++++++++++---\n>  src/libcamera/software_isp/debayer_cpu.h       | 10 +++++++---\n>  6 files changed, 28 insertions(+), 26 deletions(-)\n> \n> diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h\n> index 2f75b4b5..647905c5 100644\n> --- a/include/libcamera/internal/software_isp/debayer_params.h\n> +++ b/include/libcamera/internal/software_isp/debayer_params.h\n> @@ -19,7 +19,7 @@ struct DebayerParams {\n>  \tstatic constexpr unsigned int kRGBLookupSize = 256;\n>  \tstatic constexpr float kGamma = 0.5;\n>  \n> -\tusing ColorLookupTable = std::array<uint8_t, kRGBLookupSize>;\n> +\tusing ColorLookupTable = std::array<float, kRGBLookupSize>;\n>  \n>  \tColorLookupTable red;\n>  \tColorLookupTable green;\n> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp\n> index 26597c99..b006ec4a 100644\n> --- a/src/ipa/simple/soft_simple.cpp\n> +++ b/src/ipa/simple/soft_simple.cpp\n> @@ -86,7 +86,7 @@ private:\n>  \tBlackLevel blackLevel_;\n>  \n>  \tstatic constexpr unsigned int kGammaLookupSize = 1024;\n> -\tstd::array<uint8_t, kGammaLookupSize> gammaTable_;\n> +\tstd::array<float, kGammaLookupSize> gammaTable_;\n>  \tint lastBlackLevel_ = -1;\n>  \n>  \tint32_t exposureMin_, exposureMax_;\n> @@ -281,8 +281,7 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)\n>  \t\tstd::fill(gammaTable_.begin(), gammaTable_.begin() + blackIndex, 0);\n>  \t\tconst float divisor = kGammaLookupSize - blackIndex - 1.0;\n>  \t\tfor (unsigned int i = blackIndex; i < kGammaLookupSize; i++)\n> -\t\t\tgammaTable_[i] = UINT8_MAX *\n> -\t\t\t\t\t powf((i - blackIndex) / divisor, DebayerParams::kGamma);\n> +\t\t\tgammaTable_[i] = powf((i - blackIndex) / divisor, DebayerParams::kGamma);\n>  \n>  \t\tlastBlackLevel_ = blackLevel;\n>  \t}\n> diff --git a/src/libcamera/software_isp/TODO b/src/libcamera/software_isp/TODO\n> index 4fcee39b..6bdc5905 100644\n> --- a/src/libcamera/software_isp/TODO\n> +++ b/src/libcamera/software_isp/TODO\n> @@ -72,19 +72,6 @@ stats in hardware, such as the i.MX7), but please keep it on your radar.\n>  \n>  ---\n>  \n> -4. Hide internal representation of gains from callers\n> -\n> -> struct DebayerParams {\n> -> \tstatic constexpr unsigned int kGain10 = 256;\n> -\n> -Forcing the caller to deal with the internal representation of gains\n> -isn't nice, especially given that it precludes implementing gains of\n> -different precisions in different backend. Wouldn't it be better to pass\n> -the values as floating point numbers, and convert them to the internal\n> -representation in the implementation of process() before using them ?\n> -\n> ----\n> -\n>  5. Store ISP parameters in per-frame buffers\n>  \n>  > /**\n> diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp\n> index 80bf5dbe..03001ae1 100644\n> --- a/src/libcamera/software_isp/debayer.cpp\n> +++ b/src/libcamera/software_isp/debayer.cpp\n> @@ -35,17 +35,17 @@ namespace libcamera {\n>  \n>  /**\n>   * \\var DebayerParams::red\n> - * \\brief Lookup table for red color, mapping input values to output values\n> + * \\brief Lookup table for red color, mapping input values to 0.0..1.0\n>   */\n>  \n>  /**\n>   * \\var DebayerParams::green\n> - * \\brief Lookup table for green color, mapping input values to output values\n> + * \\brief Lookup table for green color, mapping input values to 0.0..1.0\n>   */\n>  \n>  /**\n>   * \\var DebayerParams::blue\n> - * \\brief Lookup table for blue color, mapping input values to output values\n> + * \\brief Lookup table for blue color, mapping input values to 0.0..1.0\n>   */\n>  \n>  /**\n> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\n> index c038eed4..9dcb5f91 100644\n> --- a/src/libcamera/software_isp/debayer_cpu.cpp\n> +++ b/src/libcamera/software_isp/debayer_cpu.cpp\n> @@ -11,6 +11,8 @@\n>  \n>  #include \"debayer_cpu.h\"\n>  \n> +#include <stddef.h>\n> +#include <stdint.h>\n>  #include <stdlib.h>\n>  #include <time.h>\n>  \n> @@ -688,6 +690,14 @@ static inline int64_t timeDiff(timespec &after, timespec &before)\n>  \t       (int64_t)after.tv_nsec - (int64_t)before.tv_nsec;\n>  }\n>  \n> +void DebayerCpu::updateColorLookupTable(\n> +\tconst DebayerParams::ColorLookupTable &src,\n> +\tColorLookupTable &dst)\n> +{\n> +\tfor (std::size_t i = 0; i < src.size(); i++)\n> +\t\tdst[i] = src[i] * UINT8_MAX;\n> +}\n> +\n>  void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params)\n>  {\n>  \ttimespec frameStartTime;\n> @@ -697,9 +707,11 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams\n>  \t\tclock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);\n>  \t}\n>  \n> -\tgreen_ = params.green;\n> -\tred_ = swapRedBlueGains_ ? params.blue : params.red;\n> -\tblue_ = swapRedBlueGains_ ? params.red : params.blue;\n> +\tupdateColorLookupTable(params.green, green_);\n> +\tupdateColorLookupTable(swapRedBlueGains_ ? params.blue : params.red,\n> +\t\t\t       red_);\n> +\tupdateColorLookupTable(swapRedBlueGains_ ? params.red : params.blue,\n> +\t\t\t       blue_);\n>  \n>  \t/* Copy metadata from the input buffer */\n>  \tFrameMetadata &metadata = output->_d()->metadata();\n> diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\n> index be7dcdca..dcf4e37d 100644\n> --- a/src/libcamera/software_isp/debayer_cpu.h\n> +++ b/src/libcamera/software_isp/debayer_cpu.h\n> @@ -18,6 +18,7 @@\n>  #include <libcamera/base/object.h>\n>  \n>  #include \"libcamera/internal/bayer_format.h\"\n> +#include \"libcamera/internal/software_isp/debayer_params.h\"\n>  \n>  #include \"debayer.h\"\n>  #include \"swstats_cpu.h\"\n> @@ -125,9 +126,12 @@ private:\n>  \t/* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */\n>  \tstatic constexpr unsigned int kMaxLineBuffers = 5;\n>  \n> -\tDebayerParams::ColorLookupTable red_;\n> -\tDebayerParams::ColorLookupTable green_;\n> -\tDebayerParams::ColorLookupTable blue_;\n> +\tusing ColorLookupTable = std::array<uint8_t, DebayerParams::kRGBLookupSize>;\n> +\tvoid updateColorLookupTable(const DebayerParams::ColorLookupTable &src,\n> +\t\t\t\t    ColorLookupTable &dst);\n> +\tColorLookupTable red_;\n> +\tColorLookupTable green_;\n> +\tColorLookupTable blue_;\n>  \tdebayerFn debayer0_;\n>  \tdebayerFn debayer1_;\n>  \tdebayerFn debayer2_;","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 C8603BD87C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 29 May 2024 00:34:14 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B3805634B9;\n\tWed, 29 May 2024 02:34:13 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D4067634B0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 May 2024 02:34:12 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi\n\t[81.175.209.231])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 304C34AB;\n\tWed, 29 May 2024 02:34:09 +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=\"EUujdOQM\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1716942849;\n\tbh=Q2P20b0ixgQDJtAL+lDWZvjlr9d1IJ0/yYFErOnyD3c=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=EUujdOQM+MW6ETKkg20NPoaJbrHbUAczhmJoczPoEgKUnEzYmgblq2eXGBOb0lAD1\n\tr7Slbii8o1a9YNec41xxdx0+KeFcYzl0o4UA7Kqq+TykwhxJoUQqqRr/8NvtBqBMpf\n\tXcsm6gLQA0ei5Jpdm+e6EuDIr+1DpQx8CpBE6qeE=","Date":"Wed, 29 May 2024 03:34:00 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Milan Zamazal <mzamazal@redhat.com>","Cc":"libcamera-devel@lists.libcamera.org,\n\tKieran Bingham <kieran.bingham@ideasonboard.com>,\n\tAndrei Konovalov <andrey.konovalov.ynk@gmail.com>","Subject":"Re: [PATCH v4 5/5] libcamera: software_isp: Pass color lookup tables\n\tas floats","Message-ID":"<20240529003400.GC11144@pendragon.ideasonboard.com>","References":"<20240528161126.35119-1-mzamazal@redhat.com>\n\t<20240528161126.35119-6-mzamazal@redhat.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20240528161126.35119-6-mzamazal@redhat.com>","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":29678,"web_url":"https://patchwork.libcamera.org/comment/29678/","msgid":"<87v82vow1e.fsf@redhat.com>","date":"2024-05-30T20:59:57","subject":"Re: [PATCH v4 5/5] libcamera: software_isp: Pass color lookup\n\ttables as floats","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Hi Laurent,\n\nthank you for review.\n\nLaurent Pinchart <laurent.pinchart@ideasonboard.com> writes:\n\n> Hi Milan,\n>\n> Thank you for the patch.\n>\n> On Tue, May 28, 2024 at 06:11:26PM +0200, Milan Zamazal wrote:\n>> The color lookup tables are passed from stats processing to debayering\n>> for direct use as 8-bit color output values.  Let's pass the values as\n>> 0.0..1.0 floats to make the gains color bit width independent.\n>> \n>> Completes software ISP TODO #4.\n>\n> The implementation looks good, and this indeed covers TODO #4. The\n> conversion of the tables from float to integer takes a big more CPU\n> time, which is reasonable, but it got me thinking.\n>\n> TODO #4 was recorded at a time where the IPA module computed gain\n> values, and the ISP computed the look up tables. The gains were\n> higher-level parameters. I thought it would be good to not hardcode in\n> their representation what was an internal implementation feature of the\n> ISP, as that would allow changing the ISP implementation later without\n> impacting the IPA module.\n>\n> Now that the look up tables are computed in the IPA module, the IPA and\n> ISP are more tightly coupled. Do you think it's still useful to abstract\n> the internal representation of the table entries from the IPA module, or\n> would that just consume more CPU cycles without offering any benefit for\n> later evolutions of the ISP ? I'm thinking in particular about future\n> work on a GPU-based implementation of the soft ISP. Do you foresee that\n> we would use the same IPA module, or a different one ?\n>\n> If you think it's useful we can merge this patch, otherwise we could\n> drop the patch and drop TODO #4.\n\nWell, after thinking about it too, I decided for dropping the patch (and\ndropping TODO #4 as a replacement patch).  My reasoning:\n\n- The conversion cost is negligible to the whole frame processing on CPU\n  but it's still some cost and it's better to avoid adding small costs\n  without a good reason (and let's not make Hans crying ;-) ).\n\n- We don't have a good reason for the conversion right now.\n\n- Hardware pipelines seem to use integers in similar situations.\n\n- I'm not sure about a GPU-based implementation but I think using the\n  same IPA module would be preferable.\n\n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n>\n>> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n>> Reviewed-by: Andrei Konovalov <andrey.konovalov.ynk@gmail.com>\n>> ---\n>>  .../internal/software_isp/debayer_params.h     |  2 +-\n>>  src/ipa/simple/soft_simple.cpp                 |  5 ++---\n>>  src/libcamera/software_isp/TODO                | 13 -------------\n>>  src/libcamera/software_isp/debayer.cpp         |  6 +++---\n>>  src/libcamera/software_isp/debayer_cpu.cpp     | 18 +++++++++++++++---\n>>  src/libcamera/software_isp/debayer_cpu.h       | 10 +++++++---\n>>  6 files changed, 28 insertions(+), 26 deletions(-)\n>> \n>> diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h\n>> index 2f75b4b5..647905c5 100644\n>> --- a/include/libcamera/internal/software_isp/debayer_params.h\n>> +++ b/include/libcamera/internal/software_isp/debayer_params.h\n>> @@ -19,7 +19,7 @@ struct DebayerParams {\n>>  \tstatic constexpr unsigned int kRGBLookupSize = 256;\n>>  \tstatic constexpr float kGamma = 0.5;\n>>  \n>> -\tusing ColorLookupTable = std::array<uint8_t, kRGBLookupSize>;\n>> +\tusing ColorLookupTable = std::array<float, kRGBLookupSize>;\n>>  \n>>  \tColorLookupTable red;\n>>  \tColorLookupTable green;\n>> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp\n>> index 26597c99..b006ec4a 100644\n>> --- a/src/ipa/simple/soft_simple.cpp\n>> +++ b/src/ipa/simple/soft_simple.cpp\n>> @@ -86,7 +86,7 @@ private:\n>>  \tBlackLevel blackLevel_;\n>>  \n>>  \tstatic constexpr unsigned int kGammaLookupSize = 1024;\n>> -\tstd::array<uint8_t, kGammaLookupSize> gammaTable_;\n>> +\tstd::array<float, kGammaLookupSize> gammaTable_;\n>>  \tint lastBlackLevel_ = -1;\n>>  \n>>  \tint32_t exposureMin_, exposureMax_;\n>> @@ -281,8 +281,7 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)\n>>  \t\tstd::fill(gammaTable_.begin(), gammaTable_.begin() + blackIndex, 0);\n>>  \t\tconst float divisor = kGammaLookupSize - blackIndex - 1.0;\n>>  \t\tfor (unsigned int i = blackIndex; i < kGammaLookupSize; i++)\n>> -\t\t\tgammaTable_[i] = UINT8_MAX *\n>> -\t\t\t\t\t powf((i - blackIndex) / divisor, DebayerParams::kGamma);\n>> +\t\t\tgammaTable_[i] = powf((i - blackIndex) / divisor, DebayerParams::kGamma);\n>>  \n>>  \t\tlastBlackLevel_ = blackLevel;\n>>  \t}\n>> diff --git a/src/libcamera/software_isp/TODO b/src/libcamera/software_isp/TODO\n>> index 4fcee39b..6bdc5905 100644\n>> --- a/src/libcamera/software_isp/TODO\n>> +++ b/src/libcamera/software_isp/TODO\n>> @@ -72,19 +72,6 @@ stats in hardware, such as the i.MX7), but please keep it on your radar.\n>>  \n>>  ---\n>>  \n>> -4. Hide internal representation of gains from callers\n>> -\n>> -> struct DebayerParams {\n>> -> \tstatic constexpr unsigned int kGain10 = 256;\n>> -\n>> -Forcing the caller to deal with the internal representation of gains\n>> -isn't nice, especially given that it precludes implementing gains of\n>> -different precisions in different backend. Wouldn't it be better to pass\n>> -the values as floating point numbers, and convert them to the internal\n>> -representation in the implementation of process() before using them ?\n>> -\n>> ----\n>> -\n>>  5. Store ISP parameters in per-frame buffers\n>>  \n>>  > /**\n>> diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp\n>> index 80bf5dbe..03001ae1 100644\n>> --- a/src/libcamera/software_isp/debayer.cpp\n>> +++ b/src/libcamera/software_isp/debayer.cpp\n>> @@ -35,17 +35,17 @@ namespace libcamera {\n>>  \n>>  /**\n>>   * \\var DebayerParams::red\n>> - * \\brief Lookup table for red color, mapping input values to output values\n>> + * \\brief Lookup table for red color, mapping input values to 0.0..1.0\n>>   */\n>>  \n>>  /**\n>>   * \\var DebayerParams::green\n>> - * \\brief Lookup table for green color, mapping input values to output values\n>> + * \\brief Lookup table for green color, mapping input values to 0.0..1.0\n>>   */\n>>  \n>>  /**\n>>   * \\var DebayerParams::blue\n>> - * \\brief Lookup table for blue color, mapping input values to output values\n>> + * \\brief Lookup table for blue color, mapping input values to 0.0..1.0\n>>   */\n>>  \n>>  /**\n>> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\n>> index c038eed4..9dcb5f91 100644\n>> --- a/src/libcamera/software_isp/debayer_cpu.cpp\n>> +++ b/src/libcamera/software_isp/debayer_cpu.cpp\n>> @@ -11,6 +11,8 @@\n>>  \n>>  #include \"debayer_cpu.h\"\n>>  \n>> +#include <stddef.h>\n>> +#include <stdint.h>\n>>  #include <stdlib.h>\n>>  #include <time.h>\n>>  \n>> @@ -688,6 +690,14 @@ static inline int64_t timeDiff(timespec &after, timespec &before)\n>>  \t       (int64_t)after.tv_nsec - (int64_t)before.tv_nsec;\n>>  }\n>>  \n>> +void DebayerCpu::updateColorLookupTable(\n>> +\tconst DebayerParams::ColorLookupTable &src,\n>> +\tColorLookupTable &dst)\n>> +{\n>> +\tfor (std::size_t i = 0; i < src.size(); i++)\n>> +\t\tdst[i] = src[i] * UINT8_MAX;\n>> +}\n>> +\n>>  void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params)\n>>  {\n>>  \ttimespec frameStartTime;\n>> @@ -697,9 +707,11 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams\n>>  \t\tclock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);\n>>  \t}\n>>  \n>> -\tgreen_ = params.green;\n>> -\tred_ = swapRedBlueGains_ ? params.blue : params.red;\n>> -\tblue_ = swapRedBlueGains_ ? params.red : params.blue;\n>> +\tupdateColorLookupTable(params.green, green_);\n>> +\tupdateColorLookupTable(swapRedBlueGains_ ? params.blue : params.red,\n>> +\t\t\t       red_);\n>> +\tupdateColorLookupTable(swapRedBlueGains_ ? params.red : params.blue,\n>> +\t\t\t       blue_);\n>>  \n>>  \t/* Copy metadata from the input buffer */\n>>  \tFrameMetadata &metadata = output->_d()->metadata();\n>> diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\n>> index be7dcdca..dcf4e37d 100644\n>> --- a/src/libcamera/software_isp/debayer_cpu.h\n>> +++ b/src/libcamera/software_isp/debayer_cpu.h\n>> @@ -18,6 +18,7 @@\n>>  #include <libcamera/base/object.h>\n>>  \n>>  #include \"libcamera/internal/bayer_format.h\"\n>> +#include \"libcamera/internal/software_isp/debayer_params.h\"\n>>  \n>>  #include \"debayer.h\"\n>>  #include \"swstats_cpu.h\"\n>> @@ -125,9 +126,12 @@ private:\n>>  \t/* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */\n>>  \tstatic constexpr unsigned int kMaxLineBuffers = 5;\n>>  \n>> -\tDebayerParams::ColorLookupTable red_;\n>> -\tDebayerParams::ColorLookupTable green_;\n>> -\tDebayerParams::ColorLookupTable blue_;\n>> +\tusing ColorLookupTable = std::array<uint8_t, DebayerParams::kRGBLookupSize>;\n>> +\tvoid updateColorLookupTable(const DebayerParams::ColorLookupTable &src,\n>> +\t\t\t\t    ColorLookupTable &dst);\n>> +\tColorLookupTable red_;\n>> +\tColorLookupTable green_;\n>> +\tColorLookupTable blue_;\n>>  \tdebayerFn debayer0_;\n>>  \tdebayerFn debayer1_;\n>>  \tdebayerFn debayer2_;","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 02FFDBDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 30 May 2024 21:00:06 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1AF8A634B6;\n\tThu, 30 May 2024 23:00:06 +0200 (CEST)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.133.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D041461A43\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 30 May 2024 23:00:03 +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-538-H_oZJfKANDSWXyxOm_4pQQ-1; Thu, 30 May 2024 17:00:01 -0400","by mail-wm1-f72.google.com with SMTP id\n\t5b1f17b1804b1-42129affd18so4714755e9.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 30 May 2024 14:00:00 -0700 (PDT)","from nuthatch (ip-77-48-47-2.net.vodafone.cz. [77.48.47.2])\n\tby smtp.gmail.com with ESMTPSA id\n\tffacd0b85a97d-35dd04d9c68sm317558f8f.56.2024.05.30.13.59.58\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 30 May 2024 13:59:58 -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=\"QFNrx6C2\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1717102802;\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=N8EG+x8m09mUzxSqqClqeAXOknJktQEtV+oG5FaF4cw=;\n\tb=QFNrx6C2cb7gL5jzFTqUqm2bNSzIDEfFZth9712xQqCsxvPYKjiE+JnLcrPqR39TLCZDmN\n\tsOY0TLupfl6hLXejTiK9MaklFzCdW4cLKQFv2swPMU5EDwNOlnZi2ChUdobRZeiggDPTit\n\tbufl2Td2799IjN+oj7MiX5EDvUMbytY=","X-MC-Unique":"H_oZJfKANDSWXyxOm_4pQQ-1","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1717102799; x=1717707599;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=N8EG+x8m09mUzxSqqClqeAXOknJktQEtV+oG5FaF4cw=;\n\tb=Q5uQA1rd23uHV01Y9issJMOgKXjMIS7870e6xgFFD0tcX38NX0niDLwj4bXJWESzuW\n\tw7UE1naEqgRN7E6DlI67O7Hr/oLO32kI6SqZkpXOs1l+deDm1gipSA+pAz7joYdjk39T\n\tlGKq/KsmHl+VNuIJM8E28vR4vpgG2WbCJ+5DDIH54m3IUdlEAbiUTmmyj7yKHN9Vf0g6\n\tU/cy07VTDDLadYSSnAVTJedjisO0LJsQRP0C8m2N7B0ADZVRTHPcMOtiucQgd8BNXpM3\n\tsq9CqGc7MXXNcnSVNzPKgVb7N8jlgLYVCJYgZlZT3uSxXPHdxa7kHgbOPvb4Ffgz7Inp\n\tG87Q==","X-Gm-Message-State":"AOJu0YxHpuOXp/Uc+J05y33HbXI7eaFgqq01jKXBqT5U1yjUBPHKKJTD\n\tM7ibnIPMHlTMEkkNm18irM9LQfSs03bc5Xycs5D0YIlk7ZqeKJC1zeDx+xEUGEwSZpoQM4bO+2Q\n\tV1ss6xEP8kSJFC2qv6S/c6LB/QCO+ZV/e+N7N1kPjW1CVywvQFKiyrqoqU+eCd0+PseFXSHzKeo\n\tzE8RE=","X-Received":["by 2002:a05:600c:1e1a:b0:41a:8b39:8040 with SMTP id\n\t5b1f17b1804b1-4212781af17mr28153665e9.20.1717102799519; \n\tThu, 30 May 2024 13:59:59 -0700 (PDT)","by 2002:a05:600c:1e1a:b0:41a:8b39:8040 with SMTP id\n\t5b1f17b1804b1-4212781af17mr28153495e9.20.1717102798936; \n\tThu, 30 May 2024 13:59:58 -0700 (PDT)"],"X-Google-Smtp-Source":"AGHT+IFIrEPncB3Z4z1Gsdjn2aunSABZ+KJUbf5eLScyTWFtYD243fsT/sZRk3HUsUyOrUvRhWXcTQ==","From":"Milan Zamazal <mzamazal@redhat.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org,  Kieran Bingham\n\t<kieran.bingham@ideasonboard.com>,  Andrei Konovalov\n\t<andrey.konovalov.ynk@gmail.com>","Subject":"Re: [PATCH v4 5/5] libcamera: software_isp: Pass color lookup\n\ttables as floats","In-Reply-To":"<20240529003400.GC11144@pendragon.ideasonboard.com> (Laurent\n\tPinchart's message of \"Wed, 29 May 2024 03:34:00 +0300\")","References":"<20240528161126.35119-1-mzamazal@redhat.com>\n\t<20240528161126.35119-6-mzamazal@redhat.com>\n\t<20240529003400.GC11144@pendragon.ideasonboard.com>","Date":"Thu, 30 May 2024 22:59:57 +0200","Message-ID":"<87v82vow1e.fsf@redhat.com>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","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>"}}]