From patchwork Thu Oct 31 16:07:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 21791 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 CA85EC3292 for ; Thu, 31 Oct 2024 16:08:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1819E653AD; Thu, 31 Oct 2024 17:08:20 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="FWXXuDzH"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A0DBB6039B for ; Thu, 31 Oct 2024 17:08:12 +0100 (CET) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7465BE0D; Thu, 31 Oct 2024 17:08:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1730390888; bh=/FxZ1eFssi/jct/GeklGlD2CrAQhC5ZephJEYXf+Uuc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FWXXuDzHvlnbozP5Yhti0zULpVYl7T1pDgIQIqp1Df6DOK5UUdwLnT9l9hqMcfxr0 oMozwc7bWDu0Ba+wa3s04A8OnJRsBoPFMpvc8Ey1w0OBX86tpTISmBCvbpFoLmI3R5 DF4jyIFfy4k1exEfxvmPWhiwsZ4WPp2n3V+Ry3Yw= From: Daniel Scally To: libcamera-devel@lists.libcamera.org Cc: mike.rudenko@gmail.com, Daniel Scally Subject: [PATCH 1/6] ipa: libipa: Add miscellaneous helpers Date: Thu, 31 Oct 2024 16:07:36 +0000 Message-Id: <20241031160741.253855-2-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241031160741.253855-1-dan.scally@ideasonboard.com> References: <20241031160741.253855-1-dan.scally@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" We start to have functions that are effectively identical crop up across the IPA modules. Add a file allowing those to be centralised within libipa so that a single implementation can be used in all of the IPAs. Signed-off-by: Daniel Scally --- src/ipa/libipa/helpers.cpp | 103 +++++++++++++++++++++++++++++++++++++ src/ipa/libipa/helpers.h | 23 +++++++++ src/ipa/libipa/meson.build | 2 + 3 files changed, 128 insertions(+) create mode 100644 src/ipa/libipa/helpers.cpp create mode 100644 src/ipa/libipa/helpers.h diff --git a/src/ipa/libipa/helpers.cpp b/src/ipa/libipa/helpers.cpp new file mode 100644 index 00000000..cc0cd586 --- /dev/null +++ b/src/ipa/libipa/helpers.cpp @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2024, Ideas on Board Oy + * + * libipa miscellaneous helpers + */ + +#include "helpers.h" + +#include +#include + +namespace libcamera { + +namespace ipa { + +/** + * \file helpers.h + * \brief Functions to reduce code duplication between IPA modules + */ + +/** + * \brief Estimate luminance from RGB values following ITU-R BT.601 + * \param[in] r The red value + * \param[in] g The green value + * \param[in] b The blue valye + * \return The estimated luminance value + * + * This function estimates a luminance value from a triplet of Red, Green and + * Blue values, following the formula defined by ITU-R Recommendation BT.601-7 + * which can be found at https://www.itu.int/rec/R-REC-BT.601 + */ +unsigned int rec601LuminanceFromRGB(unsigned int r, unsigned int g, unsigned int b) +{ + return (r * .299) + (g * .587) + (b * .114); +} + +/** + * \brief Estimate correlated colour temperature from RGB color space input + * \param[in] red The input red value + * \param[in] green The input green value + * \param[in] blue The input blue value + * \return The estimated color temperature + * + * This function estimates the correlated color temperature RGB color space + * input. In physics and color science, the Planckian locus or black body locus + * is the path or locus that the color of an incandescent black body would take + * in a particular chromaticity space as the blackbody temperature changes. + * + * If a narrow range of color temperatures is considered (those encapsulating + * daylight being the most practical case) one can approximate the Planckian + * locus in order to calculate the CCT in terms of chromaticity coordinates. + * + * More detailed information can be found in: + * https://en.wikipedia.org/wiki/Color_temperature#Approximation + */ +uint32_t estimateCCT(double red, double green, double blue) +{ + /* Convert the RGB values to CIE tristimulus values (XYZ) */ + double X = (-0.14282) * (red) + (1.54924) * (green) + (-0.95641) * (blue); + double Y = (-0.32466) * (red) + (1.57837) * (green) + (-0.73191) * (blue); + double Z = (-0.68202) * (red) + (0.77073) * (green) + (0.56332) * (blue); + + /* Calculate the normalized chromaticity values */ + double x = X / (X + Y + Z); + double y = Y / (X + Y + Z); + + /* Calculate CCT */ + double n = (x - 0.3320) / (0.1858 - y); + return 449 * n * n * n + 3525 * n * n + 6823.3 * n + 5520.33; +} + +/** + * \brief Convert double to Q(m.n) format + * \param[in] value The value to convert + * \param[in] m The number of bits used to represent the integer part + * \param[in] n The number of bits used to represent the fraction part + * + * This function converts a double into an unsigned Q format, clamping at the + * largest possible value given m and n. + */ +unsigned int toQFormat(double value, unsigned int m, unsigned int n) +{ + double maxVal = (std::pow(2, m + n) - 1) / std::pow(2, n); + + return std::clamp(value, 0.0, maxVal) * std::pow(2, n); +} + +/** + * \brief Convert Q(m.n) formatted number to double + * \param[in] value The value to convert + * \param[in] n The number of bits used to represent the fraction part + * + * This function converts an unsigned Q formatted value into a double. + */ +double fromQFormat(unsigned int value, unsigned int n) +{ + return value / std::pow(2, n); +} + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/helpers.h b/src/ipa/libipa/helpers.h new file mode 100644 index 00000000..361b63bd --- /dev/null +++ b/src/ipa/libipa/helpers.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2024, Ideas on Board Oy + * + * libipa miscellaneous helpers + */ + +#pragma once + +#include + +namespace libcamera { + +namespace ipa { + +unsigned int rec601LuminanceFromRGB(unsigned int r, unsigned int g, unsigned int b); +uint32_t estimateCCT(double red, double green, double blue); +unsigned int toQFormat(double value, unsigned int m, unsigned int n); +double fromQFormat(unsigned int value, unsigned int n); + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build index e78cbcd6..ca4f3e28 100644 --- a/src/ipa/libipa/meson.build +++ b/src/ipa/libipa/meson.build @@ -6,6 +6,7 @@ libipa_headers = files([ 'camera_sensor_helper.h', 'exposure_mode_helper.h', 'fc_queue.h', + 'helpers.h', 'histogram.h', 'interpolator.h', 'lsc_polynomial.h', @@ -21,6 +22,7 @@ libipa_sources = files([ 'camera_sensor_helper.cpp', 'exposure_mode_helper.cpp', 'fc_queue.cpp', + 'helpers.cpp', 'histogram.cpp', 'interpolator.cpp', 'lsc_polynomial.cpp',