forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
color_space.h
432 lines (367 loc) · 15.2 KB
/
color_space.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
// 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_