tags:

views:

879

answers:

3

Within the property window of a JPEG image, there is a tab called 'Summary'. Within this tab, there is a field called 'Comments' I would like to write some c# code which will add a given string to this field e.g "This is a photo".

Does some kind soul out there know how to do this?

Many thanks.

A: 

Maybe this helps: Write EXIF Metadata to Jpeg file

Konamiman
A: 

The easy part:

Add this property item:

var data = System.Text.Encoding.UTF8.GetBytes( "Some comments" );
PropertyItem pi;
*** create an empty PropertyItem here
pi.Type = 2;
pi.Id = 37510;
pi.Len = data.Length;
pi.Value = data;

To the Image's PropertItems collection.

The somewhat more cumbersome part: How do you create a new PropertyItem, since it has no public constructor?

The common "trick" is to have an empty image lying around from which you can steal a PropertyItem. sigh

danbystrom
and how do you associate the stolen PropertyItem to the real image? Is it a read-write property/variable?
Vinko Vrsalovic
realImage.PropertyItems.Add( emptyImage.PropertyItems[0] );
danbystrom
Frustrating. From msdn: "A PropertyItem is not intended to be used as a stand-alone object. A PropertyItem object is intended to be used by classes that are derived from Image. A PropertyItem object is used to retrieve and to change the metadata of existing image files, not to create the metadata. Therefore, the PropertyItem class does not have a defined Public constructor, and you cannot create an instance of a PropertyItem object."
JYelton
+1  A: 

The following code solves my problem and adds comments to a given JPEG image:

public void addImageComment(string imageFlePath, string comments)
    {
        string jpegDirectory = Path.GetDirectoryName(imageFlePath);
        string jpegFileName = Path.GetFileNameWithoutExtension(imageFlePath);

        BitmapDecoder decoder = null;
        BitmapFrame bitmapFrame = null;
        BitmapMetadata metadata = null;
        FileInfo originalImage = new FileInfo(imageFlePath);

        if (File.Exists(imageFlePath))
        {
            // load the jpg file with a JpegBitmapDecoder    
            using (Stream jpegStreamIn = File.Open(imageFlePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
                decoder = new JpegBitmapDecoder(jpegStreamIn, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
            }

            bitmapFrame = decoder.Frames[0];
            metadata = (BitmapMetadata)bitmapFrame.Metadata;

            if (bitmapFrame != null)
            {
                BitmapMetadata metaData = (BitmapMetadata)bitmapFrame.Metadata.Clone();

                if (metaData != null)
                {
                    // modify the metadata   
                    metaData.SetQuery("/app1/ifd/exif:{uint=40092}", comments);

                    // get an encoder to create a new jpg file with the new metadata.      
                    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(bitmapFrame, bitmapFrame.Thumbnail, metaData, bitmapFrame.ColorContexts));
                    //string jpegNewFileName = Path.Combine(jpegDirectory, "JpegTemp.jpg");

                    // Delete the original
                    originalImage.Delete();

                    // Save the new image 
                    using (Stream jpegStreamOut = File.Open(imageFlePath, FileMode.CreateNew, FileAccess.ReadWrite))
                    {
                        encoder.Save(jpegStreamOut);
                    }
                }
            }
        }
    }

This is essentially a lightly modified version of the code found under the link which Konamiman kindly supplied.

Please be aware that to make this work you will need to add .NET references to System.Core and WindowsBase. If using Visual Studio 2008, this can be achieved via the following:

  1. Right click on your project in the Solution Explorer

  2. From the drop down list, select Add 'Reference...'

  3. From the new box which opens, select the '.NET' tab

  4. Scroll to the two references mentioned above and on each, click ok

Many thanks to both danbystrom and Konamiman for your help in this matter. I really appreciate the quick response.

John P
You should vote up and/or accept their answers if you found them helpful. Cheers!
RickL
Oops, I made a small mistake with my solution above. I should have said that you need to add the PresentationCore reference, not the System.CorePs. Thanks for the heads-up Rick! I will do that straight away.
John P