/// <summary> /// Initializes a new instance of the <see cref="AvifReader"/> class. /// </summary> /// <param name="parser">The parser.</param> /// <exception cref="ArgumentNullException"><paramref name="input"/> is null.</exception> public AvifReader(Stream input, bool leaveOpen, IByteArrayPool arrayPool) { if (input is null) { ExceptionUtil.ThrowArgumentNullException(nameof(input)); } // The parser is initialized first because it will throw an exception // if the AVIF file is invalid or not supported. this.parser = new AvifParser(input, leaveOpen, arrayPool); this.primaryItemId = this.parser.GetPrimaryItemId(); this.alphaItemId = this.parser.GetAlphaItemId(this.primaryItemId); this.colorInfoBox = this.parser.TryGetColorInfoBox(this.primaryItemId); this.parser.GetTransformationProperties(this.primaryItemId, out this.cleanApertureBox, out this.imageRotateBox, out this.imageMirrorBox); this.colorGridInfo = this.parser.TryGetImageGridInfo(this.primaryItemId); if (this.alphaItemId != 0) { this.alphaGridInfo = this.parser.TryGetImageGridInfo(this.alphaItemId); } else { this.alphaGridInfo = null; } }
private void CheckImageItemType(uint itemId, ImageGridInfo gridInfo, string imageName, bool checkingGridChildren = false) { IItemInfoEntry entry = this.parser.TryGetItemInfoEntry(itemId); if (entry is null) { ExceptionUtil.ThrowFormatException($"The { imageName } image does not exist."); } else if (entry.ItemType != ItemInfoEntryTypes.AV01) { if (entry.ItemType == ItemInfoEntryTypes.ImageGrid) { if (checkingGridChildren) { ExceptionUtil.ThrowFormatException("Nested image grids are not supported."); } if (gridInfo is null) { ExceptionUtil.ThrowFormatException($"The { imageName } image does not have any image grid information."); } IReadOnlyList <uint> childImageIds = gridInfo.ChildImageIds; for (int i = 0; i < childImageIds.Count; i++) { CheckImageItemType(childImageIds[i], null, imageName, true); } } else { ExceptionUtil.ThrowFormatException($"The { imageName } image is not a supported format."); } } }
private void CheckRequiredImageProperties(uint itemId, ImageGridInfo gridInfo, string imageName) { bool hasUnsupportedProperties = false; IItemInfoEntry entry = this.parser.TryGetItemInfoEntry(itemId); if (entry is null) { ExceptionUtil.ThrowFormatException($"The { imageName } image does not exist."); } else if (entry.ItemType == ItemInfoEntryTypes.AV01) { hasUnsupportedProperties = this.parser.HasUnsupportedEssentialProperties(itemId); } else if (entry.ItemType == ItemInfoEntryTypes.ImageGrid) { if (gridInfo is null) { ExceptionUtil.ThrowFormatException($"The { imageName } image does not have any image grid information."); } IReadOnlyList <uint> childImageIds = gridInfo.ChildImageIds; for (int i = 0; i < childImageIds.Count; i++) { if (this.parser.HasUnsupportedEssentialProperties(childImageIds[i])) { hasUnsupportedProperties = true; break; } } } else { ExceptionUtil.ThrowFormatException($"The { imageName } image is not a supported format."); } if (hasUnsupportedProperties) { ExceptionUtil.ThrowFormatException($"The { imageName } image has essential item properties that are not supported."); } }
private Size GetImageSize(uint itemId, ImageGridInfo gridInfo, string imageName) { IItemInfoEntry entry = this.parser.TryGetItemInfoEntry(itemId); uint width; uint height; if (entry.ItemType == ItemInfoEntryTypes.AV01) { ImageSpatialExtentsBox extents = this.parser.TryGetAssociatedItemProperty <ImageSpatialExtentsBox>(itemId); if (extents is null) { ExceptionUtil.ThrowFormatException($"The { imageName } image size property was not found."); } width = extents.ImageWidth; height = extents.ImageHeight; } else if (entry.ItemType == ItemInfoEntryTypes.ImageGrid) { if (gridInfo is null) { ExceptionUtil.ThrowFormatException($"The { imageName } image does not have any image grid information."); } width = gridInfo.OutputWidth; height = gridInfo.OutputHeight; } else { throw new FormatException($"The { imageName } image is not a supported format."); } if (width > int.MaxValue || height > int.MaxValue) { throw new FormatException($"The { imageName } image dimensions are too large."); } return(new Size((int)width, (int)height)); }
private static void CheckImageGridAndTileBounds(uint tileWidth, uint tileHeight, YUVChromaSubsampling tileChroma, ImageGridInfo gridInfo) { // The MIAF specification (ISO/IEC 23000-22:2019) requires that the tile size be at least 64x64. if (tileWidth < 64 || tileHeight < 64) { ExceptionUtil.ThrowFormatException("The image grid tile size must be at least 64x64."); } // HEIF (ISO/IEC 23008-12:2017), section 6.6.2.3.1: // The tiled input images shall completely “cover” the reconstructed image grid canvas... if ((tileWidth * gridInfo.TileColumnCount) < gridInfo.OutputWidth || (tileHeight * gridInfo.TileRowCount) < gridInfo.OutputHeight) { ExceptionUtil.ThrowFormatException("The image grid tiles do not cover the entire output image."); } if (tileChroma == YUVChromaSubsampling.Subsampling420 || tileChroma == YUVChromaSubsampling.Subsampling422) { if ((tileWidth & 1) != 0 || (gridInfo.OutputWidth & 1) != 0) { ExceptionUtil.ThrowFormatException("The tile and output image width must be an even number."); } if (tileChroma == YUVChromaSubsampling.Subsampling420) { if ((tileHeight & 1) != 0 || (gridInfo.OutputHeight & 1) != 0) { ExceptionUtil.ThrowFormatException("The tile and output image height must be an even number."); } } } }