| 219 | } |
| 220 | |
| 221 | avifResult avifImageRGBToYUV(avifImage * image, const avifRGBImage * rgb) |
| 222 | { |
| 223 | if (!rgb->pixels || rgb->format == AVIF_RGB_FORMAT_RGB_565) { |
| 224 | return AVIF_RESULT_REFORMAT_FAILED; |
| 225 | } |
| 226 | |
| 227 | avifReformatState state; |
| 228 | if (!avifPrepareReformatState(image, rgb, &state)) { |
| 229 | return AVIF_RESULT_REFORMAT_FAILED; |
| 230 | } |
| 231 | |
| 232 | if (rgb->isFloat) { |
| 233 | return AVIF_RESULT_NOT_IMPLEMENTED; |
| 234 | } |
| 235 | |
| 236 | const avifBool hasAlpha = avifRGBFormatHasAlpha(rgb->format) && !rgb->ignoreAlpha; |
| 237 | avifResult allocationResult = avifImageAllocatePlanes(image, hasAlpha ? AVIF_PLANES_ALL : AVIF_PLANES_YUV); |
| 238 | if (allocationResult != AVIF_RESULT_OK) { |
| 239 | return allocationResult; |
| 240 | } |
| 241 | |
| 242 | avifAlphaMultiplyMode alphaMode = AVIF_ALPHA_MULTIPLY_MODE_NO_OP; |
| 243 | if (hasAlpha) { |
| 244 | if (!rgb->alphaPremultiplied && image->alphaPremultiplied) { |
| 245 | alphaMode = AVIF_ALPHA_MULTIPLY_MODE_MULTIPLY; |
| 246 | } else if (rgb->alphaPremultiplied && !image->alphaPremultiplied) { |
| 247 | alphaMode = AVIF_ALPHA_MULTIPLY_MODE_UNMULTIPLY; |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | const avifBool isGray = avifRGBFormatIsGray(rgb->format); |
| 252 | avifBool converted = AVIF_FALSE; |
| 253 | |
| 254 | // Try converting with libsharpyuv. |
| 255 | if (!isGray) { |
| 256 | if ((rgb->chromaDownsampling == AVIF_CHROMA_DOWNSAMPLING_SHARP_YUV) && (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420)) { |
| 257 | const avifResult libSharpYUVResult = avifImageRGBToYUVLibSharpYUV(image, rgb, &state); |
| 258 | if (libSharpYUVResult != AVIF_RESULT_OK) { |
| 259 | // Return the error if sharpyuv was requested but failed for any reason, including libsharpyuv not being available. |
| 260 | return libSharpYUVResult; |
| 261 | } |
| 262 | converted = AVIF_TRUE; |
| 263 | } |
| 264 | |
| 265 | if (!converted && !rgb->avoidLibYUV && (alphaMode == AVIF_ALPHA_MULTIPLY_MODE_NO_OP)) { |
| 266 | avifResult libyuvResult = avifImageRGBToYUVLibYUV(image, rgb); |
| 267 | if (libyuvResult == AVIF_RESULT_OK) { |
| 268 | converted = AVIF_TRUE; |
| 269 | } else if (libyuvResult != AVIF_RESULT_NOT_IMPLEMENTED) { |
| 270 | return libyuvResult; |
| 271 | } |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | if (!converted && !isGray) { |
| 276 | const float kr = state.yuv.kr; |
| 277 | const float kg = state.yuv.kg; |
| 278 | const float kb = state.yuv.kb; |