Skip to content

Commit e176f5b

Browse files
authored
Encoder: fix ispe property for tmap with grid. (#2730)
Decoder: check the ispe property of tmap items. The new check will fail files with gain map grids created with previous versions of libavif. However, I believe that there are probably zero such images (apart from test images in this repo). avifenc cannot produce such images: if you specify --grid it discards the gain map (this is a bug, not intentional). So you would have to write specific code to call the API to produce such images.
1 parent 6ba8922 commit e176f5b

File tree

5 files changed

+24
-6
lines changed

5 files changed

+24
-6
lines changed

src/read.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5704,6 +5704,19 @@ static avifResult avifDecoderFindGainMapItem(const avifDecoder * decoder,
57045704
gainMap->altDepth = pixiProp->u.pixi.planeDepths[0];
57055705
}
57065706

5707+
const avifProperty * ispeProp = avifPropertyArrayFind(&toneMappedImageItemTmp->properties, "ispe");
5708+
if (!ispeProp) {
5709+
// HEIF (ISO/IEC 23008-12:2022), Section 6.5.3.1:
5710+
// Every image item shall be associated with one property of this type, prior to the association
5711+
// of all transformative properties.
5712+
avifDiagnosticsPrintf(data->diag, "Box[tmap] missing mandatory ispe property");
5713+
return AVIF_RESULT_BMFF_PARSE_FAILED;
5714+
}
5715+
if (ispeProp->u.ispe.width != colorItem->width || ispeProp->u.ispe.height != colorItem->height) {
5716+
avifDiagnosticsPrintf(data->diag, "Box[tmap] ispe property width/height does not match base image");
5717+
return AVIF_RESULT_BMFF_PARSE_FAILED;
5718+
}
5719+
57075720
if (avifPropertyArrayFind(&toneMappedImageItemTmp->properties, "pasp") ||
57085721
avifPropertyArrayFind(&toneMappedImageItemTmp->properties, "clap") ||
57095722
avifPropertyArrayFind(&toneMappedImageItemTmp->properties, "irot") ||

src/write.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,10 +1046,12 @@ size_t avifEncoderGetGainMapSizeBytes(avifEncoder * encoder)
10461046
}
10471047

10481048
// Sets altImageMetadata's metadata values to represent the "alternate" image as if applying the gain map to the base image.
1049-
static avifResult avifImageCopyAltImageMetadata(avifImage * altImageMetadata, const avifImage * imageWithGainMap)
1049+
// For grid images, imageWithGainMap is the metadata of the first cell. gridWidth and gridHeight are the dimensions of the
1050+
// full image.
1051+
static avifResult avifImageCopyAltImageMetadata(avifImage * altImageMetadata, const avifImage * imageWithGainMap, uint32_t gridWidth, uint32_t gridHeight)
10501052
{
1051-
altImageMetadata->width = imageWithGainMap->width;
1052-
altImageMetadata->height = imageWithGainMap->height;
1053+
altImageMetadata->width = gridWidth;
1054+
altImageMetadata->height = gridHeight;
10531055
AVIF_CHECKRES(avifRWDataSet(&altImageMetadata->icc, imageWithGainMap->gainMap->altICC.data, imageWithGainMap->gainMap->altICC.size));
10541056
altImageMetadata->colorPrimaries = imageWithGainMap->gainMap->altColorPrimaries;
10551057
altImageMetadata->transferCharacteristics = imageWithGainMap->gainMap->altTransferCharacteristics;
@@ -1885,14 +1887,17 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder,
18851887
if (encoder->data->items.count == 0) {
18861888
// Make a copy of the first image's metadata (sans pixels) for future writing/validation
18871889
AVIF_CHECKRES(avifImageCopy(encoder->data->imageMetadata, firstCell, 0));
1890+
1891+
const uint32_t gridWidth = avifGridWidth(gridCols, firstCell, bottomRightCell);
1892+
const uint32_t gridHeight = avifGridHeight(gridRows, firstCell, bottomRightCell);
1893+
18881894
if (hasGainMap) {
1889-
AVIF_CHECKRES(avifImageCopyAltImageMetadata(encoder->data->altImageMetadata, encoder->data->imageMetadata));
1895+
AVIF_CHECKRES(
1896+
avifImageCopyAltImageMetadata(encoder->data->altImageMetadata, encoder->data->imageMetadata, gridWidth, gridHeight));
18901897
}
18911898

18921899
// Prepare all AV1 items
18931900
uint16_t colorItemID;
1894-
const uint32_t gridWidth = avifGridWidth(gridCols, firstCell, bottomRightCell);
1895-
const uint32_t gridHeight = avifGridHeight(gridRows, firstCell, bottomRightCell);
18961901
AVIF_CHECKRES(avifEncoderAddImageItems(encoder, gridCols, gridRows, gridWidth, gridHeight, AVIF_ITEM_COLOR, &colorItemID));
18971902
encoder->data->primaryItemID = colorItemID;
18981903

0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
-14 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)