From patchwork Wed Mar 4 23:13:46 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Javier Tia X-Patchwork-Id: 26258 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 63803BE086 for ; Wed, 4 Mar 2026 23:25:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 297A8625E1; Thu, 5 Mar 2026 00:25:36 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=jetm.me header.i=@jetm.me header.b="VoIQOM1T"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="CLqTphPS"; dkim-atps=neutral Received: from fout-b7-smtp.messagingengine.com (fout-b7-smtp.messagingengine.com [202.12.124.150]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7396B623B5 for ; Thu, 5 Mar 2026 00:25:34 +0100 (CET) Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfout.stl.internal (Postfix) with ESMTP id 9E3361D0020E for ; Wed, 4 Mar 2026 18:25:33 -0500 (EST) Received: from phl-imap-07 ([10.202.2.97]) by phl-compute-02.internal (MEProxy); Wed, 04 Mar 2026 18:25:33 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jetm.me; h=cc :content-transfer-encoding:content-type:content-type:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm3; t=1772666733; x=1772753133; bh=vr23QiuLsfOcE/tj37mfrxI3IjI3XSG1oeye/ccoASc=; b= VoIQOM1Tfpm768edYjGdQ1Qd0fZ7jwrozodlp2JjKhsvwi+Ap5WmGuArNo3fI2ET HZzjRsN22H5XHj4ejTvslGxCvcXSRn+OY433kEMUiDOsuolYLV0by9rwGxhh5yyZ ov5S/F8F9FcHH7z6Scl4VFX8dLqeJ4JppzXBGzcJIT6DUj8j2zWjSnLWm2qR8H4b jDaa5571XbMtvBbZg4Q5xEb469er5GbJ1SGKEXx2KphuuHDTOMo3i+C+KCyb/aAE PkHJQ8yfgy65h5UDnA87dGjeSOpFMgkV03lDYSMC3iyqg3VVQKcaRkxvt728jaTw IFpnRIsKNFAkWBmfGDwYlA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1772666733; x=1772753133; bh=v r23QiuLsfOcE/tj37mfrxI3IjI3XSG1oeye/ccoASc=; b=CLqTphPSJL5Z2bral RMWCpiN0iYx4c2OzLJLWhSOL/51b0xDDWFmE8Bjx/XdJijrq3YLlijujaqWHzwE4 oYwF436IlJjUMGLULJbnDD8SBkCDJA7jr19Fmlun7VffSbLnTBn98eAHvITX1kkN IimfUYnjD3gpqcZDUbFNigTOD98jOZzgTWlYY01ozCCyicI4IN+iLml4AL4ZPhw5 hfH5c7G9MeoZeqUWoyVoOcXePklR85PaBd58Bvwe41J1kTWULTiwi+4hzUrEJ1Nc g1vEC8xQN5TLtiywBq3ZGdIAuxMWa1sKnfQ+3WtZBbMAGrWsSt/AUFHOLZ/LFcWP rWZ1Q== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgddvieegkeduucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucgopfhokfffucdluddtmdenucfjughrpefotggggffhvf ffufgjfhesthektddtredtjeenucfhrhhomheplfgrvhhivghrucfvihgruceofhhlohhs shesjhgvthhmrdhmvgeqnecuggftrfgrthhtvghrnhepteetvdeklefgledtjefhhfdtle dvhfffgfeuieelgeeigfekgffhleeghfefhfejnecuvehluhhsthgvrhfuihiivgepvden ucfrrghrrghmpehmrghilhhfrhhomhepfhhlohhsshesjhgvthhmrdhmvgdpnhgspghrtg hpthhtohepuddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtoheplhhisggtrghmvghr rgdquggvvhgvlheslhhishhtshdrlhhisggtrghmvghrrgdrohhrgh X-ME-Proxy: Feedback-ID: i9dde48b3:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 56D641EA006B; Wed, 4 Mar 2026 18:25:33 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface MIME-Version: 1.0 From: Javier Tia To: libcamera-devel@lists.libcamera.org Date: Wed, 04 Mar 2026 17:13:46 -0600 Subject: [PATCH v2 2/4] libcamera: software_isp: Normalize statistics sums to 8-bit In-Reply-To: 20260225221859.600869-1-floss@jetm.me References: 20260225221859.600869-1-floss@jetm.me Message-Id: <20260304232533.56D641EA006B@mailuser.phl.internal> 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" The SWSTATS_ACCUMULATE_LINE_STATS() macro divides the luminance value for the histogram to normalize it to 8-bit range, but does not apply the same normalization to the RGB sums. For 10-bit and 12-bit unpacked Bayer formats this means the sums are accumulated at native bit depth (0-1023 or 0-4095 per pixel) while the AWB algorithm subtracts an 8-bit black level from them, under-correcting by 4x or 16x respectively. This mismatch between the AWB's gain calculation (using incorrectly BLC-subtracted sums) and the debayer's correct normalized BLC subtraction produces a visible color cast. For example, with the OV2740 sensor (10-bit, BLC=16), the under-subtraction skews R/G gain by ~9%. Fix this by right-shifting the RGB sums in finishFrame() to normalize them to 8-bit scale, matching the histogram and the 8-bit black level used by AWB. A per-format sumShift_ value is set in configure(): 0 for 8-bit and CSI-2 packed formats (already 8-bit), 2 for 10-bit, and 4 for 12-bit unpacked formats. Signed-off-by: Javier Tia --- include/libcamera/internal/software_isp/swstats_cpu.h | 1 + src/libcamera/software_isp/swstats_cpu.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index 64b3e23f..37bfde53 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -115,6 +115,7 @@ private: unsigned int xShift_; unsigned int stride_; + unsigned int sumShift_; SharedMemObject sharedStats_; SwIspStats stats_; diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 5c3011a7..bf5e1960 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -346,6 +346,11 @@ void SwStatsCpu::startFrame(uint32_t frame) void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId) { stats_.valid = frame % kStatPerNumFrames == 0; + if (stats_.valid && sumShift_) { + stats_.sum_.r() >>= sumShift_; + stats_.sum_.g() >>= sumShift_; + stats_.sum_.b() >>= sumShift_; + } *sharedStats_ = stats_; statsReady.emit(frame, bufferId); } @@ -405,12 +410,15 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) switch (bayerFormat.bitDepth) { case 8: stats0_ = &SwStatsCpu::statsBGGR8Line0; + sumShift_ = 0; return 0; case 10: stats0_ = &SwStatsCpu::statsBGGR10Line0; + sumShift_ = 2; return 0; case 12: stats0_ = &SwStatsCpu::statsBGGR12Line0; + sumShift_ = 4; return 0; } } @@ -422,6 +430,7 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) /* Skip every 3th and 4th line, sample every other 2x2 block */ ySkipMask_ = 0x02; xShift_ = 0; + sumShift_ = 0; processFrame_ = &SwStatsCpu::processBayerFrame2; switch (bayerFormat.order) {