mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-17 17:35:06 +03:00
libcamera: Add ColorSpace class
This class represents a color space by defining its color primaries, the transfer (gamma) function it uses, the YCbCr encoding and whether the output is full or limited range. Signed-off-by: David Plowman <david.plowman@raspberrypi.com> Reviewed-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
015fa7f718
commit
ddb5e9d37e
4 changed files with 389 additions and 0 deletions
70
include/libcamera/color_space.h
Normal file
70
include/libcamera/color_space.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Copyright (C) 2021, Raspberry Pi (Trading) Limited
|
||||
*
|
||||
* color_space.h - color space definitions
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace libcamera {
|
||||
|
||||
class ColorSpace
|
||||
{
|
||||
public:
|
||||
enum class Primaries {
|
||||
Raw,
|
||||
Smpte170m,
|
||||
Rec709,
|
||||
Rec2020,
|
||||
};
|
||||
|
||||
enum class TransferFunction {
|
||||
Linear,
|
||||
Srgb,
|
||||
Rec709,
|
||||
};
|
||||
|
||||
enum class YcbcrEncoding {
|
||||
None,
|
||||
Rec601,
|
||||
Rec709,
|
||||
Rec2020,
|
||||
};
|
||||
|
||||
enum class Range {
|
||||
Full,
|
||||
Limited,
|
||||
};
|
||||
|
||||
constexpr ColorSpace(Primaries p, TransferFunction t, YcbcrEncoding e, Range r)
|
||||
: primaries(p), transferFunction(t), ycbcrEncoding(e), range(r)
|
||||
{
|
||||
}
|
||||
|
||||
static const ColorSpace Raw;
|
||||
static const ColorSpace Jpeg;
|
||||
static const ColorSpace Srgb;
|
||||
static const ColorSpace Smpte170m;
|
||||
static const ColorSpace Rec709;
|
||||
static const ColorSpace Rec2020;
|
||||
|
||||
Primaries primaries;
|
||||
TransferFunction transferFunction;
|
||||
YcbcrEncoding ycbcrEncoding;
|
||||
Range range;
|
||||
|
||||
std::string toString() const;
|
||||
static std::string toString(const std::optional<ColorSpace> &colorSpace);
|
||||
};
|
||||
|
||||
bool operator==(const ColorSpace &lhs, const ColorSpace &rhs);
|
||||
static inline bool operator!=(const ColorSpace &lhs, const ColorSpace &rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
} /* namespace libcamera */
|
|
@ -5,6 +5,7 @@ libcamera_include_dir = 'libcamera' / 'libcamera'
|
|||
libcamera_public_headers = files([
|
||||
'camera.h',
|
||||
'camera_manager.h',
|
||||
'color_space.h',
|
||||
'controls.h',
|
||||
'fence.h',
|
||||
'framebuffer.h',
|
||||
|
|
317
src/libcamera/color_space.cpp
Normal file
317
src/libcamera/color_space.cpp
Normal file
|
@ -0,0 +1,317 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Copyright (C) 2021, Raspberry Pi (Trading) Limited
|
||||
*
|
||||
* color_space.cpp - color spaces.
|
||||
*/
|
||||
|
||||
#include <libcamera/color_space.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* \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 transfer function,
|
||||
* the Y'CbCr encoding 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".
|
||||
*
|
||||
* In the strictest sense a "color space" formally only refers to the
|
||||
* color primaries and white point. Here, however, the ColorSpace class
|
||||
* adopts the common broader usage that includes the transfer function,
|
||||
* Y'CbCr encoding method and quantisation.
|
||||
*
|
||||
* For more information on the specific color spaces described here, please
|
||||
* see:
|
||||
*
|
||||
* - <a href="https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/colorspaces-details.html#col-srgb">sRGB</a>
|
||||
* - <a href="https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/colorspaces-details.html#col-jpeg">JPEG</a>
|
||||
* - <a href="https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/colorspaces-details.html#col-smpte-170m">SMPTE 170M</a>
|
||||
* - <a href="https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/colorspaces-details.html#col-rec709">Rec.709</a>
|
||||
* - <a href="https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/colorspaces-details.html#col-bt2020">Rec.2020</a>
|
||||
*/
|
||||
|
||||
/**
|
||||
* \enum ColorSpace::Primaries
|
||||
* \brief The color primaries for this color space
|
||||
*
|
||||
* \var ColorSpace::Primaries::Raw
|
||||
* \brief These are raw colors directly from a sensor, the primaries are
|
||||
* unspecified
|
||||
*
|
||||
* \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::TransferFunction
|
||||
* \brief The transfer function used for this color space
|
||||
*
|
||||
* \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 Rec.709 transfer function
|
||||
*/
|
||||
|
||||
/**
|
||||
* \enum ColorSpace::YcbcrEncoding
|
||||
* \brief The Y'CbCr encoding
|
||||
*
|
||||
* \var ColorSpace::YcbcrEncoding::None
|
||||
* \brief There is no defined Y'CbCr encoding (used for non-YUV formats)
|
||||
*
|
||||
* \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::Range
|
||||
* \brief The range (sometimes "quantisation") for this color space
|
||||
*
|
||||
* \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 (8 bits per sample)
|
||||
* or 64 to 940 for Y' and 16 to 960 for Cb and Cr (10 bits)
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn ColorSpace::ColorSpace(Primaries p, TransferFunction t, Encoding e, Range r)
|
||||
* \brief Construct a ColorSpace from explicit values
|
||||
* \param[in] p The color primaries
|
||||
* \param[in] t The transfer function for the color space
|
||||
* \param[in] e The Y'CbCr encoding
|
||||
* \param[in] r The range of the pixel values in this color space
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Assemble and return a readable string representation of the
|
||||
* ColorSpace
|
||||
*
|
||||
* If the color space matches a standard ColorSpace (such as ColorSpace::Jpeg)
|
||||
* then the short name of the color space ("JPEG") is returned. Otherwise
|
||||
* the four constituent parts of the ColorSpace are assembled into a longer
|
||||
* string.
|
||||
*
|
||||
* \return A string describing the ColorSpace
|
||||
*/
|
||||
std::string ColorSpace::toString() const
|
||||
{
|
||||
/* Print out a brief name only for standard color spaces. */
|
||||
|
||||
static const std::array<std::pair<ColorSpace, const char *>, 6> colorSpaceNames = { {
|
||||
{ ColorSpace::Raw, "RAW" },
|
||||
{ ColorSpace::Jpeg, "JPEG" },
|
||||
{ ColorSpace::Srgb, "sRGB" },
|
||||
{ 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);
|
||||
|
||||
/* Assemble a name made of the constituent fields. */
|
||||
|
||||
static const std::map<Primaries, std::string> primariesNames = {
|
||||
{ Primaries::Raw, "RAW" },
|
||||
{ Primaries::Smpte170m, "SMPTE170M" },
|
||||
{ Primaries::Rec709, "Rec709" },
|
||||
{ Primaries::Rec2020, "Rec2020" },
|
||||
};
|
||||
static const std::map<TransferFunction, std::string> transferNames = {
|
||||
{ TransferFunction::Linear, "Linear" },
|
||||
{ TransferFunction::Srgb, "sRGB" },
|
||||
{ TransferFunction::Rec709, "Rec709" },
|
||||
};
|
||||
static const std::map<YcbcrEncoding, std::string> encodingNames = {
|
||||
{ YcbcrEncoding::None, "None" },
|
||||
{ YcbcrEncoding::Rec601, "Rec601" },
|
||||
{ YcbcrEncoding::Rec709, "Rec709" },
|
||||
{ YcbcrEncoding::Rec2020, "Rec2020" },
|
||||
};
|
||||
static const std::map<Range, std::string> rangeNames = {
|
||||
{ Range::Full, "Full" },
|
||||
{ Range::Limited, "Limited" },
|
||||
};
|
||||
|
||||
auto itPrimaries = primariesNames.find(primaries);
|
||||
std::string primariesName =
|
||||
itPrimaries == primariesNames.end() ? "Invalid" : itPrimaries->second;
|
||||
|
||||
auto itTransfer = transferNames.find(transferFunction);
|
||||
std::string transferName =
|
||||
itTransfer == transferNames.end() ? "Invalid" : itTransfer->second;
|
||||
|
||||
auto itEncoding = encodingNames.find(ycbcrEncoding);
|
||||
std::string encodingName =
|
||||
itEncoding == encodingNames.end() ? "Invalid" : itEncoding->second;
|
||||
|
||||
auto itRange = rangeNames.find(range);
|
||||
std::string rangeName =
|
||||
itRange == rangeNames.end() ? "Invalid" : itRange->second;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << primariesName << "/" << transferName << "/" << encodingName << "/" << rangeName;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Assemble and return a readable string representation of an
|
||||
* optional ColorSpace
|
||||
*
|
||||
* This is a convenience helper to easily obtain a string representation
|
||||
* for a ColorSpace in parts of the libcamera API where it is stored in a
|
||||
* std::optional<>. If the ColorSpace is set, this function returns
|
||||
* \a colorSpace.toString(), otherwise it returns "Unset".
|
||||
*
|
||||
* \return A string describing the optional ColorSpace
|
||||
*/
|
||||
std::string ColorSpace::toString(const std::optional<ColorSpace> &colorSpace)
|
||||
{
|
||||
if (!colorSpace)
|
||||
return "Unset";
|
||||
|
||||
return colorSpace->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* \var ColorSpace::primaries
|
||||
* \brief The color primaries of this color space
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var ColorSpace::transferFunction
|
||||
* \brief The transfer function used by this color space
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var ColorSpace::ycbcrEncoding
|
||||
* \brief The Y'CbCr encoding used by this color space
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var ColorSpace::range
|
||||
* \brief The pixel range used with by color space
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief A constant representing a raw color space (from a sensor)
|
||||
*/
|
||||
const ColorSpace ColorSpace::Raw = {
|
||||
Primaries::Raw,
|
||||
TransferFunction::Linear,
|
||||
YcbcrEncoding::None,
|
||||
Range::Full
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A constant representing the JPEG color space used for
|
||||
* encoding JPEG images
|
||||
*/
|
||||
const ColorSpace ColorSpace::Jpeg = {
|
||||
Primaries::Rec709,
|
||||
TransferFunction::Srgb,
|
||||
YcbcrEncoding::Rec601,
|
||||
Range::Full
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A constant representing the sRGB color space
|
||||
*
|
||||
* This is identical to the JPEG color space except that the Y'CbCr
|
||||
* range is limited rather than full.
|
||||
*/
|
||||
const ColorSpace ColorSpace::Srgb = {
|
||||
Primaries::Rec709,
|
||||
TransferFunction::Srgb,
|
||||
YcbcrEncoding::Rec601,
|
||||
Range::Limited
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A constant representing the SMPTE170M color space
|
||||
*/
|
||||
const ColorSpace ColorSpace::Smpte170m = {
|
||||
Primaries::Smpte170m,
|
||||
TransferFunction::Rec709,
|
||||
YcbcrEncoding::Rec601,
|
||||
Range::Limited
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A constant representing the Rec.709 color space
|
||||
*/
|
||||
const ColorSpace ColorSpace::Rec709 = {
|
||||
Primaries::Rec709,
|
||||
TransferFunction::Rec709,
|
||||
YcbcrEncoding::Rec709,
|
||||
Range::Limited
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A constant representing the Rec.2020 color space
|
||||
*/
|
||||
const ColorSpace ColorSpace::Rec2020 = {
|
||||
Primaries::Rec2020,
|
||||
TransferFunction::Rec709,
|
||||
YcbcrEncoding::Rec2020,
|
||||
Range::Limited
|
||||
};
|
||||
|
||||
/**
|
||||
* \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.transferFunction == rhs.transferFunction &&
|
||||
lhs.ycbcrEncoding == rhs.ycbcrEncoding &&
|
||||
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 */
|
|
@ -9,6 +9,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',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue