From patchwork Wed Oct 20 11:08:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 14194 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 AA324BDB1C for ; Wed, 20 Oct 2021 11:08:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 686A868F63; Wed, 20 Oct 2021 13:08:31 +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="EW4ecQoI"; dkim-atps=neutral Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E94976023A for ; Wed, 20 Oct 2021 13:08:28 +0200 (CEST) Received: by mail-wm1-x329.google.com with SMTP id o24-20020a05600c511800b0030d9da600aeso9268434wms.4 for ; Wed, 20 Oct 2021 04:08:28 -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=3wsXnte+0apF9covIJAO5fYmIQ9gPUg+RchAtukBl9Y=; b=EW4ecQoIwArS+wV478/XwBmGUrr4At/oyXgVkfEfaPoAB8MG4kz9Zidi8JCULftKZl K2aSY5Frfo2p5YoJe22CJYDdddISKKe9LJ/kUapa8REPg56C/CEcH5/jlLTb8gPe0OCf vwKjoWybwpxBHfWn48OM8b0sTU6v6I8OhM6KtC3ssd6MQJLzKP7UFxSXD+2TElw8c+Rr EvFt0eiwHiidJphJiY4d7/R0lDzY7QCNYEWKTcHFkto+fv7nDkKNlsNIpb3o20MCrDXy oa8erEyn9AFh56efr/zOt4sIoCT2vCO++h5+49Atc1ykjUkALgbdgAdIQZNXwPDSeHTf FayA== 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=3wsXnte+0apF9covIJAO5fYmIQ9gPUg+RchAtukBl9Y=; b=jPC60ZOjU9J2HxF3KsbKaLvXRBVdIWmx3DWLbpUVWw8JmIA/jGyZke1v4q35wbvWgp axg+sFyiY8lFGa26KERTHu8jV2kP4xUj2RidgVAT92pmzAXptwiiDUCkNdvz7duWPvQl o8a+PIl6xuoaVovzPZ4Vyde1y9gP8qr91pYiSUTfb8Gv9jFGciIZ1MiyYJGIEvCWyGaP yvB6I2JSqJfUci3ESmn4o1I6oM4gm2fo4vSEnT4gOtt8X21dl/E9suREZvfu9KmWLwyd dBWfNfS+07eRJyLcfXX/b2lEP62sM6CmxnzxMI6ysXJkcBLFTwCUA638hLZc3HKpSnsf g9kg== X-Gm-Message-State: AOAM533ZaMi29TeVXXTEXo9ZX7hgKTJaMAZl/ykn3WQnZzT7FAyWYUS4 OXF7EMFGmctUHqO8a0TImpKBIDBnUEU/Tw== X-Google-Smtp-Source: ABdhPJxap4UavBh0CSB08n4Npxqh1Slpf4sQSlDWEVIJprpbAI8sIRlbhFPCVDORwvAtLEMJ03oO/Q== X-Received: by 2002:adf:a556:: with SMTP id j22mr50336297wrb.431.1634728108216; Wed, 20 Oct 2021 04:08:28 -0700 (PDT) Received: from pi4-davidp.pitowers.org ([2a00:1098:3142:14:1ce1:9965:4328:89c4]) by smtp.gmail.com with ESMTPSA id f20sm1929654wmq.38.2021.10.20.04.08.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Oct 2021 04:08:27 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Wed, 20 Oct 2021 12:08:19 +0100 Message-Id: <20211020110825.12902-2-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20211020110825.12902-1-david.plowman@raspberrypi.com> References: <20211020110825.12902-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 1/7] 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 color space by defining its color primaries, YCbCr encoding, the transfer (gamma) function it uses, and whether the output is full or limited range. Signed-off-by: David Plowman Reviewed-by: Naushir Patuck --- include/libcamera/color_space.h | 88 +++++++++++ include/libcamera/meson.build | 1 + src/libcamera/color_space.cpp | 256 ++++++++++++++++++++++++++++++++ src/libcamera/meson.build | 1 + 4 files changed, 346 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..2af9da31 --- /dev/null +++ b/include/libcamera/color_space.h @@ -0,0 +1,88 @@ +/* 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 Primaries : int { + Undefined, + Raw, + Smpte170m, + Rec709, + Rec2020, + }; + + enum class YcbcrEncoding : int { + Undefined, + Rec601, + Rec709, + Rec2020, + }; + + enum class TransferFunction : int { + Undefined, + Linear, + Srgb, + Rec709, + }; + + enum class Range : int { + Undefined, + Full, + Limited, + }; + + constexpr ColorSpace() + : ColorSpace(Primaries::Undefined, YcbcrEncoding::Undefined, TransferFunction::Undefined, Range::Undefined) + { + } + + constexpr ColorSpace(Primaries p, YcbcrEncoding e, TransferFunction t, Range r) + : primaries(p), ycbcrEncoding(e), transferFunction(t), range(r) + { + } + + static const ColorSpace Undefined; + static const ColorSpace Raw; + static const ColorSpace Jpeg; + static const ColorSpace Smpte170m; + static const ColorSpace Rec709; + static const ColorSpace Rec2020; + + Primaries primaries; + YcbcrEncoding ycbcrEncoding; + TransferFunction transferFunction; + Range range; + + bool isFullyDefined() const; + + const std::string toString() const; +}; + +constexpr ColorSpace ColorSpace::Undefined = { Primaries::Undefined, YcbcrEncoding::Undefined, TransferFunction::Undefined, Range::Undefined }; +constexpr ColorSpace ColorSpace::Raw = { Primaries::Raw, YcbcrEncoding::Rec601, TransferFunction::Linear, Range::Full }; +constexpr ColorSpace ColorSpace::Jpeg = { Primaries::Rec709, YcbcrEncoding::Rec601, TransferFunction::Srgb, Range::Full }; +constexpr ColorSpace ColorSpace::Smpte170m = { Primaries::Smpte170m, YcbcrEncoding::Rec601, TransferFunction::Rec709, Range::Limited }; +constexpr ColorSpace ColorSpace::Rec709 = { Primaries::Rec709, YcbcrEncoding::Rec709, TransferFunction::Rec709, Range::Limited }; +constexpr ColorSpace ColorSpace::Rec2020 = { Primaries::Rec2020, YcbcrEncoding::Rec2020, 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 7155ff20..131e1740 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -5,6 +5,7 @@ libcamera_include_dir = 'libcamera' / 'libcamera' 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..aec4107f --- /dev/null +++ b/src/libcamera/color_space.cpp @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Raspberry Pi (Trading) Limited + * + * color_space.cpp - color spaces. + */ + +#include + +#include +#include +#include + +/** + * \file color_space.h + * \brief Class and enums to represent color spaces + */ + +namespace libcamera { + +/** + * \class ColorSpace + * \brief Class to describe a color space + * + * The ColorSpace class defines the color primaries, the Y'CbCr encoding, + * 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 "JPEG" or "REC709". Applications must not request color + * spaces with undefined fields, but the "Undefined" value may be + * returned if the camera drivers decide to use a color space that is + * not recognised by the ColorSpace class. + * + * For more information on the specific color spaces described here, please + * see: + * + * sRGB and JPEG +>* SMPTE 170M + * Rec.709 + * Rec.2020 + */ + +/** + * \enum ColorSpace::Primaries + * \brief The color primaries for this color space + * + * \var ColorSpace::Primaries::Undefined + * \brief The color primaries are undefined + * \var ColorSpace::Primaries::Raw + * \brief These are raw colors directly from a sensor + * \var ColorSpace::Primaries::Smpte170m + * \brief SMPTE 170M color primaries + * \var ColorSpace::Primaries::Rec709 + * \brief Rec.709 color primaries + * \var ColorSpace::Primaries::Rec2020 + * \brief Rec.2020 color primaries + */ + +/** + * \enum ColorSpace::YcbcrEncoding + * \brief The Y'CbCr encoding + * + * \var ColorSpace::YcbcrEncoding::Undefined + * \brief The Y'CbCr encoding is undefined + * \var ColorSpace::YcbcrEncoding::Rec601 + * \brief Rec.601 Y'CbCr encoding + * \var ColorSpace::YcbcrEncoding::Rec709 + * \brief Rec.709 Y'CbCr encoding + * \var ColorSpace::YcbcrEncoding::Rec2020 + * \brief Rec.2020 Y'CbCr encoding + */ + +/** + * \enum ColorSpace::TransferFunction + * \brief The transfer function used for this color space + * + * \var ColorSpace::TransferFunction::Undefined + * \brief The transfer function is not specified + * \var ColorSpace::TransferFunction::Linear + * \brief This color space uses a linear (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, being + * 16 to 235 for Y' and 16 to 240 for Cb and Cr + */ + +/** + * \fn ColorSpace::ColorSpace(Encoding e, TransferFunction t, Range r) + * \brief Construct a ColorSpace from explicit values + * \param[in] e The Y'CbCr encoding + * \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 Check if all the fields of the color space are defined + * \return Return true if all the fields of the color space are defined, + * otherwise false + */ +bool ColorSpace::isFullyDefined() const +{ + return primaries != Primaries::Undefined && + ycbcrEncoding != YcbcrEncoding::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 +{ + /* Print out a brief name only for standard color sapces. */ + + static const std::vector> colorSpaceNames = { + { ColorSpace::Undefined, "Undefined" }, + { ColorSpace::Raw, "Raw" }, + { ColorSpace::Jpeg, "Jpeg" }, + { ColorSpace::Smpte170m, "Smpte170m" }, + { ColorSpace::Rec709, "Rec709" }, + { ColorSpace::Rec2020, "Rec2020" }, + }; + auto it = std::find_if(colorSpaceNames.begin(), colorSpaceNames.end(), + [this](const auto &item) { + return *this == item.first; + }); + if (it != colorSpaceNames.end()) + return std::string(it->second); + + static const char *primariesNames[] = { + "Undefined", + "Raw", + "Smpte170m", + "Rec709", + "Rec2020", + }; + static const char *encodingNames[] = { + "Undefined", + "Rec601", + "Rec709", + "Rec2020", + }; + static const char *transferFunctionNames[] = { + "Undefined", + "Linear", + "Srgb", + "Rec709", + }; + static const char *rangeNames[] = { + "Undefined", + "Full", + "Limited", + }; + + std::stringstream ss; + ss << std::string(primariesNames[static_cast(primaries)]) << "/" + << std::string(encodingNames[static_cast(ycbcrEncoding)]) << "/" + << std::string(transferFunctionNames[static_cast(transferFunction)]) << "/" + << std::string(rangeNames[static_cast(range)]); + + return ss.str(); +} + +/** + * \var ColorSpace::primaries + * \brief The color primaries + */ + +/** + * \var ColorSpace::ycbcrEncoding + * \brief The Y'CbCr encoding + */ + +/** + * \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::Jpeg + * \brief A constant representing the JPEG color space used for + * encoding JPEG images (and regarded as being the same as the sRGB + * color space) + */ + +/** + * \var ColorSpace::Smpte170m + * \brief A constant representing the SMPTE170M color space + */ + +/** + * \var ColorSpace::Rec709 + * \brief A constant representing the Rec.709 color space + */ + +/** + * \var ColorSpace::Rec2020 + * \brief A constant representing the Rec.2020 color space + */ + +/** + * \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.primaries == rhs.primaries && + lhs.ycbcrEncoding == rhs.ycbcrEncoding && + 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 243dd3c1..8dc5d39d 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',