| // Copyright 2022 Google LLC |
| // SPDX-License-Identifier: BSD-2-Clause |
| |
| #include "avif/internal.h" |
| |
| #if defined(AVIF_LIBSHARPYUV_ENABLED) |
| #include <limits.h> |
| #include <sharpyuv/sharpyuv.h> |
| #include <sharpyuv/sharpyuv_csp.h> |
| |
| avifResult avifImageRGBToYUVLibSharpYUV(avifImage * image, const avifRGBImage * rgb, const avifReformatState * state) |
| { |
| // The width, height, and stride parameters of SharpYuvConvertWithOptions() |
| // and SharpYuvConvert() are all of the int type. |
| if (rgb->width > INT_MAX || rgb->height > INT_MAX || rgb->rowBytes > INT_MAX || image->yuvRowBytes[AVIF_CHAN_Y] > INT_MAX) { |
| return AVIF_RESULT_NOT_IMPLEMENTED; |
| } |
| const SharpYuvColorSpace colorSpace = { |
| state->yuv.kr, state->yuv.kb, image->depth, (state->yuv.range == AVIF_RANGE_LIMITED) ? kSharpYuvRangeLimited : kSharpYuvRangeFull |
| }; |
| |
| SharpYuvConversionMatrix matrix; |
| // Fills in 'matrix' for the given YUVColorSpace. |
| SharpYuvComputeConversionMatrix(&colorSpace, &matrix); |
| #if SHARPYUV_VERSION >= SHARPYUV_MAKE_VERSION(0, 4, 0) |
| SharpYuvOptions options; |
| SharpYuvOptionsInit(&matrix, &options); |
| if (image->transferCharacteristics == AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED) { |
| // Set to sRGB for backward compatibility. |
| options.transfer_type = kSharpYuvTransferFunctionSrgb; |
| } else { |
| options.transfer_type = (SharpYuvTransferFunctionType)image->transferCharacteristics; |
| } |
| const int sharpyuvRes = SharpYuvConvertWithOptions(&rgb->pixels[state->rgb.offsetBytesR], |
| &rgb->pixels[state->rgb.offsetBytesG], |
| &rgb->pixels[state->rgb.offsetBytesB], |
| state->rgb.pixelBytes, |
| rgb->rowBytes, |
| rgb->depth, |
| 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], |
| image->depth, |
| rgb->width, |
| rgb->height, |
| &options); |
| #else |
| const int sharpyuvRes = SharpYuvConvert(&rgb->pixels[state->rgb.offsetBytesR], |
| &rgb->pixels[state->rgb.offsetBytesG], |
| &rgb->pixels[state->rgb.offsetBytesB], |
| state->rgb.pixelBytes, |
| rgb->rowBytes, |
| rgb->depth, |
| 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], |
| image->depth, |
| rgb->width, |
| rgb->height, |
| &matrix); |
| #endif // SHARPYUV_VERSION >= SHARPYUV_MAKE_VERSION(0, 4, 0) |
| if (!sharpyuvRes) { |
| return AVIF_RESULT_REFORMAT_FAILED; |
| } |
| |
| return AVIF_RESULT_OK; |
| } |
| |
| #else |
| |
| avifResult avifImageRGBToYUVLibSharpYUV(avifImage * image, const avifRGBImage * rgb, const avifReformatState * state) |
| { |
| (void)image; |
| (void)rgb; |
| (void)state; |
| return AVIF_RESULT_NOT_IMPLEMENTED; |
| } |
| #endif // defined(AVIF_LIBSHARPYUV_ENABLED) |