From patchwork Tue Jun 24 17:12:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 23647 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 E8CE8C3237 for ; Tue, 24 Jun 2025 17:12:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5DC2B68DEC; Tue, 24 Jun 2025 19:12:33 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="keClc7JD"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B6E8768DE6 for ; Tue, 24 Jun 2025 19:12:27 +0200 (CEST) Received: from Monstersaurus.hippo-penny.ts.net (cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 347D9134A; Tue, 24 Jun 2025 19:12:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1750785130; bh=6g3S9fjkjcq7fIKKMWKaZbPmvsHirjBCKluUsFM+Abw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=keClc7JDLIowTwqzCbvkCVEiG5Geo0zNRBdU/KJasWztWKE2hj9CtwRPKZjqlvWzk BP+1J1CPL7cTLCvc5R9KbNw1GW3lkd61lCf+Cm9OQgg5ZSZ/vGdbrDF6rsujytUaXC PnR1qmUILzdtN3kRkIImzZBBOJC88BId8sr4TiGY= From: Kieran Bingham To: libcamera devel Cc: "van Veen, Stephan" , Kieran Bingham Subject: [PATCH 3/3] ipa: rkisp1: cproc: Provide a Hue control Date: Tue, 24 Jun 2025 18:12:23 +0100 Message-ID: <20250624171223.2181226-4-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250624171223.2181226-1-kieran.bingham@ideasonboard.com> References: <20250624171223.2181226-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 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" From: "van Veen, Stephan" The RKISP1 supports a configurable Hue as part of the colour processing unit (cproc). This is implemented as a phase shift of the chrominance values between -90 and +87.188 degrees. Implement the new control converting to the hardware scale accordingly and report the applied control in the completed request metadata. Signed-off-by: van Veen, Stephan Signed-off-by: Kieran Bingham --- src/ipa/rkisp1/algorithms/cproc.cpp | 31 ++++++++++++++++++++++------- src/ipa/rkisp1/ipa_context.h | 2 ++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/cproc.cpp b/src/ipa/rkisp1/algorithms/cproc.cpp index 9213ee49b374..217c1ee2b039 100644 --- a/src/ipa/rkisp1/algorithms/cproc.cpp +++ b/src/ipa/rkisp1/algorithms/cproc.cpp @@ -27,8 +27,8 @@ namespace ipa::rkisp1::algorithms { * \brief RkISP1 Color Processing control * * The ColorProcessing algorithm is responsible for applying brightness, - * contrast and saturation corrections. The values are directly provided - * through requests by the corresponding controls. + * contrast, hue and saturation corrections. The values are directly + * provided through requests by the corresponding controls. */ LOG_DEFINE_CATEGORY(RkISP1CProc) @@ -37,14 +37,15 @@ namespace { constexpr float kDefaultBrightness = 0.0f; constexpr float kDefaultContrast = 1.0f; +constexpr float kDefaultHue = 0.0f; constexpr float kDefaultSaturation = 1.0f; -int convertBrightness(const float v) +int convertBrightnessOrHue(const float v) { return std::clamp(std::lround(v * 128), -128, 127); } -float convertBrightness(const int v) +float convertBrightnessOrHue(const int v) { return static_cast(v) / 128.0f; } @@ -71,6 +72,7 @@ int ColorProcessing::init(IPAContext &context, cmap[&controls::Brightness] = ControlInfo(-1.0f, 0.993f, kDefaultBrightness); cmap[&controls::Contrast] = ControlInfo(0.0f, 1.993f, kDefaultContrast); + cmap[&controls::Hue] = ControlInfo(-1.0f, 0.993f, kDefaultHue); cmap[&controls::Saturation] = ControlInfo(0.0f, 1.993f, kDefaultSaturation); return 0; @@ -84,8 +86,9 @@ int ColorProcessing::configure(IPAContext &context, { auto &cproc = context.activeState.cproc; - cproc.brightness = convertBrightness(kDefaultBrightness); + cproc.brightness = convertBrightnessOrHue(kDefaultBrightness); cproc.contrast = convertContrastOrSaturation(kDefaultContrast); + cproc.hue = convertBrightnessOrHue(kDefaultHue); cproc.saturation = convertContrastOrSaturation(kDefaultSaturation); return 0; @@ -107,7 +110,7 @@ void ColorProcessing::queueRequest(IPAContext &context, const auto &brightness = controls.get(controls::Brightness); if (brightness) { - int value = convertBrightness(*brightness); + int value = convertBrightnessOrHue(*brightness); if (cproc.brightness != value) { cproc.brightness = value; update = true; @@ -127,6 +130,17 @@ void ColorProcessing::queueRequest(IPAContext &context, LOG(RkISP1CProc, Debug) << "Set contrast to " << value; } + const auto &hue = controls.get(controls::Hue); + if (hue) { + int value = convertBrightnessOrHue(*hue); + if (cproc.hue != value) { + cproc.hue = value; + update = true; + } + + LOG(RkISP1CProc, Debug) << "Set hue to " << value; + } + const auto saturation = controls.get(controls::Saturation); if (saturation) { int value = convertContrastOrSaturation(*saturation); @@ -140,6 +154,7 @@ void ColorProcessing::queueRequest(IPAContext &context, frameContext.cproc.brightness = cproc.brightness; frameContext.cproc.contrast = cproc.contrast; + frameContext.cproc.hue = cproc.hue; frameContext.cproc.saturation = cproc.saturation; frameContext.cproc.update = update; } @@ -160,6 +175,7 @@ void ColorProcessing::prepare([[maybe_unused]] IPAContext &context, config.setEnabled(true); config->brightness = frameContext.cproc.brightness; config->contrast = frameContext.cproc.contrast; + config->hue = frameContext.cproc.hue; config->sat = frameContext.cproc.saturation; } @@ -170,8 +186,9 @@ void ColorProcessing::process([[maybe_unused]] IPAContext &context, [[maybe_unus IPAFrameContext &frameContext, [[maybe_unused]] const rkisp1_stat_buffer *stats, ControlList &metadata) { - metadata.set(controls::Brightness, convertBrightness(frameContext.cproc.brightness)); + metadata.set(controls::Brightness, convertBrightnessOrHue(frameContext.cproc.brightness)); metadata.set(controls::Contrast, convertContrastOrSaturation(frameContext.cproc.contrast)); + metadata.set(controls::Hue, convertBrightnessOrHue(frameContext.cproc.hue)); metadata.set(controls::Saturation, convertContrastOrSaturation(frameContext.cproc.saturation)); } diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index f0d504215d34..54234ea3acc4 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -108,6 +108,7 @@ struct IPAActiveState { struct { int8_t brightness; uint8_t contrast; + int8_t hue; uint8_t saturation; } cproc; @@ -152,6 +153,7 @@ struct IPAFrameContext : public FrameContext { struct { int8_t brightness; uint8_t contrast; + int8_t hue; uint8_t saturation; bool update; } cproc;