From patchwork Fri Aug 28 14:06:29 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "D. Manresa" X-Patchwork-Id: 28142 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 069C3C333F for ; Fri, 28 Aug 2026 14:40:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4B201684AB; Fri, 28 Aug 2026 16:40:53 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Z4Per+pt"; dkim-atps=neutral Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 16F1968494 for ; Fri, 28 Aug 2026 16:06:37 +0200 (CEST) Received: by mail-wm1-x332.google.com with SMTP id 5b1f17b1804b1-4954a9e8490so12837955e9.1 for ; Fri, 28 Aug 2026 07:06:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787925997; x=1788530797; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=7JxQwCGXRBOL/sHqY+LFGr1vi9k2TcunwY1W1Ntfoqk=; b=Z4Per+ptCJu+pRWx/DQB38QEDBgTIsV7Sj0mljLx8DcOtzDbkA/D1/Ce2jzq3todBb m4ZKAGPOCM7UGJh4lY+TtSKVUJnzyuSm9vG/TFskxtL+XqomvV6Wshm2zDOYdu1PiN8W WT9Ag6jG1NIn/AtFM3g9gpK4bNeuWcJqe58zKxf8GXfM4gOtdFf5JOIft20xvkLSTzgs uIj5/uL+bFDf68ActmJYNHL54NAdWmWwPvXqYOoKw3i/BhUcO4+6e6gWkLhrYDn8GgGH eN0sB0lQmaDrQJ5EPR+cPTvDq8y3hA7928e2EeT1RAl1Own3O4CSzxmseiAVPusTKVrU d1MA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787925997; x=1788530797; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=7JxQwCGXRBOL/sHqY+LFGr1vi9k2TcunwY1W1Ntfoqk=; b=THj4P4ZAJUHuLX74ICbD3vDRZZtpTGE16OrivU1UviMf3JmjrB3dBiowcdaVU6dIxA VymyUiO3+DES4sK0Pqmq91qIQcF5OzK7GrRNRGxMfH4oRODIUFlaO8pgqfaJLL4vzSq7 R8s+N123rHrZiT9GAyWTyn8EpsedJQZAl0KTjlizvtjERD02MCEecSnKar1WrweKHUAY 6BLeG1fMw2U0XXIygnE5Dbf9H73GVOXFELqhnasQgLZ9CPXSIZ8B48DuDtqW1hv9X05U U3k0NXKe0gt85vH7SiDnDu55P4fkbADBchtO6ewTTJ6O/qWH7rrHNtVZL6WZQKfigTNP AYWw== X-Gm-Message-State: AFuF++mg2eC+Kqs1yzf+r1STCaSX0dbmqO8r/z/MpyGg++7yKbM+P9da izq3LF+ZeeqhmtcTZKo+F4ZdEikxf8eavTYmJyVBITHCRmrgMGpjIDh5a73/nVEnOjgE X-Gm-Gg: AR+sD13yX9PFxadcmxqeijx2HVUzHGzeEPwOswaTdPJpVTSuFFRSMpTWZlSA9iutkRS OmYgkWLQlp8lYJf2o9Z0v7WVPxUOborPcFEkyXG2/YZ7P5BgMwLnXrv+7QpKUV7T6EhvnODicoU 0zsKaq2xSUwCx1sae9S7Wy818FWSn3AtgTUtHmjBX9Zlz4TrYffFZx4PLoZ3YdqbmjhoukOQ4bG eSVUB35tL3DcBrgqen0OYVp64d3Liy/KUQ2I5r6+KxS5N3pDzRfyoyHtNKOCWc/qNCGtms6FEre G9Le0/WyGvRuHOKtJJKefjsPOur7COSym5uucTjoIEvXzzlo6vc/0WjGOjG6Ot6i+VNw5SjDUf5 Pa87/hkvtPEIjmye1JELPc0cTslYbX4ZFhkBH1kVkwrOFgc4XJRyRMmdhNllE778mpY33EG4kss cHYEcTO6a8akUdxyhtcwJANjcuySC2gKe9Df2RZQ/nN6p5bUNwAPX5bKPcXKTSycxQe0EMUOjxe zvZe4/OE0e2 X-Received: by 2002:a05:600c:4683:b0:493:f783:c46a with SMTP id 5b1f17b1804b1-49cca3125c5mr2946325e9.6.1787925996347; Fri, 28 Aug 2026 07:06:36 -0700 (PDT) Received: from surface.. ([217.61.227.23]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49b9500c7cfsm57858645e9.11.2026.08.28.07.06.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Aug 2026 07:06:34 -0700 (PDT) From: "D. Manresa" To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Kieran Bingham , Milan Zamazal , Hans de Goede , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , "D. Manresa" Subject: [RFC PATCH 1/1] ipa: libipa: awb: Allow tuning files to lower the minimum gain Date: Fri, 28 Aug 2026 16:06:29 +0200 Message-ID: <20260828140629.128831-2-dmanresa@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260828140629.128831-1-dmanresa@gmail.com> References: <20260828140629.128831-1-dmanresa@gmail.com> MIME-Version: 1.0 X-Mailman-Approved-At: Fri, 28 Aug 2026 16:40:50 +0200 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" AwbAlgorithm clamps the computed white balance gains to a minimum of 1.0. The floor reflects a common hardware limitation, as many AWB engines cannot attenuate a colour channel, but it is applied even on platforms whose gain range does go below 1.0, most notably the software ISP which applies the gains in floating point during debayering. Some camera modules are calibrated with a white point that genuinely requires attenuating a channel. The front OV5693 of the Microsoft Surface Pro 7+ is one such module: the OEM calibration Microsoft ships in the public Surface driver package (the Intel CPFF/.aiqb container OV5693_MSHW0220_TGL.aiqb) stores per-illuminant sensor white points, and decoding them yields a red gain of 0.87 at 2592 K (illuminant A). With the floor in place the algorithm cannot reach the calibrated white point under warm light, and the picture keeps a red cast that no tuning can remove. Keep the 1.0 default and let the tuning file lower the limit with a new optional "gainMin" property, clamped to the gain range of the platform AWB engine. Platforms and sensors that do not opt in behave exactly as before. An alternative would be to drop the floor entirely and trust the platform gain range alone, but hardware IPA modules currently reuse their gain register format (e.g. UQ2.8) as the algorithm limits, and their pipelines may rely on gains never attenuating. An opt-in tuning property keeps the default behaviour unchanged everywhere. Developed with the assistance of an AI tool (Claude) and verified on a Surface Pro 7+ (software ISP, OEM-derived colour tuning) against the Windows 11 rendition of the same scenes. Signed-off-by: D. Manresa --- src/ipa/libipa/awb.cpp | 4 ++++ src/ipa/libipa/awb.h | 14 +++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ipa/libipa/awb.cpp b/src/ipa/libipa/awb.cpp index da835bec0..b7f309298 100644 --- a/src/ipa/libipa/awb.cpp +++ b/src/ipa/libipa/awb.cpp @@ -526,6 +526,10 @@ int AwbAlgorithmBase::parseModeConfigs(const ValueNode &tuningData, * Minimum gain value used to clamp the AWB algorithm calculation results in the * range supported by the platform AWB engine. * + * The minimum defaults to 1.0, as most ISPs cannot attenuate a colour channel. + * On platforms that can, the "gainMin" tuning file property may lower the + * limit, within the range supported by the platform AWB engine. + * * The min and max gain values are initialized by AwbAlgorithm::init(). */ diff --git a/src/ipa/libipa/awb.h b/src/ipa/libipa/awb.h index d35a85167..7fe2e5f06 100644 --- a/src/ipa/libipa/awb.h +++ b/src/ipa/libipa/awb.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -117,7 +118,18 @@ public: { AwbAlgorithmBase::init(tuningData); - gainMin_ = std::max(Q::TraitsType::min, 1.0f); + /* + * Gains are not allowed to go below 1.0 by default, as most + * ISPs cannot attenuate a colour channel. Some camera + * modules are however calibrated with a white point that + * requires attenuating a channel, which platforms whose AWB + * gains can go below 1.0 (such as the software ISP) are able + * to apply. Let the tuning file lower the limit with the + * "gainMin" property, within the platform's gain range. + */ + float gainMin = tuningData["gainMin"].get(1.0f); + gainMin_ = std::clamp(gainMin, Q::TraitsType::min, + Q::TraitsType::max); gainMax_ = Q::TraitsType::max; controls_[&controls::ColourGains] =