skia2/include/core/SkYUVAInfo.h
Brian Salomon 87d42e5d12 A new way to specify YUVA planar data from SkCodec to SkImage_Lazy
Tunnels through SkImageGenerator as well.

The new SkCodec interface doesn't assume three 8 bit planes.

New SkYUVASpec more clearly defines chroma subsampling and siting of
the planes.

The intent is to use this for other YUVA APIs as well, in particular
SkImage factories in the future.

In this change we convert to the SkYUVASpec to SkYUVASizeInfo
and SkYUVAIndex[4] representation. But the intent is to use
the SkYUVASpec representation throughout the pipeline once
legacy APIs are removed.

orientation GM is replicated to test a variety of chroma
subsampling configs.

Bug: skia:10632

Change-Id: I3fad35752b87cac16c51b24824331f2ae7d458d3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/309658
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
2020-08-24 14:25:32 +00:00

148 lines
5.5 KiB
C++

/*
* 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/SkSize.h"
/**
* 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:
/**
* 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
*
* 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 {
kY_U_V_444, ///< Plane 0: Y, Plane 1: U, Plane 2: V
kY_U_V_422, ///< Plane 0: Y, Plane 1: U, Plane 2: V
kY_U_V_420, ///< Plane 0: Y, Plane 1: U, Plane 2: V
kY_U_V_440, ///< Plane 0: Y, Plane 1: U, Plane 2: V
kY_U_V_411, ///< Plane 0: Y, Plane 1: U, Plane 2: V
kY_U_V_410, ///< Plane 0: Y, Plane 1: U, Plane 2: V
};
/**
* 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;
/**
* Given a plane configuration, origin, and image dimensions, determine the expected size of
* each plane. Returns the number of expected planes. planeDims[0] through planeDims[<ret>] are
* written. The input image dimensions are as displayed (after the planes have been transformed
* to the intended display orientation).
*/
static int ExpectedPlaneDims(PlanarConfig,
SkEncodedOrigin,
SkISize imageDims,
SkISize planeDims[kMaxPlanes]);
/** Number of planes for a given PlanarConfig. */
static int NumPlanes(PlanarConfig);
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,
PlanarConfig,
SkYUVColorSpace,
SkEncodedOrigin origin,
Siting sitingX = Siting::kCentered,
Siting sitingY = Siting::kCentered);
SkYUVAInfo& operator=(const SkYUVAInfo& that) = default;
PlanarConfig planarConfig() const { return fPlanarConfig; }
/**
* 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; }
/**
* Returns the number of planes and initializes planeDims[0]..planeDims[<ret>] to the expected
* dimensions for each plane.
*/
int expectedPlaneDims(SkISize planeDims[kMaxPlanes]) const {
return ExpectedPlaneDims(fPlanarConfig, fOrigin, fDimensions, planeDims);
}
/**
* Given a per-plane row bytes, determine size to allocate for all planes. Optionally retrieves
* the per-plane 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(fPlanarConfig); }
bool operator==(const SkYUVAInfo& that) const;
bool operator!=(const SkYUVAInfo& that) const { return !(*this == that); }
private:
SkISize fDimensions = {0, 0};
PlanarConfig fPlanarConfig = PlanarConfig::kY_U_V_444;
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;
};
#endif