/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD - style license that can be
* found in the LICENSE file .
*/
#ifndef SkYUVAInfo_DEFINED
#define SkYUVAInfo_DEFINED
#include "include/codec/SkEncodedOrigin.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkSize.h"
#include "include/core/SkTypes.h"
#include <array>
#include <cstddef>
#include <cstdint>
#include <tuple>
/**
* Specifies the structure of planes for a YUV image with optional alpha . The actual planar data
* is not part of this structure and depending on usage is in external textures or pixmaps .
*/
class SK_API SkYUVAInfo {
public:
enum YUVAChannels { kY, kU, kV, kA, kLast = kA };
static constexpr int kYUVAChannelCount = static_cast<int >(YUVAChannels::kLast + 1 );
struct YUVALocation; // For internal use.
using YUVALocations = std::array<YUVALocation, kYUVAChannelCount>;
/**
* Specifies how YUV ( and optionally A ) are divided among planes . Planes are separated by
* underscores in the enum value names . Within each plane the pixmap / texture channels are
* mapped to the YUVA channels in the order specified , e . g . for kY_UV Y is in channel 0 of plane
* 0 , U is in channel 0 of plane 1 , and V is in channel 1 of plane 1 . Channel ordering
* within a pixmap / texture given the channels it contains :
* A : 0 : A
* Luminance / Gray : 0 : Gray
* Luminance / Gray + Alpha : 0 : Gray , 1 : A
* RG 0 : R , 1 : G
* RGB 0 : R , 1 : G , 2 : B
* RGBA 0 : R , 1 : G , 2 : B , 3 : A
*/
enum class PlaneConfig {
kUnknown,
kY_U_V, ///< Plane 0: Y, Plane 1: U, Plane 2: V
kY_V_U, ///< Plane 0: Y, Plane 1: V, Plane 2: U
kY_UV, ///< Plane 0: Y, Plane 1: UV
kY_VU, ///< Plane 0: Y, Plane 1: VU
kYUV, ///< Plane 0: YUV
kUYV, ///< Plane 0: UYV
kY_U_V_A, ///< Plane 0: Y, Plane 1: U, Plane 2: V, Plane 3: A
kY_V_U_A, ///< Plane 0: Y, Plane 1: V, Plane 2: U, Plane 3: A
kY_UV_A, ///< Plane 0: Y, Plane 1: UV, Plane 2: A
kY_VU_A, ///< Plane 0: Y, Plane 1: VU, Plane 2: A
kYUVA, ///< Plane 0: YUVA
kUYVA, ///< Plane 0: UYVA
kLast = kUYVA
};
/**
* UV subsampling is also specified in the enum value names using J : a : b notation ( e . g . 4 : 2 : 0 is
* 1 / 2 horizontal and 1 / 2 vertical resolution for U and V ) . If alpha is present it is not sub -
* sampled . Note that Subsampling values other than k444 are only valid with PlaneConfig values
* that have U and V in different planes than Y ( and A , if present ) .
*/
enum class Subsampling {
kUnknown,
k444, ///< No subsampling. UV values for each Y.
k422, ///< 1 set of UV values for each 2x1 block of Y values.
k420, ///< 1 set of UV values for each 2x2 block of Y values.
k440, ///< 1 set of UV values for each 1x2 block of Y values.
k411, ///< 1 set of UV values for each 4x1 block of Y values.
k410, ///< 1 set of UV values for each 4x2 block of Y values.
kLast = k410
};
/**
* Describes how subsampled chroma values are sited relative to luma values .
*
* Currently only centered siting is supported but will expand to support additional sitings .
*/
enum class Siting {
/**
* Subsampled chroma value is sited at the center of the block of corresponding luma values .
*/
kCentered,
};
static constexpr int kMaxPlanes = 4 ;
/** ratio of Y/A values to U/V values in x and y. */
static std::tuple<int , int > SubsamplingFactors(Subsampling);
/**
* SubsamplingFactors ( Subsampling ) if planedIdx refers to a U / V plane and otherwise { 1 , 1 } if
* inputs are valid . Invalid inputs consist of incompatible PlaneConfig / Subsampling / planeIdx
* combinations . { 0 , 0 } is returned for invalid inputs .
*/
static std::tuple<int , int > PlaneSubsamplingFactors(PlaneConfig, Subsampling, int planeIdx);
/**
* Given image dimensions , a planer configuration , subsampling , and origin , determine the
* expected size of each plane . Returns the number of expected planes . planeDimensions [ 0 ]
* through planeDimensions [ < ret > ] are written . The input image dimensions are as displayed
* ( after the planes have been transformed to the intended display orientation ) . The plane
* dimensions are output as the planes are stored in memory ( may be rotated from image
* dimensions ) .
*/
static int PlaneDimensions(SkISize imageDimensions,
PlaneConfig,
Subsampling,
SkEncodedOrigin,
SkISize planeDimensions[kMaxPlanes]);
/** Number of planes for a given PlaneConfig. */
static constexpr int NumPlanes(PlaneConfig);
/**
* Number of Y , U , V , A channels in the ith plane for a given PlaneConfig ( or 0 if i is
* invalid ) .
*/
static constexpr int NumChannelsInPlane(PlaneConfig, int i);
/**
* Given a PlaneConfig and a set of channel flags for each plane , convert to YUVALocations
* representation . Fails if channel flags aren ' t valid for the PlaneConfig ( i . e . don ' t have
* enough channels in a plane ) by returning an invalid set of locations ( plane indices are - 1 ) .
*/
static YUVALocations GetYUVALocations(PlaneConfig, const uint32_t* planeChannelFlags);
/** Does the PlaneConfig have alpha values? */
static bool HasAlpha(PlaneConfig);
SkYUVAInfo() = default ;
SkYUVAInfo(const SkYUVAInfo&) = default ;
/**
* ' dimensions ' should specify the size of the full resolution image ( after planes have been
* oriented to how the image is displayed as indicated by ' origin ' ) .
*/
SkYUVAInfo(SkISize dimensions,
PlaneConfig,
Subsampling,
SkYUVColorSpace,
SkEncodedOrigin origin = kTopLeft_SkEncodedOrigin,
Siting sitingX = Siting::kCentered,
Siting sitingY = Siting::kCentered);
SkYUVAInfo& operator =(const SkYUVAInfo& that) = default ;
PlaneConfig planeConfig() const { return fPlaneConfig; }
Subsampling subsampling() const { return fSubsampling; }
std::tuple<int , int > planeSubsamplingFactors(int planeIdx) const {
return PlaneSubsamplingFactors(fPlaneConfig, fSubsampling, planeIdx);
}
/**
* Dimensions of the full resolution image ( after planes have been oriented to how the image
* is displayed as indicated by fOrigin ) .
*/
SkISize dimensions() const { return fDimensions; }
int width() const { return fDimensions.width(); }
int height() const { return fDimensions.height(); }
SkYUVColorSpace yuvColorSpace() const { return fYUVColorSpace; }
Siting sitingX() const { return fSitingX; }
Siting sitingY() const { return fSitingY; }
SkEncodedOrigin origin() const { return fOrigin; }
SkMatrix originMatrix() const {
return SkEncodedOriginToMatrix(fOrigin, this->width(), this->height());
}
SkMatrix inverseOriginMatrix() const {
return SkEncodedOriginToMatrixInverse(fOrigin, this->width(), this->height());
}
bool hasAlpha() const { return HasAlpha(fPlaneConfig); }
/**
* Returns the number of planes and initializes planeDimensions [ 0 ] . . planeDimensions [ < ret > ] to
* the expected dimensions for each plane . Dimensions are as stored in memory , before
* transformation to image display space as indicated by origin ( ) .
*/
int planeDimensions(SkISize planeDimensions[kMaxPlanes]) const {
return PlaneDimensions(fDimensions, fPlaneConfig, fSubsampling, fOrigin, planeDimensions);
}
/**
* Given a per - plane row bytes , determine size to allocate for all planes . Optionally retrieves
* the per - plane byte sizes in planeSizes if not null . If total size overflows will return
* SIZE_MAX and set all planeSizes to SIZE_MAX .
*/
size_t computeTotalBytes(const size_t rowBytes[kMaxPlanes],
size_t planeSizes[kMaxPlanes] = nullptr) const ;
int numPlanes() const { return NumPlanes(fPlaneConfig); }
int numChannelsInPlane(int i) const { return NumChannelsInPlane(fPlaneConfig, i); }
/**
* Given a set of channel flags for each plane , converts this - > planeConfig ( ) to YUVALocations
* representation . Fails if the channel flags aren ' t valid for the PlaneConfig ( i . e . don ' t have
* enough channels in a plane ) by returning default initialized locations ( all plane indices are
* - 1 ) .
*/
YUVALocations toYUVALocations(const uint32_t* channelFlags) const ;
/**
* Makes a SkYUVAInfo that is identical to this one but with the passed Subsampling . If the
* passed Subsampling is not k444 and this info ' s PlaneConfig is not compatible with chroma
* subsampling ( because Y is in the same plane as UV ) then the result will be an invalid
* SkYUVAInfo .
*/
SkYUVAInfo makeSubsampling(SkYUVAInfo::Subsampling) const ;
/**
* Makes a SkYUVAInfo that is identical to this one but with the passed dimensions . If the
* passed dimensions is empty then the result will be an invalid SkYUVAInfo .
*/
SkYUVAInfo makeDimensions(SkISize) const ;
bool operator ==(const SkYUVAInfo& that) const ;
bool operator !=(const SkYUVAInfo& that) const { return !(*this == that); }
bool isValid() const { return fPlaneConfig != PlaneConfig::kUnknown; }
private :
SkISize fDimensions = {0 , 0 };
PlaneConfig fPlaneConfig = PlaneConfig::kUnknown;
Subsampling fSubsampling = Subsampling::kUnknown;
SkYUVColorSpace fYUVColorSpace = SkYUVColorSpace::kIdentity_SkYUVColorSpace;
/**
* YUVA data often comes from formats like JPEG that support EXIF orientation .
* Code that operates on the raw YUV data often needs to know that orientation .
*/
SkEncodedOrigin fOrigin = kTopLeft_SkEncodedOrigin;
Siting fSitingX = Siting::kCentered;
Siting fSitingY = Siting::kCentered;
};
constexpr int SkYUVAInfo::NumPlanes(PlaneConfig planeConfig) {
switch (planeConfig) {
case PlaneConfig::kUnknown: return 0 ;
case PlaneConfig::kY_U_V: return 3 ;
case PlaneConfig::kY_V_U: return 3 ;
case PlaneConfig::kY_UV: return 2 ;
case PlaneConfig::kY_VU: return 2 ;
case PlaneConfig::kYUV: return 1 ;
case PlaneConfig::kUYV: return 1 ;
case PlaneConfig::kY_U_V_A: return 4 ;
case PlaneConfig::kY_V_U_A: return 4 ;
case PlaneConfig::kY_UV_A: return 3 ;
case PlaneConfig::kY_VU_A: return 3 ;
case PlaneConfig::kYUVA: return 1 ;
case PlaneConfig::kUYVA: return 1 ;
}
SkUNREACHABLE;
}
constexpr int SkYUVAInfo::NumChannelsInPlane(PlaneConfig config, int i) {
switch (config) {
case PlaneConfig::kUnknown:
return 0 ;
case SkYUVAInfo::PlaneConfig::kY_U_V:
case SkYUVAInfo::PlaneConfig::kY_V_U:
return i >= 0 && i < 3 ? 1 : 0 ;
case SkYUVAInfo::PlaneConfig::kY_UV:
case SkYUVAInfo::PlaneConfig::kY_VU:
switch (i) {
case 0 : return 1 ;
case 1 : return 2 ;
default : return 0 ;
}
case SkYUVAInfo::PlaneConfig::kYUV:
case SkYUVAInfo::PlaneConfig::kUYV:
return i == 0 ? 3 : 0 ;
case SkYUVAInfo::PlaneConfig::kY_U_V_A:
case SkYUVAInfo::PlaneConfig::kY_V_U_A:
return i >= 0 && i < 4 ? 1 : 0 ;
case SkYUVAInfo::PlaneConfig::kY_UV_A:
case SkYUVAInfo::PlaneConfig::kY_VU_A:
switch (i) {
case 0 : return 1 ;
case 1 : return 2 ;
case 2 : return 1 ;
default : return 0 ;
}
case SkYUVAInfo::PlaneConfig::kYUVA:
case SkYUVAInfo::PlaneConfig::kUYVA:
return i == 0 ? 4 : 0 ;
}
return 0 ;
}
#endif
Messung V0.5 in Prozent C=85 H=98 G=91
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-08-26)
¤
*© Formatika GbR, Deutschland