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 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."); } } } }
private void CheckForRequiredBoxes() { if (this.fileTypeBox is null) { ExceptionUtil.ThrowFormatException("The file does not contain a FileType box."); } if (this.metaBox is null) { ExceptionUtil.ThrowFormatException("The file does not contain a Meta box."); } if (this.metaBox.ItemInfo is null) { ExceptionUtil.ThrowFormatException("The file does not have an ItemInfo box."); } if (this.metaBox.ItemLocations is null) { ExceptionUtil.ThrowFormatException("The file does not have an ItemLocations box."); } if (this.metaBox.ItemProperties is null) { ExceptionUtil.ThrowFormatException("The file does not have an ItemProperties box."); } }
private AvifItemData ReadColorImage(uint itemId) { ItemLocationEntry entry = this.parser.TryGetItemLocation(itemId); if (entry is null) { ExceptionUtil.ThrowFormatException("The color image item location was not found."); } return(this.parser.ReadItemData(entry)); }
private void EnsurePrimaryItemIsNotHidden() { IItemInfoEntry entry = this.parser.TryGetItemInfoEntry(this.primaryItemId); if (entry is null) { ExceptionUtil.ThrowFormatException("The primary item does not exist."); } else if (entry.IsHidden) { ExceptionUtil.ThrowFormatException("The primary item cannot be marked as hidden."); } }
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 ImageGridDescriptor TryGetImageGridDescriptor(uint itemId) { IItemInfoEntry entry = TryGetItemInfoEntry(itemId); if (entry != null && entry.ItemType == ItemInfoEntryTypes.ImageGrid) { ItemLocationEntry locationEntry = TryGetItemLocation(itemId); if (locationEntry != null) { if (locationEntry.TotalItemSize < ImageGridDescriptor.SmallDescriptorLength) { ExceptionUtil.ThrowFormatException("Invalid image grid descriptor length."); } using (AvifItemData itemData = ReadItemData(locationEntry)) { Stream stream = null; try { stream = itemData.GetStream(); using (EndianBinaryReader imageGridReader = new EndianBinaryReader(stream, this.reader.Endianess, this.arrayPool)) { stream = null; return(new ImageGridDescriptor(imageGridReader, itemData.Length)); } } finally { stream?.Dispose(); } } } } return(null); }
private void Parse() { while (this.reader.Position < this.reader.Length) { Box header = new Box(this.reader); if (header.Type == BoxTypes.FileType) { if (this.fileTypeBox != null) { ExceptionUtil.ThrowFormatException("The file contains multiple FileType boxes."); } EndianBinaryReaderSegment segment = this.reader.CreateSegment(header.DataStartOffset, header.DataLength); this.fileTypeBox = new FileTypeBox(segment, header); this.fileTypeBox.CheckForAvifCompatibility(); } else if (header.Type == BoxTypes.Meta) { if (this.metaBox != null) { ExceptionUtil.ThrowFormatException("The file contains multiple Meta boxes."); } EndianBinaryReaderSegment segment = this.reader.CreateSegment(header.DataStartOffset, header.DataLength); this.metaBox = new MetaBox(segment, header); } else { // Skip any other boxes this.reader.Position = header.End; } } CheckForRequiredBoxes(); }