| 351 | } |
| 352 | |
| 353 | avifResult avifImageApplyExpression(avifImage * dstImage, |
| 354 | avifSampleTransformBitDepth bitDepth, |
| 355 | const avifSampleTransformExpression * expression, |
| 356 | uint8_t numInputImageItems, |
| 357 | const avifImage * inputImageItems[], |
| 358 | avifPlanesFlags planes) |
| 359 | { |
| 360 | // Check that the expression is valid. |
| 361 | AVIF_ASSERT_OR_RETURN(avifSampleTransformExpressionIsValid(expression, numInputImageItems)); |
| 362 | const avifBool skipColor = !(planes & AVIF_PLANES_YUV); |
| 363 | const avifBool skipAlpha = !(planes & AVIF_PLANES_A); |
| 364 | for (int c = AVIF_CHAN_Y; c <= AVIF_CHAN_A; ++c) { |
| 365 | const avifBool alpha = c == AVIF_CHAN_A; |
| 366 | if ((skipColor && !alpha) || (skipAlpha && alpha)) { |
| 367 | continue; |
| 368 | } |
| 369 | |
| 370 | const uint32_t planeWidth = avifImagePlaneWidth(dstImage, c); |
| 371 | const uint32_t planeHeight = avifImagePlaneHeight(dstImage, c); |
| 372 | for (uint32_t i = 0; i < numInputImageItems; ++i) { |
| 373 | AVIF_CHECKERR(avifImagePlaneWidth(inputImageItems[i], c) == planeWidth, AVIF_RESULT_BMFF_PARSE_FAILED); |
| 374 | AVIF_CHECKERR(avifImagePlaneHeight(inputImageItems[i], c) == planeHeight, AVIF_RESULT_BMFF_PARSE_FAILED); |
| 375 | } |
| 376 | } |
| 377 | |
| 378 | // Then apply it. This part should not fail except for memory shortage reasons. |
| 379 | if (bitDepth == AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_32) { |
| 380 | uint32_t stackCapacity = expression->count / 2 + 1; |
| 381 | int32_t * stack = avifAlloc(stackCapacity * sizeof(int32_t)); |
| 382 | AVIF_CHECKERR(stack != NULL, AVIF_RESULT_OUT_OF_MEMORY); |
| 383 | const avifResult result = avifImageApplyExpression32b(dstImage, expression, inputImageItems, planes, stack, stackCapacity); |
| 384 | avifFree(stack); |
| 385 | return result; |
| 386 | } |
| 387 | return AVIF_RESULT_NOT_IMPLEMENTED; |
| 388 | } |
| 389 | |
| 390 | avifResult avifImageApplyOperations(avifImage * dstImage, |
| 391 | avifSampleTransformBitDepth bitDepth, |