Aspose.Imaging for .NET 20.6 - Release notes

KeySummaryCategory
IMAGINGNET-3618Implement support of APNG (animated PNG) file formatFeature
IMAGINGNET-3849Support of a new compression method DXT1 for BMPFeature
IMAGINGNET-3781Support batch export to WebP for multi-page imagesFeature
IMAGINGNET-3882Cannot extract Azure label information from XMP metadataEnhancement
IMAGINGNET-3804The shape collapsed on saving WMF to PNGEnhancement

Compact framework off notice:

Please note, since 20.6 release of Aspose.Imaging support of .NET Compact Framework was removed.

Public API changes:

Added APIs:

Class    Aspose.Imaging.FileFormats.Apng.ApngFrame

Class    Aspose.Imaging.FileFormats.Apng.ApngImage

Class    Aspose.Imaging.ImageOptions.ApngOptions

Field/Enum    Aspose.Imaging.FileFormat.Apng

Field/Enum    Aspose.Imaging.FileFormats.Bmp.BitmapCompression.Dxt1

Method    Aspose.Imaging.ColorPaletteHelper.GetCloseImagePalette(Aspose.Imaging.RasterImage,Aspose.Imaging.Rectangle,System.Int32,System.Boolean)

Method    Aspose.Imaging.ColorPaletteHelper.HasTransparentColors(Aspose.Imaging.IColorPalette)

Method    Aspose.Imaging.FileFormats.Apng.ApngFrame.CacheData

Method    Aspose.Imaging.FileFormats.Apng.ApngFrame.GetFullFrame

Method    Aspose.Imaging.FileFormats.Apng.ApngFrame.SaveData(System.IO.Stream)

Method    Aspose.Imaging.FileFormats.Apng.ApngFrame.UpdateDimensions(System.Int32,System.Int32)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.#ctor(Aspose.Imaging.ImageOptions.ApngOptions,System.Int32,System.Int32)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.AddFrame

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.AddFrame(Aspose.Imaging.RasterImage)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.AddFrame(Aspose.Imaging.RasterImage,System.UInt32)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.AdjustBrightness(System.Int32)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.AdjustContrast(System.Single)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.AdjustGamma(System.Single)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.AdjustGamma(System.Single,System.Single,System.Single)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.BinarizeBradley(System.Double,System.Int32)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.BinarizeFixed(System.Byte)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.BinarizeOtsu

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.Crop(Aspose.Imaging.Rectangle)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.Crop(System.Int32,System.Int32,System.Int32,System.Int32)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.Dither(Aspose.Imaging.DitheringMethod,System.Int32,Aspose.Imaging.IColorPalette)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.Filter(Aspose.Imaging.Rectangle,Aspose.Imaging.ImageFilters.FilterOptions.FilterOptionsBase)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.Grayscale

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.InsertFrame(System.Int32)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.InsertFrame(System.Int32,Aspose.Imaging.RasterImage)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.InsertFrame(System.Int32,Aspose.Imaging.RasterImage,System.UInt32)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.PopFrameAt(System.Int32)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.RemoveAllFrames

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.RemoveFrameAt(System.Int32)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.ResetDefaultImage

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.Resize(System.Int32,System.Int32,Aspose.Imaging.ImageResizeSettings)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.Resize(System.Int32,System.Int32,Aspose.Imaging.ResizeType)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.ResizeHeightProportionally(System.Int32,Aspose.Imaging.ResizeType)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.ResizeWidthProportionally(System.Int32,Aspose.Imaging.ResizeType)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.Rotate(System.Single,System.Boolean,Aspose.Imaging.Color)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.RotateFlip(Aspose.Imaging.RotateFlipType)

Method    Aspose.Imaging.FileFormats.Apng.ApngImage.SetDefaultImage(Aspose.Imaging.RasterImage)

Method    Aspose.Imaging.ImageOptions.ApngOptions.#ctor

Method    Aspose.Imaging.RasterCachedMultipageImage.GetPagesAsEnumerable

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.BackgroundColor

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.BitsPerPixel

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.FrameLeft

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.FrameTime

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.FrameTop

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.HasAlpha

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.HasBackgroundColor

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.HasTransparentColor

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.Height

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.TransparentColor

Property    Aspose.Imaging.FileFormats.Apng.ApngFrame.Width

Property    Aspose.Imaging.FileFormats.Apng.ApngImage.DefaultFrameTime

Property    Aspose.Imaging.FileFormats.Apng.ApngImage.DefaultPage

Property    Aspose.Imaging.FileFormats.Apng.ApngImage.FileFormat

Property    Aspose.Imaging.FileFormats.Apng.ApngImage.Interlaced

Property    Aspose.Imaging.FileFormats.Apng.ApngImage.NumPlays

Property    Aspose.Imaging.FileFormats.Apng.ApngImage.PageCount

Property    Aspose.Imaging.FileFormats.Apng.ApngImage.PageExportingAction

Property    Aspose.Imaging.FileFormats.Apng.ApngImage.Pages

Property    Aspose.Imaging.FileFormats.Apng.ApngImage.XmpData

Property    Aspose.Imaging.ImageOptions.ApngOptions.DefaultFrameTime

Property    Aspose.Imaging.ImageOptions.ApngOptions.NumPlays

h2. Removed APIs:

Usage Examples:

IMAGINGNET-3618 Implement support of APNG (animated PNG) file format

Creating an image and setting its pixels.

// Example 1. Creating an image and setting its pixels.

using System.Diagnostics;  
using Aspose.Imaging;  
using Aspose.Imaging.ImageOptions;  
using Aspose.Imaging.FileFormats.Png;  
using Aspose.Imaging.FileFormats.Apng;  

// Load pixels from source raster image  
Size imageSize;  
int[] imagePixels;  
using (RasterImage sourceImage = (RasterImage)Image.Load("not_animated.png"))  
{  
    imageSize = sourceImage.Size;  
    imagePixels = sourceImage.LoadArgb32Pixels(sourceImage.Bounds);  
}  

// Create APNG image and set its pixels  
using (ApngImage image = (ApngImage)Image.Create(  
   new ApngOptions()  
       {  
           Source = new FileCreateSource("created_apng.png", false),  
            ColorType = PngColorType.TruecolorWithAlpha  
       },  
    imageSize.Width,  
    imageSize.Height))  
{  
    image.SaveArgb32Pixels(image.Bounds, imagePixels);  
    image.Save();  
}  

// Check output file format  
using (Image image = Image.Load("created_apng.png")) {  
    Debug.Assert(image.FileFormat == FileFormat.Apng);  
    Debug.Assert(image is ApngImage);  
}

 **Raster image operations **

// The brightness adjustment operation  

using Aspose.Imaging;  
using Aspose.Imaging.FileFormats.Apng;  

using (ApngImage image = (ApngImage)Image.Load("elephant.png"))  
{  
 image.AdjustBrightness(100);  
 image.Save("AdjustBrightness.png");  
}

 Create an animated image from another single-page image 

// Create an animated image from another single-page image  

using Aspose.Imaging;  
using Aspose.Imaging.ImageOptions;  
using Aspose.Imaging.FileFormats.Apng;  

const int AnimationDuration = 1000; // 1 s  
const int FrameDuration = 70; // 70 ms  
using (RasterImage sourceImage = (RasterImage)Image.Load("not_animated.png"))  
{  
   ApngOptions createOptions = new ApngOptions  
    {  
       Source = new FileCreateSource("raster_animation.png", false),  
       DefaultFrameTime = (uint)FrameDuration,  
       ColorType = PngColorType.TruecolorWithAlpha,  
    };  

   using (ApngImage apngImage = (ApngImage)Image.Create(  
       createOptions,  
       sourceImage.Width,  
       sourceImage.Height))  
    {  
       int numOfFrames = AnimationDuration / FrameDuration;  
       int numOfFrames2 = numOfFrames / 2;  

       apngImage.RemoveAllFrames();  

       // add first frame  
       apngImage.AddFrame(sourceImage, FrameDuration);  

       // add intermediate frames  
       for (int frameIndex = 1; frameIndex \< numOfFrames - 1; ++frameIndex)  
        {  
           apngImage.AddFrame(sourceImage, FrameDuration);  
           ApngFrame lastFrame = (ApngFrame)apngImage.Pages[apngImage.PageCount

- 1];  
      float gamma = frameIndex \>= numOfFrames2 ? numOfFrames - frameIndex
- 1 : frameIndex;  
      lastFrame.AdjustGamma(gamma);  
          }  

       // add last frame  
       apngImage.AddFrame(sourceImage, FrameDuration);  

       apngImage.Save();  
    }  
}

 Create APNG animation based on vector graphics operations 

// Create APNG animation based on vector graphics operations  

using Aspose.Imaging;  
using Aspose.Imaging.FileFormats.Apng;  

// preparing the animation scene  
const int SceneWidth = 400;   
const int SceneHeigth = 400;  
const uint ActDuration = 1000; // Act duration, in milliseconds  
const uint TotalDuration = 4000; // Total duration, in milliseconds  
const uint FrameDuration = 50; // Frame duration, in milliseconds  
Scene scene = new Scene();  

Ellipse ellipse = new Ellipse  
                      {  
                         FillColor = Color.FromArgb(128, 128, 128),  
                         CenterPoint = new PointF(SceneWidth / 2f, SceneHeigth /
2f),  
                         RadiusX = 80,  
                         RadiusY = 80  
                      };  
scene.AddObject(ellipse);  

Line line = new Line  
                {  
                   Color = Color.Blue,  
                   LineWidth = 10,  
                   StartPoint = new PointF(30, 30),  
                   EndPoint = new PointF(SceneWidth - 30, 30)  
                };  
scene.AddObject(line);  

IAnimation lineAnimation1 = new LinearAnimation(  
                               delegate(float progress)  
                                    {  
                                       line.StartPoint = new PointF(  
                                           30 + (progress \* (SceneWidth - 60)),  
                                           30 + (progress \* (SceneHeigth -
60)));  
                                       line.Color = Color.FromArgb(  
                                           (int)(progress \* 255),  
                                           0,  
                                           255 - (int)(progress \* 255));  
                                    }) { Duration = ActDuration };  
IAnimation lineAnimation2 = new LinearAnimation(  
                               delegate(float progress)  
                                    {  
                                       line.EndPoint = new PointF(  
                                           SceneWidth - 30 - (progress \*
(SceneWidth - 60)),  
                                           30 + (progress \* (SceneHeigth -
60)));  
                                       line.Color = Color.FromArgb(  
                                           255,  
                                           (int)(progress \* 255),  
                                           0);  
                                    })  
                                { Duration = ActDuration };  
IAnimation lineAnimation3 = new LinearAnimation(  
                               delegate(float progress)  
                                    {  
                                       line.StartPoint = new PointF(  
                                           SceneWidth - 30 - (progress \*
(SceneWidth - 60)),  
                                           SceneHeigth - 30 - (progress \*
(SceneHeigth - 60)));  
                                       line.Color = Color.FromArgb(  
                                           255 - (int)(progress \* 255),  
                                           255,  
                                           0);  
                                    })  
                                { Duration = ActDuration };  
IAnimation lineAnimation4 = new LinearAnimation(  
                               delegate(float progress)  
                                    {  
                                       line.EndPoint = new PointF(  
                                           30 + (progress \* (SceneWidth - 60)),  
                                           SceneHeigth - 30 - (progress \*
(SceneHeigth - 60)));  
                                       line.Color = Color.FromArgb(  
                                           0,  
                                           255 - (int)(progress \* 255),  
                                           (int)(progress \* 255));  
                                    })  
                                { Duration = ActDuration };  
IAnimation fullLineAnimation = new SequentialAnimation() { lineAnimation1,
lineAnimation2, lineAnimation3, lineAnimation4 };  
IAnimation ellipseAnimation1 = new LinearAnimation(  
                                  delegate(float progress)  
                                       {  
                                          ellipse.RadiusX += progress \* 10;  
                                          ellipse.RadiusY += progress \* 10;  
                                          int compValue = (int)(128 + (progress
\* 112));  
                                          ellipse.FillColor = Color.FromArgb(  
                                              compValue,  
                                              compValue,  
                                              compValue);  
                                       })  
                                   { Duration = ActDuration };  
IAnimation ellipseAnimation2 = new Delay() { Duration = ActDuration };  
IAnimation ellipseAnimation3 = new LinearAnimation(  
                                  delegate(float progress)  
                                       {  
                                          ellipse.RadiusX -= progress \* 10;  
                                          int compValue = (int)(240 - (progress
\* 224));  
                                          ellipse.FillColor = Color.FromArgb(  
                                              compValue,  
                                              compValue,  
                                              compValue);  
                                       })  
                                   { Duration = ActDuration };  
IAnimation ellipseAnimation4 = new LinearAnimation(  
                                  delegate(float progress)  
                                       {  
                                          ellipse.RadiusY -= progress \* 10;  
                                          int compValue = (int)(16 + (progress
\* 112));  
                                          ellipse.FillColor = Color.FromArgb(  
                                              compValue,  
                                              compValue,  
                                              compValue);  
                                       })  
                                   { Duration = ActDuration };  
IAnimation fullEllipseAnimation = new SequentialAnimation() { ellipseAnimation1,
ellipseAnimation2, ellipseAnimation3, ellipseAnimation4 };  
scene.Animation = new ParallelAnimation() { fullLineAnimation,
fullEllipseAnimation };  

// playing the scene on the newly created ApngImage  
ApngOptions createOptions = new ApngOptions  
                                {  
                                   Source = new
FileCreateSource("vector_animation.png", false),  
                                   ColorType = PngColorType.TruecolorWithAlpha,  
                                };  

using (ApngImage image = (ApngImage)Image.Create(createOptions, SceneWidth,
SceneHeigth))  
{  
   image.DefaultFrameTime = FrameDuration;  
   scene.Play(image, TotalDuration);  
   image.Save();  
}  

/////////////////////////// Scene.cs /////////////////////////////  

using System.Collections.Generic;  
using Aspose.Imaging.FileFormats.Apng;  

using Graphics = Aspose.Imaging.Graphics;  

// The graphics scene  
public class Scene  
{  
   private readonly List\<IGraphicsObject\> graphicsObjects = new
List\<IGraphicsObject\>();  

   public IAnimation Animation { get; set; }  

   public void AddObject(IGraphicsObject graphicsObject)  
    {  
       this.graphicsObjects.Add(graphicsObject);  
    }  

   public void Play(ApngImage animationImage, uint totalDuration)  
    {  
       uint frameDuration = animationImage.DefaultFrameTime;  
       uint numFrames = totalDuration / frameDuration;  
       uint totalElapsed = 0;  
       for (uint frameIndex = 0; frameIndex \< numFrames; frameIndex++)  
        {  
           if (this.Animation != null)  
            {  
               this.Animation.Update(totalElapsed);  
            }  

           ApngFrame frame = animationImage.PageCount == 0 \|\| frameIndex \> 0  
                                  ? animationImage.AddFrame()  
                                  : (ApngFrame)animationImage.Pages[0];  
           Graphics graphics = new Graphics(frame);  
           graphics.SmoothingMode = SmoothingMode.AntiAlias;  
           foreach (IGraphicsObject graphicsObject in this.graphicsObjects)  
            {  
               graphicsObject.Render(graphics);  
            }  

           totalElapsed += frameDuration;  
        }  
    }  
}  

/////////////////////////// IGraphicsObject.cs /////////////////////////////  

using Graphics = Aspose.Imaging.Graphics;  

// The graphics object  
public interface IGraphicsObject  
{  
   void Render(Graphics graphics);  
}  

/////////////////////////// Line.cs /////////////////////////////  

using Graphics = Aspose.Imaging.Graphics;  

// The line  
public class Line : IGraphicsObject  
{  
   public PointF StartPoint { get; set; }  

   public PointF EndPoint { get; set; }  

   public float LineWidth { get; set; }  

   public Color Color { get; set; }  

   public void Render(Graphics graphics)  
    {  
       graphics.DrawLine(new Pen(this.Color, this.LineWidth), this.StartPoint,
this.EndPoint);  
    }  
}  

/////////////////////////// Ellipse.cs /////////////////////////////  

using Aspose.Imaging.Brushes;  

using Graphics = Aspose.Imaging.Graphics;  

// The ellipse  
public class Ellipse : IGraphicsObject  
{  
   public Color FillColor { get; set; }  

   public PointF CenterPoint { get; set; }  

   public float RadiusX { get; set; }  

   public float RadiusY { get; set; }  

   public void Render(Graphics graphics)  
    {  
       graphics.FillEllipse(  
           new SolidBrush(this.FillColor),  
           this.CenterPoint.X - this.RadiusX,  
           this.CenterPoint.Y - this.RadiusY,  
           this.RadiusX \* 2,  
           this.RadiusY \* 2);  
    }  
}  

/////////////////////////// IAnimation.cs /////////////////////////////  

// The animation  
public interface IAnimation  
{  
// The animation duration, in milliseconds.  
   uint Duration { get; set; }  

   void Update(uint elapsed);  
}  

/////////////////////////// LinearAnimation.cs /////////////////////////////  

// The linear animation  
public class LinearAnimation : IAnimation  
{  
   private readonly AnimationProgressHandler progressHandler;  

   public delegate void AnimationProgressHandler(float progress);  

   public LinearAnimation(AnimationProgressHandler progressHandler)  
    {  
       if (progressHandler == null)  
        {  
           throw new System.ArgumentNullException("progressHandler");  
        }  

       this.progressHandler = progressHandler;  
    }  

   public uint Duration { get; set; }  

   public void Update(uint elapsed)  
    {  
       if (elapsed \<= this.Duration)  
        {  
           this.progressHandler.Invoke((float)elapsed / this.Duration);  
        }  
    }  
}  

/////////////////////////// Delay.cs /////////////////////////////  

// The simple delay between other animations  
public class Delay : IAnimation  
{  
   public uint Duration { get; set; }  

   public void Update(uint elapsed)  
    {  
       // nop  
    }  
}  

/////////////////////////// ParallelAnimation.cs /////////////////////////////  

using System.Collections.Generic;  

// The parallel animation processor  
public class ParallelAnimation : List\<IAnimation\>, IAnimation  
{  
   public uint Duration  
    {  
       get  
        {  
           uint maxDuration = 0;  
           foreach (IAnimation animation in this)  
            {  
               if (maxDuration \< animation.Duration)  
                {  
                   maxDuration = animation.Duration;  
                }  
            }  

           return maxDuration;  
        }  

       set  
        {  
           throw new System.NotSupportedException();  
        }  
    }  

   public void Update(uint elapsed)  
    {  
       foreach (IAnimation animation in this)  
        {  
           animation.Update(elapsed);  
        }  
    }  
}  

/////////////////////////// SequentialAnimation.cs /////////////////////////////  

using System.Collections.Generic;  

// The sequential animation processor  
public class SequentialAnimation : List\<IAnimation\>, IAnimation  
{  
   public uint Duration  
    {  
       get  
        {  
           uint summDuration = 0;  
           foreach (IAnimation animation in this)  
            {  
               summDuration += animation.Duration;  
            }  

           return summDuration;  
        }  

       set  
        {  
           throw new System.NotSupportedException();  
        }  
    }  

   public void Update(uint elapsed)  
    {  
       uint totalDuration = 0;  
       foreach (IAnimation animation in this)  
        {  
           if (totalDuration \> elapsed)  
            {  
               break;  
            }  
             
           animation.Update(elapsed - totalDuration);  
           totalDuration += animation.Duration;  
        }  
    }  
}

IMAGINGNET-3804 The shape collapsed on saving WMF to PNG

using (Image image = Image.Load("image1.wmf"))  
{  
        image.Save(  
           "output.png",  
           new PngOptions()  
           {  
                   VectorRasterizationOptions = new WmfRasterizationOptions()  
                   {  
                            TextRenderingHint =
TextRenderingHint.SingleBitPerPixel,  
                            SmoothingMode = SmoothingMode.None,  
                            PageWidth = image.Width,  
                            PageHeight = image.Height  
                   }  
             });  
}

IMAGINGNET-3781 Support batch export to WebP for multi-page images

using (TiffImage tiffImage = (TiffImage)Image.Load("10MB_Tif.tif"))  
{  
   // Set batch operation for pages  
   tiffImage.PageExportingAction = delegate(int index, Image page)  
         {  
            // Fires garbage collection to avoid unnecessary garbage storage
from previous pages  
            GC.Collect();  

            ((RasterImage)page).Rotate(90);  
         };  

   tiffImage.Save("rotated.webp", new WebPOptions());  

   /* Attention! In batch mode all pages will be released in this line!  
    If you want to further perform operations on the original image, you should reload it from the source
    to another instance. */  
}

IMAGINGNET-3849 -Support of a new compression method DXT1 for BMP

DXT Compression

DXTn is a group of related lossy texture compression algorithms. There are five variations of the algorithm (named DXT1 through DXT5), each designed for specific types of image data. All convert a 4X4 block of pixels to a 64-bit or 128-bit quantity, resulting in compression ratios of 6:1 with 24-bit RGB input data or 4:1 with 32-bit RGBA input data. Its inclusion in Microsoft’s DirectX 6.0 and OpenGL 1.3 led to widespread adoption of the technology among hardware and software makers.

DXT1 Algorithm

DXT1 (also known as Block Compression 1 or BC1) is the most simple compression and also the basis for the other types of DXT algorithms. It is the smallest variation of DXT, storing 16 input pixels in 64 bits of output, consisting of two 16-bit color values and a 4X4 two-bit lookup table. The color information is also stored with a compression so that only 16 bits are used per color. This means that these 16 pixels of the texture only take 64 bits to store (32 for the palette and 32 for the indexing). That is a compression ratio of 1:8.

How to use DXT1 compression

The following code demonstrates how you can compress an existing image using DXT1 compression:

using (var image = Image.Load("Tiger.bmp"))  
{  
    image.Save("CompressedTiger.bmp", new BmpOptions { Compression =
BitmapCompression.Dxt1 });  
}

How to decompress image

The following code shows how to decompress previously compressed image:

using (var image = Image.Load("CompressedTiger.bmp"))  
{  
    image.Save("DecompressedTiger.bmp", new BmpOptions());  
}

IMAGINGNET-3882 Cannot extract Azure label information from XMP metadata

using (JpegImage image = (JpegImage)Image.Load(path))  
{  
   XmpPackage msipPackage = image.XmpData?.Packages.FirstOrDefault(p =\>
p.Prefix == "msip");  
   if (msipPackage != null)  
    {  
        Console.WriteLine(msipPackage.GetXmlValue());  
    }  
}