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:
'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()
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);
}
}
}