jpayne@69: // Copyright 2022 Google Inc. All Rights Reserved. jpayne@69: // jpayne@69: // Use of this source code is governed by a BSD-style license jpayne@69: // that can be found in the COPYING file in the root of the source jpayne@69: // tree. An additional intellectual property rights grant can be found jpayne@69: // in the file PATENTS. All contributing project authors may jpayne@69: // be found in the AUTHORS file in the root of the source tree. jpayne@69: // ----------------------------------------------------------------------------- jpayne@69: // jpayne@69: // Sharp RGB to YUV conversion. jpayne@69: jpayne@69: #ifndef WEBP_SHARPYUV_SHARPYUV_H_ jpayne@69: #define WEBP_SHARPYUV_SHARPYUV_H_ jpayne@69: jpayne@69: #ifdef __cplusplus jpayne@69: extern "C" { jpayne@69: #endif jpayne@69: jpayne@69: #ifndef SHARPYUV_EXTERN jpayne@69: #ifdef WEBP_EXTERN jpayne@69: #define SHARPYUV_EXTERN WEBP_EXTERN jpayne@69: #else jpayne@69: // This explicitly marks library functions and allows for changing the jpayne@69: // signature for e.g., Windows DLL builds. jpayne@69: #if defined(_WIN32) && defined(WEBP_DLL) jpayne@69: #define SHARPYUV_EXTERN __declspec(dllexport) jpayne@69: #elif defined(__GNUC__) && __GNUC__ >= 4 jpayne@69: #define SHARPYUV_EXTERN extern __attribute__((visibility("default"))) jpayne@69: #else jpayne@69: #define SHARPYUV_EXTERN extern jpayne@69: #endif /* defined(_WIN32) && defined(WEBP_DLL) */ jpayne@69: #endif /* WEBP_EXTERN */ jpayne@69: #endif /* SHARPYUV_EXTERN */ jpayne@69: jpayne@69: #ifndef SHARPYUV_INLINE jpayne@69: #ifdef WEBP_INLINE jpayne@69: #define SHARPYUV_INLINE WEBP_INLINE jpayne@69: #else jpayne@69: #ifndef _MSC_VER jpayne@69: #if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ jpayne@69: (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) jpayne@69: #define SHARPYUV_INLINE inline jpayne@69: #else jpayne@69: #define SHARPYUV_INLINE jpayne@69: #endif jpayne@69: #else jpayne@69: #define SHARPYUV_INLINE __forceinline jpayne@69: #endif /* _MSC_VER */ jpayne@69: #endif /* WEBP_INLINE */ jpayne@69: #endif /* SHARPYUV_INLINE */ jpayne@69: jpayne@69: // SharpYUV API version following the convention from semver.org jpayne@69: #define SHARPYUV_VERSION_MAJOR 0 jpayne@69: #define SHARPYUV_VERSION_MINOR 4 jpayne@69: #define SHARPYUV_VERSION_PATCH 1 jpayne@69: // Version as a uint32_t. The major number is the high 8 bits. jpayne@69: // The minor number is the middle 8 bits. The patch number is the low 16 bits. jpayne@69: #define SHARPYUV_MAKE_VERSION(MAJOR, MINOR, PATCH) \ jpayne@69: (((MAJOR) << 24) | ((MINOR) << 16) | (PATCH)) jpayne@69: #define SHARPYUV_VERSION \ jpayne@69: SHARPYUV_MAKE_VERSION(SHARPYUV_VERSION_MAJOR, SHARPYUV_VERSION_MINOR, \ jpayne@69: SHARPYUV_VERSION_PATCH) jpayne@69: jpayne@69: // Returns the library's version number, packed in hexadecimal. See jpayne@69: // SHARPYUV_VERSION. jpayne@69: SHARPYUV_EXTERN int SharpYuvGetVersion(void); jpayne@69: jpayne@69: // RGB to YUV conversion matrix, in 16 bit fixed point. jpayne@69: // y_ = rgb_to_y[0] * r + rgb_to_y[1] * g + rgb_to_y[2] * b + rgb_to_y[3] jpayne@69: // u_ = rgb_to_u[0] * r + rgb_to_u[1] * g + rgb_to_u[2] * b + rgb_to_u[3] jpayne@69: // v_ = rgb_to_v[0] * r + rgb_to_v[1] * g + rgb_to_v[2] * b + rgb_to_v[3] jpayne@69: // Then the values are divided by 1<<16 and rounded. jpayne@69: // y = (y_ + (1 << 15)) >> 16 jpayne@69: // u = (u_ + (1 << 15)) >> 16 jpayne@69: // v = (v_ + (1 << 15)) >> 16 jpayne@69: // jpayne@69: // Typically, the offset values rgb_to_y[3], rgb_to_u[3] and rgb_to_v[3] depend jpayne@69: // on the input's bit depth, e.g., rgb_to_u[3] = 1 << (rgb_bit_depth - 1 + 16). jpayne@69: // See also sharpyuv_csp.h to get a predefined matrix or generate a matrix. jpayne@69: typedef struct { jpayne@69: int rgb_to_y[4]; jpayne@69: int rgb_to_u[4]; jpayne@69: int rgb_to_v[4]; jpayne@69: } SharpYuvConversionMatrix; jpayne@69: jpayne@69: typedef struct SharpYuvOptions SharpYuvOptions; jpayne@69: jpayne@69: // Enums for transfer functions, as defined in H.273, jpayne@69: // https://www.itu.int/rec/T-REC-H.273-202107-I/en jpayne@69: typedef enum SharpYuvTransferFunctionType { jpayne@69: // 0 is reserved jpayne@69: kSharpYuvTransferFunctionBt709 = 1, jpayne@69: // 2 is unspecified jpayne@69: // 3 is reserved jpayne@69: kSharpYuvTransferFunctionBt470M = 4, jpayne@69: kSharpYuvTransferFunctionBt470Bg = 5, jpayne@69: kSharpYuvTransferFunctionBt601 = 6, jpayne@69: kSharpYuvTransferFunctionSmpte240 = 7, jpayne@69: kSharpYuvTransferFunctionLinear = 8, jpayne@69: kSharpYuvTransferFunctionLog100 = 9, jpayne@69: kSharpYuvTransferFunctionLog100_Sqrt10 = 10, jpayne@69: kSharpYuvTransferFunctionIec61966 = 11, jpayne@69: kSharpYuvTransferFunctionBt1361 = 12, jpayne@69: kSharpYuvTransferFunctionSrgb = 13, jpayne@69: kSharpYuvTransferFunctionBt2020_10Bit = 14, jpayne@69: kSharpYuvTransferFunctionBt2020_12Bit = 15, jpayne@69: kSharpYuvTransferFunctionSmpte2084 = 16, // PQ jpayne@69: kSharpYuvTransferFunctionSmpte428 = 17, jpayne@69: kSharpYuvTransferFunctionHlg = 18, jpayne@69: kSharpYuvTransferFunctionNum jpayne@69: } SharpYuvTransferFunctionType; jpayne@69: jpayne@69: // Converts RGB to YUV420 using a downsampling algorithm that minimizes jpayne@69: // artefacts caused by chroma subsampling. jpayne@69: // This is slower than standard downsampling (averaging of 4 UV values). jpayne@69: // Assumes that the image will be upsampled using a bilinear filter. If nearest jpayne@69: // neighbor is used instead, the upsampled image might look worse than with jpayne@69: // standard downsampling. jpayne@69: // r_ptr, g_ptr, b_ptr: pointers to the source r, g and b channels. Should point jpayne@69: // to uint8_t buffers if rgb_bit_depth is 8, or uint16_t buffers otherwise. jpayne@69: // rgb_step: distance in bytes between two horizontally adjacent pixels on the jpayne@69: // r, g and b channels. If rgb_bit_depth is > 8, it should be a jpayne@69: // multiple of 2. jpayne@69: // rgb_stride: distance in bytes between two vertically adjacent pixels on the jpayne@69: // r, g, and b channels. If rgb_bit_depth is > 8, it should be a jpayne@69: // multiple of 2. jpayne@69: // rgb_bit_depth: number of bits for each r/g/b value. One of: 8, 10, 12, 16. jpayne@69: // Note: 16 bit input is truncated to 14 bits before conversion to yuv. jpayne@69: // yuv_bit_depth: number of bits for each y/u/v value. One of: 8, 10, 12. jpayne@69: // y_ptr, u_ptr, v_ptr: pointers to the destination y, u and v channels. Should jpayne@69: // point to uint8_t buffers if yuv_bit_depth is 8, or uint16_t buffers jpayne@69: // otherwise. jpayne@69: // y_stride, u_stride, v_stride: distance in bytes between two vertically jpayne@69: // adjacent pixels on the y, u and v channels. If yuv_bit_depth > 8, they jpayne@69: // should be multiples of 2. jpayne@69: // width, height: width and height of the image in pixels jpayne@69: // yuv_matrix: RGB to YUV conversion matrix. The matrix values typically jpayne@69: // depend on the input's rgb_bit_depth. jpayne@69: // This function calls SharpYuvConvertWithOptions with a default transfer jpayne@69: // function of kSharpYuvTransferFunctionSrgb. jpayne@69: SHARPYUV_EXTERN int SharpYuvConvert(const void* r_ptr, const void* g_ptr, jpayne@69: const void* b_ptr, int rgb_step, jpayne@69: int rgb_stride, int rgb_bit_depth, jpayne@69: void* y_ptr, int y_stride, void* u_ptr, jpayne@69: int u_stride, void* v_ptr, int v_stride, jpayne@69: int yuv_bit_depth, int width, int height, jpayne@69: const SharpYuvConversionMatrix* yuv_matrix); jpayne@69: jpayne@69: struct SharpYuvOptions { jpayne@69: // This matrix cannot be NULL and can be initialized by jpayne@69: // SharpYuvComputeConversionMatrix. jpayne@69: const SharpYuvConversionMatrix* yuv_matrix; jpayne@69: SharpYuvTransferFunctionType transfer_type; jpayne@69: }; jpayne@69: jpayne@69: // Internal, version-checked, entry point jpayne@69: SHARPYUV_EXTERN int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix*, jpayne@69: SharpYuvOptions*, int); jpayne@69: jpayne@69: // Should always be called, to initialize a fresh SharpYuvOptions jpayne@69: // structure before modification. SharpYuvOptionsInit() must have succeeded jpayne@69: // before using the 'options' object. jpayne@69: static SHARPYUV_INLINE int SharpYuvOptionsInit( jpayne@69: const SharpYuvConversionMatrix* yuv_matrix, SharpYuvOptions* options) { jpayne@69: return SharpYuvOptionsInitInternal(yuv_matrix, options, SHARPYUV_VERSION); jpayne@69: } jpayne@69: jpayne@69: SHARPYUV_EXTERN int SharpYuvConvertWithOptions( jpayne@69: const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step, jpayne@69: int rgb_stride, int rgb_bit_depth, void* y_ptr, int y_stride, void* u_ptr, jpayne@69: int u_stride, void* v_ptr, int v_stride, int yuv_bit_depth, int width, jpayne@69: int height, const SharpYuvOptions* options); jpayne@69: jpayne@69: // TODO(b/194336375): Add YUV444 to YUV420 conversion. Maybe also add 422 jpayne@69: // support (it's rarely used in practice, especially for images). jpayne@69: jpayne@69: #ifdef __cplusplus jpayne@69: } // extern "C" jpayne@69: #endif jpayne@69: jpayne@69: #endif // WEBP_SHARPYUV_SHARPYUV_H_