{"id":27485,"url":"https://patchwork.libcamera.org/api/patches/27485/?format=json","web_url":"https://patchwork.libcamera.org/patch/27485/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260723154327.1357866-37-barnabas.pocze@ideasonboard.com>","date":"2026-07-23T15:43:19","name":"[RFC,v2,36/43] ipa: simple: agc: Adjust histogram for black level","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"bd6fefde1c60c98097f7ae9d04df34b2ca631032","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/?format=json","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/27485/mbox/","series":[{"id":6075,"url":"https://patchwork.libcamera.org/api/series/6075/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=6075","date":"2026-07-23T15:42:43","name":"ipa: libipa: agc rework","version":2,"mbox":"https://patchwork.libcamera.org/series/6075/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/27485/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/27485/checks/","tags":{},"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 9BE69BE080\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 23 Jul 2026 15:44:22 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1B40B67F82;\n\tThu, 23 Jul 2026 17:44:22 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A014167EEF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 Jul 2026 17:43:39 +0200 (CEST)","from pb-laptop.local (185.182.215.156.nat.pool.zt.hu\n\t[185.182.215.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C397B1F0F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 Jul 2026 17:42:38 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"ND4zj1N/\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1784821358;\n\tbh=Ch7Eiq1lpvW3U4J8QDDus2uEA7uHeblo7NL8vJMXO1U=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=ND4zj1N/BWy1Uiu9xVRQJzYi7w1Rf+zQOiFFTPVLmKCJjd0h+Kqbtng1MOaSrMLCK\n\tHJtJre04FuknBIHWvOAzih4LJSPYNeRzgBveDv4dBoCdnGslTJdU6UdqcCI9B/UAph\n\tH30ZKta5wyhWC6Ur1AHubnG6o2RlcoOiYC4rooHc=","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Subject":"[RFC PATCH v2 36/43] ipa: simple: agc: Adjust histogram for black\n\tlevel","Date":"Thu, 23 Jul 2026 17:43:19 +0200","Message-ID":"<20260723154327.1357866-37-barnabas.pocze@ideasonboard.com>","X-Mailer":"git-send-email 2.55.0","In-Reply-To":"<20260723154327.1357866-1-barnabas.pocze@ideasonboard.com>","References":"<20260723154327.1357866-1-barnabas.pocze@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","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>"},"content":"Instead of providing the black separately, adjust the luminance histogram\naccording to the current black level. This changes the behaviour slightly\nas previously everything under the black level was ignored, and only the\nremaining part was split into the 5 bins, but now the full histogram is\nsplit into the 5 bins.\n\nTODO: or should the previous behaviour be preserved and a smaller histogram be used without adjustments?\nTODO: is it `i < blackLevelHistIdx` or `i <= blackLevelHistIdx` ???\n\nSigned-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n---\n src/ipa/simple/algorithms/agc.cpp | 24 ++++++++++++++----------\n 1 file changed, 14 insertions(+), 10 deletions(-)","diff":"diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp\nindex cc33b269bf..199b444f5a 100644\n--- a/src/ipa/simple/algorithms/agc.cpp\n+++ b/src/ipa/simple/algorithms/agc.cpp\n@@ -11,6 +11,7 @@\n #include <cmath>\n #include <optional>\n #include <stdint.h>\n+#include <utility>\n \n #include <libcamera/base/log.h>\n \n@@ -66,19 +67,15 @@ static constexpr float kExpMaxStep = 0.15;\n \n namespace {\n \n-std::optional<float> calculateMSV(const Histogram &histogram, uint8_t blackLevel)\n+std::optional<float> calculateMSV(const Histogram &histogram)\n {\n \t/*\n \t * Calculate Mean Sample Value (MSV) according to formula from:\n \t * https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf\n \t */\n-\tconst unsigned int blackLevelHistIdx =\n-\t\tblackLevel * histogram.bins() / 256;\n-\tconst unsigned int histogramSize =\n-\t\thistogram.bins() - blackLevelHistIdx;\n-\tconst unsigned int yHistValsPerBin = histogramSize / kExposureBinsCount;\n+\tconst unsigned int yHistValsPerBin = histogram.bins() / kExposureBinsCount;\n \tconst unsigned int yHistValsPerBinMod =\n-\t\thistogramSize / (histogramSize % kExposureBinsCount + 1);\n+\t\thistogram.bins() / (histogram.bins() % kExposureBinsCount + 1);\n \tint exposureBins[kExposureBinsCount] = {};\n \tunsigned int denom = 0;\n \tunsigned int num = 0;\n@@ -86,9 +83,9 @@ std::optional<float> calculateMSV(const Histogram &histogram, uint8_t blackLevel\n \tif (yHistValsPerBin == 0)\n \t\treturn {};\n \n-\tfor (unsigned int i = 0; i < histogramSize; i++) {\n+\tfor (unsigned int i = 0; i < histogram.bins(); i++) {\n \t\tunsigned int idx = (i - (i / yHistValsPerBinMod)) / yHistValsPerBin;\n-\t\texposureBins[idx] += histogram[blackLevelHistIdx + i];\n+\t\texposureBins[idx] += histogram[i];\n \t}\n \n \tfor (unsigned int i = 0; i < kExposureBinsCount; i++) {\n@@ -193,7 +190,14 @@ void Agc::process(IPAContext &context,\n \t\treturn;\n \t}\n \n-\tauto exposureMSV = calculateMSV({ stats->yHistogram }, context.activeState.blc.level);\n+\tauto histogram = stats->yHistogram;\n+\tconst unsigned int blackLevelHistIdx =\n+\t\tcontext.activeState.blc.level * std::size(histogram) / 256;\n+\n+\tfor (unsigned int i = 1; i < blackLevelHistIdx; i++)\n+\t\thistogram[0] += std::exchange(histogram[i], 0);\n+\n+\tauto exposureMSV = calculateMSV({ histogram });\n \tif (!exposureMSV) {\n \t\tLOG(IPASoftExposure, Debug)\n \t\t\t<< \"Not adjusting exposure due to insufficient histogram data\";\n","prefixes":["RFC","v2","36/43"]}