This documentation is for the old version. Go to the latest Graphics Mill docs

Preserving Metadata when Processing Images

When you process JPEG or TIFF images that have some metadata inside, you may wonder how to preserve this metadata during saving modified image into the file. Indeed, after you load bitmap into memory, no information about metadata is stored anymore, and when we save this bitmap into file, this metadata is lost. But metadata are often used in later processing, e.g. EXIF is widely used by printing machines.

Fortunately, Graphics Mill for .NET provides an elegant way to copy metadata from one file to another. The idea is very simple: we open format reader that reads not only bitmap, but also extracts EXIF, IPTC, XMP and Adobe® image resource blocks collections. After the image is processed, create a format writer, and put not only the modified bitmap, but also write the EXIF, IPTC, XMP, or Adobe® image resource blocks details.

The code example below demonstrates how to implement this approach. It does the following:

  1. Loads the bitmap and associated EXIF, IPTC, XMP, and Adobe® image resource blocks.
  2. Resizes the bitmap.
  3. Updates EXIF, IPTC, and XMP fields and Adobe® image resource blocks.
  4. Saves new bitmap and metadata into a file.
Visual Basic
'Open reader on the file
Dim jpegReader As New Aurigma.GraphicsMill.Codecs.JpegReader("C:\IMG_0001.jpg")

'Read metadata
Dim exif As Aurigma.GraphicsMill.Codecs.ExifDictionary = jpegReader.Exif
Dim iptc As Aurigma.GraphicsMill.Codecs.IptcDictionary = jpegReader.Iptc
Dim adobeResources As Aurigma.GraphicsMill.Codecs.AdobeResourceDictionary = jpegReader.AdobeResources
Dim xmp As Aurigma.GraphicsMill.Codecs.XmpData = Nothing
If Not jpegReader.Xmp Is Nothing Then
    xmp = New Aurigma.GraphicsMill.Codecs.XmpData(jpegReader.Xmp)
End If

'Read bitmap
Dim frame As Aurigma.GraphicsMill.Codecs.Frame = jpegReader.LoadFrame(0)
Dim bitmap As New Aurigma.GraphicsMill.Bitmap
frame.GetBitmap(bitmap)
frame.Dispose()
jpegReader.Dispose()

'Resize bitmap
bitmap.Transforms.Resize(bitmap.Width \ 2, 0)

'Change metadata items

'EXIF
'Loaded image can be without EXIF metadata
If exif Is Nothing Then
    exif = New Aurigma.GraphicsMill.Codecs.ExifDictionary
End If
exif.Item(Aurigma.GraphicsMill.Codecs.ExifDictionary.Software) = "Aurigma Graphics Mill"

'IPTC
'Loaded image can be without IPTC metadata
If iptc Is Nothing Then
    iptc = New Aurigma.GraphicsMill.Codecs.IptcDictionary
End If
iptc.Item(Aurigma.GraphicsMill.Codecs.IptcDictionary.Keyword) = "mountain"

'Adobe resource blocks
'Loaded image can be without adobe image resource blocks
If adobeResources Is Nothing Then
    adobeResources = New Aurigma.GraphicsMill.Codecs.AdobeResourceDictionary
End If
'Create new adobe image resource block with the required metadata
Dim arBlock As New Aurigma.GraphicsMill.Codecs.AdobeResourceBlock("Copyright", New Byte() {1})
'Set this block to the item with 0x040A ID (copyright flag)
adobeResources.Item(&H40A) = arBlock

'XMP
'Loaded image can be without XMP metadata
If xmp Is Nothing Then
    xmp = New Aurigma.GraphicsMill.Codecs.XmpData()
End If
'Create a node with the required metadata
Dim node As New Aurigma.GraphicsMill.Codecs.XmpValueNode( _
    Aurigma.GraphicsMill.Codecs.XmpNodeType.SimpleProperty, _
    "John Doe", _
    Aurigma.GraphicsMill.Codecs.XmpTagNames.DCCreator)
xmp.AddNode(node)

'Write bitmap and metadata
Dim jpegWriter As New Aurigma.GraphicsMill.Codecs.JpegWriter("C:\IMG_0002.jpg")

'Write metadata
jpegWriter.Exif = exif
jpegWriter.Iptc = iptc
jpegWriter.AdobeResources = adobeResources
jpegWriter.Xmp = xmp.Save()

'Write bitmap
Dim frame2 As New Aurigma.GraphicsMill.Codecs.JpegFrame(bitmap, 70, False)
jpegWriter.AddFrame(frame2)
jpegWriter.Dispose()

bitmap.Dispose()
C#
using (Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap())
{
    Aurigma.GraphicsMill.Codecs.ExifDictionary exif = null;
    Aurigma.GraphicsMill.Codecs.IptcDictionary iptc = null;
    Aurigma.GraphicsMill.Codecs.XmpData xmp = null;
    Aurigma.GraphicsMill.Codecs.AdobeResourceDictionary adobeResources = null;

    //Read bitmap and metadata
    using (Aurigma.GraphicsMill.Codecs.JpegReader jpegReader =
        new Aurigma.GraphicsMill.Codecs.JpegReader(@"C:\IMG_0001.jpg"))
    {
        //Read metadata
        exif = jpegReader.Exif;
        iptc = jpegReader.Iptc;
        adobeResources = jpegReader.AdobeResources;
        if (jpegReader.Xmp != null)
        {
            xmp = new Aurigma.GraphicsMill.Codecs.XmpData();
            xmp.Load(jpegReader.Xmp);
        }

        //Read bitmap
        using (Aurigma.GraphicsMill.Codecs.IFrame frame1 = jpegReader.LoadFrame(0))
        {
            frame1.GetBitmap(bitmap);
        }
    }

    //Resize bitmap
    bitmap.Transforms.Resize(bitmap.Width / 2, 0);

    //Change metadata items

    //EXIF
    //Loaded image can be without EXIF metadata
    if (exif == null)
    {
        exif = new Aurigma.GraphicsMill.Codecs.ExifDictionary();
    }
    exif[Aurigma.GraphicsMill.Codecs.ExifDictionary.Software] = "Aurigma Graphics Mill";

    //IPTC
    //Loaded image can be without IPTC metadata
    if (iptc == null)
    {
        iptc = new Aurigma.GraphicsMill.Codecs.IptcDictionary();
    }
    iptc[Aurigma.GraphicsMill.Codecs.IptcDictionary.Keyword] = "mountain";

    //Adobe resource blocks
    //Loaded image can be without adobe image resource blocks
    if (adobeResources == null)
    {
        adobeResources = new Aurigma.GraphicsMill.Codecs.AdobeResourceDictionary();
    }
    //Create new adobe image resource block with the required metadata
    Aurigma.GraphicsMill.Codecs.AdobeResourceBlock arBlock = new
        Aurigma.GraphicsMill.Codecs.AdobeResourceBlock("Copyright", new byte[] { 1 });
    //Set this block to the item with 0x040A ID (copyright flag)
    adobeResources[0x040A] = arBlock;

    //XMP
    //Loaded image can be without XMP metadata
    if (xmp == null)
    {
        xmp = new Aurigma.GraphicsMill.Codecs.XmpData();
    }
    //Create a node with the required metadata
    Aurigma.GraphicsMill.Codecs.XmpValueNode node = new
        Aurigma.GraphicsMill.Codecs.XmpValueNode(
            Aurigma.GraphicsMill.Codecs.XmpNodeType.SimpleProperty,
            "John Doe",
            Aurigma.GraphicsMill.Codecs.XmpTagNames.DCCreator);
    xmp.AddNode(node);

    //Write bitmap and metadata
    using (Aurigma.GraphicsMill.Codecs.JpegWriter jpegWriter =
        new Aurigma.GraphicsMill.Codecs.JpegWriter(@"C:\IMG_0002.jpg"))
    {
        //Read metadata
        jpegWriter.Exif = exif;
        jpegWriter.Iptc = iptc;
        jpegWriter.AdobeResources = adobeResources;
        jpegWriter.Xmp = xmp.Save();

        //Write bitmap
        using (Aurigma.GraphicsMill.Codecs.JpegFrame frame2 =
            new Aurigma.GraphicsMill.Codecs.JpegFrame(bitmap, 70, false))
        {
            jpegWriter.AddFrame(frame2);
        }
    }
}