blob: a6bd523b0b14cbeb7bfc81c6a89f4391038f949d [file] [log] [blame]
// 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)