From patchwork Thu May 16 12:41:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20048 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id C79FFBDE6B for ; Thu, 16 May 2024 12:43:07 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 733746347C; Thu, 16 May 2024 14:43:07 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="PYTeR/i3"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 25DC36346B for ; Thu, 16 May 2024 14:43:06 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:3fef:fa64:e35:24d4]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B5A98327; Thu, 16 May 2024 14:42:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1715863377; bh=HC5ZBL/KGrbTanVK+WYCFhSrLUaWNENOSaD+40ITgjI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PYTeR/i3OyyEILH9ORR7pGbupSOuvoFrwScPnScJUUAFxWqvtvrlyGN8UgbfyIkZb nsnpZQJgSkGDZ7KSry7XFNNaJxYRYZRga5CTT1ZMwRBMI7Ewu92l5353UkCRzOg15U vuIKpuiGyjmMnnnUDx2L8nSbbJ3p2GbLb9j27T9k= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 1/3] ipa: rkisp1: Add gamma algorithm Date: Thu, 16 May 2024 14:41:48 +0200 Message-Id: <20240516124150.219054-2-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240516124150.219054-1-stefan.klug@ideasonboard.com> References: <20240516124150.219054-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a gamma algorithm for the rkisp1. It defaults to a gamma of 2.2 which closely resembles sRGB. No seperate sRGB mode was implemented because the pwl that models the gamma curve is so coarse that there is basically no difference between srgb and gamma=2.2 The gamma algorithm is not enabled by default. This will be done in future tuning file updates. Signed-off-by: Stefan Klug --- Note: This patch breaks the naming conventions. It is implemented inside goc.h/cpp because the hardware block and params inside the rkisp1 are called "goc". The class itself is called Gamma, and the algorithm is registered with the name "Gamma". The idea was that similar functionalities should be named the same inside the tuning files (even among multipe isps). It still feels a bit awkward. So thoughts are welcome :-) Cheers, Stefan src/ipa/rkisp1/algorithms/goc.cpp | 89 +++++++++++++++++++++++++++ src/ipa/rkisp1/algorithms/goc.h | 32 ++++++++++ src/ipa/rkisp1/algorithms/meson.build | 1 + 3 files changed, 122 insertions(+) create mode 100644 src/ipa/rkisp1/algorithms/goc.cpp create mode 100644 src/ipa/rkisp1/algorithms/goc.h diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp new file mode 100644 index 00000000..1598d730 --- /dev/null +++ b/src/ipa/rkisp1/algorithms/goc.cpp @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024 Ideas On Board + * + * RkISP1 Gamma out control + */ +#include "goc.h" + +#include + +#include +#include + +#include "libcamera/internal/yaml_parser.h" + +#include "linux/rkisp1-config.h" + +/** + * \file gsl.h + */ + +namespace libcamera { + +namespace ipa::rkisp1::algorithms { + +/** + * \class Gamma + * \brief RkISP1 Gamma out control + * + * This algorithm implements the gamma out curve for the RkISP1. + * It defaults to a gamma value of 2.2 + * As gamma is internally represented as a piecewise linear function with only + * 16 knots, the difference between gamma=2.2 and sRGB gamma is minimal. + * Therefore sRGB gamma was not implemented as special case. + * + * Useful links: + * https://www.cambridgeincolour.com/tutorials/gamma-correction.htm + * https://en.wikipedia.org/wiki/SRGB + */ + +LOG_DEFINE_CATEGORY(RkISP1Gamma) + +Gamma::Gamma() +{ +} + +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int Gamma::init([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const YamlObject &tuningData) +{ + return 0; +} + +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Gamma::prepare([[maybe_unused]] IPAContext &context, + const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, + rkisp1_params_cfg *params) +{ + /* The logarithmic segments as specified in the reference. + Plus an additional 0 to make the loop easier */ + int segments[] = { 64, 64, 64, 64, 128, 128, 128, 128, 256, 256, 256, + 512, 512, 512, 512, 512, 0 }; + auto gamma_y = params->others.goc_config.gamma_y; + + if (frame > 0) + return; + + int x = 0; + for (int i = 0; i < RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10; i++) { + gamma_y[i] = std::pow(x / 4096.0, 1.0 / gamma_) * 1023.0; + x += segments[i]; + } + + params->others.goc_config.mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC; + params->module_en_update |= RKISP1_CIF_ISP_MODULE_GOC; + params->module_ens |= RKISP1_CIF_ISP_MODULE_GOC; + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_GOC; +} + +REGISTER_IPA_ALGORITHM(Gamma, "Gamma") + +} /* namespace ipa::rkisp1::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/algorithms/goc.h b/src/ipa/rkisp1/algorithms/goc.h new file mode 100644 index 00000000..3c83655b --- /dev/null +++ b/src/ipa/rkisp1/algorithms/goc.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021-2022, Ideas On Board + * + * gsl.h - RkISP1 Gamma Sensor Linearization control + */ + +#pragma once + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::rkisp1::algorithms { + +class Gamma : public Algorithm +{ +public: + Gamma(); + ~Gamma() = default; + + int init(IPAContext &context, const YamlObject &tuningData) override; + void prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + rkisp1_params_cfg *params) override; + +private: + float gamma_ = 2.2; +}; + +} /* namespace ipa::rkisp1::algorithms */ +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build index 93a48329..6ee71a9b 100644 --- a/src/ipa/rkisp1/algorithms/meson.build +++ b/src/ipa/rkisp1/algorithms/meson.build @@ -8,6 +8,7 @@ rkisp1_ipa_algorithms = files([ 'dpcc.cpp', 'dpf.cpp', 'filter.cpp', + 'goc.cpp', 'gsl.cpp', 'lsc.cpp', ]) From patchwork Thu May 16 12:41:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20049 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 86B02BDE6B for ; Thu, 16 May 2024 12:43:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3D21863482; Thu, 16 May 2024 14:43:10 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="NZ6tDFN0"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BAA396347E for ; Thu, 16 May 2024 14:43:08 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:3fef:fa64:e35:24d4]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 514839D5; Thu, 16 May 2024 14:43:00 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1715863380; bh=NBUQGgzgDnhnzt+SHSpduQBh+VyD7Ldv5dWg7jK4Qn4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NZ6tDFN0y9P9J3vS67J7LaIz7JnCFAAnnN7ps7W3bYK5CQoOcDFMHSwJhRCu1qiRU fK2R008mGm0+DODZ3KdPA78Dn76k3ajJAC1cCLDHrXZhznZYLsO8WTehgI7b0/SDYQ y/33U+RCViSTODQTUPbQhKL3NIWJfs1KWzdku4TQ= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 2/3] libcamera: Add gamma control id Date: Thu, 16 May 2024 14:41:49 +0200 Message-Id: <20240516124150.219054-3-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240516124150.219054-1-stefan.klug@ideasonboard.com> References: <20240516124150.219054-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" A camera gamma of roughly 2.2 is necessary to produce correct output images on a standard monitor. Add a control for that. Further information is available here: https://en.wikipedia.org/wiki/SRGB https://www.cambridgeincolour.com/tutorials/gamma-correction.htm Signed-off-by: Stefan Klug Reviewed-by: Daniel Scally --- src/libcamera/control_ids_core.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml index bf1f1a83..43b85135 100644 --- a/src/libcamera/control_ids_core.yaml +++ b/src/libcamera/control_ids_core.yaml @@ -243,6 +243,12 @@ controls: Specify a fixed contrast parameter. Normal contrast is given by the value 1.0; larger values produce images with more contrast. + - Gamma: + type: float + description: | + Specify a fixed gamma value. Default is 2.2 which closely mimics sRGB + gamma. Note that this is camera gamma, so it is applied as 1.0/gamma + - Lux: type: float description: | From patchwork Thu May 16 12:41:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20050 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 73E7BBDE6B for ; Thu, 16 May 2024 12:43:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1749263485; Thu, 16 May 2024 14:43:13 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Ssugqst0"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1A5846347C for ; Thu, 16 May 2024 14:43:11 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:3fef:fa64:e35:24d4]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A25DF9D5; Thu, 16 May 2024 14:43:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1715863382; bh=1dM5gDq2CRxvX58nohspzt7v2JBfH0OQcd62FSa0dhc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ssugqst0kZsQSm4hKJFOmLDkBf28Fr7ND1FOKyCMnTV0stiu8T2L0Xyco9koLKpZq QjVCbQJL2MRSsANqd0P7npQYAnu37IfHwthxAnT1pePg/rfaYfS0QmDkCIp5UXqckp OcLZU8jUIIEZRxHgDe3EcvH1ShchvHMtz5xPbAE4= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 3/3] pipeline: rkisp1: Implement gamma control Date: Thu, 16 May 2024 14:41:50 +0200 Message-Id: <20240516124150.219054-4-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240516124150.219054-1-stefan.klug@ideasonboard.com> References: <20240516124150.219054-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add support for the gamma control on the rkisp1. This was tested on an imx8mp. While at it, reorder the controls inside rkisp1.cpp alphabetically. Signed-off-by: Stefan Klug --- src/ipa/rkisp1/algorithms/goc.cpp | 74 ++++++++++++++++++++++++++----- src/ipa/rkisp1/algorithms/goc.h | 11 ++++- src/ipa/rkisp1/ipa_context.h | 4 ++ src/ipa/rkisp1/rkisp1.cpp | 3 +- 4 files changed, 80 insertions(+), 12 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp index 1598d730..2c7cb8a8 100644 --- a/src/ipa/rkisp1/algorithms/goc.cpp +++ b/src/ipa/rkisp1/algorithms/goc.cpp @@ -11,6 +11,8 @@ #include #include +#include + #include "libcamera/internal/yaml_parser.h" #include "linux/rkisp1-config.h" @@ -53,6 +55,41 @@ int Gamma::init([[maybe_unused]] IPAContext &context, return 0; } +/** + * \brief Configure the Gamma given a configInfo + * \param[in] context The shared IPA context + * \param[in] configInfo The IPA configuration data + * + * \return 0 + */ +int Gamma::configure(IPAContext &context, + [[maybe_unused]] const IPACameraSensorInfo &configInfo) +{ + context.activeState.gamma = 2.2; + return 0; +} + +/** + * \copydoc libcamera::ipa::Algorithm::queueRequest + */ +void Gamma::queueRequest([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) +{ + const auto &gamma = controls.get(controls::Gamma); + if (gamma) { + /* \todo This is not correct as it updates the current state with a + * future value. But it does no harm at the moment an allows us to + * track the last active gamma + */ + context.activeState.gamma = *gamma; + LOG(RkISP1Gamma, Debug) << "Set gamma to " << *gamma; + } + + frameContext.gamma = context.activeState.gamma; +} + /** * \copydoc libcamera::ipa::Algorithm::prepare */ @@ -67,19 +104,36 @@ void Gamma::prepare([[maybe_unused]] IPAContext &context, 512, 512, 512, 512, 512, 0 }; auto gamma_y = params->others.goc_config.gamma_y; - if (frame > 0) - return; + if (frame == 0 || std::fabs(frameContext.gamma - gamma_) > 0.001) { + gamma_ = frameContext.gamma; + + int x = 0; + for (int i = 0; i < RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10; i++) { + gamma_y[i] = std::pow(x / 4096.0, 1.0 / gamma_) * 1023.0; + x += segments[i]; + } - int x = 0; - for (int i = 0; i < RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10; i++) { - gamma_y[i] = std::pow(x / 4096.0, 1.0 / gamma_) * 1023.0; - x += segments[i]; + params->others.goc_config.mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC; + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_GOC; + + /* It is unclear why these bits need to be set more than once. + * Setting them only on frame 0 didn't apply gamma. + */ + params->module_en_update |= RKISP1_CIF_ISP_MODULE_GOC; + params->module_ens |= RKISP1_CIF_ISP_MODULE_GOC; } +} - params->others.goc_config.mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC; - params->module_en_update |= RKISP1_CIF_ISP_MODULE_GOC; - params->module_ens |= RKISP1_CIF_ISP_MODULE_GOC; - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_GOC; +/** + * \copydoc libcamera::ipa::Algorithm::process + */ +void Gamma::process([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + [[maybe_unused]] const rkisp1_stat_buffer *stats, + ControlList &metadata) +{ + metadata.set(controls::Gamma, frameContext.gamma); } REGISTER_IPA_ALGORITHM(Gamma, "Gamma") diff --git a/src/ipa/rkisp1/algorithms/goc.h b/src/ipa/rkisp1/algorithms/goc.h index 3c83655b..c6414040 100644 --- a/src/ipa/rkisp1/algorithms/goc.h +++ b/src/ipa/rkisp1/algorithms/goc.h @@ -20,12 +20,21 @@ public: ~Gamma() = default; int init(IPAContext &context, const YamlObject &tuningData) override; + int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override; + void queueRequest(IPAContext &context, + const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, rkisp1_params_cfg *params) override; + void process(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const rkisp1_stat_buffer *stats, + ControlList &metadata) override; private: - float gamma_ = 2.2; + float gamma_; }; } /* namespace ipa::rkisp1::algorithms */ diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index bd02a7a2..5252e222 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -104,6 +104,8 @@ struct IPAActiveState { uint8_t denoise; uint8_t sharpness; } filter; + + double gamma; }; struct IPAFrameContext : public FrameContext { @@ -146,6 +148,8 @@ struct IPAFrameContext : public FrameContext { uint32_t exposure; double gain; } sensor; + + double gamma; }; struct IPAContext { diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 6687c91e..7364fd73 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -108,9 +108,10 @@ const IPAHwSettings ipaHwSettingsV12{ const ControlInfoMap::Map rkisp1Controls{ { &controls::AeEnable, ControlInfo(false, true) }, { &controls::AwbEnable, ControlInfo(false, true) }, - { &controls::ColourGains, ControlInfo(0.0f, 3.996f, 1.0f) }, { &controls::Brightness, ControlInfo(-1.0f, 0.993f, 0.0f) }, + { &controls::ColourGains, ControlInfo(0.0f, 3.996f, 1.0f) }, { &controls::Contrast, ControlInfo(0.0f, 1.993f, 1.0f) }, + { &controls::Gamma, ControlInfo(0.1f, 10.0f, 2.2f) }, { &controls::Saturation, ControlInfo(0.0f, 1.993f, 1.0f) }, { &controls::Sharpness, ControlInfo(0.0f, 10.0f, 1.0f) }, { &controls::draft::NoiseReductionMode, ControlInfo(controls::draft::NoiseReductionModeValues) },