[{"id":38337,"web_url":"https://patchwork.libcamera.org/comment/38337/","msgid":"<85wlzqccva.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","date":"2026-03-05T19:09:13","subject":"Re: [PATCH v2 2/4] libcamera: software_isp: Normalize statistics\n\tsums to 8-bit","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Hi Javier,\n\nthank you for the patch.\n\nJavier Tia <floss@jetm.me> writes:\n\n> The SWSTATS_ACCUMULATE_LINE_STATS() macro divides the luminance value\n> for the histogram to normalize it to 8-bit range, but does not apply\n> the same normalization to the RGB sums. For 10-bit and 12-bit unpacked\n> Bayer formats this means the sums are accumulated at native bit depth\n> (0-1023 or 0-4095 per pixel) while the AWB algorithm subtracts an\n> 8-bit black level from them, under-correcting by 4x or 16x\n> respectively.\n\nGood finding!\n\nI've been playing with an independent implementation of software ISP\nstats+processing and when comparing its output with libcamera output, I\ncould also see a slight green cast in my libcamera images.  With your\npatch, the green cast is gone and the outputs are basically the same.\n\nReviewed-by: Milan Zamazal <mzamazal@redhat.com>\nTested-by: Milan Zamazal <mzamazal@redhat.com>\n\n> This mismatch between the AWB's gain calculation (using incorrectly\n> BLC-subtracted sums) and the debayer's correct normalized BLC\n> subtraction produces a visible color cast. For example, with the\n> OV2740 sensor (10-bit, BLC=16), the under-subtraction skews R/G gain\n> by ~9%.\n>\n> Fix this by right-shifting the RGB sums in finishFrame() to normalize\n> them to 8-bit scale, matching the histogram and the 8-bit black level\n> used by AWB. A per-format sumShift_ value is set in configure():\n> 0 for 8-bit and CSI-2 packed formats (already 8-bit), 2 for 10-bit,\n> and 4 for 12-bit unpacked formats.\n>\n> Signed-off-by: Javier Tia <floss@jetm.me>\n> ---\n>  include/libcamera/internal/software_isp/swstats_cpu.h | 1 +\n>  src/libcamera/software_isp/swstats_cpu.cpp            | 9 +++++++++\n>  2 files changed, 10 insertions(+)\n>\n> diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h\n> index 64b3e23f..37bfde53 100644\n> --- a/include/libcamera/internal/software_isp/swstats_cpu.h\n> +++ b/include/libcamera/internal/software_isp/swstats_cpu.h\n> @@ -115,6 +115,7 @@ private:\n>  \n>  \tunsigned int xShift_;\n>  \tunsigned int stride_;\n> +\tunsigned int sumShift_;\n>  \n>  \tSharedMemObject<SwIspStats> sharedStats_;\n>  \tSwIspStats stats_;\n> diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp\n> index 5c3011a7..bf5e1960 100644\n> --- a/src/libcamera/software_isp/swstats_cpu.cpp\n> +++ b/src/libcamera/software_isp/swstats_cpu.cpp\n> @@ -346,6 +346,11 @@ void SwStatsCpu::startFrame(uint32_t frame)\n>  void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId)\n>  {\n>  \tstats_.valid = frame % kStatPerNumFrames == 0;\n> +\tif (stats_.valid && sumShift_) {\n> +\t\tstats_.sum_.r() >>= sumShift_;\n> +\t\tstats_.sum_.g() >>= sumShift_;\n> +\t\tstats_.sum_.b() >>= sumShift_;\n> +\t}\n>  \t*sharedStats_ = stats_;\n>  \tstatsReady.emit(frame, bufferId);\n>  }\n> @@ -405,12 +410,15 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)\n>  \t\tswitch (bayerFormat.bitDepth) {\n>  \t\tcase 8:\n>  \t\t\tstats0_ = &SwStatsCpu::statsBGGR8Line0;\n> +\t\t\tsumShift_ = 0;\n>  \t\t\treturn 0;\n>  \t\tcase 10:\n>  \t\t\tstats0_ = &SwStatsCpu::statsBGGR10Line0;\n> +\t\t\tsumShift_ = 2;\n>  \t\t\treturn 0;\n>  \t\tcase 12:\n>  \t\t\tstats0_ = &SwStatsCpu::statsBGGR12Line0;\n> +\t\t\tsumShift_ = 4;\n>  \t\t\treturn 0;\n>  \t\t}\n>  \t}\n> @@ -422,6 +430,7 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)\n>  \t\t/* Skip every 3th and 4th line, sample every other 2x2 block */\n>  \t\tySkipMask_ = 0x02;\n>  \t\txShift_ = 0;\n> +\t\tsumShift_ = 0;\n>  \t\tprocessFrame_ = &SwStatsCpu::processBayerFrame2;\n>  \n>  \t\tswitch (bayerFormat.order) {","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 1652FC0DA4\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  5 Mar 2026 19:09:24 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 44B49623AC;\n\tThu,  5 Mar 2026 20:09:23 +0100 (CET)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.133.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id EDED4622AE\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Mar 2026 20:09:20 +0100 (CET)","from mail-wm1-f71.google.com (mail-wm1-f71.google.com\n\t[209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-90-Hpe9oJuUNYC2vviChPb1ow-1; Thu, 05 Mar 2026 14:09:18 -0500","by mail-wm1-f71.google.com with SMTP id\n\t5b1f17b1804b1-48069a43217so84435055e9.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 05 Mar 2026 11:09:18 -0800 (PST)","from mzamazal-thinkpadp1gen7.tpbc.csb\n\t(ip-77-48-47-2.net.vodafone.cz. [77.48.47.2])\n\tby smtp.gmail.com with ESMTPSA id\n\t5b1f17b1804b1-485237ec5cbsm2582985e9.6.2026.03.05.11.09.14\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 05 Mar 2026 11:09:14 -0800 (PST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"hOwXvJrc\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1772737759;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=CnJOldgthi9HrBLJfgfwuRcb7yOn5xnvp3Qbks1Ul1Q=;\n\tb=hOwXvJrcdNQuwx5i7qpjxLwo1P/3yTYDhkwhey1rzHYOhJmmWIUCHG+8YEsIj3R67KcQRF\n\tFOFxa7/Aqb3eqgxaY9k5MHM08mwHzsvWKoKYdAXyU+6b5ns9zPgAHlAFn2aaNBBDTIveyO\n\tokjR//tT8ViACO2lJRjs//QBoXU0bgk=","X-MC-Unique":"Hpe9oJuUNYC2vviChPb1ow-1","X-Mimecast-MFC-AGG-ID":"Hpe9oJuUNYC2vviChPb1ow_1772737757","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1772737757; x=1773342557;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject\n\t:date:message-id:reply-to;\n\tbh=CnJOldgthi9HrBLJfgfwuRcb7yOn5xnvp3Qbks1Ul1Q=;\n\tb=T4plmOs3ZjawkGQTc586aPH3O5apKrlOhzzkw/HRM+oe1XK8i9Hzo1KzhpMNGf+/AH\n\tUnujZqKDazmd/QgobD2XuLHdTFht7AqnGzqNXoV023KHiJaixt1Yj7kIyfyZjQpcngZf\n\t+NZgFesyOUXiNp4faXCP3RbqPWj5yvCRY2d5To55d/atTHtyIK0ys402ZegJL4UWsMVM\n\tth/3S52/JAxVDheflKrF2CrT/RhgnEkeUUerPwmp50fHYkke/E2stSzGNZ5Qsnjr9fUj\n\tEM+/MXI2ePVzwD67hrTbt1gtlSjcfDqLNQ7rqeyNpPo6MOe7nxIDVg+tIGXY1WS/vSi/\n\tYjkA==","X-Gm-Message-State":"AOJu0YwfaZiK3uDYjaIFgM9FLCc95AAeNXxLPcU289R2+wcdoCRk7mpF\n\t/SVccKEKLRB/ia9StqEUYOLasqlbEhMWtm+uhxVB45pnNZ2ZFoR/EbwFLlMgozbqJdq2+yYjjZm\n\tdbJbRxj0LaVKUG/mlAVv7SM2DoAcbYvLVyFY/1fiiXuLuT+tzApSt9At5CPofxb33mnPvcMNCVx\n\tOLiS2cEQ5z55x6N7zoMDg94fcWWixZzbyxdkGXdWT/2EHVwSK7Xq0jHs2SXrU=","X-Gm-Gg":"ATEYQzw/S1ygAsSkHwNU07PSDYz+Hu/lEkXkHc2JONOeuW31frSel09KqK7EvSnXGbV\n\tIghpYJo4ltpXukVYnJZTigIgH32Iq9RmcTCiQyfWOowoXv6uJb1BuNSQtMx7hNbDWnad4TYsHWS\n\t1pcybHxe9e0yFi+5cHBtXyb+J7/Co1AzBWb6U2RcLFMemS2QZu5aUSk0yKLEyn8OBqjlTnheTYN\n\tSkT/TOjoytnUN9fJKBaGF88wgM5URqwOYdB0ZeUkL0XM+woVeOK75fZZx8tqri9ksDASoFSSbGZ\n\t8vpYFgJnEPZBby4hCtJcQwicOqWH0et6s72C0ZYWxf/M3Sg+yhdmyOLma8BwYEpI7TjwJXx8ThQ\n\t+EuS4TgPtZBePEgmhbB1VPKkTbHct1GsfySlTTnt0yjrL6QTrPpW9T6cIJNnPEPQnKRHscoshWl\n\tA=","X-Received":["by 2002:a05:600c:3b12:b0:47a:814c:eea1 with SMTP id\n\t5b1f17b1804b1-485198b3304mr116931675e9.35.1772737756663; \n\tThu, 05 Mar 2026 11:09:16 -0800 (PST)","by 2002:a05:600c:3b12:b0:47a:814c:eea1 with SMTP id\n\t5b1f17b1804b1-485198b3304mr116931125e9.35.1772737756077; \n\tThu, 05 Mar 2026 11:09:16 -0800 (PST)"],"From":"Milan Zamazal <mzamazal@redhat.com>","To":"Javier Tia <floss@jetm.me>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v2 2/4] libcamera: software_isp: Normalize statistics\n\tsums to 8-bit","In-Reply-To":"<20260304232533.56D641EA006B@mailuser.phl.internal> (Javier\n\tTia's message of \"Wed, 04 Mar 2026 17:13:46 -0600\")","References":"<20260304232533.56D641EA006B@mailuser.phl.internal>","Date":"Thu, 05 Mar 2026 20:09:13 +0100","Message-ID":"<85wlzqccva.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"muJxecKur0J2sPv_S98gadxHCLxgffkbXQIATCpQ2Lo_1772737757","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]