Esempio n. 1
0
        private void PopulateItemInfos()
        {
            IReadOnlyList <AvifWriterItem> items = this.state.Items;
            ItemInfoBox itemInfoBox = this.metaBox.ItemInfo;

            for (int i = 0; i < items.Count; i++)
            {
                AvifWriterItem item = items[i];
                if (item.ItemInfoEntry != null)
                {
                    itemInfoBox.Add(item.ItemInfoEntry);
                }
            }
        }
Esempio n. 2
0
        private void PopulateItemReferences()
        {
            IReadOnlyList <AvifWriterItem> items = this.state.Items;
            ItemReferenceBox itemReferenceBox    = this.metaBox.ItemReferences;

            for (int i = 0; i < items.Count; i++)
            {
                AvifWriterItem item = items[i];
                if (item.ItemReferences.Count > 0)
                {
                    itemReferenceBox.Add(item.ItemReferences);
                }
            }
        }
Esempio n. 3
0
        private void PopulateItemLocations()
        {
            IReadOnlyList <AvifWriterItem> items = this.state.Items;
            ItemLocationBox itemLocationBox      = this.metaBox.ItemLocations;

            for (int i = 0; i < items.Count; i++)
            {
                AvifWriterItem item = items[i];
                if (item.ItemLocation != null)
                {
                    itemLocationBox.Add(item.ItemLocation);
                }
            }
        }
            private void Initialize(IReadOnlyList <CompressedAV1Image> colorImages,
                                    IReadOnlyList <CompressedAV1Image> alphaImages,
                                    ImageGridMetadata imageGridMetadata,
                                    AvifMetadata metadata,
                                    IByteArrayPool arrayPool)
            {
                ImageStateInfo result;

                if (imageGridMetadata != null)
                {
                    result           = InitializeFromImageGrid(colorImages, alphaImages, imageGridMetadata);
                    this.ItemDataBox = CreateItemDataBox(imageGridMetadata, arrayPool);
                }
                else
                {
                    result           = InitializeFromSingleImage(colorImages[0], alphaImages?[0]);
                    this.ItemDataBox = null;
                }

                uint  itemId = result.NextId;
                ulong mediaDataBoxContentSize = result.MediaDataBoxContentSize;

                byte[] exif = metadata.GetExifBytesReadOnly();
                if (exif != null && exif.Length > 0)
                {
                    AvifWriterItem exifItem = AvifWriterItem.CreateFromExif(itemId, exif);
                    itemId++;
                    exifItem.ItemReferences.Add(new ItemReferenceEntryBox(exifItem.Id, ReferenceTypes.ContentDescription, this.PrimaryItemId));

                    this.items.Add(exifItem);
                    mediaDataBoxContentSize += (ulong)exifItem.ContentBytes.Length;
                }

                byte[] xmp = metadata.GetXmpBytesReadOnly();
                if (xmp != null && xmp.Length > 0)
                {
                    AvifWriterItem xmpItem = AvifWriterItem.CreateFromXmp(itemId, xmp);
                    xmpItem.ItemReferences.Add(new ItemReferenceEntryBox(xmpItem.Id, ReferenceTypes.ContentDescription, this.PrimaryItemId));

                    this.items.Add(xmpItem);
                    mediaDataBoxContentSize += (ulong)xmpItem.ContentBytes.Length;
                }

                this.MediaDataBoxContentSize = mediaDataBoxContentSize;
            }
Esempio n. 5
0
        public void WriteTo(Stream stream)
        {
            using (BigEndianBinaryWriter writer = new BigEndianBinaryWriter(stream, true, this.arrayPool))
            {
                this.fileTypeBox.Write(writer);
                this.metaBox.Write(writer);

                new MediaDataBox(this.state.MediaDataBoxContentSize).Write(writer);

                IReadOnlyList <AvifWriterItem> items = this.state.Items;

                for (int i = 0; i < items.Count; i++)
                {
                    AvifWriterItem item = items[i];

                    if (item.Image is null && item.ContentBytes is null)
                    {
                        continue;
                    }

                    // We only ever write items with a single extent.
                    item.ItemLocation.Extents[0].WriteFinalOffset(writer, (ulong)writer.Position);

                    if (item.Image != null)
                    {
                        item.Image.Data.Write(writer);

                        this.progressDone++;
                        this.progressCallback?.Invoke(this, new ProgressEventArgs(((double)this.progressDone / this.progressTotal) * 100.0));
                    }
                    else
                    {
                        writer.Write(item.ContentBytes);
                    }
                }
            }
        }
            private ImageStateInfo InitializeFromSingleImage(CompressedAV1Image color, CompressedAV1Image alpha)
            {
                ulong mediaDataBoxContentSize = color.Data.ByteLength;
                uint  itemId = FirstItemId;

                AvifWriterItem colorItem = AvifWriterItem.CreateFromImage(itemId, "Color", color, false);

                itemId++;
                this.PrimaryItemId = colorItem.Id;
                this.items.Add(colorItem);

                if (alpha != null)
                {
                    AvifWriterItem alphaItem = AvifWriterItem.CreateFromImage(itemId, "Alpha", alpha, true);
                    itemId++;
                    alphaItem.ItemReferences.Add(new ItemReferenceEntryBox(alphaItem.Id, ReferenceTypes.AuxiliaryImage, this.PrimaryItemId));
                    this.AlphaItemId = alphaItem.Id;

                    this.items.Add(alphaItem);
                    mediaDataBoxContentSize += alpha.Data.ByteLength;
                }

                return(new ImageStateInfo(mediaDataBoxContentSize, itemId));
            }
Esempio n. 7
0
        private void PopulateItemProperties()
        {
            IReadOnlyList <AvifWriterItem> items = this.state.Items;
            ItemPropertiesBox itemPropertiesBox  = this.metaBox.ItemProperties;

            // The property association ids are 1-based
            ushort propertyAssociationIndex = 1;

            // Cache the property association index values for the ImageSpatialExtentsBox
            // and PixelAspectRatioBox.
            // These boxes can be shared between the color and alpha images, which provides
            // a small reduction in file size.
            //
            // Gray-scale images can also share the AV1ConfigBox and PixelInformationBox
            // between the color and alpha images.
            // This works because the color and alpha images are the same size and YUV format.
            ushort imageSpatialExtentsAssociationIndex   = 0;
            ushort pixelAspectRatioAssociationIndex      = 0;
            ushort colorAv1ConfigAssociationIndex        = 0;
            ushort colorPixelInformationAssociationIndex = 0;
            ushort alphaAv1ConfigAssociationIndex        = 0;
            ushort alphaPixelInformationAssociationIndex = 0;
            ushort alphaChannelAssociationIndex          = 0;

            for (int i = 0; i < items.Count; i++)
            {
                AvifWriterItem item = items[i];
                if (item.Image != null)
                {
                    if (imageSpatialExtentsAssociationIndex == 0)
                    {
                        itemPropertiesBox.AddProperty(new ImageSpatialExtentsBox((uint)item.Image.Width, (uint)item.Image.Height));
                        imageSpatialExtentsAssociationIndex = propertyAssociationIndex;
                        propertyAssociationIndex++;
                    }

                    itemPropertiesBox.AddPropertyAssociation(item.Id, false, imageSpatialExtentsAssociationIndex);

                    if (pixelAspectRatioAssociationIndex == 0)
                    {
                        itemPropertiesBox.AddProperty(new PixelAspectRatioBox(1, 1));
                        pixelAspectRatioAssociationIndex = propertyAssociationIndex;
                        propertyAssociationIndex++;
                    }

                    itemPropertiesBox.AddPropertyAssociation(item.Id, false, pixelAspectRatioAssociationIndex);

                    if (colorAv1ConfigAssociationIndex == 0 || item.IsAlphaImage && alphaAv1ConfigAssociationIndex == 0)
                    {
                        itemPropertiesBox.AddProperty(AV1ConfigBoxBuilder.Build(item.Image));
                        if (this.colorImageIsGrayscale)
                        {
                            colorAv1ConfigAssociationIndex = alphaAv1ConfigAssociationIndex = propertyAssociationIndex;
                        }
                        else
                        {
                            if (item.IsAlphaImage)
                            {
                                alphaAv1ConfigAssociationIndex = propertyAssociationIndex;
                            }
                            else
                            {
                                colorAv1ConfigAssociationIndex = propertyAssociationIndex;
                            }
                        }
                        propertyAssociationIndex++;
                    }


                    if (colorPixelInformationAssociationIndex == 0 || item.IsAlphaImage && alphaPixelInformationAssociationIndex == 0)
                    {
                        itemPropertiesBox.AddProperty(new PixelInformationBox(item.Image.Format));
                        if (this.colorImageIsGrayscale)
                        {
                            colorPixelInformationAssociationIndex = alphaPixelInformationAssociationIndex = propertyAssociationIndex;
                        }
                        else
                        {
                            if (item.IsAlphaImage)
                            {
                                alphaPixelInformationAssociationIndex = propertyAssociationIndex;
                            }
                            else
                            {
                                colorPixelInformationAssociationIndex = propertyAssociationIndex;
                            }
                        }
                        propertyAssociationIndex++;
                    }


                    if (item.IsAlphaImage)
                    {
                        itemPropertiesBox.AddPropertyAssociation(item.Id, true, alphaAv1ConfigAssociationIndex);
                        itemPropertiesBox.AddPropertyAssociation(item.Id, true, alphaPixelInformationAssociationIndex);

                        if (alphaChannelAssociationIndex == 0)
                        {
                            itemPropertiesBox.AddProperty(new AlphaChannelBox());
                            alphaChannelAssociationIndex = propertyAssociationIndex;
                            propertyAssociationIndex++;
                        }

                        itemPropertiesBox.AddPropertyAssociation(item.Id, true, alphaChannelAssociationIndex);
                    }
                    else
                    {
                        itemPropertiesBox.AddPropertyAssociation(item.Id, true, colorAv1ConfigAssociationIndex);
                        itemPropertiesBox.AddPropertyAssociation(item.Id, true, colorPixelInformationAssociationIndex);
                    }
                }
            }

            if (this.state.ImageGrid != null)
            {
                itemPropertiesBox.AddProperty(new ImageSpatialExtentsBox(this.state.ImageGrid.OutputWidth, this.state.ImageGrid.OutputHeight));
                ushort gridImageSpatialExtentsAssociationIndex = propertyAssociationIndex;
                propertyAssociationIndex++;

                itemPropertiesBox.AddPropertyAssociation(this.state.PrimaryItemId, false, gridImageSpatialExtentsAssociationIndex);
                if (this.state.AlphaItemId != 0)
                {
                    itemPropertiesBox.AddPropertyAssociation(this.state.AlphaItemId, false, gridImageSpatialExtentsAssociationIndex);
                    itemPropertiesBox.AddPropertyAssociation(this.state.AlphaItemId, true, alphaChannelAssociationIndex);
                }
            }

            if (this.colorInformationBox != null)
            {
                itemPropertiesBox.AddProperty(this.colorInformationBox);
                itemPropertiesBox.AddPropertyAssociation(this.state.PrimaryItemId, true, propertyAssociationIndex);
            }
        }
            private ImageStateInfo InitializeFromImageGrid(IReadOnlyList <CompressedAV1Image> colorImages,
                                                           IReadOnlyList <CompressedAV1Image> alphaImages,
                                                           ImageGridMetadata imageGridMetadata)
            {
                ulong mediaDataBoxContentSize = 0;
                uint  itemId = FirstItemId;

                List <uint> colorImageIds = new List <uint>(colorImages.Count);
                List <uint> alphaImageIds = alphaImages != null ? new List <uint>(alphaImages.Count) : null;

                for (int i = 0; i < colorImages.Count; i++)
                {
                    CompressedAV1Image color     = colorImages[i];
                    AvifWriterItem     colorItem = AvifWriterItem.CreateFromImage(itemId, null, color, false);
                    itemId++;
                    colorImageIds.Add(colorItem.Id);
                    this.items.Add(colorItem);
                    mediaDataBoxContentSize += color.Data.ByteLength;

                    if (alphaImages != null)
                    {
                        CompressedAV1Image alpha     = alphaImages[i];
                        AvifWriterItem     alphaItem = AvifWriterItem.CreateFromImage(itemId, null, alpha, true);
                        itemId++;
                        alphaItem.ItemReferences.Add(new ItemReferenceEntryBox(alphaItem.Id, ReferenceTypes.AuxiliaryImage, colorItem.Id));
                        alphaImageIds.Add(alphaItem.Id);

                        this.items.Add(alphaItem);
                        mediaDataBoxContentSize += alpha.Data.ByteLength;
                    }
                }

                ulong gridDescriptorLength;

                if (imageGridMetadata.OutputHeight > ushort.MaxValue || imageGridMetadata.OutputWidth > ushort.MaxValue)
                {
                    gridDescriptorLength = ImageGridDescriptor.LargeDescriptorLength;
                }
                else
                {
                    gridDescriptorLength = ImageGridDescriptor.SmallDescriptorLength;
                }

                AvifWriterItem colorGridItem = AvifWriterItem.CreateFromImageGrid(itemId, "Color", 0, gridDescriptorLength);

                itemId++;
                colorGridItem.ItemReferences.Add(new ItemReferenceEntryBox(colorGridItem.Id, ReferenceTypes.DerivedImage, colorImageIds));

                this.PrimaryItemId = colorGridItem.Id;
                this.items.Add(colorGridItem);

                if (alphaImages != null)
                {
                    // The ImageGridDescriptor is shared between the color and alpha image.
                    AvifWriterItem alphaGridItem = AvifWriterItem.CreateFromImageGrid(itemId, "Alpha", 0, gridDescriptorLength);
                    itemId++;
                    alphaGridItem.ItemReferences.Add(new ItemReferenceEntryBox(alphaGridItem.Id, ReferenceTypes.AuxiliaryImage, colorGridItem.Id));
                    alphaGridItem.ItemReferences.Add(new ItemReferenceEntryBox(alphaGridItem.Id, ReferenceTypes.DerivedImage, alphaImageIds));

                    this.AlphaItemId = alphaGridItem.Id;
                    this.items.Add(alphaGridItem);
                }

                return(new ImageStateInfo(mediaDataBoxContentSize, itemId));
            }