[{"id":29594,"web_url":"https://patchwork.libcamera.org/comment/29594/","msgid":"<6d429662-26d4-40f8-8862-0cfc6f9d4e5f@gmail.com>","date":"2024-05-22T09:49:15","subject":"Re: [PATCH v2 3/5] libcamera: software_isp: Move color mappings out\n\tof debayering","submitter":{"id":179,"url":"https://patchwork.libcamera.org/api/people/179/","name":"Andrei Konovalov","email":"andrey.konovalov.ynk@gmail.com"},"content":"Hi Milan,\n\nThank you for the patch!\n\nOn 30.04.2024 20:34, Milan Zamazal wrote:\n> Constructing the color mapping tables is related to stats rather than\n> debayering, where they are applied.  Let's move the corresponding code\n> to stats processing.\n> \n> This is a preliminary step towards building this functionality on top of\n> libipa/algorithm.h, which should follow.\n> \n> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n> ---\n>   .../internal/software_isp/debayer_params.h    | 18 +++----\n>   src/ipa/simple/soft_simple.cpp                | 51 +++++++++++++++----\n>   src/libcamera/software_isp/debayer.cpp        | 29 +++++------\n>   src/libcamera/software_isp/debayer_cpu.cpp    | 41 +++------------\n>   src/libcamera/software_isp/debayer_cpu.h      |  9 ++--\n>   src/libcamera/software_isp/software_isp.cpp   |  4 +-\n>   6 files changed, 75 insertions(+), 77 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 32cd448a..09f4ff00 100644\n> --- a/include/libcamera/internal/software_isp/debayer_params.h\n> +++ b/include/libcamera/internal/software_isp/debayer_params.h\n> @@ -1,6 +1,6 @@\n>   /* SPDX-License-Identifier: LGPL-2.1-or-later */\n>   /*\n> - * Copyright (C) 2023, Red Hat Inc.\n> + * Copyright (C) 2023, 2024 Red Hat Inc.\n>    *\n>    * Authors:\n>    * Hans de Goede <hdegoede@redhat.com>\n> @@ -10,20 +10,20 @@\n>   \n>   #pragma once\n>   \n> +#include <array>\n> +#include <stdint.h>\n> +\n>   namespace libcamera {\n>   \n>   struct DebayerParams {\n>   \tstatic constexpr unsigned int kGain10 = 256;\n> +\tstatic constexpr unsigned int kRGBLookupSize = 256;\n>   \n> -\tunsigned int gainR;\n> -\tunsigned int gainG;\n> -\tunsigned int gainB;\n> +\tusing ColorLookupTable = std::array<uint8_t, kRGBLookupSize>;\n>   \n> -\tfloat gamma;\n> -\t/**\n> -\t * \\brief Level of the black point, 0..255, 0 is no correction.\n> -\t */\n> -\tunsigned int blackLevel;\n> +\tColorLookupTable red;\n> +\tColorLookupTable green;\n> +\tColorLookupTable blue;\n>   };\n>   \n>   } /* namespace libcamera */\n> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp\n> index f595abc2..981e1ae0 100644\n> --- a/src/ipa/simple/soft_simple.cpp\n> +++ b/src/ipa/simple/soft_simple.cpp\n> @@ -5,6 +5,7 @@\n>    * soft_simple.cpp - Simple Software Image Processing Algorithm module\n>    */\n>   \n> +#include <math.h>\n>   #include <numeric>\n>   #include <stdint.h>\n>   #include <sys/mman.h>\n> @@ -84,6 +85,10 @@ private:\n>   \tControlInfoMap sensorInfoMap_;\n>   \tBlackLevel blackLevel_;\n>   \n> +\tstatic constexpr unsigned int kGammaLookupSize = 1024;\n> +\tstd::array<uint8_t, kGammaLookupSize> gammaTable_;\n> +\tint lastBlackLevel_ = -1;\n> +\n>   \tint32_t exposureMin_, exposureMax_;\n>   \tint32_t exposure_;\n>   \tdouble againMin_, againMax_, againMinStep_;\n> @@ -246,7 +251,6 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)\n>   \tif (ignoreUpdates_ > 0)\n>   \t\tblackLevel_.update(histogram);\n>   \tconst uint8_t blackLevel = blackLevel_.get();\n> -\tparams_->blackLevel = blackLevel;\n>   \n>   \t/*\n>   \t * Calculate red and blue gains for AWB.\n> @@ -265,12 +269,41 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)\n>   \tconst uint64_t sumG = subtractBlackLevel(stats_->sumG_, 2);\n>   \tconst uint64_t sumB = subtractBlackLevel(stats_->sumB_, 4);\n>   \n> -\tparams_->gainR = sumR <= sumG / 4 ? 1024 : 256 * sumG / sumR;\n> -\tparams_->gainB = sumB <= sumG / 4 ? 1024 : 256 * sumG / sumB;\n> -\n> +\t/* Gain: 128 = 0.5, 256 = 1.0, 512 = 2.0, etc. */\n> +\tconst unsigned int gainR = sumR <= sumG / 4 ? 1024 : 256 * sumG / sumR;\n> +\tconst unsigned int gainB = sumB <= sumG / 4 ? 1024 : 256 * sumG / sumB;\n>   \t/* Green gain and gamma values are fixed */\n> -\tparams_->gainG = 256;\n> -\tparams_->gamma = 0.5;\n> +\tconstexpr unsigned int gainG = 256;\n> +\t/* gamma == 1.0 means no correction */\n> +\tconstexpr float gamma = 0.5;\n> +\n> +\t/* Update the gamma table if needed */\n> +\tif (blackLevel != lastBlackLevel_) {\n> +\t\tconst unsigned int blackIndex = blackLevel * kGammaLookupSize / 256;\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 * powf((i - blackIndex) / divisor, gamma);\n> +\n> +\t\tlastBlackLevel_ = blackLevel;\n> +\t}\n> +\n> +\tfor (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {\n> +\t\tconstexpr unsigned int div =\n> +\t\t\tDebayerParams::kRGBLookupSize * DebayerParams::kGain10 /\n> +\t\t\tkGammaLookupSize;\n> +\t\tunsigned int idx;\n> +\n> +\t\t/* Apply gamma after gain! */\n> +\t\tidx = std::min({ i * gainR / div, (kGammaLookupSize - 1) });\n> +\t\tparams_->red[i] = gammaTable_[idx];\n> +\n> +\t\tidx = std::min({ i * gainG / div, (kGammaLookupSize - 1) });\n> +\t\tparams_->green[i] = gammaTable_[idx];\n> +\n> +\t\tidx = std::min({ i * gainB / div, (kGammaLookupSize - 1) });\n> +\t\tparams_->blue[i] = gammaTable_[idx];\n> +\t}\n>   \n>   \tsetIspParams.emit();\n>   \n> @@ -291,7 +324,7 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)\n>   \t * https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf\n>   \t */\n>   \tconst unsigned int blackLevelHistIdx =\n> -\t\tparams_->blackLevel / (256 / SwIspStats::kYHistogramSize);\n> +\t\tblackLevel / (256 / SwIspStats::kYHistogramSize);\n>   \tconst unsigned int histogramSize =\n>   \t\tSwIspStats::kYHistogramSize - blackLevelHistIdx;\n>   \tconst unsigned int yHistValsPerBin = histogramSize / kExposureBinsCount;\n> @@ -339,8 +372,8 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)\n>   \n>   \tLOG(IPASoft, Debug) << \"exposureMSV \" << exposureMSV\n>   \t\t\t    << \" exp \" << exposure_ << \" again \" << again_\n> -\t\t\t    << \" gain R/B \" << params_->gainR << \"/\" << params_->gainB\n> -\t\t\t    << \" black level \" << params_->blackLevel;\n> +\t\t\t    << \" gain R/B \" << gainR << \"/\" << gainB\n> +\t\t\t    << \" black level \" << blackLevel;\n\nHere blackLevel needs a type cast as otherwise uint8_t is printed as a character, not a number.\n\nWith this minor issue fixed,\n\nReviewed-by: Andrei Konovalov <andrey.konovalov.ynk@gmail.com>\n\n>   }\n>   \n>   void IPASoftSimple::updateExposure(double exposureMSV)\n> diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp\n> index 1c035e9b..ac438a33 100644\n> --- a/src/libcamera/software_isp/debayer.cpp\n> +++ b/src/libcamera/software_isp/debayer.cpp\n> @@ -1,7 +1,7 @@\n>   /* SPDX-License-Identifier: LGPL-2.1-or-later */\n>   /*\n>    * Copyright (C) 2023, Linaro Ltd\n> - * Copyright (C) 2023, Red Hat Inc.\n> + * Copyright (C) 2023, 2024 Red Hat Inc.\n>    *\n>    * Authors:\n>    * Hans de Goede <hdegoede@redhat.com>\n> @@ -24,29 +24,28 @@ namespace libcamera {\n>    */\n>   \n>   /**\n> - * \\var DebayerParams::gainR\n> - * \\brief Red gain\n> - *\n> - * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.\n> + * \\var DebayerParams::kRGBLookupSize\n> + * \\brief Size of a color lookup table\n>    */\n>   \n>   /**\n> - * \\var DebayerParams::gainG\n> - * \\brief Green gain\n> - *\n> - * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.\n> + * \\typedef DebayerParams::ColorLookupTable\n> + * \\brief Type of the lookup tables for red, green, blue values\n>    */\n>   \n>   /**\n> - * \\var DebayerParams::gainB\n> - * \\brief Blue gain\n> - *\n> - * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.\n> + * \\var DebayerParams::red\n> + * \\brief Lookup table for red color, mapping input values to output values\n> + */\n> +\n> +/**\n> + * \\var DebayerParams::green\n> + * \\brief Lookup table for green color, mapping input values to output values\n>    */\n>   \n>   /**\n> - * \\var DebayerParams::gamma\n> - * \\brief Gamma correction, 1.0 is no correction\n> + * \\var DebayerParams::blue\n> + * \\brief Lookup table for blue color, mapping input values to output values\n>    */\n>   \n>   /**\n> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\n> index 88d6578b..8b2b2f40 100644\n> --- a/src/libcamera/software_isp/debayer_cpu.cpp\n> +++ b/src/libcamera/software_isp/debayer_cpu.cpp\n> @@ -11,7 +11,6 @@\n>   \n>   #include \"debayer_cpu.h\"\n>   \n> -#include <math.h>\n>   #include <stdlib.h>\n>   #include <time.h>\n>   \n> @@ -47,9 +46,9 @@ DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)\n>   \t */\n>   \tenableInputMemcpy_ = true;\n>   \n> -\t/* Initialize gamma to 1.0 curve */\n> -\tfor (unsigned int i = 0; i < kGammaLookupSize; i++)\n> -\t\tgamma_[i] = i / (kGammaLookupSize / kRGBLookupSize);\n> +\t/* Initialize color lookup tables */\n> +\tfor (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++)\n> +\t\tred_[i] = green_[i] = blue_[i] = i;\n>   \n>   \tfor (unsigned int i = 0; i < kMaxLineBuffers; i++)\n>   \t\tlineBuffers_[i] = nullptr;\n> @@ -698,37 +697,9 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams\n>   \t\tclock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);\n>   \t}\n>   \n> -\t/* Apply DebayerParams */\n> -\tif (params.gamma != gammaCorrection_ || params.blackLevel != blackLevel_) {\n> -\t\tconst unsigned int blackIndex =\n> -\t\t\tparams.blackLevel * kGammaLookupSize / 256;\n> -\t\tstd::fill(gamma_.begin(), gamma_.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\tgamma_[i] = UINT8_MAX * powf((i - blackIndex) / divisor, params.gamma);\n> -\n> -\t\tgammaCorrection_ = params.gamma;\n> -\t\tblackLevel_ = params.blackLevel;\n> -\t}\n> -\n> -\tif (swapRedBlueGains_)\n> -\t\tstd::swap(params.gainR, params.gainB);\n> -\n> -\tfor (unsigned int i = 0; i < kRGBLookupSize; i++) {\n> -\t\tconstexpr unsigned int div =\n> -\t\t\tkRGBLookupSize * DebayerParams::kGain10 / kGammaLookupSize;\n> -\t\tunsigned int idx;\n> -\n> -\t\t/* Apply gamma after gain! */\n> -\t\tidx = std::min({ i * params.gainR / div, (kGammaLookupSize - 1) });\n> -\t\tred_[i] = gamma_[idx];\n> -\n> -\t\tidx = std::min({ i * params.gainG / div, (kGammaLookupSize - 1) });\n> -\t\tgreen_[i] = gamma_[idx];\n> -\n> -\t\tidx = std::min({ i * params.gainB / div, (kGammaLookupSize - 1) });\n> -\t\tblue_[i] = gamma_[idx];\n> -\t}\n> +\tgreen_ = params.green;\n> +\tred_ = swapRedBlueGains_ ? params.blue : params.red;\n> +\tblue_ = swapRedBlueGains_ ? params.red : params.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 689c1075..47373426 100644\n> --- a/src/libcamera/software_isp/debayer_cpu.h\n> +++ b/src/libcamera/software_isp/debayer_cpu.h\n> @@ -122,15 +122,12 @@ private:\n>   \tvoid process2(const uint8_t *src, uint8_t *dst);\n>   \tvoid process4(const uint8_t *src, uint8_t *dst);\n>   \n> -\tstatic constexpr unsigned int kGammaLookupSize = 1024;\n> -\tstatic constexpr unsigned int kRGBLookupSize = 256;\n>   \t/* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */\n>   \tstatic constexpr unsigned int kMaxLineBuffers = 5;\n>   \n> -\tstd::array<uint8_t, kGammaLookupSize> gamma_;\n> -\tstd::array<uint8_t, kRGBLookupSize> red_;\n> -\tstd::array<uint8_t, kRGBLookupSize> green_;\n> -\tstd::array<uint8_t, kRGBLookupSize> blue_;\n> +\tDebayerParams::ColorLookupTable red_;\n> +\tDebayerParams::ColorLookupTable green_;\n> +\tDebayerParams::ColorLookupTable blue_;\n>   \tdebayerFn debayer0_;\n>   \tdebayerFn debayer1_;\n>   \tdebayerFn debayer2_;\n> diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\n> index e4e56086..3e07453d 100644\n> --- a/src/libcamera/software_isp/software_isp.cpp\n> +++ b/src/libcamera/software_isp/software_isp.cpp\n> @@ -63,9 +63,7 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)\n>    * handler\n>    */\n>   SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor)\n> -\t: debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10,\n> -\t\t\t  DebayerParams::kGain10, 0.5f, 0 },\n> -\t  dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System)\n> +\t: dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System)\n>   {\n>   \tif (!dmaHeap_.isValid()) {\n>   \t\tLOG(SoftwareIsp, Error) << \"Failed to create DmaHeap object\";","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 8A173BDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 22 May 2024 09:49:20 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6308663492;\n\tWed, 22 May 2024 11:49:19 +0200 (CEST)","from mail-wm1-x336.google.com (mail-wm1-x336.google.com\n\t[IPv6:2a00:1450:4864:20::336])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8400E61A50\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 22 May 2024 11:49:17 +0200 (CEST)","by mail-wm1-x336.google.com with SMTP id\n\t5b1f17b1804b1-4200ee78e56so5450765e9.3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 22 May 2024 02:49:17 -0700 (PDT)","from [192.168.118.26] ([87.116.162.89])\n\tby smtp.gmail.com with ESMTPSA id\n\t5b1f17b1804b1-42014f563adsm379539235e9.38.2024.05.22.02.49.15\n\t(version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n\tWed, 22 May 2024 02:49:16 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"U3p3cjH9\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=gmail.com; s=20230601; t=1716371357; x=1716976157;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:in-reply-to:from:content-language\n\t:references:cc:to:subject:user-agent:mime-version:date:message-id\n\t:from:to:cc:subject:date:message-id:reply-to;\n\tbh=mWkpWwAmaeXr8qLM9WeyYVzWvSlvsTYrl2ca/6Wz2n0=;\n\tb=U3p3cjH9gS5cScARcV35GEbq6y7b5wz2AWqdlPqmy7slIg4r9wX3ylBuRIVKF90JVD\n\tIT9AdrWN/hB3CgAH4jrmpD8jUoJkCjuTWH7cQk8iXma7/ce4hW4L3ecPVe1CCuWrpzPT\n\t2+uZNVsm7KbQUPzemSC9g0uXdJPQmqcTadtCUBeEEFtZhv8YuhF/+F8Xj+w2NeLXlpbl\n\tlcfkdIA/RG2Xi8i4dXqF8KqwwXmQ3+/17jRr0LKeoVDyuVTCF6NmiCVbfS15eCNIRnm5\n\tF2hGcSTIGYd6CyKXuLSN5obizWNs7Jcd594NGRyrRs50oFZR+396B87rA2usw7nZNoBE\n\tsycQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1716371357; x=1716976157;\n\th=content-transfer-encoding:in-reply-to:from:content-language\n\t:references:cc:to:subject:user-agent:mime-version:date:message-id\n\t:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;\n\tbh=mWkpWwAmaeXr8qLM9WeyYVzWvSlvsTYrl2ca/6Wz2n0=;\n\tb=tuUTK/3Yy9ZPctgxzdy6m5+svvlpTRSSBZp5W12lujMp0cnpGqOHvWDNiMqedaDIGW\n\tzgC+Bi4EttfQ3ZX99FArJJ+KxUy70luRTRkmU8jrMJpFYUH1ZAQCzbtiorcj5PjdTyIc\n\th9E6Z2qWvlS/kRlSM8QKEkXUwg/WQHi584tlLM5Q2q0HAkzADUzZdgWPV+xdZcEg9Ws4\n\tZj78dCpWzLT5E0sqlyitEn4RxCVAdCDTM6Gg/33OS3mzXbiCVK9XYTLlgPjcPmlKnWDF\n\t3XphS/laKLmBHkmvOXjPN6Gn5TAWeMADhahYRZtWCXlJpkHSBa6zEfG04kqFkmWXPDA2\n\two0Q==","X-Forwarded-Encrypted":"i=1;\n\tAJvYcCV7Qr/UtFTp0y/650bKydoJgZABtQsvlhTI2SYHed2J2D0rTqinzdvlZJKMoqOMSIqRl2sDsrnVA8LLWeBnxFAjU+7lSpnxoLTw1R7+QMGjt5J4RQ==","X-Gm-Message-State":"AOJu0Yz+Xh7CVHfuZArIlCvm4u4Y+Ylu+QXhA9DunJq1ZV1OPyhSgcLO\n\tkmtio/3wm/nEnondF3zrLYvIrsRW/ynmhV4PtOnqfIjEgnIPavJn0vGpCIEk","X-Google-Smtp-Source":"AGHT+IHttcSNqgfvxh9AE2ZX2zFp3KoaJWqUfDOrC7sNKcNCftqQjUDPItNhwnoa00b0V0QuW9A1cw==","X-Received":"by 2002:a7b:c38a:0:b0:41e:454b:2f7 with SMTP id\n\t5b1f17b1804b1-420fd31fe36mr12833515e9.23.1716371356574; \n\tWed, 22 May 2024 02:49:16 -0700 (PDT)","Message-ID":"<6d429662-26d4-40f8-8862-0cfc6f9d4e5f@gmail.com>","Date":"Wed, 22 May 2024 12:49:15 +0300","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v2 3/5] libcamera: software_isp: Move color mappings out\n\tof debayering","To":"Milan Zamazal <mzamazal@redhat.com>, libcamera-devel@lists.libcamera.org","Cc":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","References":"<20240430173430.200392-1-mzamazal@redhat.com>\n\t<20240430173430.200392-4-mzamazal@redhat.com>","Content-Language":"en-US","From":"Andrei Konovalov <andrey.konovalov.ynk@gmail.com>","In-Reply-To":"<20240430173430.200392-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":29610,"web_url":"https://patchwork.libcamera.org/comment/29610/","msgid":"<87jzjk4vos.fsf@redhat.com>","date":"2024-05-23T11:25:07","subject":"Re: [PATCH v2 3/5] libcamera: software_isp: Move color mappings out\n\tof debayering","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Andrei Konovalov <andrey.konovalov.ynk@gmail.com> writes:\n\n> Hi Milan,\n>\n> Thank you for the patch!\n\nHi Andrei,\n\nthank you for your reviews!\n\n> On 30.04.2024 20:34, Milan Zamazal wrote:\n>> Constructing the color mapping tables is related to stats rather than\n>> debayering, where they are applied.  Let's move the corresponding code\n>> to stats processing.\n>> This is a preliminary step towards building this functionality on top of\n>> libipa/algorithm.h, which should follow.\n>> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n>> ---\n>>   .../internal/software_isp/debayer_params.h    | 18 +++----\n>>   src/ipa/simple/soft_simple.cpp                | 51 +++++++++++++++----\n>>   src/libcamera/software_isp/debayer.cpp        | 29 +++++------\n>>   src/libcamera/software_isp/debayer_cpu.cpp    | 41 +++------------\n>>   src/libcamera/software_isp/debayer_cpu.h      |  9 ++--\n>>   src/libcamera/software_isp/software_isp.cpp   |  4 +-\n>>   6 files changed, 75 insertions(+), 77 deletions(-)\n>> diff --git a/include/libcamera/internal/software_isp/debayer_params.h\n>> b/include/libcamera/internal/software_isp/debayer_params.h\n>> index 32cd448a..09f4ff00 100644\n>> --- a/include/libcamera/internal/software_isp/debayer_params.h\n>> +++ b/include/libcamera/internal/software_isp/debayer_params.h\n>> @@ -1,6 +1,6 @@\n>>   /* SPDX-License-Identifier: LGPL-2.1-or-later */\n>>   /*\n>> - * Copyright (C) 2023, Red Hat Inc.\n>> + * Copyright (C) 2023, 2024 Red Hat Inc.\n>>    *\n>>    * Authors:\n>>    * Hans de Goede <hdegoede@redhat.com>\n>> @@ -10,20 +10,20 @@\n>>     #pragma once\n>>   +#include <array>\n>> +#include <stdint.h>\n>> +\n>>   namespace libcamera {\n>>     struct DebayerParams {\n>>   \tstatic constexpr unsigned int kGain10 = 256;\n>> +\tstatic constexpr unsigned int kRGBLookupSize = 256;\n>>   -\tunsigned int gainR;\n>> -\tunsigned int gainG;\n>> -\tunsigned int gainB;\n>> +\tusing ColorLookupTable = std::array<uint8_t, kRGBLookupSize>;\n>>   -\tfloat gamma;\n>> -\t/**\n>> -\t * \\brief Level of the black point, 0..255, 0 is no correction.\n>> -\t */\n>> -\tunsigned int blackLevel;\n>> +\tColorLookupTable red;\n>> +\tColorLookupTable green;\n>> +\tColorLookupTable blue;\n>>   };\n>>     } /* namespace libcamera */\n>> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp\n>> index f595abc2..981e1ae0 100644\n>> --- a/src/ipa/simple/soft_simple.cpp\n>> +++ b/src/ipa/simple/soft_simple.cpp\n>> @@ -5,6 +5,7 @@\n>>    * soft_simple.cpp - Simple Software Image Processing Algorithm module\n>>    */\n>>   +#include <math.h>\n>>   #include <numeric>\n>>   #include <stdint.h>\n>>   #include <sys/mman.h>\n>> @@ -84,6 +85,10 @@ private:\n>>   \tControlInfoMap sensorInfoMap_;\n>>   \tBlackLevel blackLevel_;\n>>   +\tstatic constexpr unsigned int kGammaLookupSize = 1024;\n>> +\tstd::array<uint8_t, kGammaLookupSize> gammaTable_;\n>> +\tint lastBlackLevel_ = -1;\n>> +\n>>   \tint32_t exposureMin_, exposureMax_;\n>>   \tint32_t exposure_;\n>>   \tdouble againMin_, againMax_, againMinStep_;\n>> @@ -246,7 +251,6 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)\n>>   \tif (ignoreUpdates_ > 0)\n>>   \t\tblackLevel_.update(histogram);\n>>   \tconst uint8_t blackLevel = blackLevel_.get();\n>> -\tparams_->blackLevel = blackLevel;\n>>     \t/*\n>>   \t * Calculate red and blue gains for AWB.\n>> @@ -265,12 +269,41 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)\n>>   \tconst uint64_t sumG = subtractBlackLevel(stats_->sumG_, 2);\n>>   \tconst uint64_t sumB = subtractBlackLevel(stats_->sumB_, 4);\n>>   -\tparams_->gainR = sumR <= sumG / 4 ? 1024 : 256 * sumG / sumR;\n>> -\tparams_->gainB = sumB <= sumG / 4 ? 1024 : 256 * sumG / sumB;\n>> -\n>> +\t/* Gain: 128 = 0.5, 256 = 1.0, 512 = 2.0, etc. */\n>> +\tconst unsigned int gainR = sumR <= sumG / 4 ? 1024 : 256 * sumG / sumR;\n>> +\tconst unsigned int gainB = sumB <= sumG / 4 ? 1024 : 256 * sumG / sumB;\n>>   \t/* Green gain and gamma values are fixed */\n>> -\tparams_->gainG = 256;\n>> -\tparams_->gamma = 0.5;\n>> +\tconstexpr unsigned int gainG = 256;\n>> +\t/* gamma == 1.0 means no correction */\n>> +\tconstexpr float gamma = 0.5;\n>> +\n>> +\t/* Update the gamma table if needed */\n>> +\tif (blackLevel != lastBlackLevel_) {\n>> +\t\tconst unsigned int blackIndex = blackLevel * kGammaLookupSize / 256;\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 * powf((i - blackIndex) / divisor, gamma);\n>> +\n>> +\t\tlastBlackLevel_ = blackLevel;\n>> +\t}\n>> +\n>> +\tfor (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {\n>> +\t\tconstexpr unsigned int div =\n>> +\t\t\tDebayerParams::kRGBLookupSize * DebayerParams::kGain10 /\n>> +\t\t\tkGammaLookupSize;\n>> +\t\tunsigned int idx;\n>> +\n>> +\t\t/* Apply gamma after gain! */\n>> +\t\tidx = std::min({ i * gainR / div, (kGammaLookupSize - 1) });\n>> +\t\tparams_->red[i] = gammaTable_[idx];\n>> +\n>> +\t\tidx = std::min({ i * gainG / div, (kGammaLookupSize - 1) });\n>> +\t\tparams_->green[i] = gammaTable_[idx];\n>> +\n>> +\t\tidx = std::min({ i * gainB / div, (kGammaLookupSize - 1) });\n>> +\t\tparams_->blue[i] = gammaTable_[idx];\n>> +\t}\n>>     \tsetIspParams.emit();\n>>   @@ -291,7 +324,7 @@ void IPASoftSimple::processStats(const ControlList\n>> &sensorControls)\n>>   \t * https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf\n>>   \t */\n>>   \tconst unsigned int blackLevelHistIdx =\n>> -\t\tparams_->blackLevel / (256 / SwIspStats::kYHistogramSize);\n>> +\t\tblackLevel / (256 / SwIspStats::kYHistogramSize);\n>>   \tconst unsigned int histogramSize =\n>>   \t\tSwIspStats::kYHistogramSize - blackLevelHistIdx;\n>>   \tconst unsigned int yHistValsPerBin = histogramSize / kExposureBinsCount;\n>> @@ -339,8 +372,8 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)\n>>     \tLOG(IPASoft, Debug) << \"exposureMSV \" << exposureMSV\n>>   \t\t\t    << \" exp \" << exposure_ << \" again \" << again_\n>> -\t\t\t    << \" gain R/B \" << params_->gainR << \"/\" << params_->gainB\n>> -\t\t\t    << \" black level \" << params_->blackLevel;\n>> +\t\t\t    << \" gain R/B \" << gainR << \"/\" << gainB\n>> +\t\t\t    << \" black level \" << blackLevel;\n>\n> Here blackLevel needs a type cast as otherwise uint8_t is printed as a\n> character, not a number.\n\nAh, I see, thank you, will fix it.\n\n> With this minor issue fixed,\n>\n> Reviewed-by: Andrei Konovalov <andrey.konovalov.ynk@gmail.com>\n>\n>>   }\n>>     void IPASoftSimple::updateExposure(double exposureMSV)\n>> diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp\n>> index 1c035e9b..ac438a33 100644\n>> --- a/src/libcamera/software_isp/debayer.cpp\n>> +++ b/src/libcamera/software_isp/debayer.cpp\n>> @@ -1,7 +1,7 @@\n>>   /* SPDX-License-Identifier: LGPL-2.1-or-later */\n>>   /*\n>>    * Copyright (C) 2023, Linaro Ltd\n>> - * Copyright (C) 2023, Red Hat Inc.\n>> + * Copyright (C) 2023, 2024 Red Hat Inc.\n>>    *\n>>    * Authors:\n>>    * Hans de Goede <hdegoede@redhat.com>\n>> @@ -24,29 +24,28 @@ namespace libcamera {\n>>    */\n>>     /**\n>> - * \\var DebayerParams::gainR\n>> - * \\brief Red gain\n>> - *\n>> - * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.\n>> + * \\var DebayerParams::kRGBLookupSize\n>> + * \\brief Size of a color lookup table\n>>    */\n>>     /**\n>> - * \\var DebayerParams::gainG\n>> - * \\brief Green gain\n>> - *\n>> - * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.\n>> + * \\typedef DebayerParams::ColorLookupTable\n>> + * \\brief Type of the lookup tables for red, green, blue values\n>>    */\n>>     /**\n>> - * \\var DebayerParams::gainB\n>> - * \\brief Blue gain\n>> - *\n>> - * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.\n>> + * \\var DebayerParams::red\n>> + * \\brief Lookup table for red color, mapping input values to output values\n>> + */\n>> +\n>> +/**\n>> + * \\var DebayerParams::green\n>> + * \\brief Lookup table for green color, mapping input values to output values\n>>    */\n>>     /**\n>> - * \\var DebayerParams::gamma\n>> - * \\brief Gamma correction, 1.0 is no correction\n>> + * \\var DebayerParams::blue\n>> + * \\brief Lookup table for blue color, mapping input values to output values\n>>    */\n>>     /**\n>> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\n>> index 88d6578b..8b2b2f40 100644\n>> --- a/src/libcamera/software_isp/debayer_cpu.cpp\n>> +++ b/src/libcamera/software_isp/debayer_cpu.cpp\n>> @@ -11,7 +11,6 @@\n>>     #include \"debayer_cpu.h\"\n>>   -#include <math.h>\n>>   #include <stdlib.h>\n>>   #include <time.h>\n>>   @@ -47,9 +46,9 @@ DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)\n>>   \t */\n>>   \tenableInputMemcpy_ = true;\n>>   -\t/* Initialize gamma to 1.0 curve */\n>> -\tfor (unsigned int i = 0; i < kGammaLookupSize; i++)\n>> -\t\tgamma_[i] = i / (kGammaLookupSize / kRGBLookupSize);\n>> +\t/* Initialize color lookup tables */\n>> +\tfor (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++)\n>> +\t\tred_[i] = green_[i] = blue_[i] = i;\n>>     \tfor (unsigned int i = 0; i < kMaxLineBuffers; i++)\n>>   \t\tlineBuffers_[i] = nullptr;\n>> @@ -698,37 +697,9 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams\n>>   \t\tclock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);\n>>   \t}\n>>   -\t/* Apply DebayerParams */\n>> -\tif (params.gamma != gammaCorrection_ || params.blackLevel != blackLevel_) {\n>> -\t\tconst unsigned int blackIndex =\n>> -\t\t\tparams.blackLevel * kGammaLookupSize / 256;\n>> -\t\tstd::fill(gamma_.begin(), gamma_.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\tgamma_[i] = UINT8_MAX * powf((i - blackIndex) / divisor, params.gamma);\n>> -\n>> -\t\tgammaCorrection_ = params.gamma;\n>> -\t\tblackLevel_ = params.blackLevel;\n>> -\t}\n>> -\n>> -\tif (swapRedBlueGains_)\n>> -\t\tstd::swap(params.gainR, params.gainB);\n>> -\n>> -\tfor (unsigned int i = 0; i < kRGBLookupSize; i++) {\n>> -\t\tconstexpr unsigned int div =\n>> -\t\t\tkRGBLookupSize * DebayerParams::kGain10 / kGammaLookupSize;\n>> -\t\tunsigned int idx;\n>> -\n>> -\t\t/* Apply gamma after gain! */\n>> -\t\tidx = std::min({ i * params.gainR / div, (kGammaLookupSize - 1) });\n>> -\t\tred_[i] = gamma_[idx];\n>> -\n>> -\t\tidx = std::min({ i * params.gainG / div, (kGammaLookupSize - 1) });\n>> -\t\tgreen_[i] = gamma_[idx];\n>> -\n>> -\t\tidx = std::min({ i * params.gainB / div, (kGammaLookupSize - 1) });\n>> -\t\tblue_[i] = gamma_[idx];\n>> -\t}\n>> +\tgreen_ = params.green;\n>> +\tred_ = swapRedBlueGains_ ? params.blue : params.red;\n>> +\tblue_ = swapRedBlueGains_ ? params.red : params.blue;\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 689c1075..47373426 100644\n>> --- a/src/libcamera/software_isp/debayer_cpu.h\n>> +++ b/src/libcamera/software_isp/debayer_cpu.h\n>> @@ -122,15 +122,12 @@ private:\n>>   \tvoid process2(const uint8_t *src, uint8_t *dst);\n>>   \tvoid process4(const uint8_t *src, uint8_t *dst);\n>>   -\tstatic constexpr unsigned int kGammaLookupSize = 1024;\n>> -\tstatic constexpr unsigned int kRGBLookupSize = 256;\n>>   \t/* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */\n>>   \tstatic constexpr unsigned int kMaxLineBuffers = 5;\n>>   -\tstd::array<uint8_t, kGammaLookupSize> gamma_;\n>> -\tstd::array<uint8_t, kRGBLookupSize> red_;\n>> -\tstd::array<uint8_t, kRGBLookupSize> green_;\n>> -\tstd::array<uint8_t, kRGBLookupSize> blue_;\n>> +\tDebayerParams::ColorLookupTable red_;\n>> +\tDebayerParams::ColorLookupTable green_;\n>> +\tDebayerParams::ColorLookupTable blue_;\n>>   \tdebayerFn debayer0_;\n>>   \tdebayerFn debayer1_;\n>>   \tdebayerFn debayer2_;\n>> diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\n>> index e4e56086..3e07453d 100644\n>> --- a/src/libcamera/software_isp/software_isp.cpp\n>> +++ b/src/libcamera/software_isp/software_isp.cpp\n>> @@ -63,9 +63,7 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)\n>>    * handler\n>>    */\n>>   SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor)\n>> -\t: debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10,\n>> -\t\t\t  DebayerParams::kGain10, 0.5f, 0 },\n>> -\t  dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System)\n>> +\t: dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System)\n>>   {\n>>   \tif (!dmaHeap_.isValid()) {\n>>   \t\tLOG(SoftwareIsp, Error) << \"Failed to create DmaHeap object\";","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 CF404BDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 23 May 2024 11:25:18 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E83B663497;\n\tThu, 23 May 2024 13:25:17 +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 0421961A49\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 May 2024 13:25:15 +0200 (CEST)","from mail-wr1-f71.google.com (mail-wr1-f71.google.com\n\t[209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-32-M1eXhii0Pq6wM-XIDlS8JQ-1; Thu, 23 May 2024 07:25:13 -0400","by mail-wr1-f71.google.com with SMTP id\n\tffacd0b85a97d-34d9deebf38so9350263f8f.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 May 2024 04:25:12 -0700 (PDT)","from nuthatch ([2a00:102a:401d:ff06:90d1:42a:55b2:2ad8])\n\tby smtp.gmail.com with ESMTPSA id\n\tffacd0b85a97d-354f276a49bsm2716808f8f.96.2024.05.23.04.25.08\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 23 May 2024 04:25:10 -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=\"c+tcwRQb\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1716463514;\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=2yzbkpHSZs7kwkPwIa2WQGcHAEqZpWAtwQwlsNmba3g=;\n\tb=c+tcwRQbSyxz18YnpRCHzrJQvqwNSsmpY91BpFuB/5RVvRqS1EysCoZcpP7xmKGHBN5UNX\n\tcFwMxtgYFinzTSdBb2jy5rnKxvQ0mwqnfbIGZ+6wQHzSMjaFE8ZW2gmvcVW+1gjY20PRdI\n\tfwea6hKFc0mzpjZ2kcLF0SzrGe+GVHs=","X-MC-Unique":"M1eXhii0Pq6wM-XIDlS8JQ-1","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1716463512; x=1717068312;\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=2yzbkpHSZs7kwkPwIa2WQGcHAEqZpWAtwQwlsNmba3g=;\n\tb=gW3I1iSgFI3W0wk18F9s8g//OG8qnc7okHeatVS1IVejvcIO1Mn5NBtnpKPjYuIIhh\n\tKJe2Z7+K3oXdAXWezgZora1g1m/5RaPgx1bFc2SQ6BR4NMadDO1gnwHLG5JVL81VGM4J\n\tfqTwkPRZGMLeIGDk5Mg7QA8PGJunBaosQrkNJwAyRlmxiz9Brm5s9JM34AkSF5BrEjHX\n\taR4jDKs4vTqj1Z0Nfy+Dpb0GtI1oOyBgc+l4uKPsHNFWHudIYzSdsGHes08kg4w6kDI4\n\tQhP4qmc7YooXrVQ+vI6Rslsys4FiinyA6ekLK5siFAyIbG89JnZmLx3Vp4mALAJISHy0\n\tu6Qw==","X-Gm-Message-State":"AOJu0YzYTAxdlO2tjzDPTqtohkFuNBPwuKuGwOdUrELU8jjkKAQWj8JI\n\t1ZoO7661/nxu1MCJeSAR1/sx1FfJu4Fj1Zf6vOmXOFFKCCu4h2D/jxjz+OXIyOFB6ZWw4hAqN8M\n\tA4CzDXhsDJhgf03g2lltlCRlMjKpSiNvf5AoafLyxr/cwLnpj4XLKGUy2Z3raqVzLlHnUB80=","X-Received":["by 2002:a05:6000:511:b0:34a:4ad9:a93f with SMTP id\n\tffacd0b85a97d-354d8d8e71dmr4499590f8f.55.1716463511740; \n\tThu, 23 May 2024 04:25:11 -0700 (PDT)","by 2002:a05:6000:511:b0:34a:4ad9:a93f with SMTP id\n\tffacd0b85a97d-354d8d8e71dmr4499563f8f.55.1716463511243; \n\tThu, 23 May 2024 04:25:11 -0700 (PDT)"],"X-Google-Smtp-Source":"AGHT+IGJrke0HSGjGDuieqo2JxsiwguvUSRm1PZA/DtTpvC/WLrp/ffQjONVwG882blPyk/4IfXddw==","From":"Milan Zamazal <mzamazal@redhat.com>","To":"Andrei Konovalov <andrey.konovalov.ynk@gmail.com>","Cc":"libcamera-devel@lists.libcamera.org,  Laurent Pinchart\n\t<laurent.pinchart@ideasonboard.com>","Subject":"Re: [PATCH v2 3/5] libcamera: software_isp: Move color mappings out\n\tof debayering","In-Reply-To":"<6d429662-26d4-40f8-8862-0cfc6f9d4e5f@gmail.com> (Andrei\n\tKonovalov's message of \"Wed, 22 May 2024 12:49:15 +0300\")","References":"<20240430173430.200392-1-mzamazal@redhat.com>\n\t<20240430173430.200392-4-mzamazal@redhat.com>\n\t<6d429662-26d4-40f8-8862-0cfc6f9d4e5f@gmail.com>","Date":"Thu, 23 May 2024 13:25:07 +0200","Message-ID":"<87jzjk4vos.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>"}}]