| // Copyright 2019 Joe Drago. All rights reserved. | 
 | // SPDX-License-Identifier: BSD-2-Clause | 
 |  | 
 | #include "avif/internal.h" | 
 |  | 
 | #if !defined(AVIF_LIBYUV_ENABLED) | 
 |  | 
 | // No libyuv! | 
 | avifResult avifImageYUVToRGBLibYUV(const avifImage * image, avifRGBImage * rgb) | 
 | { | 
 |     (void)image; | 
 |     (void)rgb; | 
 |     return AVIF_RESULT_NOT_IMPLEMENTED; | 
 | } | 
 | avifResult avifRGBImagePremultiplyAlphaLibYUV(avifRGBImage * rgb) | 
 | { | 
 |     (void)rgb; | 
 |     return AVIF_RESULT_NOT_IMPLEMENTED; | 
 | } | 
 | avifResult avifRGBImageUnpremultiplyAlphaLibYUV(avifRGBImage * rgb) | 
 | { | 
 |     (void)rgb; | 
 |     return AVIF_RESULT_NOT_IMPLEMENTED; | 
 | } | 
 | avifResult avifRGBImageToF16LibYUV(avifRGBImage * rgb) | 
 | { | 
 |     (void)rgb; | 
 |     return AVIF_RESULT_NOT_IMPLEMENTED; | 
 | } | 
 | unsigned int avifLibYUVVersion(void) | 
 | { | 
 |     return 0; | 
 | } | 
 |  | 
 | #else | 
 |  | 
 | #if defined(__clang__) | 
 | #pragma clang diagnostic push | 
 | #pragma clang diagnostic ignored "-Wstrict-prototypes" // "this function declaration is not a prototype" | 
 | #endif | 
 | #include <libyuv.h> | 
 | #if defined(__clang__) | 
 | #pragma clang diagnostic pop | 
 | #endif | 
 |  | 
 | avifResult avifImageYUVToRGBLibYUV(const avifImage * image, avifRGBImage * rgb) | 
 | { | 
 |     // See if the current settings can be accomplished with libyuv, and use it (if possible). | 
 |  | 
 |     if ((image->depth != 8) || (rgb->depth != 8)) { | 
 |         return AVIF_RESULT_NOT_IMPLEMENTED; | 
 |     } | 
 |  | 
 |     if ((rgb->chromaUpsampling != AVIF_CHROMA_UPSAMPLING_AUTOMATIC) && (rgb->chromaUpsampling != AVIF_CHROMA_UPSAMPLING_FASTEST)) { | 
 |         // libyuv uses its own upsampling filter. If the enduser chose a specific one, avoid using libyuv. | 
 |         return AVIF_RESULT_NOT_IMPLEMENTED; | 
 |     } | 
 |  | 
 |     // Find the correct libyuv YuvConstants, based on range and CP/MC | 
 |     const struct YuvConstants * matrixYUV = NULL; | 
 |     const struct YuvConstants * matrixYVU = NULL; | 
 |     if (image->yuvRange == AVIF_RANGE_FULL) { | 
 |         switch (image->matrixCoefficients) { | 
 |             // BT.709 full range YuvConstants were added in libyuv version 1772. | 
 |             // See https://chromium-review.googlesource.com/c/libyuv/libyuv/+/2646472. | 
 |             case AVIF_MATRIX_COEFFICIENTS_BT709: | 
 | #if LIBYUV_VERSION >= 1772 | 
 |                 matrixYUV = &kYuvF709Constants; | 
 |                 matrixYVU = &kYvuF709Constants; | 
 | #endif | 
 |                 break; | 
 |             case AVIF_MATRIX_COEFFICIENTS_BT470BG: | 
 |             case AVIF_MATRIX_COEFFICIENTS_BT601: | 
 |             case AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED: | 
 |                 matrixYUV = &kYuvJPEGConstants; | 
 |                 matrixYVU = &kYvuJPEGConstants; | 
 |                 break; | 
 |             // BT.2020 full range YuvConstants were added in libyuv version 1775. | 
 |             // See https://chromium-review.googlesource.com/c/libyuv/libyuv/+/2678859. | 
 |             case AVIF_MATRIX_COEFFICIENTS_BT2020_NCL: | 
 | #if LIBYUV_VERSION >= 1775 | 
 |                 matrixYUV = &kYuvV2020Constants; | 
 |                 matrixYVU = &kYvuV2020Constants; | 
 | #endif | 
 |                 break; | 
 |             case AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL: | 
 |                 switch (image->colorPrimaries) { | 
 |                     case AVIF_COLOR_PRIMARIES_BT709: | 
 |                     case AVIF_COLOR_PRIMARIES_UNSPECIFIED: | 
 | #if LIBYUV_VERSION >= 1772 | 
 |                         matrixYUV = &kYuvF709Constants; | 
 |                         matrixYVU = &kYvuF709Constants; | 
 | #endif | 
 |                         break; | 
 |                     case AVIF_COLOR_PRIMARIES_BT470BG: | 
 |                     case AVIF_COLOR_PRIMARIES_BT601: | 
 |                         matrixYUV = &kYuvJPEGConstants; | 
 |                         matrixYVU = &kYvuJPEGConstants; | 
 |                         break; | 
 |                     case AVIF_COLOR_PRIMARIES_BT2020: | 
 | #if LIBYUV_VERSION >= 1775 | 
 |                         matrixYUV = &kYuvV2020Constants; | 
 |                         matrixYVU = &kYvuV2020Constants; | 
 | #endif | 
 |                         break; | 
 |  | 
 |                     case AVIF_COLOR_PRIMARIES_UNKNOWN: | 
 |                     case AVIF_COLOR_PRIMARIES_BT470M: | 
 |                     case AVIF_COLOR_PRIMARIES_SMPTE240: | 
 |                     case AVIF_COLOR_PRIMARIES_GENERIC_FILM: | 
 |                     case AVIF_COLOR_PRIMARIES_XYZ: | 
 |                     case AVIF_COLOR_PRIMARIES_SMPTE431: | 
 |                     case AVIF_COLOR_PRIMARIES_SMPTE432: | 
 |                     case AVIF_COLOR_PRIMARIES_EBU3213: | 
 |                         break; | 
 |                 } | 
 |                 break; | 
 |  | 
 |             case AVIF_MATRIX_COEFFICIENTS_IDENTITY: | 
 |             case AVIF_MATRIX_COEFFICIENTS_FCC: | 
 |             case AVIF_MATRIX_COEFFICIENTS_SMPTE240: | 
 |             case AVIF_MATRIX_COEFFICIENTS_YCGCO: | 
 |             case AVIF_MATRIX_COEFFICIENTS_BT2020_CL: | 
 |             case AVIF_MATRIX_COEFFICIENTS_SMPTE2085: | 
 |             case AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL: | 
 |             case AVIF_MATRIX_COEFFICIENTS_ICTCP: | 
 |                 break; | 
 |         } | 
 |     } else { | 
 |         switch (image->matrixCoefficients) { | 
 |             case AVIF_MATRIX_COEFFICIENTS_BT709: | 
 |                 matrixYUV = &kYuvH709Constants; | 
 |                 matrixYVU = &kYvuH709Constants; | 
 |                 break; | 
 |             case AVIF_MATRIX_COEFFICIENTS_BT470BG: | 
 |             case AVIF_MATRIX_COEFFICIENTS_BT601: | 
 |             case AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED: | 
 |                 matrixYUV = &kYuvI601Constants; | 
 |                 matrixYVU = &kYvuI601Constants; | 
 |                 break; | 
 |             case AVIF_MATRIX_COEFFICIENTS_BT2020_NCL: | 
 |                 matrixYUV = &kYuv2020Constants; | 
 |                 matrixYVU = &kYvu2020Constants; | 
 |                 break; | 
 |             case AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL: | 
 |                 switch (image->colorPrimaries) { | 
 |                     case AVIF_COLOR_PRIMARIES_BT709: | 
 |                     case AVIF_COLOR_PRIMARIES_UNSPECIFIED: | 
 |                         matrixYUV = &kYuvH709Constants; | 
 |                         matrixYVU = &kYvuH709Constants; | 
 |                         break; | 
 |                     case AVIF_COLOR_PRIMARIES_BT470BG: | 
 |                     case AVIF_COLOR_PRIMARIES_BT601: | 
 |                         matrixYUV = &kYuvI601Constants; | 
 |                         matrixYVU = &kYvuI601Constants; | 
 |                         break; | 
 |                     case AVIF_COLOR_PRIMARIES_BT2020: | 
 |                         matrixYUV = &kYuv2020Constants; | 
 |                         matrixYVU = &kYvu2020Constants; | 
 |                         break; | 
 |  | 
 |                     case AVIF_COLOR_PRIMARIES_UNKNOWN: | 
 |                     case AVIF_COLOR_PRIMARIES_BT470M: | 
 |                     case AVIF_COLOR_PRIMARIES_SMPTE240: | 
 |                     case AVIF_COLOR_PRIMARIES_GENERIC_FILM: | 
 |                     case AVIF_COLOR_PRIMARIES_XYZ: | 
 |                     case AVIF_COLOR_PRIMARIES_SMPTE431: | 
 |                     case AVIF_COLOR_PRIMARIES_SMPTE432: | 
 |                     case AVIF_COLOR_PRIMARIES_EBU3213: | 
 |                         break; | 
 |                 } | 
 |                 break; | 
 |             case AVIF_MATRIX_COEFFICIENTS_IDENTITY: | 
 |             case AVIF_MATRIX_COEFFICIENTS_FCC: | 
 |             case AVIF_MATRIX_COEFFICIENTS_SMPTE240: | 
 |             case AVIF_MATRIX_COEFFICIENTS_YCGCO: | 
 |             case AVIF_MATRIX_COEFFICIENTS_BT2020_CL: | 
 |             case AVIF_MATRIX_COEFFICIENTS_SMPTE2085: | 
 |             case AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL: | 
 |             case AVIF_MATRIX_COEFFICIENTS_ICTCP: | 
 |                 break; | 
 |         } | 
 |     } | 
 |  | 
 |     if (!matrixYVU) { | 
 |         // No YuvConstants exist for the current image; use the built-in YUV conversion | 
 |         return AVIF_RESULT_NOT_IMPLEMENTED; | 
 |     } | 
 |  | 
 |     // This following section might be a bit complicated to audit without a bit of explanation: | 
 |     // | 
 |     // libavif uses byte-order when describing pixel formats, such that the R in RGBA is the lowest address, | 
 |     // similar to PNG. libyuv orders in word-order, so libavif's RGBA would be referred to in libyuv as ABGR. | 
 |     // In addition, swapping U and V in any of these calls, along with using the Yvu matrix instead of Yuv matrix, | 
 |     // swaps B and R in these orderings as well. This table summarizes this block's intent: | 
 |     // | 
 |     // libavif format        libyuv Func     UV matrix (and UV argument ordering) | 
 |     // --------------------  -------------   ------------------------------------ | 
 |     // AVIF_RGB_FORMAT_RGB   n/a             n/a | 
 |     // AVIF_RGB_FORMAT_BGR   n/a             n/a | 
 |     // AVIF_RGB_FORMAT_BGRA  *ToARGBMatrix   matrixYUV | 
 |     // AVIF_RGB_FORMAT_RGBA  *ToARGBMatrix   matrixYVU | 
 |     // AVIF_RGB_FORMAT_ABGR  *ToRGBAMatrix   matrixYUV | 
 |     // AVIF_RGB_FORMAT_ARGB  *ToRGBAMatrix   matrixYVU | 
 |  | 
 |     if (rgb->format == AVIF_RGB_FORMAT_BGRA) { | 
 |         // AVIF_RGB_FORMAT_BGRA  *ToARGBMatrix   matrixYUV | 
 |  | 
 |         if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV444) { | 
 |             if (I444ToARGBMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYUV, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422) { | 
 |             if (I422ToARGBMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYUV, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) { | 
 |             if (I420ToARGBMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYUV, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV400) { | 
 |             if (I400ToARGBMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYUV, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } | 
 |     } else if (rgb->format == AVIF_RGB_FORMAT_RGBA) { | 
 |         // AVIF_RGB_FORMAT_RGBA  *ToARGBMatrix   matrixYVU | 
 |  | 
 |         if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV444) { | 
 |             if (I444ToARGBMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYVU, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422) { | 
 |             if (I422ToARGBMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYVU, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) { | 
 |             if (I420ToARGBMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYVU, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV400) { | 
 |             if (I400ToARGBMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYVU, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } | 
 |     } else if (rgb->format == AVIF_RGB_FORMAT_ABGR) { | 
 |         // AVIF_RGB_FORMAT_ABGR  *ToRGBAMatrix   matrixYUV | 
 |  | 
 |         if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV444) { | 
 |             // This doesn't currently exist in libyuv | 
 | #if 0 | 
 |             if (I444ToRGBAMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYUV, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 | #endif | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422) { | 
 |             if (I422ToRGBAMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYUV, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) { | 
 |             if (I420ToRGBAMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYUV, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV400) { | 
 |             // This doesn't currently exist in libyuv | 
 | #if 0 | 
 |             if (I400ToRGBAMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYUV, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 | #endif | 
 |         } | 
 |     } else if (rgb->format == AVIF_RGB_FORMAT_ARGB) { | 
 |         // AVIF_RGB_FORMAT_ARGB  *ToRGBAMatrix   matrixYVU | 
 |  | 
 |         if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV444) { | 
 |             // This doesn't currently exist in libyuv | 
 | #if 0 | 
 |             if (I444ToRGBAMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYVU, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 | #endif | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422) { | 
 |             if (I422ToRGBAMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYVU, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) { | 
 |             if (I420ToRGBAMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  image->yuvPlanes[AVIF_CHAN_V], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_V], | 
 |                                  image->yuvPlanes[AVIF_CHAN_U], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_U], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYVU, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 |         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV400) { | 
 |             // This doesn't currently exist in libyuv | 
 | #if 0 | 
 |             if (I400ToRGBAMatrix(image->yuvPlanes[AVIF_CHAN_Y], | 
 |                                  image->yuvRowBytes[AVIF_CHAN_Y], | 
 |                                  rgb->pixels, | 
 |                                  rgb->rowBytes, | 
 |                                  matrixYVU, | 
 |                                  image->width, | 
 |                                  image->height) != 0) { | 
 |                 return AVIF_RESULT_REFORMAT_FAILED; | 
 |             } | 
 |             return AVIF_RESULT_OK; | 
 | #endif | 
 |         } | 
 |     } | 
 |  | 
 |     // This function didn't do anything; use the built-in YUV conversion | 
 |     return AVIF_RESULT_NOT_IMPLEMENTED; | 
 | } | 
 |  | 
 | avifResult avifRGBImagePremultiplyAlphaLibYUV(avifRGBImage * rgb) | 
 | { | 
 |     // See if the current settings can be accomplished with libyuv, and use it (if possible). | 
 |  | 
 |     if (rgb->depth != 8) { | 
 |         return AVIF_RESULT_NOT_IMPLEMENTED; | 
 |     } | 
 |  | 
 |     // libavif uses byte-order when describing pixel formats, such that the R in RGBA is the lowest address, | 
 |     // similar to PNG. libyuv orders in word-order, so libavif's RGBA would be referred to in libyuv as ABGR. | 
 |  | 
 |     // Order of RGB doesn't matter here. | 
 |     if (rgb->format == AVIF_RGB_FORMAT_RGBA || rgb->format == AVIF_RGB_FORMAT_BGRA) { | 
 |         if (ARGBAttenuate(rgb->pixels, rgb->rowBytes, rgb->pixels, rgb->rowBytes, rgb->width, rgb->height) != 0) { | 
 |             return AVIF_RESULT_REFORMAT_FAILED; | 
 |         } | 
 |         return AVIF_RESULT_OK; | 
 |     } | 
 |  | 
 |     return AVIF_RESULT_NOT_IMPLEMENTED; | 
 | } | 
 |  | 
 | avifResult avifRGBImageUnpremultiplyAlphaLibYUV(avifRGBImage * rgb) | 
 | { | 
 |     // See if the current settings can be accomplished with libyuv, and use it (if possible). | 
 |  | 
 |     if (rgb->depth != 8) { | 
 |         return AVIF_RESULT_NOT_IMPLEMENTED; | 
 |     } | 
 |  | 
 |     // libavif uses byte-order when describing pixel formats, such that the R in RGBA is the lowest address, | 
 |     // similar to PNG. libyuv orders in word-order, so libavif's RGBA would be referred to in libyuv as ABGR. | 
 |  | 
 |     if (rgb->format == AVIF_RGB_FORMAT_RGBA || rgb->format == AVIF_RGB_FORMAT_BGRA) { | 
 |         if (ARGBUnattenuate(rgb->pixels, rgb->rowBytes, rgb->pixels, rgb->rowBytes, rgb->width, rgb->height) != 0) { | 
 |             return AVIF_RESULT_REFORMAT_FAILED; | 
 |         } | 
 |         return AVIF_RESULT_OK; | 
 |     } | 
 |  | 
 |     return AVIF_RESULT_NOT_IMPLEMENTED; | 
 | } | 
 |  | 
 | avifResult avifRGBImageToF16LibYUV(avifRGBImage * rgb) | 
 | { | 
 |     const float scale = 1.0f / ((1 << rgb->depth) - 1); | 
 |     const int result = HalfFloatPlane((const uint16_t *)rgb->pixels, | 
 |                                       rgb->rowBytes, | 
 |                                       (uint16_t *)rgb->pixels, | 
 |                                       rgb->rowBytes, | 
 |                                       scale, | 
 |                                       rgb->width * avifRGBFormatChannelCount(rgb->format), | 
 |                                       rgb->height); | 
 |     return (result == 0) ? AVIF_RESULT_OK : AVIF_RESULT_INVALID_ARGUMENT; | 
 | } | 
 |  | 
 | unsigned int avifLibYUVVersion(void) | 
 | { | 
 |     return (unsigned int)LIBYUV_VERSION; | 
 | } | 
 |  | 
 | #endif |