From patchwork Wed May 6 23:07:15 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: devve X-Patchwork-Id: 26660 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 4CDCCC3300 for ; Wed, 6 May 2026 23:07:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8A0AC6302D; Thu, 7 May 2026 01:07:33 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="FzsouHG/"; dkim-atps=neutral Received: from mail-qk1-x72b.google.com (mail-qk1-x72b.google.com [IPv6:2607:f8b0:4864:20::72b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4984963024 for ; Thu, 7 May 2026 01:07:30 +0200 (CEST) Received: by mail-qk1-x72b.google.com with SMTP id af79cd13be357-8cbc593a67aso20497185a.2 for ; Wed, 06 May 2026 16:07:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778108849; x=1778713649; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=TdmC3s5OWUslsg0CaqrHDC/ToejoU6twUaRb3QtsRVI=; b=FzsouHG/eg8YUKdALa8MY/IeHUIZ9FQESUDeGOiwl4ii4WSwAJGjnSmTsd9Zc9RDmr YkBVlfFHi26yjwx9S1UOsiyHMnAz+Bwo158KggbNU/qgTbjXmRyUpzacdGdn3G78xoJo b4Ce09sjwVOZ0LyLkULaW7CL8GdJR+BydQsS0XQdvkwsMqQBjiQhOdYg0COU0Yq0PVL0 +gpmXfbdah46XzcB+RlDrEdwM/qQ1tBQxdBR3dfdpm9S8IyzJicil/Yd4+Y4voE7ugpr mWFwjCn7FjThiYDW6ksbKCBclA48L2BtjMgqFXXEDhqTc23Zo6mHVymqhxVlkMCdoxCw PPtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778108849; x=1778713649; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=TdmC3s5OWUslsg0CaqrHDC/ToejoU6twUaRb3QtsRVI=; b=irfBMbjM1UYA3Nr+wnIRSjENACIJLD0wNQzTBM+eme243kR/12rIOA/0Zb9NKgYrTw zCjmpZ/hqJstoBHZJy1NK+lyI32cakAxu5uhDPqSLJcOsGjErv6ofgafYuqC9ganKWTY FX6DYgE806Xj08HsmvT/MDY+CwTlBt9DF5T2cogveKSZK+OEf0YMyRzpwljVQ0tLVVXH aO24Eur1ZZ/1fVXmcY4UEwt0xI1gX/C3guD6UyHLpQDfmBBGAPYFevT6KRnqiSwOrQxT lqoKuvysiMpEUICIs6rH3WpOlJa2+rR9oELHXUe55PwGd4GJvmHbd0Zhz+imYP7KOYGu YnyA== X-Gm-Message-State: AOJu0Yx+her1lhivfetdSZKA7BS4CDogimiM2yD80TDbdG4H8mRx/8Gg CratFoydcc+Vr8vsEQrPSfqjFjOQiAqAkc38kvDxDtbxh83c7RqiYVdt5Gg+XA== X-Gm-Gg: AeBDieugnjyqV9VRQCsTcueNHvDBHVAicJuFN2OCcMRBeYGZNj4hACTh/aKIWJAGXDh K68RcfL6hXJEhTrPfIiW5O2PrafhzcUpBopFDNAj5ACJ2fhAZrwxlQA8soNQS5V/80BKQjC7ZRk tBPaN++z74YE/XHX9AMyvOzvExB6VTcakP6VHcRI2NbdkrZ7FQkKoi2j8j9hLOSc1qUgR3d5T3W dlr09yAvfPDIrZLDerH/85h9DS9ajmcvR7YKR9AzynRj3Bh7wGmVjmV2+EK60QRl7XPDPjqHqGA P1nNGZyw7rfYpP0jG+LhE0Cy5on4mjSqwzY6I3fV2O80pPog+Mbogt7+X3+5FCdzpqYAF4lXyut M5LaC8U7mZZr4DhIU8ghwMKOy5aWQIqGMf+O4zKmrd9Cv12T5rNGffTsQCGohILdSuX6mDDec/r dDi5VCVike7a8OiSlOG/ZrwYAihFGhS9o3Qu7SfwiaIn3PKrTyYW/yE/5zo7/IqzJKJSLCDPhZr q5yesxgx6U0uPKnokVHove/J0XOUX0m X-Received: by 2002:a05:620a:2890:b0:8f4:3895:25d7 with SMTP id af79cd13be357-904d486edb2mr858797885a.23.1778108849148; Wed, 06 May 2026 16:07:29 -0700 (PDT) Received: from dexps.speedport.ip (p200300eda74453cf3cf3f7929e513b94.dip0.t-ipconnect.de. [2003:ed:a744:53cf:3cf3:f792:9e51:3b94]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8fc2c25324esm2035266385a.23.2026.05.06.16.07.28 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 May 2026 16:07:28 -0700 (PDT) From: d3vv3 To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 03/10] ipa: simple: adjust: Support gamma, contrast, saturation defaults from YAML Date: Thu, 7 May 2026 01:07:15 +0200 Message-ID: <20260506230722.1041596-4-devve.3@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260506230722.1041596-1-devve.3@gmail.com> References: <20260506230722.1041596-1-devve.3@gmail.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" Read default values for gamma, contrast, and saturation from the tuning file so sensors can specify different image processing defaults without code changes. Falls back to prior defaults (gamma 2.2, contrast 1.0, saturation 1.0) when not specified in YAML. Signed-off-by: d3vv3 --- src/ipa/simple/algorithms/adjust.cpp | 48 +++++++++++++--------------- src/ipa/simple/algorithms/adjust.h | 4 +++ src/ipa/simple/ipa_context.h | 8 ++--- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/ipa/simple/algorithms/adjust.cpp b/src/ipa/simple/algorithms/adjust.cpp index 8bf39c4c..a03a6f1f 100644 --- a/src/ipa/simple/algorithms/adjust.cpp +++ b/src/ipa/simple/algorithms/adjust.cpp @@ -14,34 +14,37 @@ #include #include "libcamera/internal/matrix.h" +#include "libcamera/internal/yaml_parser.h" namespace libcamera { namespace ipa::soft::algorithms { -constexpr float kDefaultContrast = 1.0f; -constexpr float kDefaultSaturation = 1.0f; - LOG_DEFINE_CATEGORY(IPASoftAdjust) -int Adjust::init(IPAContext &context, [[maybe_unused]] const ValueNode &tuningData) +int Adjust::init(IPAContext &context, const ValueNode &tuningData) { + defaultGamma_ = tuningData["gamma"].get().value_or(kDefaultGamma); + defaultContrast_ = tuningData["contrast"].get().value_or(1.0f); + defaultSaturation_ = tuningData["saturation"].get().value_or(1.0f); + context.ctrlMap[&controls::Gamma] = - ControlInfo(0.1f, 10.0f, kDefaultGamma); + ControlInfo(0.1f, 10.0f, defaultGamma_); context.ctrlMap[&controls::Contrast] = - ControlInfo(0.0f, 2.0f, kDefaultContrast); + ControlInfo(0.0f, 2.0f, defaultContrast_); if (context.ccmEnabled) context.ctrlMap[&controls::Saturation] = - ControlInfo(0.0f, 2.0f, kDefaultSaturation); + ControlInfo(0.0f, 2.0f, defaultSaturation_); + return 0; } int Adjust::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo) { - context.activeState.knobs.gamma = kDefaultGamma; - context.activeState.knobs.contrast = std::optional(); - context.activeState.knobs.saturation = std::optional(); + context.activeState.knobs.gamma = defaultGamma_; + context.activeState.knobs.contrast = defaultContrast_; + context.activeState.knobs.saturation = defaultSaturation_; return 0; } @@ -59,13 +62,13 @@ void Adjust::queueRequest(typename Module::Context &context, const auto &contrast = controls.get(controls::Contrast); if (contrast.has_value()) { - context.activeState.knobs.contrast = contrast; + context.activeState.knobs.contrast = contrast.value(); LOG(IPASoftAdjust, Debug) << "Setting contrast to " << contrast.value(); } const auto &saturation = controls.get(controls::Saturation); if (saturation.has_value()) { - context.activeState.knobs.saturation = saturation; + context.activeState.knobs.saturation = saturation.value(); LOG(IPASoftAdjust, Debug) << "Setting saturation to " << saturation.value(); } } @@ -100,15 +103,15 @@ void Adjust::prepare(IPAContext &context, frameContext.gamma = context.activeState.knobs.gamma; frameContext.contrast = context.activeState.knobs.contrast; - auto &saturation = context.activeState.knobs.saturation; - if (context.ccmEnabled && saturation) { - applySaturation(context.activeState.combinedMatrix, saturation.value()); + const float saturation = context.activeState.knobs.saturation; + if (context.ccmEnabled) { + applySaturation(context.activeState.combinedMatrix, saturation); frameContext.saturation = saturation; } params->gamma = 1.0 / context.activeState.knobs.gamma; - const float contrast = context.activeState.knobs.contrast.value_or(kDefaultContrast); - params->contrastExp = tan(std::clamp(contrast * M_PI_4, 0.0, M_PI_2 - 0.00001)); + params->contrastExp = tan(std::clamp(context.activeState.knobs.contrast * M_PI_4, + 0.0, M_PI_2 - 0.00001)); } void Adjust::process([[maybe_unused]] IPAContext &context, @@ -117,14 +120,9 @@ void Adjust::process([[maybe_unused]] IPAContext &context, [[maybe_unused]] const SwIspStats *stats, ControlList &metadata) { - const auto &gamma = frameContext.gamma; - metadata.set(controls::Gamma, gamma); - - const auto &contrast = frameContext.contrast; - metadata.set(controls::Contrast, contrast.value_or(kDefaultContrast)); - - const auto &saturation = frameContext.saturation; - metadata.set(controls::Saturation, saturation.value_or(kDefaultSaturation)); + metadata.set(controls::Gamma, frameContext.gamma); + metadata.set(controls::Contrast, frameContext.contrast); + metadata.set(controls::Saturation, frameContext.saturation); } REGISTER_IPA_ALGORITHM(Adjust, "Adjust") diff --git a/src/ipa/simple/algorithms/adjust.h b/src/ipa/simple/algorithms/adjust.h index 49c1f26c..a836b51b 100644 --- a/src/ipa/simple/algorithms/adjust.h +++ b/src/ipa/simple/algorithms/adjust.h @@ -43,6 +43,10 @@ public: private: void applySaturation(Matrix &ccm, float saturation); + + float defaultGamma_; + float defaultContrast_; + float defaultSaturation_; }; } /* namespace ipa::soft::algorithms */ diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index 34f7403a..cd9a8eda 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -58,8 +58,8 @@ struct IPAActiveState { struct { float gamma; /* 0..2 range, 1.0 = normal */ - std::optional contrast; - std::optional saturation; + float contrast; + float saturation; } knobs; }; @@ -77,8 +77,8 @@ struct IPAFrameContext : public FrameContext { } gains; float gamma; - std::optional contrast; - std::optional saturation; + float contrast; + float saturation; }; struct IPAContext {