From patchwork Mon Sep 27 12:33:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 13951 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 32AACBDC71 for ; Mon, 27 Sep 2021 12:33:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EA85769197; Mon, 27 Sep 2021 14:33:35 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="fKGmSx2w"; dkim-atps=neutral Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E2B0E6918A for ; Mon, 27 Sep 2021 14:33:32 +0200 (CEST) Received: by mail-wr1-x42e.google.com with SMTP id v17so8250924wrv.9 for ; Mon, 27 Sep 2021 05:33:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=tmZBQE4orKD4XTYhvhaHMaOkQ+/79Rt9g3dMNGENyY0=; b=fKGmSx2wTs5HnfNGvUGfksD7LUrjfqFF7n13SX4FHIZP7N+uwQ39Kfr4MlUXPnA0cS 4//eUUgv4hHteuioVa+fjkkVbYbAfdhRm250kOnT/WTpTnB39V6ZuNlwFkVQh9+KvcBm od1guBgtRphBt6Gny/pZjZrUnvuEUyqFSAmA/RyihbDt4uzyYamD9yf3zE16e/ciB6ya eYdlWfGEIX8J/f1j7gSa2QwVUC7dfaLyCERUlL9b98JwHAFyAOeBmnbsiVktjU5tYI2t 6ECWMi+TddG3z4J627avV0tiLuWQGjBlEfAQprWsy+KwMOpf7aZ1P4wx+F6Ote7YkUHO v3fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=tmZBQE4orKD4XTYhvhaHMaOkQ+/79Rt9g3dMNGENyY0=; b=F3WJVjNT9M5wB0aQky6ntqiFtesBz6zetQhuqG3xBrjWhnj4ZOpbeq3S5eoa9hR7XA NaNMsNNeku4PIZoN6omRhc/Q0lJz3pv8asmCuMok7IyGkCj8subO4gCvxqbRJjDm5SGc u2fDQ/dM7hQNHkl/Lehsss3dm484GmxtqQ3dUztfx4ONtApfiQhG5pM40ZBt5fYxuHlS roysmy3FxWWsE/zYrgQXyNPvS3syHyf6PpyFZtbxZlcVUOLrBPHEHmCxEviyEqi5dmV1 eTH3M1aNh1IR7kUblGm8bSd4DiFqV56QaoM5r5903BE5aiWr/2/XE4UmfkHReE/z1wXw Nuzw== X-Gm-Message-State: AOAM531xGXflvtNvOH+uZCiyGm/jTKCSVlF3ZkPMEnkVi08xB0I6eltu IFYpdrGfp5V8tfo60X9Zz7G39Fgm3R/7HkXM X-Google-Smtp-Source: ABdhPJymWdPSaGlm+hqlWL30GVRgnDqYwovZlEBSjFU6/UcDrmbDbvt7wkknGXsFz7fG8gwtZbqcuQ== X-Received: by 2002:a05:6000:124f:: with SMTP id j15mr4444113wrx.366.1632746012205; Mon, 27 Sep 2021 05:33:32 -0700 (PDT) Received: from pi4-davidp.pitowers.org ([2a00:1098:3142:14:1ce1:9965:4328:89c4]) by smtp.gmail.com with ESMTPSA id r9sm16285110wru.2.2021.09.27.05.33.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Sep 2021 05:33:31 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Mon, 27 Sep 2021 13:33:25 +0100 Message-Id: <20210927123327.14554-2-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210927123327.14554-1-david.plowman@raspberrypi.com> References: <20210927123327.14554-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/3] libcamera: Add ColorSpace class 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" This class represents a colour space by defining its YCbCr encoding, the transfer (gamma) function is uses, and whether the output is full or limited range. Signed-off-by: David Plowman --- include/libcamera/color_space.h | 83 +++++++++++++ include/libcamera/meson.build | 1 + src/libcamera/color_space.cpp | 207 ++++++++++++++++++++++++++++++++ src/libcamera/meson.build | 1 + 4 files changed, 292 insertions(+) create mode 100644 include/libcamera/color_space.h create mode 100644 src/libcamera/color_space.cpp diff --git a/include/libcamera/color_space.h b/include/libcamera/color_space.h new file mode 100644 index 00000000..9cd10503 --- /dev/null +++ b/include/libcamera/color_space.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Raspberry Pi (Trading) Limited + * + * color_space.h - color space definitions + */ + +#ifndef __LIBCAMERA_COLOR_SPACE_H__ +#define __LIBCAMERA_COLOR_SPACE_H__ + +#include + +namespace libcamera { + +class ColorSpace +{ +public: + enum class Encoding : int { + UNDEFINED, + RAW, + REC601, + REC709, + REC2020, + VIDEO, + }; + + enum class TransferFunction : int { + UNDEFINED, + IDENTITY, + SRGB, + REC709, + }; + + enum class Range : int { + UNDEFINED, + FULL, + LIMITED, + }; + + constexpr ColorSpace(Encoding e, TransferFunction t, Range r) + : encoding(e), transferFunction(t), range(r) + { + } + + constexpr ColorSpace() + : ColorSpace(Encoding::UNDEFINED, TransferFunction::UNDEFINED, Range::UNDEFINED) + { + } + + static const ColorSpace UNDEFINED; + static const ColorSpace RAW; + static const ColorSpace JFIF; + static const ColorSpace SMPTE170M; + static const ColorSpace REC709; + static const ColorSpace REC2020; + static const ColorSpace VIDEO; + + Encoding encoding; + TransferFunction transferFunction; + Range range; + + bool isFullyDefined() const; + + const std::string toString() const; +}; + +constexpr ColorSpace ColorSpace::UNDEFINED = { Encoding::UNDEFINED, TransferFunction::UNDEFINED, Range::UNDEFINED }; +constexpr ColorSpace ColorSpace::RAW = { Encoding::RAW, TransferFunction::IDENTITY, Range::FULL }; +constexpr ColorSpace ColorSpace::JFIF = { Encoding::REC601, TransferFunction::SRGB, Range::FULL }; +constexpr ColorSpace ColorSpace::SMPTE170M = { Encoding::REC601, TransferFunction::REC709, Range::LIMITED }; +constexpr ColorSpace ColorSpace::REC709 = { Encoding::REC709, TransferFunction::REC709, Range::LIMITED }; +constexpr ColorSpace ColorSpace::REC2020 = { Encoding::REC2020, TransferFunction::REC709, Range::LIMITED }; +constexpr ColorSpace ColorSpace::VIDEO = { Encoding::VIDEO, TransferFunction::REC709, Range::LIMITED }; + +bool operator==(const ColorSpace &lhs, const ColorSpace &rhs); +static inline bool operator!=(const ColorSpace &lhs, const ColorSpace &rhs) +{ + return !(lhs == rhs); +} + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_COLOR_SPACE_H__ */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 5b25ef84..7a8a04e5 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -3,6 +3,7 @@ libcamera_public_headers = files([ 'camera.h', 'camera_manager.h', + 'color_space.h', 'compiler.h', 'controls.h', 'file_descriptor.h', diff --git a/src/libcamera/color_space.cpp b/src/libcamera/color_space.cpp new file mode 100644 index 00000000..d1ccb4cc --- /dev/null +++ b/src/libcamera/color_space.cpp @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Raspberry Pi (Trading) Limited + * + * color_space.cpp - color spaces. + */ + +#include + +#include + +/** + * \file color_space.h + * \brief Class and enums to represent colour spaces. + */ + +namespace libcamera { + +/** + * \class ColorSpace + * \brief Class to describe a color space. + * + * The color space class defines the encodings of the color primaries, the + * transfer function associated with the color space, and the range (sometimes + * also referred to as the quantisation) of the color space. + * + * Certain combinations of these fields form well-known standard color spaces, + * such as "JFIF" or "REC709", though there is flexibility to leave some or all + * of them undefined too. + */ + +/** + * \enum ColorSpace::Encoding + * \brief The encoding used for the color primaries. + * + * \var ColorSpace::Encoding::UNDEFINED + * \brief The encoding for the colour primaries is not specified. + * \var ColorSpace::Encoding::RAW + * \brief These are raw colours from the sensor. + * \var ColorSpace::Encoding::REC601 + * \brief REC601 colour primaries. + * \var ColorSpace::Encoding::REC709 + * \brief Rec709 colour primaries. + * \var ColorSpace::Encoding::REC2020 + * \brief REC2020 colour primaries. + * \var ColorSpace::Encoding::VIDEO + * \brief A place-holder for video streams which will be resolved to one + * of REC601, REC709 or REC2020 once the video resolution is known. + */ + +/** + * \enum ColorSpace::TransferFunction + * \brief The transfer function used for this colour space. + * + * \var ColorSpace::TransferFunction::UNDEFINED + * \brief The transfer function is not specified. + * \var ColorSpace::TransferFunction::IDENTITY + * \brief This color space uses an identity transfer function. + * \var ColorSpace::TransferFunction::SRGB + * \brief sRGB transfer function. + * \var ColorSpace::TransferFunction::REC709 + * \brief Rec709 transfer function. + */ + +/** + * \enum ColorSpace::Range + * \brief The range (sometimes "quantisation") for this color space. + * + * \var ColorSpace::Range::UNDEFINED + * \brief The range is not specified. + * \var ColorSpace::Range::FULL + * \brief This color space uses full range pixel values. + * \var ColorSpace::Range::LIMITED + * \brief This color space uses limited range pixel values. + */ + +/** + * \fn ColorSpace::ColorSpace(Encoding e, TransferFunction t, Range r) + * \brief Construct a ColorSpace from explicit values + * \param[in] e The encoding for the color primaries + * \param[in] t The transfer function for the color space + * \param[in] r The range of the pixel values in this color space + */ + +/** + * \fn ColorSpace::ColorSpace() + * \brief Construct a color space with undefined encoding, transfer function + * and range + */ + +/** + * \brief Return true if all the fields of the color space are defined, otherwise false. + */ +bool ColorSpace::isFullyDefined() const +{ + return encoding != Encoding::UNDEFINED && + transferFunction != TransferFunction::UNDEFINED && + range != Range::UNDEFINED; +} + +/** + * \brief Assemble and return a readable string representation of the + * ColorSpace + * \return A string describing the ColorSpace + */ +const std::string ColorSpace::toString() const +{ + static const char *encodings[] = { + "UNDEFINED", + "RAW", + "REC601", + "REC709", + "REC2020", + }; + static const char *transferFunctions[] = { + "UNDEFINED", + "IDENTITY", + "SRGB", + "REC709", + }; + static const char *ranges[] = { + "UNDEFINED", + "FULL", + "LIMITED", + }; + + std::stringstream ss; + ss << std::string(encodings[static_cast(encoding)]) << "+" + << std::string(transferFunctions[static_cast(transferFunction)]) << "+" + << std::string(ranges[static_cast(range)]); + + return ss.str(); +} + +/** + * \var ColorSpace::encoding + * \brief The encoding of the color primaries + */ + +/** + * \var ColorSpace::transferFunction + * \brief The transfer function for this color space. + */ + +/** + * \var ColorSpace::range + * \brief The pixel range used by this color space. + */ + +/** + * \var ColorSpace::UNDEFINED + * \brief A constant representing a fully undefined color space. + */ + +/** + * \var ColorSpace::RAW + * \brief A constant representing a raw color space (from a sensor). + */ + +/** + * \var ColorSpace::JFIF + * \brief A constant representing the JFIF color space usually used for + * encoding JPEG images. + */ + +/** + * \var ColorSpace::SMPTE170M + * \brief A constant representing the SMPTE170M color space (sometimes also + * referred to as "full range BT601"). + */ + +/** + * \var ColorSpace::REC709 + * \brief A constant representing the REC709 color space. + */ + +/** + * \var ColorSpace::REC2020 + * \brief A constant representing the REC2020 color space. + */ + +/** + * \var ColorSpace::VIDEO + * \brief A constant that video streams can use to indicate the "default" + * color space for a video of this resolution, once that is is known. For + * exmample, SD streams would interpret this as SMPTE170M, HD streams as + * REC709 and ultra HD as REC2020. + */ + +/** + * \brief Compare color spaces for equality + * \return True if the two color spaces are identical, false otherwise + */ +bool operator==(const ColorSpace &lhs, const ColorSpace &rhs) +{ + return lhs.encoding == rhs.encoding && + lhs.transferFunction == rhs.transferFunction && + lhs.range == rhs.range; +} + +/** + * \fn bool operator!=(const ColorSpace &lhs, const ColorSpace &rhs) + * \brief Compare color spaces for inequality + * \return True if the two color spaces are not identical, false otherwise + */ + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index bf82d38b..88dfbf24 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -8,6 +8,7 @@ libcamera_sources = files([ 'camera_manager.cpp', 'camera_sensor.cpp', 'camera_sensor_properties.cpp', + 'color_space.cpp', 'controls.cpp', 'control_serializer.cpp', 'control_validator.cpp',