@@ -526,6 +526,11 @@ 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: gains below 1.0 attenuate a colour channel,
+ * which is normally undesirable. On platforms whose gain range goes below
+ * 1.0, 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().
*/
@@ -7,6 +7,7 @@
#pragma once
+#include <algorithm>
#include <array>
#include <map>
#include <optional>
@@ -117,7 +118,20 @@ public:
{
AwbAlgorithmBase::init(tuningData);
- gainMin_ = std::max(Q::TraitsType::min, 1.0f);
+ /*
+ * Gains are not allowed to go below 1.0 by default: attenuating
+ * a colour channel discards part of its dynamic range, so
+ * balancing by amplifying the other channels is normally
+ * preferable. 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<float>(1.0f);
+ gainMin_ = std::clamp(gainMin, Q::TraitsType::min,
+ Q::TraitsType::max);
gainMax_ = Q::TraitsType::max;
controls_[&controls::ColourGains] =
AwbAlgorithm clamps the computed white balance gains to a minimum of 1.0. The floor is a sensible default, as attenuating a colour channel discards part of its dynamic range and balancing by amplifying the other channels is normally preferable, 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). Raw captures of the sensor under an incandescent lamp confirm the calibration: the red channel averages 1.15x the green channel on a white surface. 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 <dmanresa@gmail.com> --- src/ipa/libipa/awb.cpp | 5 +++++ src/ipa/libipa/awb.h | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-)