From patchwork Fri Aug 30 07:25:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 21071 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 4B856C32D5 for ; Fri, 30 Aug 2024 07:26:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AF8B0634EB; Fri, 30 Aug 2024 09:26:55 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Qzg0HYxD"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 59D0C6341E for ; Fri, 30 Aug 2024 09:26:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1725002810; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JTLOpHrUNalfC38eZPdCfc/vm6uc9RnUCdBkVqwy9H8=; b=Qzg0HYxD8AX6YF8ACsRr48qfKxSdiTjymV4s+HjM8bX65haJhT3Gf8gMDjqlhrAtxL2RDC u2Ej29IReEu/ycfJCfC2HIccMfyNHANZnOR81poJ/OIEXcq0bRjdJbErufRc+ZomPO16bY kYp5x05vms6cNK3iip2T100Dw5YVxhY= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-616-ZH8UeedSOt2ayfoET0nNdw-1; Fri, 30 Aug 2024 03:26:44 -0400 X-MC-Unique: ZH8UeedSOt2ayfoET0nNdw-1 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B350919560B1; Fri, 30 Aug 2024 07:26:43 +0000 (UTC) Received: from nuthatch.redhat.com (unknown [10.45.225.65]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5F62C19560A3; Fri, 30 Aug 2024 07:26:41 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Umang Jain , Laurent Pinchart , Daniel Scally Subject: [PATCH v5 15/18] libcamera: software_isp: Use floating point for color parameters Date: Fri, 30 Aug 2024 09:25:51 +0200 Message-ID: <20240830072554.180672-16-mzamazal@redhat.com> In-Reply-To: <20240830072554.180672-1-mzamazal@redhat.com> References: <20240830072554.180672-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com 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" It's more natural to represent color gains and black level as floating point numbers rather than using a particular pixel-related representation. double is used rather than float because it's a more common floating point type in libcamera algorithms. Otherwise there is no obvious reason to select one over the other here. The constructed color tables still use integer representation for efficiency. Signed-off-by: Milan Zamazal --- src/ipa/simple/algorithms/awb.cpp | 11 +++++------ src/ipa/simple/algorithms/blc.cpp | 8 ++++---- src/ipa/simple/algorithms/gamma.cpp | 2 +- src/ipa/simple/algorithms/lut.cpp | 13 ++++++++----- src/ipa/simple/ipa_context.h | 11 +++++------ 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp index 4b49996a..16a0fa61 100644 --- a/src/ipa/simple/algorithms/awb.cpp +++ b/src/ipa/simple/algorithms/awb.cpp @@ -24,7 +24,7 @@ int Awb::init(IPAContext &context, [[maybe_unused]] const YamlObject &tuningData) { auto &gains = context.activeState.gains; - gains.red = gains.green = gains.blue = 256; + gains.red = gains.green = gains.blue = 1.0; return 0; } @@ -36,7 +36,7 @@ void Awb::process(IPAContext &context, [[maybe_unused]] ControlList &metadata) { const SwIspStats::Histogram &histogram = stats->yHistogram; - const uint8_t blackLevel = context.activeState.black.level; + const double blackLevel = context.activeState.black.level; /* * Black level must be subtracted to get the correct AWB ratios, they @@ -53,12 +53,11 @@ void Awb::process(IPAContext &context, /* * Calculate red and blue gains for AWB. * Clamp max gain at 4.0, this also avoids 0 division. - * Gain: 128 = 0.5, 256 = 1.0, 512 = 2.0, etc. */ auto &gains = context.activeState.gains; - gains.red = sumR <= sumG / 4 ? 1024 : 256 * sumG / sumR; - gains.blue = sumB <= sumG / 4 ? 1024 : 256 * sumG / sumB; - /* Green gain is fixed to 256 */ + gains.red = sumR <= sumG / 4 ? 4.0 : static_cast(sumG) / sumR; + gains.blue = sumB <= sumG / 4 ? 4.0 : static_cast(sumG) / sumB; + /* Green gain is fixed to 1.0 */ LOG(IPASoftAwb, Debug) << "gain R/B " << gains.red << "/" << gains.blue; } diff --git a/src/ipa/simple/algorithms/blc.cpp b/src/ipa/simple/algorithms/blc.cpp index 3b73d830..ab7e7dd9 100644 --- a/src/ipa/simple/algorithms/blc.cpp +++ b/src/ipa/simple/algorithms/blc.cpp @@ -24,7 +24,7 @@ BlackLevel::BlackLevel() int BlackLevel::init(IPAContext &context, [[maybe_unused]] const YamlObject &tuningData) { - context.activeState.black.level = 255; + context.activeState.black.level = 1.0; return 0; } @@ -44,16 +44,16 @@ void BlackLevel::process(IPAContext &context, const unsigned int total = std::accumulate(begin(histogram), end(histogram), 0); const unsigned int pixelThreshold = ignoredPercentage_ * total; - const unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize; const unsigned int currentBlackIdx = - context.activeState.black.level / histogramRatio; + context.activeState.black.level * SwIspStats::kYHistogramSize; for (unsigned int i = 0, seen = 0; i < currentBlackIdx && i < SwIspStats::kYHistogramSize; i++) { seen += histogram[i]; if (seen >= pixelThreshold) { - context.activeState.black.level = i * histogramRatio; + context.activeState.black.level = + static_cast(i) / SwIspStats::kYHistogramSize; LOG(IPASoftBL, Debug) << "Auto-set black level: " << i << "/" << SwIspStats::kYHistogramSize diff --git a/src/ipa/simple/algorithms/gamma.cpp b/src/ipa/simple/algorithms/gamma.cpp index 0b8ec5ee..b03dff25 100644 --- a/src/ipa/simple/algorithms/gamma.cpp +++ b/src/ipa/simple/algorithms/gamma.cpp @@ -34,7 +34,7 @@ void Gamma::updateGammaTable(IPAContext &context) auto &gammaTable = context.activeState.gamma.gammaTable; auto blackLevel = context.activeState.black.level; const unsigned int blackIndex = - blackLevel * IPAActiveState::kGammaLookupSize / 256; + blackLevel * IPAActiveState::kGammaLookupSize; std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, 0); const float divisor = kGammaLookupSize - blackIndex - 1.0; for (unsigned int i = blackIndex; i < kGammaLookupSize; i++) diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 748f10aa..a0e67080 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -37,15 +37,18 @@ void Lut::prepare(IPAContext &context, auto &gains = context.activeState.gains; auto &gammaTable = context.activeState.gamma.gammaTable; for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { - constexpr unsigned int div = - static_cast(DebayerParams::kRGBLookupSize) * 256 / kGammaLookupSize; + constexpr double div = + static_cast(DebayerParams::kRGBLookupSize) / kGammaLookupSize; /* Apply gamma after gain! */ unsigned int idx; - idx = std::min({ i * gains.red / div, kGammaLookupSize - 1 }); + idx = std::min({ static_cast(i * gains.red / div), + kGammaLookupSize - 1 }); params->red[i] = gammaTable[idx]; - idx = std::min({ i * gains.green / div, kGammaLookupSize - 1 }); + idx = std::min({ static_cast(i * gains.green / div), + kGammaLookupSize - 1 }); params->green[i] = gammaTable[idx]; - idx = std::min({ i * gains.blue / div, kGammaLookupSize - 1 }); + idx = std::min({ static_cast(i * gains.blue / div), + kGammaLookupSize - 1 }); params->blue[i] = gammaTable[idx]; } } diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index f8b8834d..28a02475 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -8,7 +8,6 @@ #pragma once #include -#include #include @@ -22,17 +21,17 @@ struct IPASessionConfiguration { struct IPAActiveState { struct { - uint8_t level; + double level; } black; struct { - unsigned int red; - unsigned int green; - unsigned int blue; + double red; + double green; + double blue; } gains; static constexpr unsigned int kGammaLookupSize = 1024; struct { std::array gammaTable; - uint8_t blackLevel; + double blackLevel; } gamma; };