Split SkYUVAInfo::PlanarConfig into PlaneConfig and Subsampling enums

Sometimes it's helpful to think about subsampling separately from
how the channels are spread across planes.

Bug: skia:10632
Change-Id: Ib03f71195f9706ef6def418b1f2125c29e0cf738
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/334102
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Brian Salomon 2020-11-11 16:34:19 -05:00 committed by Skia Commit-Bot
parent 70eba23828
commit e4387382c2
15 changed files with 456 additions and 251 deletions

View File

@ -7,6 +7,10 @@ This file includes a list of high level updates for each milestone release.
Milestone 88
------------
* SkYUVAInfo now has separate enums for division of channels among planes and
the subsampling. The previous combined enum, PlanarConfig, is deprecated.
https://review.skia.org/334102
* Simplified SkDeferredDisplayListRecorder promise image API. Removed "release"
callback and renamed "done" callback to "release". The new "release" proc can
be null. Added a new SkYUVAInfo-based factory for YUVA promise texture images

View File

@ -166,7 +166,10 @@ static sk_sp<SkImage> make_yuv_420(GrRecordingContext* rContext,
int const strides[],
SkYUVColorSpace yuvSpace,
sk_sp<SkColorSpace> cs) {
SkYUVAInfo yuvaInfo({w, h}, SkYUVAInfo::PlanarConfig::kY_U_V_420, yuvSpace);
SkYUVAInfo yuvaInfo({w, h},
SkYUVAInfo::PlaneConfig::kY_U_V,
SkYUVAInfo::Subsampling::k420,
yuvSpace);
SkPixmap pixmaps[3];
pixmaps[0].reset(SkImageInfo::MakeA8(w, h), data[0], strides[0]);
w = (w + 1)/2;

View File

@ -94,7 +94,10 @@ static sk_sp<SkImage> do_read_and_scale_yuv(Src* src,
if (!asyncContext.fResult) {
return nullptr;
}
SkYUVAInfo yuvaInfo(size, SkYUVAInfo::PlanarConfig::kY_U_V_420, yuvCS);
SkYUVAInfo yuvaInfo(size,
SkYUVAInfo::PlaneConfig::kY_U_V,
SkYUVAInfo::Subsampling::k420,
yuvCS);
SkPixmap yuvPMs[] = {
{yII, asyncContext.fResult->data(0), asyncContext.fResult->rowBytes(0)},
{uvII, asyncContext.fResult->data(1), asyncContext.fResult->rowBytes(1)},

View File

@ -61,7 +61,8 @@ protected:
bmp = copy;
}
SkYUVAPixmapInfo pixmapInfo({bmp.dimensions(),
SkYUVAInfo::PlanarConfig::kY_U_V_A_4204,
SkYUVAInfo::PlaneConfig::kY_U_V_A,
SkYUVAInfo::Subsampling::k420,
kJPEG_Full_SkYUVColorSpace},
SkYUVAPixmapInfo::DataType::kUnorm8,
nullptr);

View File

@ -123,51 +123,63 @@ public:
case kP016F_YUVFormat:
case kNV12_YUVFormat:
if (opaque) {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kY_UV_420;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kY_UV;
fSubsampling = SkYUVAInfo::Subsampling::k420;
} else {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kY_UV_A_4204;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kY_UV_A;
fSubsampling = SkYUVAInfo::Subsampling::k420;
}
break;
case kY416_YUVFormat:
case kY410_YUVFormat:
if (opaque) {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kUYV_444;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kUYV;
fSubsampling = SkYUVAInfo::Subsampling::k444;
} else {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kUYVA_4444;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kUYVA;
fSubsampling = SkYUVAInfo::Subsampling::k444;
}
break;
case kAYUV_YUVFormat:
if (opaque) {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kYUV_444;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kYUV;
fSubsampling = SkYUVAInfo::Subsampling::k444;
} else {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kYUVA_4444;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kYUVA;
fSubsampling = SkYUVAInfo::Subsampling::k444;
}
break;
case kNV21_YUVFormat:
if (opaque) {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kY_VU_420;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kY_VU;
fSubsampling = SkYUVAInfo::Subsampling::k420;
} else {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kY_VU_A_4204;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kY_VU_A;
fSubsampling = SkYUVAInfo::Subsampling::k420;
}
break;
case kI420_YUVFormat:
if (opaque) {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kY_U_V_420;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kY_U_V;
fSubsampling = SkYUVAInfo::Subsampling::k420;
} else {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kY_U_V_A_4204;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kY_U_V_A;
fSubsampling = SkYUVAInfo::Subsampling::k420;
}
break;
case kYV12_YUVFormat:
if (opaque) {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kY_V_U_420;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kY_V_U;
fSubsampling = SkYUVAInfo::Subsampling::k420;
} else {
fPlanarConfig = SkYUVAInfo::PlanarConfig::kY_V_U_A_4204;
fPlaneConfig = SkYUVAInfo::PlaneConfig::kY_V_U_A;
fSubsampling = SkYUVAInfo::Subsampling::k420;
}
break;
}
}
int numPlanes() const { return SkYUVAInfo::NumPlanes(fPlanarConfig); }
int numPlanes() const { return SkYUVAInfo::NumPlanes(fPlaneConfig); }
SkYUVAPixmaps makeYUVAPixmaps(SkISize dimensions,
SkYUVColorSpace yuvColorSpace,
@ -175,14 +187,15 @@ public:
int numBitmaps) const;
private:
SkYUVAInfo::PlanarConfig fPlanarConfig;
SkYUVAInfo::PlaneConfig fPlaneConfig;
SkYUVAInfo::Subsampling fSubsampling;
};
SkYUVAPixmaps YUVAPlanarConfig::makeYUVAPixmaps(SkISize dimensions,
SkYUVColorSpace yuvColorSpace,
const SkBitmap bitmaps[],
int numBitmaps) const {
SkYUVAInfo info(dimensions, fPlanarConfig, yuvColorSpace);
SkYUVAInfo info(dimensions, fPlaneConfig, fSubsampling, yuvColorSpace);
SkPixmap pmaps[SkYUVAInfo::kMaxPlanes];
int n = info.numPlanes();
if (numBitmaps < n) {
@ -1198,7 +1211,10 @@ protected:
for (auto cs : {kRec709_SkYUVColorSpace, kRec601_SkYUVColorSpace, kJPEG_SkYUVColorSpace,
kBT2020_SkYUVColorSpace}) {
split_into_yuv(fOrig.get(), cs, fPM);
SkYUVAInfo yuvaInfo(fOrig->dimensions(), SkYUVAInfo::PlanarConfig::kY_U_V_444, cs);
SkYUVAInfo yuvaInfo(fOrig->dimensions(),
SkYUVAInfo::PlaneConfig::kY_U_V,
SkYUVAInfo::Subsampling::k444,
cs);
auto yuvaPixmaps = SkYUVAPixmaps::FromExternalPixmaps(yuvaInfo, fPM);
auto img = SkImage::MakeFromYUVAPixmaps(canvas->recordingContext(),
yuvaPixmaps,

View File

@ -13,6 +13,8 @@
#include "include/core/SkSize.h"
#include "include/core/SkYUVAIndex.h"
#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.
@ -20,6 +22,59 @@
class SK_API SkYUVAInfo {
public:
/**
* 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
* 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
};
/**
* Deprecated in favor of separate PlaneConfig and Subsampling enums.
*
* 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
@ -34,9 +89,6 @@ public:
* 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). A fourth number is added if alpha
* is present (always 4 as only full resolution alpha is supported).
*
* Currently this only has three-plane formats but more will be added as usage and testing of
* this expands.
*/
enum class PlanarConfig {
kUnknown,
@ -65,6 +117,9 @@ public:
kUYVA_4444, ///< Plane 0: UYVA
};
static constexpr std::tuple<PlaneConfig, Subsampling>
PlanarConfigToPlaneConfigAndSubsampling(PlanarConfig);
/**
* Describes how subsampled chroma values are sited relative to luma values.
*
@ -80,37 +135,39 @@ public:
static constexpr int kMaxPlanes = 4;
/**
* Given image dimensions, a planar configuration, and origin, determine the expected size of
* each plane. Returns the number of expected planes. planeDimensions[0] through
* planeDimensons[<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 stored in memory.
* 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,
PlanarConfig,
PlaneConfig,
Subsampling ,
SkEncodedOrigin,
SkISize planeDimensions[kMaxPlanes]);
/** Number of planes for a given PlanarConfig. */
static constexpr int NumPlanes(PlanarConfig);
/** 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 PlanarConfig (or 0 if i is
* 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(PlanarConfig, int i);
static constexpr int NumChannelsInPlane(PlaneConfig, int i);
/**
* Given a PlanarConfig and a set of channel flags for each plane, convert to SkYUVAIndex
* representation. Fails if channel flags aren't valid for the PlanarConfig (i.e. don't have
* Given a PlaneConfig and a set of channel flags for each plane, convert to SkYUVAIndex
* representation. Fails if channel flags aren't valid for the PlaneConfig (i.e. don't have
* enough channels in a plane).
*/
static bool GetYUVAIndices(PlanarConfig,
static bool GetYUVAIndices(PlaneConfig,
const uint32_t planeChannelFlags[kMaxPlanes],
SkYUVAIndex indices[SkYUVAIndex::kIndexCount]);
/** Does the PlanarConfig have alpha values? */
static bool HasAlpha(PlanarConfig);
/** Does the PlaneConfig have alpha values? */
static bool HasAlpha(PlaneConfig);
SkYUVAInfo() = default;
SkYUVAInfo(const SkYUVAInfo&) = default;
@ -119,6 +176,20 @@ public:
* '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);
/**
* Deprecated in favor of constructor that takes PlaneConfig and Subsampling.
*
* '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,
PlanarConfig,
SkYUVColorSpace,
@ -128,7 +199,14 @@ public:
SkYUVAInfo& operator=(const SkYUVAInfo& that) = default;
PlanarConfig planarConfig() const { return fPlanarConfig; }
PlaneConfig planeConfig() const { return fPlaneConfig; }
Subsampling subsampling() const { return fSubsampling; }
/**
* Deprecated. May return kUnknown even if this is valid because not all valid PlaneConfig/
* Subsampling pairs have am equivalent PlanarConfig value.
*/
PlanarConfig planarConfig() const;
/**
* Dimensions of the full resolution image (after planes have been oriented to how the image
@ -144,7 +222,7 @@ public:
SkEncodedOrigin origin() const { return fOrigin; }
bool hasAlpha() const { return HasAlpha(fPlanarConfig); }
bool hasAlpha() const { return HasAlpha(fPlaneConfig); }
/**
* Returns the number of planes and initializes planeDimensions[0]..planeDimensions[<ret>] to
@ -152,7 +230,7 @@ public:
* transformation to image display space as indicated by origin().
*/
int planeDimensions(SkISize planeDimensions[kMaxPlanes]) const {
return PlaneDimensions(fDimensions, fPlanarConfig, fOrigin, planeDimensions);
return PlaneDimensions(fDimensions, fPlaneConfig, fSubsampling, fOrigin, planeDimensions);
}
/**
@ -163,28 +241,29 @@ public:
size_t computeTotalBytes(const size_t rowBytes[kMaxPlanes],
size_t planeSizes[kMaxPlanes] = nullptr) const;
int numPlanes() const { return NumPlanes(fPlanarConfig); }
int numPlanes() const { return NumPlanes(fPlaneConfig); }
int numChannelsInPlane(int i) const { return NumChannelsInPlane(fPlanarConfig, i); }
int numChannelsInPlane(int i) const { return NumChannelsInPlane(fPlaneConfig, i); }
/**
* Given a set of channel flags for each plane, converts this->planarConfig() to SkYUVAIndex
* representation. Fails if the channel flags aren't valid for the PlanarConfig (i.e. don't have
* representation. Fails if the channel flags aren't valid for the PlaneConfig (i.e. don't have
* enough channels in a plane).
*/
bool toYUVAIndices(const uint32_t channelFlags[4], SkYUVAIndex indices[4]) const {
return GetYUVAIndices(fPlanarConfig, channelFlags, indices);
return GetYUVAIndices(fPlaneConfig, channelFlags, indices);
}
bool operator==(const SkYUVAInfo& that) const;
bool operator!=(const SkYUVAInfo& that) const { return !(*this == that); }
bool isValid() const { return fPlanarConfig != PlanarConfig::kUnknown; }
bool isValid() const { return fPlaneConfig != PlaneConfig::kUnknown; }
private:
SkISize fDimensions = {0, 0};
PlanarConfig fPlanarConfig = PlanarConfig::kUnknown;
PlaneConfig fPlaneConfig = PlaneConfig::kUnknown;
Subsampling fSubsampling = Subsampling::kUnknown;
SkYUVColorSpace fYUVColorSpace = SkYUVColorSpace::kIdentity_SkYUVColorSpace;
@ -198,74 +277,87 @@ private:
Siting fSitingY = Siting::kCentered;
};
constexpr int SkYUVAInfo::NumPlanes(PlanarConfig planarConfig) {
switch (planarConfig) {
case PlanarConfig::kUnknown: return 0;
case PlanarConfig::kY_U_V_444: return 3;
case PlanarConfig::kY_U_V_422: return 3;
case PlanarConfig::kY_U_V_420: return 3;
case PlanarConfig::kY_V_U_420: return 3;
case PlanarConfig::kY_U_V_440: return 3;
case PlanarConfig::kY_U_V_411: return 3;
case PlanarConfig::kY_U_V_410: return 3;
case PlanarConfig::kY_U_V_A_4204: return 4;
case PlanarConfig::kY_V_U_A_4204: return 4;
case PlanarConfig::kY_UV_420: return 2;
case PlanarConfig::kY_VU_420: return 2;
case PlanarConfig::kY_UV_A_4204: return 3;
case PlanarConfig::kY_VU_A_4204: return 3;
case PlanarConfig::kYUV_444: return 1;
case PlanarConfig::kUYV_444: return 1;
case PlanarConfig::kYUVA_4444: return 1;
case PlanarConfig::kUYVA_4444: return 1;
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(PlanarConfig config, int i) {
constexpr int SkYUVAInfo::NumChannelsInPlane(PlaneConfig config, int i) {
switch (config) {
case PlanarConfig::kUnknown:
case PlaneConfig::kUnknown:
return 0;
case SkYUVAInfo::PlanarConfig::kY_U_V_444:
case SkYUVAInfo::PlanarConfig::kY_U_V_422:
case SkYUVAInfo::PlanarConfig::kY_U_V_420:
case SkYUVAInfo::PlanarConfig::kY_V_U_420:
case SkYUVAInfo::PlanarConfig::kY_U_V_440:
case SkYUVAInfo::PlanarConfig::kY_U_V_411:
case SkYUVAInfo::PlanarConfig::kY_U_V_410:
case SkYUVAInfo::PlaneConfig::kY_U_V:
case SkYUVAInfo::PlaneConfig::kY_V_U:
return i >= 0 && i < 3 ? 1 : 0;
case SkYUVAInfo::PlanarConfig::kY_U_V_A_4204:
case SkYUVAInfo::PlanarConfig::kY_V_U_A_4204:
return i >= 0 && i < 4 ? 1 : 0;
case SkYUVAInfo::PlanarConfig::kY_UV_420:
case SkYUVAInfo::PlanarConfig::kY_VU_420:
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::PlanarConfig::kY_UV_A_4204:
case SkYUVAInfo::PlanarConfig::kY_VU_A_4204:
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::PlanarConfig::kYUV_444:
case SkYUVAInfo::PlanarConfig::kUYV_444:
return i == 0 ? 3 : 0;
case SkYUVAInfo::PlanarConfig::kYUVA_4444:
case SkYUVAInfo::PlanarConfig::kUYVA_4444:
case SkYUVAInfo::PlaneConfig::kYUVA:
case SkYUVAInfo::PlaneConfig::kUYVA:
return i == 0 ? 4 : 0;
}
return 0;
}
constexpr std::tuple<SkYUVAInfo::PlaneConfig, SkYUVAInfo::Subsampling>
SkYUVAInfo::PlanarConfigToPlaneConfigAndSubsampling(PlanarConfig planarConfig) {
switch (planarConfig) {
case PlanarConfig::kUnknown:
return {PlaneConfig::kUnknown, Subsampling ::kUnknown};
case PlanarConfig::kY_U_V_444: return {PlaneConfig::kY_U_V, Subsampling::k444};
case PlanarConfig::kY_U_V_422: return {PlaneConfig::kY_U_V, Subsampling::k422};
case PlanarConfig::kY_U_V_420: return {PlaneConfig::kY_U_V, Subsampling::k420};
case PlanarConfig::kY_V_U_420: return {PlaneConfig::kY_V_U, Subsampling::k420};
case PlanarConfig::kY_U_V_440: return {PlaneConfig::kY_U_V, Subsampling::k440};
case PlanarConfig::kY_U_V_411: return {PlaneConfig::kY_U_V, Subsampling::k411};
case PlanarConfig::kY_U_V_410: return {PlaneConfig::kY_U_V, Subsampling::k410};
case PlanarConfig::kY_U_V_A_4204: return {PlaneConfig::kY_U_V_A, Subsampling::k420};
case PlanarConfig::kY_V_U_A_4204: return {PlaneConfig::kY_V_U_A, Subsampling::k420};
case PlanarConfig::kY_UV_420: return {PlaneConfig::kY_UV, Subsampling::k420};
case PlanarConfig::kY_VU_420: return {PlaneConfig::kY_VU, Subsampling::k420};
case PlanarConfig::kY_UV_A_4204: return {PlaneConfig::kY_UV_A, Subsampling::k420};
case PlanarConfig::kY_VU_A_4204: return {PlaneConfig::kY_VU_A, Subsampling::k420};
case PlanarConfig::kYUV_444: return {PlaneConfig::kYUV, Subsampling::k444};
case PlanarConfig::kUYV_444: return {PlaneConfig::kUYV, Subsampling::k444};
case PlanarConfig::kYUVA_4444: return {PlaneConfig::kYUVA, Subsampling::k444};
case PlanarConfig::kUYVA_4444: return {PlaneConfig::kUYVA, Subsampling::k444};
}
SkUNREACHABLE;
}
#endif

View File

@ -29,6 +29,8 @@ class SK_API SkYUVAPixmapInfo {
public:
static constexpr auto kMaxPlanes = SkYUVAInfo::kMaxPlanes;
using PlaneConfig = SkYUVAInfo::PlaneConfig;
using Subsampling = SkYUVAInfo::Subsampling;
using PlanarConfig = SkYUVAInfo::PlanarConfig;
/**
@ -53,13 +55,16 @@ public:
/** Init based on texture formats supported by the context. */
SupportedDataTypes(const GrImageContext&);
/** All legal combinations of PlanarConfig and DataType are supported. */
/** All legal combinations of PlaneConfig and DataType are supported. */
static constexpr SupportedDataTypes All();
/**
* Checks whether there is a supported combination of color types for planes structured
* as indicated by PlanarConfig with channel data types as indicated by DataType.
* as indicated by PlaneConfig with channel data types as indicated by DataType.
*/
constexpr bool supported(PlaneConfig, DataType) const;
/** Deprecated. Use PlaneConfig version. */
constexpr bool supported(PlanarConfig, DataType) const;
/**
@ -152,7 +157,7 @@ public:
* Returns true if this has been configured with a non-empty dimensioned SkYUVAInfo with
* compatible color types and row bytes.
*/
bool isValid() const { return fPlaneInfos[0].colorType() != kUnknown_SkColorType; }
bool isValid() const { return fYUVAInfo.isValid(); }
/** Is this valid and does it use color types allowed by the passed SupportedDataTypes? */
bool isSupported(const SupportedDataTypes&) const;
@ -281,7 +286,7 @@ constexpr SkYUVAPixmapInfo::SupportedDataTypes SkYUVAPixmapInfo::SupportedDataTy
return combinations;
}
constexpr bool SkYUVAPixmapInfo::SupportedDataTypes::supported(PlanarConfig config,
constexpr bool SkYUVAPixmapInfo::SupportedDataTypes::supported(PlaneConfig config,
DataType type) const {
int n = SkYUVAInfo::NumPlanes(config);
for (int i = 0; i < n; ++i) {
@ -295,6 +300,12 @@ constexpr bool SkYUVAPixmapInfo::SupportedDataTypes::supported(PlanarConfig conf
return true;
}
constexpr bool SkYUVAPixmapInfo::SupportedDataTypes::supported(PlanarConfig planarConfig,
DataType type) const {
auto pc = std::get<0>(SkYUVAInfo::PlanarConfigToPlaneConfigAndSubsampling(planarConfig));
return this->supported(pc, type);
}
constexpr SkColorType SkYUVAPixmapInfo::DefaultColorTypeForDataType(DataType dataType,
int numChannels) {
switch (numChannels) {

View File

@ -23,8 +23,6 @@ class SK_API GrYUVABackendTextureInfo {
public:
static constexpr auto kMaxPlanes = SkYUVAInfo::kMaxPlanes;
using PlanarConfig = SkYUVAInfo::PlanarConfig;
/** Default GrYUVABackendTextureInfo is invalid. */
GrYUVABackendTextureInfo() = default;

View File

@ -796,24 +796,25 @@ static bool is_yuv_supported(const jpeg_decompress_struct* dinfo,
SkASSERT(hSampY == dinfo->max_h_samp_factor);
SkASSERT(vSampY == dinfo->max_v_samp_factor);
SkYUVAInfo::PlanarConfig tempPlanarConfig;
SkYUVAInfo::Subsampling tempSubsampling;
if (1 == hSampY && 1 == vSampY) {
tempPlanarConfig = SkYUVAInfo::PlanarConfig::kY_U_V_444;
tempSubsampling = SkYUVAInfo::Subsampling::k444;
} else if (2 == hSampY && 1 == vSampY) {
tempPlanarConfig = SkYUVAInfo::PlanarConfig::kY_U_V_422;
tempSubsampling = SkYUVAInfo::Subsampling::k422;
} else if (2 == hSampY && 2 == vSampY) {
tempPlanarConfig = SkYUVAInfo::PlanarConfig::kY_U_V_420;
tempSubsampling = SkYUVAInfo::Subsampling::k420;
} else if (1 == hSampY && 2 == vSampY) {
tempPlanarConfig = SkYUVAInfo::PlanarConfig::kY_U_V_440;
tempSubsampling = SkYUVAInfo::Subsampling::k440;
} else if (4 == hSampY && 1 == vSampY) {
tempPlanarConfig = SkYUVAInfo::PlanarConfig::kY_U_V_411;
tempSubsampling = SkYUVAInfo::Subsampling::k411;
} else if (4 == hSampY && 2 == vSampY) {
tempPlanarConfig = SkYUVAInfo::PlanarConfig::kY_U_V_410;
tempSubsampling = SkYUVAInfo::Subsampling::k410;
} else {
return false;
}
if (supportedDataTypes &&
!supportedDataTypes->supported(tempPlanarConfig, SkYUVAPixmapInfo::DataType::kUnorm8)) {
!supportedDataTypes->supported(SkYUVAInfo::PlaneConfig::kY_U_V,
SkYUVAPixmapInfo::DataType::kUnorm8)) {
return false;
}
if (yuvaPixmapInfo) {
@ -824,7 +825,8 @@ static bool is_yuv_supported(const jpeg_decompress_struct* dinfo,
rowBytes[i] = dinfo->comp_info[i].width_in_blocks * DCTSIZE;
}
SkYUVAInfo yuvaInfo(codec.dimensions(),
tempPlanarConfig,
SkYUVAInfo::PlaneConfig::kY_U_V,
tempSubsampling,
kJPEG_Full_SkYUVColorSpace,
codec.getOrigin(),
SkYUVAInfo::Siting::kCentered,

View File

@ -8,10 +8,31 @@
#include "include/core/SkYUVAInfo.h"
#include "src/core/SkSafeMath.h"
#include <algorithm>
static bool is_plane_config_compatible_with_subsampling(SkYUVAInfo::PlaneConfig config,
SkYUVAInfo::Subsampling subsampling) {
if (config == SkYUVAInfo::PlaneConfig::kUnknown ||
subsampling == SkYUVAInfo::Subsampling::kUnknown) {
return false;
}
return subsampling == SkYUVAInfo::Subsampling::k444 ||
(config != SkYUVAInfo::PlaneConfig::kYUV &&
config != SkYUVAInfo::PlaneConfig::kYUVA &&
config != SkYUVAInfo::PlaneConfig::kUYV &&
config != SkYUVAInfo::PlaneConfig::kUYVA);
}
int SkYUVAInfo::PlaneDimensions(SkISize imageDimensions,
PlanarConfig planarConfig,
PlaneConfig planeConfig,
Subsampling subsampling,
SkEncodedOrigin origin,
SkISize planeDimensions[SkYUVAInfo::kMaxPlanes]) {
std::fill_n(planeDimensions, SkYUVAInfo::kMaxPlanes, SkISize{0, 0});
if (!is_plane_config_compatible_with_subsampling(planeConfig, subsampling)) {
return 0;
}
int w = imageDimensions.width();
int h = imageDimensions.height();
if (origin >= kLeftTop_SkEncodedOrigin) {
@ -20,66 +41,50 @@ int SkYUVAInfo::PlaneDimensions(SkISize imageDimensions,
}
auto down2 = [](int x) { return (x + 1)/2; };
auto down4 = [](int x) { return (x + 3)/4; };
switch (planarConfig) {
case PlanarConfig::kUnknown:
planeDimensions[0] =
planeDimensions[1] =
planeDimensions[2] =
planeDimensions[3] = {0, 0};
return 0;
case PlanarConfig::kY_U_V_444:
planeDimensions[0] = planeDimensions[1] = planeDimensions[2] = {w, h};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_422:
SkISize uvSize;
switch (subsampling) {
case Subsampling::kUnknown: SkUNREACHABLE;
case Subsampling::k444: uvSize = { w , h }; break;
case Subsampling::k422: uvSize = {down2(w), h }; break;
case Subsampling::k420: uvSize = {down2(w), down2(h)}; break;
case Subsampling::k440: uvSize = { w , down2(h)}; break;
case Subsampling::k411: uvSize = {down4(w), h }; break;
case Subsampling::k410: uvSize = {down4(w), down2(h)}; break;
}
switch (planeConfig) {
case PlaneConfig::kUnknown: SkUNREACHABLE;
case PlaneConfig::kY_U_V:
case PlaneConfig::kY_V_U:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = {down2(w), h};
planeDimensions[3] = {0, 0};
planeDimensions[1] = planeDimensions[2] = uvSize;
return 3;
case PlanarConfig::kY_U_V_420:
case PlanarConfig::kY_V_U_420:
case PlaneConfig::kY_UV:
case PlaneConfig::kY_VU:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = {down2(w), down2(h)};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_UV_A_4204:
case PlanarConfig::kY_VU_A_4204:
planeDimensions[0] = planeDimensions[2] = {w, h};
planeDimensions[1] = {down2(w), down2(h)};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_440:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = {w, down2(h)};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_411:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = {down4(w), h};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_410:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = {down4(w), down2(h)};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_A_4204:
case PlanarConfig::kY_V_U_A_4204:
planeDimensions[0] = planeDimensions[3] = {w, h};
planeDimensions[1] = planeDimensions[2] = {down2(w), down2(h)};
return 4;
case PlanarConfig::kY_UV_420:
case PlanarConfig::kY_VU_420:
planeDimensions[0] = {w, h};
planeDimensions[1] = {down2(w), down2(h)};
planeDimensions[2] = planeDimensions[3] = {0, 0};
planeDimensions[1] = uvSize;
return 2;
case PlanarConfig::kYUV_444:
case PlanarConfig::kUYV_444:
case PlanarConfig::kYUVA_4444:
case PlanarConfig::kUYVA_4444:
case PlaneConfig::kY_U_V_A:
case PlaneConfig::kY_V_U_A:
planeDimensions[0] = planeDimensions[3] = {w, h};
planeDimensions[1] = planeDimensions[2] = uvSize;
return 4;
case PlaneConfig::kY_UV_A:
case PlaneConfig::kY_VU_A:
planeDimensions[0] = planeDimensions[2] = {w, h};
planeDimensions[1] = uvSize;
return 3;
case PlaneConfig::kYUV:
case PlaneConfig::kUYV:
case PlaneConfig::kYUVA:
case PlaneConfig::kUYVA:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = planeDimensions[3] = {0, 0};
SkASSERT(planeDimensions[0] == uvSize);
return 1;
}
SkUNREACHABLE;
@ -125,76 +130,71 @@ static bool channel_index_to_channel(uint32_t channelFlags,
}
}
bool SkYUVAInfo::GetYUVAIndices(PlanarConfig config,
bool SkYUVAInfo::GetYUVAIndices(PlaneConfig config,
const uint32_t planeChannelFlags[kMaxPlanes],
SkYUVAIndex indices[SkYUVAIndex::kIndexCount]) {
struct Location {int plane, chanIdx;};
const Location* locations = nullptr;
switch (config) {
case PlanarConfig::kUnknown:
case PlaneConfig::kUnknown:
return false;
case PlanarConfig::kY_U_V_444:
case PlanarConfig::kY_U_V_422:
case PlanarConfig::kY_U_V_420:
case PlanarConfig::kY_U_V_440:
case PlanarConfig::kY_U_V_411:
case PlanarConfig::kY_U_V_410: {
case PlaneConfig::kY_U_V: {
static constexpr Location kLocations[] = {{0, 0}, {1, 0}, {2, 0}, {-1, -1}};
locations = kLocations;
break;
}
case PlanarConfig::kY_V_U_420: {
case PlaneConfig::kY_V_U: {
static constexpr Location kLocations[] = {{0, 0}, {2, 0}, {1, 0}, {-1, -1}};
locations = kLocations;
break;
}
case PlanarConfig::kY_U_V_A_4204: {
static constexpr Location kLocations[] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}};
locations = kLocations;
break;
}
case PlanarConfig::kY_V_U_A_4204: {
static constexpr Location kLocations[] = {{0, 0}, {2, 0}, {1, 0}, {3, 0}};
locations = kLocations;
break;
}
case PlanarConfig::kY_UV_420: {
case PlaneConfig::kY_UV: {
static constexpr Location kLocations[] = {{0, 0}, {1, 0}, {1, 1}, {-1, -1}};
locations = kLocations;
break;
}
case PlanarConfig::kY_VU_420: {
case PlaneConfig::kY_VU: {
static constexpr Location kLocations[] = {{0, 0}, {1, 1}, {1, 0}, {-1, -1}};
locations = kLocations;
break;
}
case PlanarConfig::kY_UV_A_4204: {
static constexpr Location kLocations[] = {{0, 0}, {1, 0}, {1, 1}, {2, 0}};
locations = kLocations;
break;
}
case PlanarConfig::kY_VU_A_4204: {
static constexpr Location kLocations[] = {{0, 0}, {1, 1}, {1, 0}, {2, 0}};
locations = kLocations;
break;
}
case PlanarConfig::kYUV_444: {
case PlaneConfig::kYUV: {
static constexpr Location kLocations[] = {{0, 0}, {0, 1}, {0, 2}, {-1, -1}};
locations = kLocations;
break;
}
case PlanarConfig::kUYV_444: {
case PlaneConfig::kUYV: {
static constexpr Location kLocations[] = {{0, 1}, {0, 0}, {0, 2}, {-1, -1}};
locations = kLocations;
break;
}
case PlanarConfig::kYUVA_4444: {
case PlaneConfig::kY_U_V_A: {
static constexpr Location kLocations[] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}};
locations = kLocations;
break;
}
case PlaneConfig::kY_V_U_A: {
static constexpr Location kLocations[] = {{0, 0}, {2, 0}, {1, 0}, {3, 0}};
locations = kLocations;
break;
}
case PlaneConfig::kY_UV_A: {
static constexpr Location kLocations[] = {{0, 0}, {1, 0}, {1, 1}, {2, 0}};
locations = kLocations;
break;
}
case PlaneConfig::kY_VU_A: {
static constexpr Location kLocations[] = {{0, 0}, {1, 1}, {1, 0}, {2, 0}};
locations = kLocations;
break;
}
case PlaneConfig::kYUVA: {
static constexpr Location kLocations[] = {{0, 0}, {0, 1}, {0, 2}, {0, 3}};
locations = kLocations;
break;
}
case PlanarConfig::kUYVA_4444: {
case PlaneConfig::kUYVA: {
static constexpr Location kLocations[] = {{0, 1}, {0, 0}, {0, 2}, {0, 3}};
locations = kLocations;
break;
@ -217,56 +217,58 @@ bool SkYUVAInfo::GetYUVAIndices(PlanarConfig config,
return true;
}
bool SkYUVAInfo::HasAlpha(PlanarConfig planarConfig) {
switch (planarConfig) {
case PlanarConfig::kUnknown: return false;
bool SkYUVAInfo::HasAlpha(PlaneConfig planeConfig) {
switch (planeConfig) {
case PlaneConfig::kUnknown: return false;
case PlanarConfig::kY_U_V_444: return false;
case PlanarConfig::kY_U_V_422: return false;
case PlanarConfig::kY_U_V_420: return false;
case PlanarConfig::kY_V_U_420: return false;
case PlanarConfig::kY_U_V_440: return false;
case PlanarConfig::kY_U_V_411: return false;
case PlanarConfig::kY_U_V_410: return false;
case PlaneConfig::kY_U_V: return false;
case PlaneConfig::kY_V_U: return false;
case PlaneConfig::kY_UV: return false;
case PlaneConfig::kY_VU: return false;
case PlaneConfig::kYUV: return false;
case PlaneConfig::kUYV: return false;
case PlanarConfig::kY_U_V_A_4204: return true;
case PlanarConfig::kY_V_U_A_4204: return true;
case PlanarConfig::kY_UV_420: return false;
case PlanarConfig::kY_VU_420: return false;
case PlanarConfig::kY_UV_A_4204: return true;
case PlanarConfig::kY_VU_A_4204: return true;
case PlanarConfig::kYUV_444: return false;
case PlanarConfig::kUYV_444: return false;
case PlanarConfig::kYUVA_4444: return true;
case PlanarConfig::kUYVA_4444: return true;
case PlaneConfig::kY_U_V_A: return true;
case PlaneConfig::kY_V_U_A: return true;
case PlaneConfig::kY_UV_A: return true;
case PlaneConfig::kY_VU_A: return true;
case PlaneConfig::kYUVA: return true;
case PlaneConfig::kUYVA: return true;
}
SkUNREACHABLE;
}
SkYUVAInfo::SkYUVAInfo(SkISize dimensions,
PlaneConfig planeConfig,
Subsampling subsampling,
SkYUVColorSpace yuvColorSpace,
SkEncodedOrigin origin,
Siting sitingX,
Siting sitingY)
: fDimensions(dimensions)
, fPlaneConfig(planeConfig)
, fSubsampling(subsampling)
, fYUVColorSpace(yuvColorSpace)
, fOrigin(origin)
, fSitingX(sitingX)
, fSitingY(sitingY) {
if (fDimensions.isEmpty() ||
!is_plane_config_compatible_with_subsampling(planeConfig, subsampling)) {
*this = {};
SkASSERT(!this->isValid());
return;
}
SkASSERT(this->isValid());
}
SkYUVAInfo::SkYUVAInfo(SkISize dimensions,
PlanarConfig planarConfig,
SkYUVColorSpace yuvColorSpace,
SkEncodedOrigin origin,
Siting sitingX,
Siting sitingY)
: fDimensions(dimensions)
, fPlanarConfig(planarConfig)
, fYUVColorSpace(yuvColorSpace)
, fOrigin(origin)
, fSitingX(sitingX)
, fSitingY(sitingY) {
if (fDimensions.width() <= 0 ||
fDimensions.height() <= 0 ||
planarConfig == PlanarConfig::kUnknown) {
*this = {};
SkASSERT(!this->isValid());
return;
}
SkASSERT(this->isValid());
Siting sitingY) {
auto [c, s] = PlanarConfigToPlaneConfigAndSubsampling(planarConfig);
*this = SkYUVAInfo(dimensions, c, s, yuvColorSpace, origin, sitingX, sitingY);
}
size_t SkYUVAInfo::computeTotalBytes(const size_t rowBytes[kMaxPlanes],
@ -302,8 +304,75 @@ size_t SkYUVAInfo::computeTotalBytes(const size_t rowBytes[kMaxPlanes],
return safe.ok() ? totalBytes : SIZE_MAX;
}
SkYUVAInfo::PlanarConfig SkYUVAInfo::planarConfig() const {
SkASSERT(!this->isValid() || is_plane_config_compatible_with_subsampling(fPlaneConfig,
fSubsampling));
switch (fPlaneConfig) {
case PlaneConfig::kUnknown: return PlanarConfig::kUnknown;
case PlaneConfig::kY_U_V:
switch (fSubsampling) {
case Subsampling::kUnknown: SkUNREACHABLE;
case Subsampling::k444: return PlanarConfig::kY_U_V_444;
case Subsampling::k422: return PlanarConfig::kY_U_V_422;
case Subsampling::k420: return PlanarConfig::kY_U_V_420;
case Subsampling::k440: return PlanarConfig::kY_U_V_440;
case Subsampling::k411: return PlanarConfig::kY_U_V_411;
case Subsampling::k410: return PlanarConfig::kY_U_V_410;
}
SkUNREACHABLE;
case PlaneConfig::kY_V_U:
return fSubsampling == Subsampling::k420 ? PlanarConfig::kY_V_U_420
: PlanarConfig::kUnknown;
case PlaneConfig::kY_UV:
return fSubsampling == Subsampling::k420 ? PlanarConfig::kY_UV_420
: PlanarConfig::kUnknown;
case PlaneConfig::kY_VU:
return fSubsampling == Subsampling::k420 ? PlanarConfig::kY_VU_420
: PlanarConfig::kUnknown;
case PlaneConfig::kYUV:
SkASSERT(fSubsampling == Subsampling::k444);
return PlanarConfig::kYUV_444;
case PlaneConfig::kUYV:
SkASSERT(fSubsampling == Subsampling::k444);
return PlanarConfig::kUYV_444;
case PlaneConfig::kY_U_V_A:
return fSubsampling == Subsampling::k420 ? PlanarConfig::kY_U_V_A_4204
: PlanarConfig::kUnknown;
case PlaneConfig::kY_V_U_A:
return fSubsampling == Subsampling::k420 ? PlanarConfig::kY_V_U_A_4204
: PlanarConfig::kUnknown;
case PlaneConfig::kY_UV_A:
return fSubsampling == Subsampling::k420 ? PlanarConfig::kY_UV_A_4204
: PlanarConfig::kUnknown;
case PlaneConfig::kY_VU_A:
return fSubsampling == Subsampling::k420 ? PlanarConfig::kY_VU_A_4204
: PlanarConfig::kUnknown;
case PlaneConfig::kYUVA:
SkASSERT(fSubsampling == Subsampling::k444);
return PlanarConfig::kYUVA_4444;
case PlaneConfig::kUYVA:
SkASSERT(fSubsampling == Subsampling::k444);
return PlanarConfig::kUYVA_4444;
}
SkUNREACHABLE;
}
bool SkYUVAInfo::operator==(const SkYUVAInfo& that) const {
return fPlanarConfig == that.fPlanarConfig &&
return fPlaneConfig == that.fPlaneConfig &&
fSubsampling == that.fSubsampling &&
fYUVColorSpace == that.fYUVColorSpace &&
fDimensions == that.fDimensions &&
fSitingX == that.fSitingX &&

View File

@ -172,7 +172,7 @@ bool SkYUVAPixmapInfo::isSupported(const SupportedDataTypes& supportedDataTypes)
if (!this->isValid()) {
return false;
}
return supportedDataTypes.supported(fYUVAInfo.planarConfig(), fDataType);
return supportedDataTypes.supported(fYUVAInfo.planeConfig(), fDataType);
}
//////////////////////////////////////////////////////////////////////////////

View File

@ -67,7 +67,8 @@ DEF_TEST(ImageGenerator, reporter) {
// Check that the YUV decoding API does not cause any crashes
ig.queryYUVAInfo(SkYUVAPixmapInfo::SupportedDataTypes::All(), &yuvaPixmapInfo);
SkYUVAInfo yuvaInfo({250, 250},
SkYUVAInfo::PlanarConfig::kY_UV_420,
SkYUVAInfo::PlaneConfig::kY_UV,
SkYUVAInfo::Subsampling::k420,
kJPEG_Full_SkYUVColorSpace);
yuvaPixmapInfo = SkYUVAPixmapInfo(yuvaInfo,
SkYUVAPixmapInfo::DataType::kUnorm8,

View File

@ -1372,7 +1372,10 @@ DEF_TEST(Image_nonfinite_dst, reporter) {
static sk_sp<SkImage> make_yuva_image(GrDirectContext* dContext) {
SkAutoPixmapStorage pm;
pm.alloc(SkImageInfo::Make(1, 1, kAlpha_8_SkColorType, kPremul_SkAlphaType));
SkYUVAInfo yuvaInfo({1, 1}, SkYUVAInfo::PlanarConfig::kY_U_V_444, kJPEG_Full_SkYUVColorSpace);
SkYUVAInfo yuvaInfo({1, 1},
SkYUVAInfo::PlaneConfig::kY_U_V,
SkYUVAInfo::Subsampling::k444,
kJPEG_Full_SkYUVColorSpace);
const SkPixmap pmaps[] = {pm, pm, pm};
auto yuvaPixmaps = SkYUVAPixmaps::FromExternalPixmaps(yuvaInfo, pmaps);

View File

@ -34,7 +34,8 @@ DEF_TEST(YUVPlanesCache, reporter) {
SkResourceCache cache(1024);
SkYUVAInfo yuvaInfo({5, 5},
SkYUVAInfo::PlanarConfig::kY_U_V_420,
SkYUVAInfo::PlaneConfig::kY_U_V,
SkYUVAInfo::Subsampling::k420,
kRec601_Limited_SkYUVColorSpace);
SkYUVAPixmapInfo yuvaPixmapInfo(yuvaInfo,
SkYUVAPixmapInfo::DataType::kUnorm8,

View File

@ -82,39 +82,40 @@ static void codec_yuv(skiatest::Reporter* reporter,
}
DEF_TEST(Jpeg_YUV_Codec, r) {
auto setExpectations = [](SkISize dims, SkYUVAInfo::PlanarConfig planarConfig) {
auto setExpectations = [](SkISize dims, SkYUVAInfo::Subsampling subsampling) {
return SkYUVAInfo(dims,
planarConfig,
SkYUVAInfo::PlaneConfig::kY_U_V,
subsampling,
kJPEG_Full_SkYUVColorSpace,
kTopLeft_SkEncodedOrigin,
SkYUVAInfo::Siting::kCentered,
SkYUVAInfo::Siting::kCentered);
};
SkYUVAInfo expectations = setExpectations({128, 128}, SkYUVAInfo::PlanarConfig::kY_U_V_420);
SkYUVAInfo expectations = setExpectations({128, 128}, SkYUVAInfo::Subsampling::k420);
codec_yuv(r, "images/color_wheel.jpg", &expectations);
// H2V2
expectations = setExpectations({512, 512}, SkYUVAInfo::PlanarConfig::kY_U_V_420);
expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k420);
codec_yuv(r, "images/mandrill_512_q075.jpg", &expectations);
// H1V1
expectations = setExpectations({512, 512}, SkYUVAInfo::PlanarConfig::kY_U_V_444);
expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k444);
codec_yuv(r, "images/mandrill_h1v1.jpg", &expectations);
// H2V1
expectations = setExpectations({512, 512}, SkYUVAInfo::PlanarConfig::kY_U_V_422);
expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k422);
codec_yuv(r, "images/mandrill_h2v1.jpg", &expectations);
// Non-power of two dimensions
expectations = setExpectations({439, 154}, SkYUVAInfo::PlanarConfig::kY_U_V_420);
expectations = setExpectations({439, 154}, SkYUVAInfo::Subsampling::k420);
codec_yuv(r, "images/cropped_mandrill.jpg", &expectations);
expectations = setExpectations({8, 8}, SkYUVAInfo::PlanarConfig::kY_U_V_420);
expectations = setExpectations({8, 8}, SkYUVAInfo::Subsampling::k420);
codec_yuv(r, "images/randPixels.jpg", &expectations);
// Progressive images
expectations = setExpectations({512, 512}, SkYUVAInfo::PlanarConfig::kY_U_V_444);
expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k444);
codec_yuv(r, "images/brickwork-texture.jpg", &expectations);
codec_yuv(r, "images/brickwork_normal-map.jpg", &expectations);