Exemple #1
0
        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));
        }
Exemple #2
0
        public AvifItemData ReadItemData(ItemLocationEntry entry)
        {
            if (entry is null)
            {
                ExceptionUtil.ThrowArgumentNullException(nameof(entry));
            }

            AvifItemData data;

            if (entry.Extents.Count == 1)
            {
                long offset = CalculateExtentOffset(entry.BaseOffset, entry.ConstructionMethod, entry.Extents[0]);

                this.reader.Position = offset;

                ulong totalItemSize = entry.TotalItemSize;

                if (totalItemSize <= ManagedAvifItemDataMaxSize)
                {
                    ManagedAvifItemData managedItemData = new ManagedAvifItemData((int)totalItemSize, this.arrayPool);

                    this.reader.ProperRead(managedItemData.GetBuffer(), 0, (int)managedItemData.Length);

                    data = managedItemData;
                }
                else
                {
                    UnmanagedAvifItemData unmanagedItemData = new UnmanagedAvifItemData(totalItemSize);

                    try
                    {
                        this.reader.ProperRead(unmanagedItemData.UnmanagedBuffer, 0, totalItemSize);

                        data = unmanagedItemData;
                        unmanagedItemData = null;
                    }
                    finally
                    {
                        unmanagedItemData?.Dispose();
                    }
                }
            }
            else
            {
                data = ReadDataFromMultipleExtents(entry);
            }

            return(data);
        }
Exemple #3
0
        public byte[] GetExifData()
        {
            VerifyNotDisposed();

            ItemLocationEntry entry = this.parser.TryGetExifLocation(this.primaryItemId);

            if (entry != null)
            {
                ulong length = entry.TotalItemSize;

                // Ignore any EXIF blocks that are larger than 2GB.
                if (length < int.MaxValue)
                {
                    using (AvifItemData itemData = this.parser.ReadItemData(entry))
                        using (Stream stream = itemData.GetStream())
                        {
                            // The EXIF data block has a header that indicates the number of bytes
                            // that come before the start of the TIFF header.
                            // See ISO/IEC 23008-12:2017 section A.2.1.

                            long tiffStartOffset = stream.TryReadUInt32BigEndian();

                            if (tiffStartOffset != -1)
                            {
                                long dataLength = (long)length - tiffStartOffset - sizeof(uint);

                                if (dataLength > 0)
                                {
                                    if (tiffStartOffset != 0)
                                    {
                                        stream.Position += tiffStartOffset;
                                    }

                                    byte[] bytes = new byte[dataLength];

                                    stream.ProperRead(bytes, 0, bytes.Length);

                                    return(bytes);
                                }
                            }
                        }
                }
            }

            return(null);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        public byte[] GetXmpData()
        {
            VerifyNotDisposed();

            ItemLocationEntry entry = this.parser.TryGetXmpLocation(this.primaryItemId);

            if (entry != null)
            {
                ulong length = entry.TotalItemSize;

                // Ignore any XMP packets that are larger than 2GB.
                if (length < int.MaxValue)
                {
                    using (AvifItemData itemData = this.parser.ReadItemData(entry))
                    {
                        return(itemData.ToArray());
                    }
                }
            }

            return(null);
        }
Exemple #6
0
        private AvifItemData ReadDataFromMultipleExtents(ItemLocationEntry entry)
        {
            AvifItemData data;

            IReadOnlyList <ItemLocationExtent> extents = entry.Extents;
            ulong totalItemSize = entry.TotalItemSize;

            if (totalItemSize <= ManagedAvifItemDataMaxSize)
            {
                ManagedAvifItemData managedItemData = new ManagedAvifItemData((int)totalItemSize, this.arrayPool);

                int    offset         = 0;
                int    remainingBytes = (int)managedItemData.Length;
                byte[] bytes          = managedItemData.GetBuffer();

                for (int i = 0; i < extents.Count; i++)
                {
                    ItemLocationExtent extent = extents[i];

                    long itemOffset = CalculateExtentOffset(entry.BaseOffset, entry.ConstructionMethod, extent);

                    int length = (int)extent.Length;

                    if (length > remainingBytes)
                    {
                        throw new FormatException("The extent length is greater than the number of bytes remaining for the item.");
                    }

                    this.reader.Position = itemOffset;
                    this.reader.ProperRead(bytes, offset, length);

                    offset         += length;
                    remainingBytes -= length;
                }

                if (remainingBytes > 0)
                {
                    // This should never happen, the total item size is the sum of all the extent sizes.
                    throw new FormatException("The item has more data than was read from the extents.");
                }

                data = managedItemData;
            }
            else
            {
                UnmanagedAvifItemData unmanagedItemData = new UnmanagedAvifItemData(totalItemSize);

                try
                {
                    ulong offset         = 0;
                    ulong remainingBytes = totalItemSize;

                    for (int i = 0; i < extents.Count; i++)
                    {
                        ItemLocationExtent extent = extents[i];

                        long itemOffset = CalculateExtentOffset(entry.BaseOffset, entry.ConstructionMethod, extent);

                        ulong length = extent.Length;

                        if (length > remainingBytes)
                        {
                            throw new FormatException("The extent length is greater than the number of bytes remaining for the item.");
                        }

                        this.reader.Position = itemOffset;
                        this.reader.ProperRead(unmanagedItemData.UnmanagedBuffer, offset, length);

                        offset         += length;
                        remainingBytes -= length;
                    }

                    if (remainingBytes > 0)
                    {
                        // This should never happen, the total item size is the sum of all the extent sizes.
                        throw new FormatException("The item has more data than was read from the extents.");
                    }

                    data = unmanagedItemData;
                    unmanagedItemData = null;
                }
                finally
                {
                    unmanagedItemData?.Dispose();
                }
            }

            return(data);
        }