Composites hidden image items and/or the primary image item into the dstImage. Tiles are aggregated into temporary buffers (reconstructedInputImages) covering the whole dstImage dimensions in case of grids. Non-null elements of reconstructedInputImages must be destroyed after calling this function.
| 6871 | // covering the whole dstImage dimensions in case of grids. |
| 6872 | // Non-null elements of reconstructedInputImages must be destroyed after calling this function. |
| 6873 | static avifResult avifDecoderApplySampleTransformForPlanesImpl(const avifDecoder * decoder, |
| 6874 | avifPlanesFlag planes, |
| 6875 | avifImage * dstImage, |
| 6876 | avifImage * reconstructedInputImages[AVIF_SAMPLE_TRANSFORM_MAX_NUM_INPUT_IMAGE_ITEMS]) |
| 6877 | { |
| 6878 | AVIF_ASSERT_OR_RETURN(decoder->data->sampleTransformNumInputImageItems != 0); |
| 6879 | AVIF_ASSERT_OR_RETURN(decoder->data->sampleTransformNumInputImageItems <= AVIF_SAMPLE_TRANSFORM_MAX_NUM_INPUT_IMAGE_ITEMS); |
| 6880 | const avifImage * inputImages[AVIF_SAMPLE_TRANSFORM_MAX_NUM_INPUT_IMAGE_ITEMS]; |
| 6881 | for (uint32_t i = 0; i < decoder->data->sampleTransformNumInputImageItems; ++i) { |
| 6882 | avifItemCategory category = decoder->data->sampleTransformInputImageItems[i]; |
| 6883 | if (category == AVIF_ITEM_COLOR) { |
| 6884 | // If the primary image item was a grid, it was already aggregated |
| 6885 | // into this single output buffer in avifDecoderDecodeTiles(). |
| 6886 | inputImages[i] = decoder->image; |
| 6887 | } else { |
| 6888 | AVIF_ASSERT_OR_RETURN(category >= AVIF_ITEM_SAMPLE_TRANSFORM_INPUT_0_COLOR && |
| 6889 | category < AVIF_ITEM_SAMPLE_TRANSFORM_INPUT_0_COLOR + |
| 6890 | AVIF_SAMPLE_TRANSFORM_MAX_NUM_EXTRA_INPUT_IMAGE_ITEMS); |
| 6891 | if (planes == AVIF_PLANES_A) { |
| 6892 | category += AVIF_SAMPLE_TRANSFORM_MAX_NUM_EXTRA_INPUT_IMAGE_ITEMS; |
| 6893 | } |
| 6894 | const avifTileInfo * info = &decoder->data->tileInfos[category]; |
| 6895 | AVIF_ASSERT_OR_RETURN(info != NULL); |
| 6896 | const avifTile * firstTile = &decoder->data->tiles.tile[info->firstTileIndex]; |
| 6897 | AVIF_ASSERT_OR_RETURN(firstTile != NULL && firstTile->image != NULL); |
| 6898 | if (info->tileCount == 1) { |
| 6899 | inputImages[i] = firstTile->image; |
| 6900 | } else { |
| 6901 | // Combine the tiles into a single buffer used as one of the input images in avifImageApplyExpression(). |
| 6902 | reconstructedInputImages[i] = avifImageCreateEmpty(); |
| 6903 | AVIF_CHECKERR(reconstructedInputImages[i] != NULL, AVIF_RESULT_OUT_OF_MEMORY); |
| 6904 | avifImageCopyNoAlloc(reconstructedInputImages[i], firstTile->image); |
| 6905 | reconstructedInputImages[i]->width = decoder->image->width; |
| 6906 | reconstructedInputImages[i]->height = decoder->image->height; |
| 6907 | avifBool cicpSet = AVIF_TRUE; |
| 6908 | AVIF_CHECKRES(avifDecoderDataAllocateImagePlanes(decoder->data, info, reconstructedInputImages[i], &cicpSet)); |
| 6909 | for (unsigned int tileIndex = 0; tileIndex < info->tileCount; ++tileIndex) { |
| 6910 | const avifTile * tile = firstTile + tileIndex; |
| 6911 | AVIF_CHECKRES(avifDecoderDataCopyTileToImage(decoder->data, info, reconstructedInputImages[i], tile, tileIndex)); |
| 6912 | } |
| 6913 | inputImages[i] = reconstructedInputImages[i]; |
| 6914 | } |
| 6915 | } |
| 6916 | } |
| 6917 | AVIF_CHECKRES(avifImageApplyExpression(dstImage, |
| 6918 | AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_32, |
| 6919 | &decoder->data->meta->sampleTransformExpression, |
| 6920 | decoder->data->sampleTransformNumInputImageItems, |
| 6921 | inputImages, |
| 6922 | planes)); |
| 6923 | return AVIF_RESULT_OK; |
| 6924 | } |
| 6925 | |
| 6926 | // Intermediate function used to safely destroy temporary buffers even in case of error. |
| 6927 | static avifResult avifDecoderApplySampleTransformForPlanes(const avifDecoder * decoder, avifPlanesFlag planes, avifImage * dstImage) |
no test coverage detected