Flutter Engine
The Flutter Engine
SkYUVAInfo.h
Go to the documentation of this file.
1/*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkYUVAInfo_DEFINED
9#define SkYUVAInfo_DEFINED
10
14#include "include/core/SkSize.h"
16
17#include <array>
18#include <cstddef>
19#include <cstdint>
20#include <tuple>
21
22/**
23 * Specifies the structure of planes for a YUV image with optional alpha. The actual planar data
24 * is not part of this structure and depending on usage is in external textures or pixmaps.
25 */
27public:
28 enum YUVAChannels { kY, kU, kV, kA, kLast = kA };
29 static constexpr int kYUVAChannelCount = static_cast<int>(YUVAChannels::kLast + 1);
30
31 struct YUVALocation; // For internal use.
32 using YUVALocations = std::array<YUVALocation, kYUVAChannelCount>;
33
34 /**
35 * Specifies how YUV (and optionally A) are divided among planes. Planes are separated by
36 * underscores in the enum value names. Within each plane the pixmap/texture channels are
37 * mapped to the YUVA channels in the order specified, e.g. for kY_UV Y is in channel 0 of plane
38 * 0, U is in channel 0 of plane 1, and V is in channel 1 of plane 1. Channel ordering
39 * within a pixmap/texture given the channels it contains:
40 * A: 0:A
41 * Luminance/Gray: 0:Gray
42 * Luminance/Gray + Alpha: 0:Gray, 1:A
43 * RG 0:R, 1:G
44 * RGB 0:R, 1:G, 2:B
45 * RGBA 0:R, 1:G, 2:B, 3:A
46 */
47 enum class PlaneConfig {
49
50 kY_U_V, ///< Plane 0: Y, Plane 1: U, Plane 2: V
51 kY_V_U, ///< Plane 0: Y, Plane 1: V, Plane 2: U
52 kY_UV, ///< Plane 0: Y, Plane 1: UV
53 kY_VU, ///< Plane 0: Y, Plane 1: VU
54 kYUV, ///< Plane 0: YUV
55 kUYV, ///< Plane 0: UYV
56
57 kY_U_V_A, ///< Plane 0: Y, Plane 1: U, Plane 2: V, Plane 3: A
58 kY_V_U_A, ///< Plane 0: Y, Plane 1: V, Plane 2: U, Plane 3: A
59 kY_UV_A, ///< Plane 0: Y, Plane 1: UV, Plane 2: A
60 kY_VU_A, ///< Plane 0: Y, Plane 1: VU, Plane 2: A
61 kYUVA, ///< Plane 0: YUVA
62 kUYVA, ///< Plane 0: UYVA
63
64 kLast = kUYVA
65 };
66
67 /**
68 * UV subsampling is also specified in the enum value names using J:a:b notation (e.g. 4:2:0 is
69 * 1/2 horizontal and 1/2 vertical resolution for U and V). If alpha is present it is not sub-
70 * sampled. Note that Subsampling values other than k444 are only valid with PlaneConfig values
71 * that have U and V in different planes than Y (and A, if present).
72 */
73 enum class Subsampling {
75
76 k444, ///< No subsampling. UV values for each Y.
77 k422, ///< 1 set of UV values for each 2x1 block of Y values.
78 k420, ///< 1 set of UV values for each 2x2 block of Y values.
79 k440, ///< 1 set of UV values for each 1x2 block of Y values.
80 k411, ///< 1 set of UV values for each 4x1 block of Y values.
81 k410, ///< 1 set of UV values for each 4x2 block of Y values.
82
83 kLast = k410
84 };
85
86 /**
87 * Describes how subsampled chroma values are sited relative to luma values.
88 *
89 * Currently only centered siting is supported but will expand to support additional sitings.
90 */
91 enum class Siting {
92 /**
93 * Subsampled chroma value is sited at the center of the block of corresponding luma values.
94 */
96 };
97
98 static constexpr int kMaxPlanes = 4;
99
100 /** ratio of Y/A values to U/V values in x and y. */
101 static std::tuple<int, int> SubsamplingFactors(Subsampling);
102
103 /**
104 * SubsamplingFactors(Subsampling) if planedIdx refers to a U/V plane and otherwise {1, 1} if
105 * inputs are valid. Invalid inputs consist of incompatible PlaneConfig/Subsampling/planeIdx
106 * combinations. {0, 0} is returned for invalid inputs.
107 */
108 static std::tuple<int, int> PlaneSubsamplingFactors(PlaneConfig, Subsampling, int planeIdx);
109
110 /**
111 * Given image dimensions, a planer configuration, subsampling, and origin, determine the
112 * expected size of each plane. Returns the number of expected planes. planeDimensions[0]
113 * through planeDimensions[<ret>] are written. The input image dimensions are as displayed
114 * (after the planes have been transformed to the intended display orientation). The plane
115 * dimensions are output as the planes are stored in memory (may be rotated from image
116 * dimensions).
117 */
118 static int PlaneDimensions(SkISize imageDimensions,
122 SkISize planeDimensions[kMaxPlanes]);
123
124 /** Number of planes for a given PlaneConfig. */
125 static constexpr int NumPlanes(PlaneConfig);
126
127 /**
128 * Number of Y, U, V, A channels in the ith plane for a given PlaneConfig (or 0 if i is
129 * invalid).
130 */
131 static constexpr int NumChannelsInPlane(PlaneConfig, int i);
132
133 /**
134 * Given a PlaneConfig and a set of channel flags for each plane, convert to YUVALocations
135 * representation. Fails if channel flags aren't valid for the PlaneConfig (i.e. don't have
136 * enough channels in a plane) by returning an invalid set of locations (plane indices are -1).
137 */
138 static YUVALocations GetYUVALocations(PlaneConfig, const uint32_t* planeChannelFlags);
139
140 /** Does the PlaneConfig have alpha values? */
141 static bool HasAlpha(PlaneConfig);
142
143 SkYUVAInfo() = default;
144 SkYUVAInfo(const SkYUVAInfo&) = default;
145
146 /**
147 * 'dimensions' should specify the size of the full resolution image (after planes have been
148 * oriented to how the image is displayed as indicated by 'origin').
149 */
150 SkYUVAInfo(SkISize dimensions,
155 Siting sitingX = Siting::kCentered,
156 Siting sitingY = Siting::kCentered);
157
158 SkYUVAInfo& operator=(const SkYUVAInfo& that) = default;
159
160 PlaneConfig planeConfig() const { return fPlaneConfig; }
161 Subsampling subsampling() const { return fSubsampling; }
162
163 std::tuple<int, int> planeSubsamplingFactors(int planeIdx) const {
164 return PlaneSubsamplingFactors(fPlaneConfig, fSubsampling, planeIdx);
165 }
166
167 /**
168 * Dimensions of the full resolution image (after planes have been oriented to how the image
169 * is displayed as indicated by fOrigin).
170 */
171 SkISize dimensions() const { return fDimensions; }
172 int width() const { return fDimensions.width(); }
173 int height() const { return fDimensions.height(); }
174
175 SkYUVColorSpace yuvColorSpace() const { return fYUVColorSpace; }
176 Siting sitingX() const { return fSitingX; }
177 Siting sitingY() const { return fSitingY; }
178
179 SkEncodedOrigin origin() const { return fOrigin; }
180
182 return SkEncodedOriginToMatrix(fOrigin, this->width(), this->height());
183 }
184
185 bool hasAlpha() const { return HasAlpha(fPlaneConfig); }
186
187 /**
188 * Returns the number of planes and initializes planeDimensions[0]..planeDimensions[<ret>] to
189 * the expected dimensions for each plane. Dimensions are as stored in memory, before
190 * transformation to image display space as indicated by origin().
191 */
192 int planeDimensions(SkISize planeDimensions[kMaxPlanes]) const {
193 return PlaneDimensions(fDimensions, fPlaneConfig, fSubsampling, fOrigin, planeDimensions);
194 }
195
196 /**
197 * Given a per-plane row bytes, determine size to allocate for all planes. Optionally retrieves
198 * the per-plane byte sizes in planeSizes if not null. If total size overflows will return
199 * SIZE_MAX and set all planeSizes to SIZE_MAX.
200 */
201 size_t computeTotalBytes(const size_t rowBytes[kMaxPlanes],
202 size_t planeSizes[kMaxPlanes] = nullptr) const;
203
204 int numPlanes() const { return NumPlanes(fPlaneConfig); }
205
206 int numChannelsInPlane(int i) const { return NumChannelsInPlane(fPlaneConfig, i); }
207
208 /**
209 * Given a set of channel flags for each plane, converts this->planeConfig() to YUVALocations
210 * representation. Fails if the channel flags aren't valid for the PlaneConfig (i.e. don't have
211 * enough channels in a plane) by returning default initialized locations (all plane indices are
212 * -1).
213 */
214 YUVALocations toYUVALocations(const uint32_t* channelFlags) const;
215
216 /**
217 * Makes a SkYUVAInfo that is identical to this one but with the passed Subsampling. If the
218 * passed Subsampling is not k444 and this info's PlaneConfig is not compatible with chroma
219 * subsampling (because Y is in the same plane as UV) then the result will be an invalid
220 * SkYUVAInfo.
221 */
222 SkYUVAInfo makeSubsampling(SkYUVAInfo::Subsampling) const;
223
224 /**
225 * Makes a SkYUVAInfo that is identical to this one but with the passed dimensions. If the
226 * passed dimensions is empty then the result will be an invalid SkYUVAInfo.
227 */
228 SkYUVAInfo makeDimensions(SkISize) const;
229
230 bool operator==(const SkYUVAInfo& that) const;
231 bool operator!=(const SkYUVAInfo& that) const { return !(*this == that); }
232
233 bool isValid() const { return fPlaneConfig != PlaneConfig::kUnknown; }
234
235private:
236 SkISize fDimensions = {0, 0};
237
238 PlaneConfig fPlaneConfig = PlaneConfig::kUnknown;
239 Subsampling fSubsampling = Subsampling::kUnknown;
240
242
243 /**
244 * YUVA data often comes from formats like JPEG that support EXIF orientation.
245 * Code that operates on the raw YUV data often needs to know that orientation.
246 */
248
249 Siting fSitingX = Siting::kCentered;
250 Siting fSitingY = Siting::kCentered;
251};
252
253constexpr int SkYUVAInfo::NumPlanes(PlaneConfig planeConfig) {
254 switch (planeConfig) {
255 case PlaneConfig::kUnknown: return 0;
256 case PlaneConfig::kY_U_V: return 3;
257 case PlaneConfig::kY_V_U: return 3;
258 case PlaneConfig::kY_UV: return 2;
259 case PlaneConfig::kY_VU: return 2;
260 case PlaneConfig::kYUV: return 1;
261 case PlaneConfig::kUYV: return 1;
262 case PlaneConfig::kY_U_V_A: return 4;
263 case PlaneConfig::kY_V_U_A: return 4;
264 case PlaneConfig::kY_UV_A: return 3;
265 case PlaneConfig::kY_VU_A: return 3;
266 case PlaneConfig::kYUVA: return 1;
267 case PlaneConfig::kUYVA: return 1;
268 }
270}
271
272constexpr int SkYUVAInfo::NumChannelsInPlane(PlaneConfig config, int i) {
273 switch (config) {
275 return 0;
276
279 return i >= 0 && i < 3 ? 1 : 0;
282 switch (i) {
283 case 0: return 1;
284 case 1: return 2;
285 default: return 0;
286 }
289 return i == 0 ? 3 : 0;
292 return i >= 0 && i < 4 ? 1 : 0;
295 switch (i) {
296 case 0: return 1;
297 case 1: return 2;
298 case 2: return 1;
299 default: return 0;
300 }
303 return i == 0 ? 4 : 0;
304 }
305 return 0;
306}
307
308#endif
@ kCentered
#define SK_API
Definition: SkAPI.h:35
#define SkUNREACHABLE
Definition: SkAssert.h:135
SkEncodedOrigin
@ kTopLeft_SkEncodedOrigin
static SkMatrix SkEncodedOriginToMatrix(SkEncodedOrigin origin, int w, int h)
SkYUVColorSpace
Definition: SkImageInfo.h:68
@ kIdentity_SkYUVColorSpace
maps Y->R, U->G, V->B
Definition: SkImageInfo.h:93
SkYUVAInfo(const SkYUVAInfo &)=default
int width() const
Definition: SkYUVAInfo.h:172
Siting sitingY() const
Definition: SkYUVAInfo.h:177
SkMatrix originMatrix() const
Definition: SkYUVAInfo.h:181
SkYUVAInfo()=default
SkYUVColorSpace yuvColorSpace() const
Definition: SkYUVAInfo.h:175
int numPlanes() const
Definition: SkYUVAInfo.h:204
@ kY_U_V_A
Plane 0: Y, Plane 1: U, Plane 2: V, Plane 3: A.
@ kY_U_V
Plane 0: Y, Plane 1: U, Plane 2: V.
@ kYUVA
Plane 0: YUVA.
@ kY_V_U_A
Plane 0: Y, Plane 1: V, Plane 2: U, Plane 3: A.
@ kUYVA
Plane 0: UYVA.
@ kY_VU
Plane 0: Y, Plane 1: VU.
@ kY_UV
Plane 0: Y, Plane 1: UV.
@ kY_VU_A
Plane 0: Y, Plane 1: VU, Plane 2: A.
@ kY_V_U
Plane 0: Y, Plane 1: V, Plane 2: U.
@ kY_UV_A
Plane 0: Y, Plane 1: UV, Plane 2: A.
bool hasAlpha() const
Definition: SkYUVAInfo.h:185
static constexpr int NumChannelsInPlane(PlaneConfig, int i)
Definition: SkYUVAInfo.h:272
int height() const
Definition: SkYUVAInfo.h:173
std::tuple< int, int > planeSubsamplingFactors(int planeIdx) const
Definition: SkYUVAInfo.h:163
static constexpr int NumPlanes(PlaneConfig)
Definition: SkYUVAInfo.h:253
PlaneConfig planeConfig() const
Definition: SkYUVAInfo.h:160
int planeDimensions(SkISize planeDimensions[kMaxPlanes]) const
Definition: SkYUVAInfo.h:192
std::array< YUVALocation, kYUVAChannelCount > YUVALocations
Definition: SkYUVAInfo.h:32
SkEncodedOrigin origin() const
Definition: SkYUVAInfo.h:179
bool isValid() const
Definition: SkYUVAInfo.h:233
SkYUVAInfo & operator=(const SkYUVAInfo &that)=default
Subsampling subsampling() const
Definition: SkYUVAInfo.h:161
bool operator!=(const SkYUVAInfo &that) const
Definition: SkYUVAInfo.h:231
SkISize dimensions() const
Definition: SkYUVAInfo.h:171
int numChannelsInPlane(int i) const
Definition: SkYUVAInfo.h:206
Siting sitingX() const
Definition: SkYUVAInfo.h:176
@ kYUVA
Definition: embedder.h:606
bool operator==(C p1, const scoped_nsprotocol< C > &p2)
int32_t height
int32_t width
Definition: SkSize.h:16