| 1440 | } |
| 1441 | |
| 1442 | static avifResult avifEncoderCreateSatoImage(avifEncoder * encoder, |
| 1443 | const avifEncoderItem * item, |
| 1444 | avifBool itemWillBeEncodedLosslessly, |
| 1445 | const avifImage * image, |
| 1446 | avifImage ** sampleTransformedImage) |
| 1447 | { |
| 1448 | const avifPlanesFlag planes = avifIsAlpha(item->itemCategory) ? AVIF_PLANES_A : AVIF_PLANES_YUV; |
| 1449 | // The first image item used as input to the 'sato' Sample Transform derived image item. |
| 1450 | avifBool isBase = item->itemCategory == AVIF_ITEM_COLOR || item->itemCategory == AVIF_ITEM_ALPHA; |
| 1451 | if (!isBase) { |
| 1452 | // The second image item used as input to the 'sato' Sample Transform derived image item. |
| 1453 | AVIF_ASSERT_OR_RETURN(item->itemCategory >= AVIF_SAMPLE_TRANSFORM_MIN_CATEGORY && |
| 1454 | item->itemCategory <= AVIF_SAMPLE_TRANSFORM_MAX_CATEGORY); |
| 1455 | } |
| 1456 | |
| 1457 | if (encoder->sampleTransformRecipe == AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_EXTENSION_8B_8B) { |
| 1458 | if (isBase) { |
| 1459 | AVIF_CHECKRES(avifImageCreateAllocate(sampleTransformedImage, image, 8, planes)); |
| 1460 | AVIF_CHECKRES(avifImageApplyImgOpConst(*sampleTransformedImage, image, AVIF_SAMPLE_TRANSFORM_QUOTIENT, 256, planes)); |
| 1461 | } else { |
| 1462 | AVIF_CHECKRES(avifImageCreateAllocate(sampleTransformedImage, image, 8, planes)); |
| 1463 | AVIF_CHECKRES(avifImageApplyImgOpConst(*sampleTransformedImage, image, AVIF_SAMPLE_TRANSFORM_AND, 255, planes)); |
| 1464 | } |
| 1465 | } else if (encoder->sampleTransformRecipe == AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_EXTENSION_12B_4B) { |
| 1466 | if (isBase) { |
| 1467 | AVIF_CHECKRES(avifImageCreateAllocate(sampleTransformedImage, image, 12, planes)); |
| 1468 | AVIF_CHECKRES(avifImageApplyImgOpConst(*sampleTransformedImage, image, AVIF_SAMPLE_TRANSFORM_QUOTIENT, 16, planes)); |
| 1469 | } else { |
| 1470 | AVIF_CHECKRES(avifImageCreateAllocate(sampleTransformedImage, image, 8, planes)); |
| 1471 | AVIF_CHECKRES(avifImageApplyImgOpConst(*sampleTransformedImage, image, AVIF_SAMPLE_TRANSFORM_AND, 15, planes)); |
| 1472 | // AVIF only supports 8, 10 or 12-bit image items. Scale the samples to fit the range. |
| 1473 | // Note: The samples could be encoded as is without being shifted left before encoding, |
| 1474 | // but they would not be shifted right after decoding either. Right shifting after |
| 1475 | // decoding provides a guarantee on the range of values and on the lack of integer |
| 1476 | // overflow, so it is safer to do these extra steps. |
| 1477 | // It also makes more sense from a compression point-of-view to use the full range. |
| 1478 | // Transform in-place. |
| 1479 | AVIF_CHECKRES( |
| 1480 | avifImageApplyImgOpConst(*sampleTransformedImage, *sampleTransformedImage, AVIF_SAMPLE_TRANSFORM_PRODUCT, 16, planes)); |
| 1481 | if (!itemWillBeEncodedLosslessly) { |
| 1482 | // Small loss at encoding could be amplified by the truncation caused by the right |
| 1483 | // shift after decoding. Offset sample values now, before encoding, to round rather |
| 1484 | // than floor the samples shifted after decoding. |
| 1485 | // Note: Samples were just left shifted by numShiftedBits, so adding less than |
| 1486 | // (1<<numShiftedBits) will not trigger any integer overflow. |
| 1487 | // Transform in-place. |
| 1488 | AVIF_CHECKRES( |
| 1489 | avifImageApplyImgOpConst(*sampleTransformedImage, *sampleTransformedImage, AVIF_SAMPLE_TRANSFORM_SUM, 7, planes)); |
| 1490 | } |
| 1491 | } |
| 1492 | } else { |
| 1493 | AVIF_CHECKERR(encoder->sampleTransformRecipe == AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_EXTENSION_12B_8B_OVERLAP_4B, |
| 1494 | AVIF_RESULT_NOT_IMPLEMENTED); |
| 1495 | if (isBase) { |
| 1496 | AVIF_CHECKRES(avifImageCreateAllocate(sampleTransformedImage, image, 12, planes)); |
| 1497 | AVIF_CHECKRES(avifImageApplyImgOpConst(*sampleTransformedImage, image, AVIF_SAMPLE_TRANSFORM_QUOTIENT, 16, planes)); |
| 1498 | } else { |
| 1499 | AVIF_CHECKRES(avifImageCreateAllocate(sampleTransformedImage, image, 8, planes)); |
no test coverage detected