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); } } }