123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef UI_GFX_COLOR_SPACE_H_
- #define UI_GFX_COLOR_SPACE_H_
- #include <stdint.h>
- #include <iosfwd>
- #include <string>
- #include "base/gtest_prod_util.h"
- #include "build/build_config.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "third_party/skia/include/core/SkRefCnt.h"
- #include "ui/gfx/color_space_export.h"
- struct skcms_Matrix3x3;
- struct skcms_TransferFunction;
- class SkColorSpace;
- class SkM44;
- struct SkColorSpacePrimaries;
- enum SkYUVColorSpace : int;
- // These forward declarations are used to give IPC code friend access to private
- // fields of gfx::ColorSpace for the purpose of serialization and
- // deserialization.
- namespace IPC {
- template <class P>
- struct ParamTraits;
- } // namespace IPC
- namespace mojo {
- template <class T, class U>
- struct StructTraits;
- } // namespace mojo
- // Used to serialize a gfx::ColorSpace through the GPU command buffer.
- struct _GLcolorSpace;
- namespace media {
- namespace stable {
- namespace mojom {
- class ColorSpaceDataView;
- } // namespace mojom
- } // namespace stable
- } // namespace media
- namespace gfx {
- enum class ContentColorUsage : uint8_t;
- namespace mojom {
- class ColorSpaceDataView;
- } // namespace mojom
- // Used to represet a color space for the purpose of color conversion.
- // This is designed to be safe and compact enough to send over IPC
- // between any processes.
- class COLOR_SPACE_EXPORT ColorSpace {
- public:
- enum class PrimaryID : uint8_t {
- INVALID,
- // BT709 is also the primaries for SRGB.
- BT709,
- BT470M,
- BT470BG,
- SMPTE170M,
- SMPTE240M,
- FILM,
- BT2020,
- SMPTEST428_1,
- SMPTEST431_2,
- P3,
- XYZ_D50,
- ADOBE_RGB,
- // Corresponds the the primaries of the "Generic RGB" profile used in the
- // Apple ColorSync application, used by layout tests on Mac.
- APPLE_GENERIC_RGB,
- // A very wide gamut space with rotated primaries. Used by layout tests.
- WIDE_GAMUT_COLOR_SPIN,
- // Primaries defined by the primary matrix |custom_primary_matrix_|.
- CUSTOM,
- kMaxValue = CUSTOM,
- };
- enum class TransferID : uint8_t {
- INVALID,
- BT709,
- // On macOS, BT709 hardware decoded video frames, when displayed as
- // overlays, will have a transfer function of gamma=1.961.
- BT709_APPLE,
- GAMMA18,
- GAMMA22,
- GAMMA24,
- GAMMA28,
- SMPTE170M,
- SMPTE240M,
- LINEAR,
- LOG,
- LOG_SQRT,
- IEC61966_2_4,
- BT1361_ECG,
- SRGB,
- BT2020_10,
- BT2020_12,
- // Perceptual quantizer, also known as SMPTEST2084.
- PQ,
- SMPTEST428_1,
- // Hybrid-log gamma, also known as ARIB_STD_B67.
- HLG,
- // The same as SRGB on the interval [0, 1], with the nonlinear segment
- // continuing beyond 1 and point symmetry defining values below 0.
- SRGB_HDR,
- // The same as LINEAR but is defined for all real values.
- LINEAR_HDR,
- // A parametric transfer function defined by |transfer_params_|.
- CUSTOM,
- // An HDR parametric transfer function defined by |transfer_params_|.
- CUSTOM_HDR,
- // An HDR transfer function that is piecewise sRGB, and piecewise linear.
- PIECEWISE_HDR,
- // An HDR transfer function that is linear, with the value 1 at 80 nits.
- // This transfer function is not SDR-referred, and therefore can only be
- // used (e.g, by ToSkColorSpace or GetTransferFunction) when an SDR white
- // level is specified.
- SCRGB_LINEAR_80_NITS,
- kMaxValue = SCRGB_LINEAR_80_NITS,
- };
- enum class MatrixID : uint8_t {
- INVALID,
- RGB,
- BT709,
- FCC,
- BT470BG,
- SMPTE170M,
- SMPTE240M,
- YCOCG,
- BT2020_NCL,
- BT2020_CL,
- YDZDX,
- GBR,
- kMaxValue = GBR,
- };
- enum class RangeID : uint8_t {
- INVALID,
- // Limited Rec. 709 color range with RGB values ranging from 16 to 235.
- LIMITED,
- // Full RGB color range with RGB valees from 0 to 255.
- FULL,
- // Range is defined by TransferID/MatrixID.
- DERIVED,
- kMaxValue = DERIVED,
- };
- constexpr ColorSpace() {}
- constexpr ColorSpace(PrimaryID primaries, TransferID transfer)
- : ColorSpace(primaries, transfer, MatrixID::RGB, RangeID::FULL) {}
- constexpr ColorSpace(PrimaryID primaries,
- TransferID transfer,
- MatrixID matrix,
- RangeID range)
- : primaries_(primaries),
- transfer_(transfer),
- matrix_(matrix),
- range_(range) {}
- ColorSpace(PrimaryID primaries,
- TransferID transfer,
- MatrixID matrix,
- RangeID range,
- const skcms_Matrix3x3* custom_primary_matrix,
- const skcms_TransferFunction* cunstom_transfer_fn,
- bool is_hdr = false);
- explicit ColorSpace(const SkColorSpace& sk_color_space, bool is_hdr = false);
- // Returns true if this is not the default-constructor object.
- bool IsValid() const;
- static constexpr ColorSpace CreateSRGB() {
- return ColorSpace(PrimaryID::BT709, TransferID::SRGB, MatrixID::RGB,
- RangeID::FULL);
- }
- static constexpr ColorSpace CreateDisplayP3D65() {
- return ColorSpace(PrimaryID::P3, TransferID::SRGB, MatrixID::RGB,
- RangeID::FULL);
- }
- static ColorSpace CreateCustom(const skcms_Matrix3x3& to_XYZD50,
- const skcms_TransferFunction& fn);
- static ColorSpace CreateCustom(const skcms_Matrix3x3& to_XYZD50,
- TransferID transfer);
- static constexpr ColorSpace CreateXYZD50() {
- return ColorSpace(PrimaryID::XYZ_D50, TransferID::LINEAR, MatrixID::RGB,
- RangeID::FULL);
- }
- // Extended sRGB matches sRGB for values in [0, 1], and extends the transfer
- // function to all real values.
- static constexpr ColorSpace CreateExtendedSRGB() {
- return ColorSpace(PrimaryID::BT709, TransferID::SRGB_HDR, MatrixID::RGB,
- RangeID::FULL);
- }
- // scRGB uses the same primaries as sRGB but has a linear transfer function
- // for all real values.
- static constexpr ColorSpace CreateSRGBLinear() {
- return ColorSpace(PrimaryID::BT709, TransferID::LINEAR_HDR, MatrixID::RGB,
- RangeID::FULL);
- }
- // scRGB uses the same primaries as sRGB but has a linear transfer function
- // for all real values, and an SDR white level of 80 nits.
- static constexpr ColorSpace CreateSCRGBLinear80Nits() {
- return ColorSpace(PrimaryID::BT709, TransferID::SCRGB_LINEAR_80_NITS,
- MatrixID::RGB, RangeID::FULL);
- }
- // HDR10 uses BT.2020 primaries with SMPTE ST 2084 PQ transfer function.
- static constexpr ColorSpace CreateHDR10() {
- return ColorSpace(PrimaryID::BT2020, TransferID::PQ, MatrixID::RGB,
- RangeID::FULL);
- }
- // HLG uses the BT.2020 primaries with the ARIB_STD_B67 transfer function.
- static constexpr ColorSpace CreateHLG() {
- return ColorSpace(PrimaryID::BT2020, TransferID::HLG, MatrixID::RGB,
- RangeID::FULL);
- }
- // Create a piecewise-HDR color space.
- // - If |primaries| is CUSTOM, then |custom_primary_matrix| must be
- // non-nullptr.
- // - The SDR joint is the encoded pixel value where the SDR portion reaches 1,
- // usually 0.25 or 0.5, corresponding to giving 8 or 9 of 10 bits to SDR.
- // This must be in the open interval (0, 1).
- // - The HDR level the value that the transfer function will evaluate to at 1,
- // and represents the maximum HDR brightness relative to the maximum SDR
- // brightness. This must be strictly greater than 1.
- static ColorSpace CreatePiecewiseHDR(
- PrimaryID primaries,
- float sdr_joint,
- float hdr_level,
- const skcms_Matrix3x3* custom_primary_matrix = nullptr);
- // TODO(ccameron): Remove these, and replace with more generic constructors.
- static constexpr ColorSpace CreateJpeg() {
- // TODO(ccameron): Determine which primaries and transfer function were
- // intended here.
- return ColorSpace(PrimaryID::BT709, TransferID::SRGB, MatrixID::SMPTE170M,
- RangeID::FULL);
- }
- static constexpr ColorSpace CreateREC601() {
- return ColorSpace(PrimaryID::SMPTE170M, TransferID::SMPTE170M,
- MatrixID::SMPTE170M, RangeID::LIMITED);
- }
- static constexpr ColorSpace CreateREC709() {
- return ColorSpace(PrimaryID::BT709, TransferID::BT709, MatrixID::BT709,
- RangeID::LIMITED);
- }
- // The default number of nits for SDR white. This is used for transformations
- // between color spaces that do not specify an SDR white for tone mapping
- // (e.g, in 2D canvas).
- static constexpr float kDefaultSDRWhiteLevel = 203.f;
- bool operator==(const ColorSpace& other) const;
- bool operator!=(const ColorSpace& other) const;
- bool operator<(const ColorSpace& other) const;
- size_t GetHash() const;
- std::string ToString() const;
- bool IsWide() const;
- // Returns true if the transfer function is an HDR one (SMPTE 2084, HLG, etc).
- bool IsHDR() const;
- // Returns true if there exists a default tone mapping that should be applied
- // when drawing content with this color space. This is true for spaces with
- // the PQ and HLG transfer functions.
- bool IsToneMappedByDefault() const;
- // Returns true if the color space's interpretation is affected by the SDR
- // white level parameter. This is true for spaces with the PQ, HLG, and
- // SCRGB_LINEAR_80_NITS transfer functions.
- bool IsAffectedBySDRWhiteLevel() const;
- // Returns true if the encoded values can be outside of the 0.0-1.0 range.
- bool FullRangeEncodedValues() const;
- // Returns the color space's content color usage category (sRGB, WCG, or HDR).
- ContentColorUsage GetContentColorUsage() const;
- // Return this color space with any YUV to RGB conversion stripped off.
- ColorSpace GetAsRGB() const;
- // Return this color space with any range adjust or YUV to RGB conversion
- // stripped off.
- ColorSpace GetAsFullRangeRGB() const;
- // Return a color space where all values are bigger/smaller by the given
- // factor. If you convert colors from SRGB to SRGB.GetScaledColorSpace(2.0)
- // everything will be half as bright in linear lumens.
- ColorSpace GetScaledColorSpace(float factor) const;
- // Return true if blending in |this| is close enough to blending in sRGB to
- // be considered acceptable (only PQ and nearly-linear transfer functions
- // return false).
- bool IsSuitableForBlending() const;
- // Return a combined color space with has the same primary and transfer than
- // the caller but replacing the matrix and range with the given values.
- ColorSpace GetWithMatrixAndRange(MatrixID matrix, RangeID range) const;
- // This will return nullptr for non-RGB spaces, spaces with non-FULL
- // range, unspecified spaces, and spaces that require but are not provided
- // and SDR white level.
- sk_sp<SkColorSpace> ToSkColorSpace(
- absl::optional<float> sdr_white_level = absl::nullopt) const;
- // Return a GLcolorSpace value that is valid for the lifetime of |this|. This
- // function is used to serialize ColorSpace objects across the GPU command
- // buffer.
- const _GLcolorSpace* AsGLColorSpace() const;
- // For YUV color spaces, return the closest SkYUVColorSpace. Returns true if a
- // close match is found. Otherwise, leaves *out unchanged and returns false.
- // If |matrix_id| is MatrixID::BT2020_NCL and |bit_depth| is provided, a bit
- // depth appropriate SkYUVColorSpace will be provided.
- bool ToSkYUVColorSpace(int bit_depth, SkYUVColorSpace* out) const;
- bool ToSkYUVColorSpace(SkYUVColorSpace* out) const {
- return ToSkYUVColorSpace(kDefaultBitDepth, out);
- }
- // Return the RGB and whitepoint coordinates of the ColorSpace's
- // chromaticity. Assumes D65 whitepoint in the case of a custom PrimaryID.
- SkColorSpacePrimaries GetColorSpacePrimaries() const;
- void GetPrimaryMatrix(skcms_Matrix3x3* to_XYZD50) const;
- SkM44 GetPrimaryMatrix() const;
- // Retrieve the parametric transfer function for this color space. Returns
- // false if none is available, or if `sdr_white_level` is required but
- // not specified.
- bool GetTransferFunction(
- skcms_TransferFunction* fn,
- absl::optional<float> sdr_white_level = absl::nullopt) const;
- bool GetInverseTransferFunction(
- skcms_TransferFunction* fn,
- absl::optional<float> sdr_white_level = absl::nullopt) const;
- // Returns the parameters for a PIECEWISE_HDR transfer function. See
- // CreatePiecewiseHDR for parameter meanings.
- bool GetPiecewiseHDRParams(float* sdr_point, float* hdr_level) const;
- // Returns the transfer matrix for |bit_depth|. For most formats, this is the
- // RGB to YUV matrix.
- SkM44 GetTransferMatrix(int bit_depth) const;
- // Returns the range adjust matrix that converts from |range_| to full range
- // for |bit_depth|.
- SkM44 GetRangeAdjustMatrix(int bit_depth) const;
- // Returns the current primary ID.
- // Note: if SetCustomPrimaries() has been used, the primary ID returned
- // may have been set to PrimaryID::CUSTOM, or been coerced to another
- // PrimaryID if it was very close.
- PrimaryID GetPrimaryID() const;
- // Returns the current transfer ID.
- TransferID GetTransferID() const;
- // Returns the current matrix ID.
- MatrixID GetMatrixID() const;
- // Returns the current range ID.
- RangeID GetRangeID() const;
- // Returns true if the transfer function is defined by an
- // skcms_TransferFunction which is extended to all real values. This is true
- // unless the color space has a non-RGB matrix.
- bool HasExtendedSkTransferFn() const;
- // Returns true if each color in |other| can be expressed in this color space.
- bool Contains(const ColorSpace& other) const;
- private:
- // The default bit depth assumed by ToSkYUVColorSpace().
- static constexpr int kDefaultBitDepth = 8;
- static SkColorSpacePrimaries GetColorSpacePrimaries(
- PrimaryID,
- const skcms_Matrix3x3* custom_primary_matrix);
- static void GetPrimaryMatrix(PrimaryID, skcms_Matrix3x3* to_XYZD50);
- static bool GetTransferFunction(TransferID, skcms_TransferFunction* fn);
- static size_t TransferParamCount(TransferID);
- void SetCustomTransferFunction(const skcms_TransferFunction& fn, bool is_hdr);
- void SetCustomPrimaries(const skcms_Matrix3x3& to_XYZD50);
- PrimaryID primaries_ = PrimaryID::INVALID;
- TransferID transfer_ = TransferID::INVALID;
- MatrixID matrix_ = MatrixID::INVALID;
- RangeID range_ = RangeID::INVALID;
- // Only used if primaries_ is PrimaryID::CUSTOM.
- float custom_primary_matrix_[9] = {0};
- // Parameters for the transfer function. The interpretation depends on
- // |transfer_|. Only TransferParamCount() of these parameters are used, all
- // others must be zero.
- // - CUSTOM and CUSTOM_HDR: Entries A through G of the skcms_TransferFunction
- // structure in alphabetical order.
- // - SMPTEST2084: SDR white point.
- float transfer_params_[7] = {0};
- friend struct IPC::ParamTraits<gfx::ColorSpace>;
- friend struct mojo::StructTraits<gfx::mojom::ColorSpaceDataView,
- gfx::ColorSpace>;
- friend struct mojo::StructTraits<media::stable::mojom::ColorSpaceDataView,
- gfx::ColorSpace>;
- };
- // Stream operator so ColorSpace can be used in assertion statements.
- COLOR_SPACE_EXPORT std::ostream& operator<<(std::ostream& out,
- const ColorSpace& color_space);
- } // namespace gfx
- #endif // UI_GFX_COLOR_SPACE_H_
|