Reading and Writing image "Rating" metadata<p>I'm looking for a way to read and modify &quot;Rating&quot; metadata that Vista uses to rate image files. </p> <p>I'm able to read the rating although I noticed that the rating is written in several places in metadata... and I'm not sure which Vista is using... it looks like all of them are changed at the same time and are kept in sync... so do I have to modify all of them to keep them in sync?</p><font color="#00ff00" size=2> <p></font><font size=2><font color="#800000">/xmp/Rating</font></font></p> <p><font color="#800000"><font size=2>/</font><font size=2>xmp/xap:Rating</font></font><font size=2></p> <p></font><font color="#008000" size=2><font color="#800000">/app1/{uint=0}/{uint=18246}</font></font></p> <p><font color="#000000" size=2>When I'm trying to modify the rating... nothing happens... I'm using this code</font></p><font color="#008000" size=2><font color="#008000" size=2><font color="#008000"><font color="#0000ff" size=2><font color="#008000"><font color="#008080" size=2> <p>Stream </font></font></font><font color="#008000"><font size=2>fileStream = </font><font size=2>new</font><font size=2> System.IO.</font><font size=2>FileStream</font><font size=2>(path.LocalPath, </font><font size=2>FileMode</font><font size=2>.Open, </font><font size=2>FileAccess</font><font size=2>.ReadWrite, </font><font size=2>FileShare</font></font><font size=2><font color="#008000">.ReadWrite);</font></p></font><font color="#008000"><font color="#008000"><font size=2><font color="#008080" size=2> <p>BitmapDecoder </font></font><font size=2>decoder = </font><font size=2>BitmapDecoder</font><font size=2>.Create(</font><font size=2>this</font><font size=2>.fileStream, </font><font size=2>BitmapCreateOptions</font><font size=2>.PreservePixelFormat, </font><font size=2>BitmapCacheOption</font><font color="#00ff00" size=2>.None);</p></font></font></font></font> <p><font color="#008000">InPlaceBitmapMetadataWriter writer = decoder.Frames[0].CreateInPlaceBitmapMetadataWriter();</font></p> <p><font color="#008000">writer.SetQuery(&quot;/<font size=2>xmp/xap:Rating&quot;</font>, &quot;4&quot;); </font></p> <p><font color="#000000">I get no exceptions... so what's wrong?</font></p></font></font>© 2009 Microsoft Corporation. All rights reserved.Wed, 09 Sep 2009 09:31:52 Z8f297b11-99ba-459c-b085-1ff3ae526487http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#8f297b11-99ba-459c-b085-1ff3ae526487http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#8f297b11-99ba-459c-b085-1ff3ae526487Cezaryhttp://social.msdn.microsoft.com/Profile/en-US/?user=CezaryReading and Writing image "Rating" metadata<p>I'm looking for a way to read and modify &quot;Rating&quot; metadata that Vista uses to rate image files. </p> <p>I'm able to read the rating although I noticed that the rating is written in several places in metadata... and I'm not sure which Vista is using... it looks like all of them are changed at the same time and are kept in sync... so do I have to modify all of them to keep them in sync?</p><font color="#00ff00" size=2> <p></font><font size=2><font color="#800000">/xmp/Rating</font></font></p> <p><font color="#800000"><font size=2>/</font><font size=2>xmp/xap:Rating</font></font><font size=2></p> <p></font><font color="#008000" size=2><font color="#800000">/app1/{uint=0}/{uint=18246}</font></font></p> <p><font color="#000000" size=2>When I'm trying to modify the rating... nothing happens... I'm using this code</font></p><font color="#008000" size=2><font color="#008000" size=2><font color="#008000"><font color="#0000ff" size=2><font color="#008000"><font color="#008080" size=2> <p>Stream </font></font></font><font color="#008000"><font size=2>fileStream = </font><font size=2>new</font><font size=2> System.IO.</font><font size=2>FileStream</font><font size=2>(path.LocalPath, </font><font size=2>FileMode</font><font size=2>.Open, </font><font size=2>FileAccess</font><font size=2>.ReadWrite, </font><font size=2>FileShare</font></font><font size=2><font color="#008000">.ReadWrite);</font></p></font><font color="#008000"><font color="#008000"><font size=2><font color="#008080" size=2> <p>BitmapDecoder </font></font><font size=2>decoder = </font><font size=2>BitmapDecoder</font><font size=2>.Create(</font><font size=2>this</font><font size=2>.fileStream, </font><font size=2>BitmapCreateOptions</font><font size=2>.PreservePixelFormat, </font><font size=2>BitmapCacheOption</font><font color="#00ff00" size=2>.None);</p></font></font></font></font> <p><font color="#008000">InPlaceBitmapMetadataWriter writer = decoder.Frames[0].CreateInPlaceBitmapMetadataWriter();</font></p> <p><font color="#008000">writer.SetQuery(&quot;/<font size=2>xmp/xap:Rating&quot;</font>, &quot;4&quot;); </font></p> <p><font color="#000000">I get no exceptions... so what's wrong?</font></p></font></font>Sun, 11 Jun 2006 17:00:15 Z2007-07-19T04:54:50Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#2486645a-34f0-48a4-8bdf-f22a773e1925http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#2486645a-34f0-48a4-8bdf-f22a773e1925Robert A. Wlodarczykhttp://social.msdn.microsoft.com/Profile/en-US/?user=Robert%20A.%20WlodarczykReading and Writing image "Rating" metadata<p>What's likely happening is that the file doesn't have enough space in it to do an in-place edit. Typical pattern of usage with the InPlaceBitmapMetadataWriter is as follows:</p> <blockquote dir=ltr style="margin-right:0px"> <p><font face="Courier New, Courier, Monospace" color="#000000">InPlaceBitmapMetadataWriter writer = decoder.Frames[0].CreateInPlaceBitmapMetadataWriter();</font></p> <p><font face="Courier New, Courier, Monospace" color="#000000">writer.SetQuery(&quot;/xmp/xap:Rating&quot;, &quot;4&quot;); </font></p> <p><font face="Courier New, Courier, Monospace" color="#000000">if(!writer.TrySave())</font></p> <p><font face="Courier New, Courier, Monospace" color="#000000">{</font></p> <p><font face="Courier New, Courier, Monospace" color="#000000">    // In place metadata editing failed.</font></p> <p><font face="Courier New, Courier, Monospace" color="#000000">    // You will need to write out the metadata using the BitmapMetadata class and fully re-encoding the image (ie: grab the Frames from the decoder)</font></p> <p><font face="Courier New, Courier, Monospace" color="#000000">}</font></p></blockquote> <p><font color="#000000">One thing to note is that if the TrySave fails, some of the data may have been written out to the stream already. So, Ideally you should try to do the TrySave on a temporary in memory stream rather than the original file.</font></p>Fri, 28 Jul 2006 20:34:36 Z2006-07-28T20:34:39Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#3fd580d5-d3a1-4b3e-8618-ed803b025d81http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#3fd580d5-d3a1-4b3e-8618-ed803b025d81code jockeyhttp://social.msdn.microsoft.com/Profile/en-US/?user=code%20jockeyReading and Writing image "Rating" metadata<p style="font-family: Courier New,Courier,Monospace; color: rgb(0, 128, 0);"><font size="2"><span id="_ctl0_MainContent__ctl0_PostForm_ReplyBody" class="txt4"><p> // You will need to write out the metadata using the BitmapMetadata class and fully re-encoding the image (ie:<br>grab the Frames from the decoder)</p></span></font></p><p style="font-family: Geneva,Arial,Sans-serif;"><font size="3"><span id="_ctl0_MainContent__ctl0_PostForm_ReplyBody" class="txt4"></span></font></p><p style="font-family: Geneva,Arial,Sans-serif;"><font size="3"><span id="_ctl0_MainContent__ctl0_PostForm_ReplyBody" class="txt4"><p><font color="#000000">^ This is the bit i am stuck on. I can't work out how to get a copy of the metadata that isn't frozen.</font></p><p>I clone the BitmapFrame which is not fFrozen, but then its Metadata property is frozen.</p><p>I tried setting the encoder.Metadata property explicitly, but that appears to be the wrong location as the jpeg doesn't support global meta data.</p>Any chance we can get a sample that demonstrates how to do this? <br></span></font></p><p style="font-family: Geneva,Arial,Sans-serif;"><font size="3"><span id="_ctl0_MainContent__ctl0_PostForm_ReplyBody" class="txt4">The BitmapMetadata sample in the Windows SDK demonstrates </span></font><font size="3"><span id="_ctl0_MainContent__ctl0_PostForm_ReplyBody" class="txt4">only </span></font><font size="3"><span id="_ctl0_MainContent__ctl0_PostForm_ReplyBody" class="txt4">the most simple usage scenario.<br></span></font></p><p><span id="_ctl0_MainContent__ctl0_PostForm_ReplyBody" class="txt4"></span></p>Tue, 26 Dec 2006 22:05:42 Z2006-12-26T22:05:42Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#e49cefe0-158c-4f82-93da-fb04db020091http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#e49cefe0-158c-4f82-93da-fb04db020091thspoehttp://social.msdn.microsoft.com/Profile/en-US/?user=thspoeReading and Writing image "Rating" metadatayes, right!<img src="images/emoticons/smile_regular.gif">, an example would be great.<br><br>thomas<br>Thu, 18 Jan 2007 12:13:01 Z2007-01-18T12:13:01Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#b359a8e1-9e95-4b9a-afaf-e79eb5fb3609http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#b359a8e1-9e95-4b9a-afaf-e79eb5fb3609RenRenhttp://social.msdn.microsoft.com/Profile/en-US/?user=RenRenReading and Writing image "Rating" metadata<p><font size=2>Hello, here is a sample test</font></p> <p><font face="Courier New, Courier, Monospace" color="#0000ff" size=2>Stream JpegStreamIn = new FileStream(&quot;iptcIN.jpg&quot;, FileMode.Open, FileAccess.Read, FileShare.Read);<br>JpegBitmapDecoder JpegDecoder = new JpegBitmapDecoder(JpegStreamIn,<br>        BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);<br>FileStream JpegStreamOut = new FileStream(&quot;IPTCOUT.jpg&quot;, FileMode.Create);<br>JpegBitmapEncoder JpegEncoder = new JpegBitmapEncoder();<br><br>BitmapFrame JpegFrame = BitmapFrame.Create(JpegDecoder.Frames[0]);<br>JpegEncoder.Frames.Add(JpegFrame);<br>BitmapMetadata JpegMeta = (BitmapMetadata)JpegFrame.Metadata;<br></font><font face="Courier New, Courier, Monospace"><br><font color="#0000ff" size=2>JpegMeta.Copyright = &quot;COPYRIGHT&quot;;<br></font></font><font face="Courier New, Courier, Monospace"><br><font color="#0000ff" size=2>string[] MC = new string[JpegMeta.Keywords.Count + 1];<br>JpegMeta.Keywords.CopyTo(MC, 0);<br>MC[MC.Length - 1] = &quot;NEW-KEYWORD&quot;;<br>JpegMeta.Keywords = new ReadOnlyCollection&lt;string&gt;(MC);<br></font></font><font size=1><br><font face="Courier New, Courier, Monospace"><font color="#0000ff" size=2>JpegEncoder.Save(JpegStreamOut);</font><br><br></font><font face="Geneva, Arial, Sans-serif"><font size=2>Where can I find a complète list of metadatas string identifiers (like &quot;<font color="#800000">/xmp/Rating&quot; &quot;</font><font color="#800000">/xmp/xap:Rating&quot; <font color="#000000">and </font>&quot;</font><font color="#008000"><font color="#800000">/app1/{uint=0}/{uint=18246}&quot;</font></font><font color="#000000">) ?? The only example I found in doc is &quot;/text/Description&quot; !<br><br>Thanks.</font></font></font></font></p> <p><font size=2>Jean-Luc</font><font size=1><font face="Courier New, Courier, Monospace"></p></font></font>Fri, 19 Jan 2007 21:54:24 Z2007-01-19T21:54:24Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#73a4bdad-3872-493e-b179-e831e5c203f1http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#73a4bdad-3872-493e-b179-e831e5c203f1thspoehttp://social.msdn.microsoft.com/Profile/en-US/?user=thspoeReading and Writing image "Rating" metadatalook <a title="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/DMD_Imag/htm/photo_metadata_policy__mvoo.asp" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/DMD_Imag/htm/photo_metadata_policy__mvoo.asp">here</a><br>thomas<br><br>Sat, 20 Jan 2007 08:43:28 Z2007-01-20T08:43:28Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#5857e9f3-d8bb-41bf-81d9-795f0c6c1e70http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#5857e9f3-d8bb-41bf-81d9-795f0c6c1e70thspoehttp://social.msdn.microsoft.com/Profile/en-US/?user=thspoeReading and Writing image "Rating" metadatai have another question. when i set:<br><br>            //System.Author<br>            string[] _author = new string[1];<br>            _author[0] = &quot;John Doe&quot;;<br>            JpegMeta.Author = new ReadOnlyCollection&lt;string&gt;(_author);<br><br>then this works fine. when i set the single values (in order ---&gt; <a title="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/DMD_Imag/htm/photo_metadata_policy__mvoo.asp" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/DMD_Imag/htm/photo_metadata_policy__mvoo.asp">here</a>) like this:<br><br><table border=1 cellpadding=5 rules=all><tbody><tr valign=top><td class=label width="12%"><b>Order</b></td> <td class=label width="50%"><b>Path</b></td> <td class=label width="22%"><b>Disk Format</b></td> <td class=label width="16%"><b>Required</b></td> </tr> <tr valign=top> <td width="12%">1</td> <td width="50%">/xmp/&lt;xmpseq&gt;dc:creator</td> <td width="22%">A vector of Unicode strings. The XMP format of the string is xmpseq. </td> <td width="16%">Yes</td> </tr> <tr valign=top> <td width="12%">2</td> <td width="50%">/xmp/tiff:artist</td> <td width="22%">A vector of Unicode strings.</td> <td width="16%">Yes</td> </tr> <tr valign=top> <td width="12%">3</td> <td width="50%">/app13/irb/8bimiptc/iptc/by-line</td> <td width="22%">An ASCII vector</td> <td width="16%">No</td> </tr> <tr valign=top> <td width="12%">4</td> <td width="50%">/app1/ifd/{ushort=315}</td> <td width="22%">An ASCII vector. Delimited.</td> <td width="16%">No</td> </tr> <tr valign=top> <td width="12%">5</td> <td width="50%">/app1/ifd/{ushort=40093}</td> <td width="22%">Unicode bytes. Semicolon delimited.</td> <td width="16%">No</td></tr></tbody></table><br>&quot;/xmp/tiff:artist&quot; works fine with a string like &quot;John Doe&quot; ...<br>but how to set &quot;xmp/&lt;xmpseq&gt;dc:creator&quot; ?!? (with a hashtable or what ...?)<br><br>thomas<br>Sat, 20 Jan 2007 14:49:12 Z2007-01-20T14:49:12Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#0e84e48e-0528-404e-a2fb-a7c12d1422d8http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#0e84e48e-0528-404e-a2fb-a7c12d1422d8code jockeyhttp://social.msdn.microsoft.com/Profile/en-US/?user=code%20jockeyReading and Writing image "Rating" metadata<font style="color:rgb(0, 0, 0)" size=3><span style="font-family:Geneva,Arial,Sans-serif">thanks for your sample Jean-Luc.</span><br style="font-family:Geneva,Arial,Sans-serif"><span style="font-family:Geneva,Arial,Sans-serif">This is my code that doesn't work. The bmpWriter .TrySave() always fails.</span><br style="font-family:Geneva,Arial,Sans-serif"><span style="font-family:Geneva,Arial,Sans-serif">I am using a memoryStream as suggested by Robert in his earlier post.</span><br style="font-family:Geneva,Arial,Sans-serif"><span style="font-family:Geneva,Arial,Sans-serif">If I ignore the TrySave failure and save anyway, then the jpeg saves, but the meta data doesn't reflect the new value.</span><br style="font-family:Geneva,Arial,Sans-serif"><br style="font-family:Geneva,Arial,Sans-serif"><span style="font-family:Geneva,Arial,Sans-serif">I also tried using the BitmapFrame.Create ctor as you do to seed the encoder, however in that case the </span></font><font style="font-family:Geneva,Arial,Sans-serif;color:rgb(0, 0, 0)" size=3>CreateInPlaceBitmapMetadataWriter method returns null :|<br><br>If I use your technique of editing the </font><font style="color:rgb(0, 0, 0)" size=3><span style="font-family:Geneva,Arial,Sans-serif"><span id="_ctl0_MainContent__ctl0_PostForm_ReplyBody" class=txt4>BitmapMetadata directly  then the meta data is not updated with the new value that I set.</span></span></font><br><br><font style="font-family:Courier New,Courier,Monospace;color:rgb(0, 128, 0)" size=2>Stream fileStream = File.Open(photo.FilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);<br>            BinaryReader br = new BinaryReader(fileStream);<br><br>            MemoryStream memoryStream = new MemoryStream(br.ReadBytes((int) fileStream.Length));<br><br>            string outputFilename = photo.FilePath + &quot;.bak.jpg&quot;;<br><br>            FileStream outputFile = File.Open(outputFilename, FileMode.Create);<br><br>            using (memoryStream)<br>            {<br>                BitmapDecoder decoder = BitmapDecoder.Create(memoryStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);<br>                BitmapFrame sourceFrame = decoder.Frames[0];<br><br>                JpegBitmapEncoder encoder = new JpegBitmapEncoder();<br>                encoder.Frames.Add(sourceFrame);<br><br>                InPlaceBitmapMetadataWriter bmpWriter = sourceFrame.CreateInPlaceBitmapMetadataWriter();<br><br>                bmpWriter.Title = photo.Title;<br>                <br>                if (!bmpWriter.TrySave())<br>                {<br>                    throw new Exception(&quot;It didn't work&quot;);<br>                }<br><br>                encoder.Save(outputFile);<br>            }<br><br>            outputFile.Close();</font>Tue, 30 Jan 2007 07:43:16 Z2007-01-30T07:43:16Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#ceba1dd6-b67f-43d3-a0f2-a082e52aa0echttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#ceba1dd6-b67f-43d3-a0f2-a082e52aa0ecRenRenhttp://social.msdn.microsoft.com/Profile/en-US/?user=RenRenReading and Writing image "Rating" metadata<p>Thank you thspoe.</p> <p>code jockey: I think you can't use &quot;BitmapCacheOption.None&quot; if you want to use InPlaceBitmapMetadaWriter. <br>Here's remark  in MSDN: </p> <blockquote dir=ltr style="margin-right:0px"> <p><font color="#0000ff">If BitmapMetadata is not associated with a BitmapFrame that is obtained through a BitmapDecoder, the attempt to write metadata by using the in-place writer will fail. Successful write operations apply the metadata directly to the image stream by means of a decoder. </font></p> <p><font color="#0000ff">In-place metadata updates fail if an attempt is made to write metadata that a given bitmap format does not support.</font></p> <p><font color="#0000ff">To perform in-place metadata edits, the bitmap <u>must be decoded using either the Default or OnDemand cache options</u>. OnLoad does not guarantee access to the metadata stream needed for in-place metadata edits.</font></p></blockquote> <p> Also, if you want to create a copy of your photo with modified metadatas, it's not usefull to use InPlaceBitmapMetadataWriter, you can do that like in my sample above.<br>I think it's usefull only if you want to save metadatas directely in original file.</p> <p>But... I don't like my sample because the picture is decoded and encoded in another file. The encoder has a QualityLevel property wich is 75 (%) by default. If you compare in and out files, there are differences (with a zoom in Photoshop). If you use 100 for QualityLevel, out file size is +/- 3x biger than original. If you use repetitive update you loose quality, it's not acceptable.</p> <p>The solution is in this case InPlaceMetadataWriter but I've never seen a sample wich is realy working!<br>TrySave() return true before any modification and return false after a modification. If you use sample from MS:</p> <blockquote dir=ltr style="margin-right:0px"> <p><font face="Courier New, Courier, Monospace" color="#339966"><span style="color:blue"><span style="color:blue">if (pngInplace.TrySave() == true)<br>{<br> pngInplace.SetQuery(&quot;/Text/Description&quot;, &quot;Have a nice day.&quot;); <br>}<br>pngStream.Close();</span></span></font></p></blockquote> <p dir=ltr><font face="Courier New, Courier, Monospace"><font color="#000000"><span style="color:blue"><span style="color:blue"></span></span></font></font><span style="color:blue"><font face="Geneva, Arial, Sans-serif" color="#000000">It seems TrySave is used to test if it's possible to save, not to append modifications to file.<br>Or I dont' understand? (It's possible, i'm so stupid....)<br><br>If anybody has some working samples with InPlaceMetadataWriter, please share it !</font></span></p> <p dir=ltr><font face="Courier New, Courier, Monospace"><font color="#339966"><span style="color:blue"><font color="#000000"><font face="Geneva, Arial, Sans-serif">Jean-Luc<br><br>PS: sorry for my poor english, I'm from Belgium and I speak french.</font></p> <p dir=ltr style="margin-right:0px"></font></span></font></font> </p> <p dir=ltr> </p>Tue, 30 Jan 2007 10:50:21 Z2007-01-30T10:50:21Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#a0b791b7-a4d5-4e7b-96a7-d9500730464fhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#a0b791b7-a4d5-4e7b-96a7-d9500730464fcode jockeyhttp://social.msdn.microsoft.com/Profile/en-US/?user=code%20jockeyReading and Writing image "Rating" metadataYes looks like you are right according to the doco Jean Luc - however I just tried it with OnDemand and that didn't work either.<br><br>WRT the TrySave() method - I have been working on the assumption that the MSDN doco is wrong.<br>For several reasons<br>1) As you say it does nothing when you call it before the SetQuery <br>2) Robert's sample above shows usage contrary to MSDN doco<br>3) Using reflector shows this<br><br><table style="margin-bottom:0px" cellpadding=0 cellspacing=0 width="100%"> <tbody> <tr> <td style="padding:4px 5px" colspan=2 valign=top><pre>[<a title="System.Security.SecurityCriticalAttribute.SecurityCriticalAttribute();" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=1">SecurityCritical</a>]<br><font color="#1000a0">public</font> <a title=System.Boolean href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=2">bool</a> <b>TrySave</b>()<br>{<br> <a title=System.Int32 href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=3">int</a> <b>num1</b>;<br> <a title=MS.Internal.Invariant href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=4">Invariant</a>.<a title="void MS.Internal.Invariant.Assert(bool);" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=5">Assert</a>(<font color="#1000a0">this</font>.<a title="SafeMILHandle System.Windows.Media.Imaging.InPlaceBitmapMetadataWriter._fmeHandle;" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=6">_fmeHandle</a> != <font color="#800000">null</font>);<br> <font color="#1000a0">lock</font> (<font color="#1000a0">base</font>.<a title="object System.Windows.Media.Imaging.BitmapMetadata.SyncObject { ... }" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=7">SyncObject</a>)<br> {<br> <a title="int num1 // Local Variable">num1</a> = <a title="" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=8">UnsafeNativeMethods</a>.<a title="MS.Win32.PresentationCore.UnsafeNativeMethods+WICFastMetadataEncoder" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=9">WICFastMetadataEncoder</a>.<a title="int MS.Win32.PresentationCore.UnsafeNativeMethods+WICFastMetadataEncoder.Commit(SafeMILHandle THIS_PTR);" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=10">Commit</a>(<font color="#1000a0">this</font>.<a title="SafeMILHandle System.Windows.Media.Imaging.InPlaceBitmapMetadataWriter._fmeHandle;" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=11">_fmeHandle</a>);<br> }<br> <font color="#1000a0">return</font> <a title=MS.Internal.HRESULT href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=12">HRESULT</a>.<a title="bool MS.Internal.HRESULT.Succeeded(int hr);" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=13">Succeeded</a>(<a title="int num1 // Local Variable">num1</a>);<br>}<br></pre></td></tr></tbody></table>The commit statement looks awfully like a 'write' operation.<br><br>I don't think any of us here are stupid, more that the doco is a bit lacking.<br>Looking at more of the SDK samples today, it does look a bit rushed.<br>There are lots of readme.htm's for samples that are just blank templates that the MS developers didn't bother filling out!<br><br>ps: Your English is far better than my French. au revior!<br><br><br>Tue, 30 Jan 2007 12:17:50 Z2007-01-30T12:17:50Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#468e9f8a-9f34-4e65-9cc3-a2594c65045chttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#468e9f8a-9f34-4e65-9cc3-a2594c65045cRenRenhttp://social.msdn.microsoft.com/Profile/en-US/?user=RenRenReading and Writing image "Rating" metadata<p>Here is a sample code to retrieve all metadata from an image file. In a form add a button and a RichTextBox. It's not my code, I don't remember wher I found it, sorry.</p> <p><font color="#008000">        private void button3_Click(object sender, EventArgs e)<br>        {<br>            richTextBox1.Clear();<br>            using (Stream fileStream = File.Open(&quot;iptcx.jpg&quot;, FileMode.Open))<br>            {<br>                BitmapDecoder decoder = BitmapDecoder.Create(fileStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);<br>                PrintMetadata(decoder.Frames[0].Metadata, string.Empty);<br>            }<br>        }</font></p> <p><font color="#008000">        private void PrintMetadata(System.Windows.Media.ImageMetadata metadata, string fullQuery)<br>        {<br>            BitmapMetadata theMetadata = metadata as BitmapMetadata;<br>            if (theMetadata != null)<br>            {<br>                foreach (string query in theMetadata)<br>                {<br>                    string tempQuery = fullQuery + query;<br>                    // query string here is relative to the previous metadata reader.<br>                    object o = theMetadata.GetQuery(query);<br>                    richTextBox1.Text += &quot;\n&quot; + tempQuery + &quot;, &quot; + query + &quot;, &quot; + o;<br>                    BitmapMetadata moreMetadata = o as BitmapMetadata;<br>                    if (moreMetadata != null)<br>                    {<br>                        PrintMetadata(moreMetadata, tempQuery);<br>                    }<br>                }<br>            }<br>        }<br></font></p> <p>thspoe : if you change Authors property, /xmp/dc:creator is changed.<br>If you want to change these values individualy, you can do that like:</p> <p><font color="#008000">            JpegMeta.SetQuery(&quot;/xmp/dc:creator/{ulong=0}&quot;,&quot;Auth 1&quot;);<br>            JpegMeta.SetQuery(&quot;/xmp/dc:creator/{ulong=1}&quot;,&quot;Auth 2&quot;);<br>            JpegMeta.SetQuery(&quot;/xmp/dc:creator/{ulong=2}&quot;,&quot;Auth 3&quot;);<br>            JpegMeta.SetQuery(&quot;/xmp/dc:creator/{ulong=3}&quot;,&quot;Auth 4&quot;);</font></p> <p>Jean-Luc</p>Tue, 30 Jan 2007 12:32:19 Z2007-01-30T12:32:19Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#1d011a74-971b-476a-b084-19a4716491c7http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#1d011a74-971b-476a-b084-19a4716491c7thspoehttp://social.msdn.microsoft.com/Profile/en-US/?user=thspoeReading and Writing image "Rating" metadata<p><font size=2>Hello Jean-Luc,</font></p> <p><font size=2>thank you! <img src="images/emoticons/smile_regular.gif"></font></p> <p><font size=2>Thomas</font></p> <p><font size=2></font> </p>Tue, 30 Jan 2007 13:34:07 Z2007-01-30T13:34:07Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#eaca0bed-fcc9-4c15-9980-ea20f576fc64http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#eaca0bed-fcc9-4c15-9980-ea20f576fc64code jockeyhttp://social.msdn.microsoft.com/Profile/en-US/?user=code%20jockeyReading and Writing image "Rating" metadata<P><FONT style="COLOR: rgb(0,0,0); FONT-FAMILY: Geneva,Arial,Sans-serif" size=3>OK, so yesterday I worked something out that I didn't fully realise.<BR>The TrySave / <SPAN><SPAN class=txt4 id=_ctl0_MainContent__ctl0_PostForm_ReplyBody>InPlaceMetadataWriter will only work if there is enough space in the file to save metadata. That is why the method is called TrySave() - it won't always work </SPAN></SPAN><SPAN><SPAN class=txt4 id=_ctl0_MainContent__ctl0_PostForm_ReplyBody>(see here http://msdn2.microsoft.com/en-us/library/aa968941.aspx)</SPAN></SPAN></FONT><SPAN><SPAN class=txt4 id=_ctl0_MainContent__ctl0_PostForm_ReplyBody><SPAN style="COLOR: blue"><FONT face="Geneva, Arial, Sans-serif" color=#000000><FONT style="COLOR: rgb(0,0,0); FONT-FAMILY: Geneva,Arial,Sans-serif" size=3>. It is there to be a faster alternative to doing a full resave of the file - which you have to be prepared to do in order to get enough space for the metadata.<BR><BR>Robert W was actually telling us this in his reply - I just didn't understand it fully until yesterday.<BR><BR>Following from that, it means no matter what, we still have to get the full encoding to work to perform as a last resort on any file that TrySave fails on. The loss of jpeg quality is a concern - but before I get to worrying about that, I still haven't got any code to actually reliably work doing the save :|<BR>My current hurdle is I get HRESULT exceptions when the encoder tries to save.</FONT></FONT></SPAN></SPAN></SPAN></P> <P><SPAN><SPAN class=txt4><SPAN style="COLOR: blue"><FONT face="Geneva, Arial, Sans-serif" color=#000000><FONT style="COLOR: rgb(0,0,0); FONT-FAMILY: Geneva,Arial,Sans-serif" size=3>EDIT: Interestingly the HRESULT error is different in XP and Vista. In XP it is something like 0xC000005. In Vista it is 0x88982F71 and comes with additional message of "Cannot write to the stream." (but if I don't try and edit any meta data it writes to the stream fine)<BR><BR>Below are three different methods. The first two are based on some rough samples that Robert sent me off line. The third is your sample JL.<BR>The code fully compiles as a console app - you just need to add references - see the usage doco below.<BR><BR>If it helps anyone get to the next step and can get the files to encode without these damn HRESULT errors (or the codec does not support this or that) then let us know!<BR></FONT><BR></FONT></SPAN></SPAN></SPAN><SPAN><SPAN class=txt4 id=_ctl0_MainContent__ctl0_PostForm_ReplyBody><SPAN style="COLOR: blue"><FONT face="Geneva, Arial, Sans-serif" color=#000000></FONT></SPAN></SPAN></SPAN><BR><FONT style="COLOR: rgb(0,128,0); FONT-FAMILY: Courier New,Courier,Monospace" size=2><BR>using System;<BR>using System.IO;<BR>using System.Collections.ObjectModel;<BR>using System.Collections.Generic;<BR>using System.Text;<BR>using System.Windows.Media.Imaging;<BR>using System.Globalization;<BR>using System.Diagnostics;<BR><BR>/*<BR>&nbsp;* Usage<BR>&nbsp;* 1) Create a new Console Application solution<BR>&nbsp;* 2) Paste this into the Program.cs file<BR>&nbsp;* 3) Add References to PresentationCore and WindowsBase<BR>&nbsp;* 4) Compile and drop a "test.jpg" file into the Debug output folder<BR>&nbsp;*/<BR>namespace ConsoleApplication1<BR>{<BR>&nbsp;&nbsp;&nbsp; class Program<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (args.Length == 0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; args = new string[1] { @"IMG_8968.JPG" };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (args.Length &gt; 0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MetaWriter metaWriter = new MetaWriter(args[0]);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //metaWriter.ModifyExistingData();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //metaWriter.WriteCleanMetaData();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metaWriter.JLWrite();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("Specify a file as an argument");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<BR>&nbsp;&nbsp;&nbsp; /// Note http://msdn2.microsoft.com/en-us/library/aa968941.aspx<BR>&nbsp;&nbsp;&nbsp; /// indicates that the whole TrySave() with InPlaceWriter isn't guaranteed to always work.<BR>&nbsp;&nbsp;&nbsp; /// It is a fast way of doing the encoding.<BR>&nbsp;&nbsp;&nbsp; /// So we have to fall back to reencoding the whole thing again as a last resort if try save fails...<BR>&nbsp;&nbsp;&nbsp; /// ... so lets get that working first<BR>&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<BR>&nbsp;&nbsp;&nbsp; class MetaWriter<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string _fileIn;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string _fileOut;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public MetaWriter(string filename)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _fileIn = filename;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _fileOut = filename + ".out.jpg";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void ModifyExistingData()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Setup input/decoder<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Stream inputStream = new System.IO.FileStream(_fileIn, FileMode.Open, FileAccess.Read, FileShare.Read);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegBitmapDecoder decoder = new JpegBitmapDecoder(inputStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitmapFrame inputFrame = decoder.Frames[0];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitmapMetadata inputMetadata = inputFrame.Metadata as BitmapMetadata;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Notify("Input Title = {0}", inputMetadata.Title);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Notify("Input DateTime = {0}", inputMetadata.DateTaken);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inputMetadata.Keywords != null)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; inputMetadata.Keywords.Count; i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Notify("Input Keyword = {0}", inputMetadata.Keywords<img src="/MSDN//emoticons/emotion-55.gif" alt="Idea" />);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Setup output/encoder<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Stream outputStream = new System.IO.FileStream(_fileOut, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outputStream.SetLength(0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegBitmapEncoder encoder = new JpegBitmapEncoder();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Set the meta data<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string[] authorArray = { "abc"};<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string[] keywordArray = { "yesterday", "today", "Debug time " + DateTime.Now.ToString("HH:mm:ss") };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String dateTimeString = DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReadOnlyCollection&lt;String&gt; collectionAuthors = (new ReadOnlyCollection&lt;String&gt;(authorArray));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReadOnlyCollection&lt;String&gt; collectionKeywords = (new ReadOnlyCollection&lt;String&gt;(keywordArray));<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // This following works until we try to edit any of the data.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // At which point, we get "HRESULT: 0xC0000005" failure on the encoder.Save() method<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // (We can't try and modify inputMetadata directly since it is frozen)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitmapMetadata outputMetadata = inputMetadata.Clone();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Mucking around trying to get stuff to work by adding padding<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //outputMetadata.SetQuery("/app1/ifd/PaddingSchema:padding", (UInt32)4096);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //outputMetadata.SetQuery("/app13/ifd/PaddingSchema:padding", (UInt32)4096);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //outputMetadata.SetQuery("/xmp/PaddingSchema:padding", (UInt32)4096);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // If we uncomment these lines we get the "HRESULT: 0xC0000005" failure&nbsp; on save<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //outputMetadata.Author = collectionAuthors;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outputMetadata.Keywords = collectionKeywords;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //outputMetadata.DateTaken = dateTimeString;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //outputMetadata.SetQuery("System.Title", "monkey");<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Uncommenting these lines give "This codec does not support the specified property."<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * The paths came from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/DMD_Imag/htm/photo_metadata_policy__mvoo.asp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outputMetadata.SetQuery("/xmp/&lt;xmpbag&gt;dc:subject", collectionKeywords);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //outputMetadata.SetQuery("/app13/arb/8bimiptc/iptc/keywords", collectionKeywords);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //outputMetadata.SetQuery("/app1/ifd/{ushort=18247}", collectionKeywords);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //outputMetadata.SetQuery("/app1/ifd/{ushort=40094}", collectionKeywords);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create output<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitmapFrame outputFrame = BitmapFrame.Create(inputFrame, null, outputMetadata, null);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encoder.Frames.Add(outputFrame);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encoder.Save(outputStream);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outputStream.Flush();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outputStream.Close();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void WriteCleanMetaData()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Stream inputStream = new System.IO.FileStream(_fileIn, FileMode.Open, FileAccess.Read, FileShare.Read);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegBitmapDecoder decoder = new JpegBitmapDecoder(inputStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Stream outputStream = new System.IO.FileStream(_fileOut, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outputStream.SetLength(0);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegBitmapEncoder encoder = new JpegBitmapEncoder();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitmapMetadata metadata = new BitmapMetadata("jpg");<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // this works fine - setting DateTime in EXIF<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metadata.SetQuery("/app1/ifd/exif/{ushort=36867}", DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo));<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // this works fine - creating a by line in IPTC<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metadata.SetQuery("/app13/irb/8bimiptc/iptc/by-line", "Monkey");<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // This gives HRESULT: 0xC0000005 when saving (It should write to XMP??)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //metadata.SetQuery("System.Author", "Monkey");<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Not sure what these are writing <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metadata.SetQuery("/app1/ifd/{uint=1000}", 12345);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metadata.SetQuery("/app1/ifd/{uint=1001}", 23456);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metadata.SetQuery("/app1/ifd/{uint=1002}", 34567);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Make space in the metadata header for our data<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metadata.SetQuery("/app1/ifd/PaddingSchema:padding", (UInt32)4096);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encoder.Frames.Add(BitmapFrame.Create(decoder.Frames[0], null, metadata, null));<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encoder.Save(outputStream);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outputStream.Flush();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outputStream.Close();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// Jean-Luc sample<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void JLWrite()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Stream JpegStreamIn = new FileStream(_fileIn, FileMode.Open, FileAccess.Read, FileShare.Read);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegBitmapDecoder JpegDecoder = new JpegBitmapDecoder(JpegStreamIn,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileStream JpegStreamOut = new FileStream(_fileOut, FileMode.Create);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegBitmapEncoder JpegEncoder = new JpegBitmapEncoder();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitmapFrame JpegFrame = BitmapFrame.Create(JpegDecoder.Frames[0]);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegEncoder.Frames.Add(JpegFrame);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitmapMetadata JpegMeta = (BitmapMetadata)JpegFrame.Metadata;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegMeta.Copyright = "COPYRIGHT";<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string[] MC = new string[JpegMeta.Keywords.Count + 1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegMeta.Keywords.CopyTo(MC, 0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MC[MC.Length - 1] = "NEW-KEYWORD";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegMeta.Keywords = new ReadOnlyCollection&lt;string&gt;(MC);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JpegEncoder.Save(JpegStreamOut);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void Notify(string format, params object[] args)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Notify(String.Format(format, args));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void Notify(string message)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Trace.WriteLine(message);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(message);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>}<BR></FONT><BR></P>Thu, 01 Feb 2007 07:41:39 Z2007-02-01T07:41:39Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#0fb94678-972c-4533-9b9e-df5443aa8912http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#0fb94678-972c-4533-9b9e-df5443aa8912RenRenhttp://social.msdn.microsoft.com/Profile/en-US/?user=RenRenReading and Writing image "Rating" metadata<p>Thank you Code Jockey for your code.</p> <p>Strange but your code don't run correctely if it run in a console app. I get exception &quot;Invalid cast&quot; when I access metadata's properties. No problem with the same code in a Windows form app. (Yesyes, my config is strange too :o)</p> <p>I understand why in-place editing don't work. So I don't have enough space in photo files.</p> <p>Here is my investigation results:<br>Some properties (like Authors and Keywords) can be modified with 3 différent ways.  Keep in mind you get a photo without metadata inside, so you must create them.</p> <p>1) with BitmapMetadata object's properties</p> <p dir=ltr style="margin-right:0px"><font face="Courier New, Courier, Monospace" color="#008000">if (!JpegMeta.ContainsQuery(&quot;/xmp/Authors&quot;))<br>{<br>    string[] authors = new string[2] { &quot;Auth1&quot;, &quot;Auth2&quot; };<br>    JpegMeta.Author = new ReadOnlyCollection&lt;string&gt;(authors);<br>}</font></p> <p>2) with SetQuery</p> <p dir=ltr style="margin-right:0px"><font face="Courier New, Courier, Monospace" color="#008000">if (!JpegMeta.ContainsQuery(&quot;/xmp/Authors&quot;))<br>{<br>    string[] authors = new string[2] { &quot;Auth1&quot;, &quot;Auth2&quot; };<br>    JpegMeta.SetQuery(&quot;System.Author&quot;, authors);<br>}</font></p> <p>3) second way with SetQuery</p> <p dir=ltr style="margin-right:0px"><font color="#008000"><font face="Courier New, Courier, Monospace">if (!JpegMeta.ContainsQuery(&quot;/xmp/Authors&quot;))<br>{<br>    string[] authors = new string[2] { &quot;Auth1&quot;, &quot;Auth2&quot; };<br>    JpegMeta.SetQuery(&quot;/xmp/dc:creator&quot;, new BitmapMetadata(&quot;xmpseq&quot;));    // use &quot;xmpbag&quot; for keywords<br>    JpegMeta.SetQuery(&quot;/xmp/dc:creator/{ulong=0}&quot;, authors[0]);<br>    JpegMeta.SetQuery(&quot;/xmp/dc:creator/{ulong=1}&quot;, authors[1]);</font><br>}</font></p> <p dir=ltr>The third way is the only one if you want to set &quot;/xmp/photoshop:SupplementalCategories&quot;. </p> <p dir=ltr style="margin-right:0px"><font face="Courier New, Courier, Monospace" color="#008000">string[] cat = new string[2] { &quot;C1&quot;, &quot;C2&quot; };<br>JpegMeta.SetQuery(&quot;/xmp/photoshop:SupplementalCategories&quot;, new BitmapMetadata(&quot;xmpbag&quot;));<br>JpegMeta.SetQuery(&quot;/xmp/photoshop:SupplementalCategories/{ulong=0}&quot;, cat[0]);<br>JpegMeta.SetQuery(&quot;/xmp/photoshop:SupplementalCategories/{ulong=1}&quot;, cat[1]);<br><br>JpegMeta.SetQuery(&quot;/app13/{ushort=0}/{ulonglong=61857348781060}/{ushort=1}/{str=Supplemental Category}&quot;, cat);</font></p> <p dir=ltr>Well, I think I have everything to begin, even I can't use in-place editing.</p> <p>Jean-Luc</p>Thu, 01 Feb 2007 15:26:07 Z2007-02-01T15:26:07Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#482d1b27-a7c7-4988-a89d-a7c5c479d885http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#482d1b27-a7c7-4988-a89d-a7c5c479d885Avnerhttp://social.msdn.microsoft.com/Profile/en-US/?user=AvnerReading and Writing image "Rating" metadata<P>&nbsp;See next post :)</P>Fri, 02 Feb 2007 01:04:42 Z2007-02-02T01:04:42Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#de3eb29b-94ff-4ee8-bd72-0eaadee5e5e1http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#de3eb29b-94ff-4ee8-bd72-0eaadee5e5e1Avnerhttp://social.msdn.microsoft.com/Profile/en-US/?user=AvnerReading and Writing image "Rating" metadata<P>It seems that there is a much simpler way to save metadata to jpeg image, by assigning to the properties of the bitmapmetadata object.</P> <P>Here is a code sample for writing the new metadata:</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> strm <SPAN style="COLOR: blue">As</SPAN> FileStream = <SPAN style="COLOR: blue">New</SPAN> FileStream(<SPAN style="COLOR: #a31515">"..\Picture 003.jpg"</SPAN>, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> decoder <SPAN style="COLOR: blue">As</SPAN> JpegBitmapDecoder = <SPAN style="COLOR: blue">New</SPAN> JpegBitmapDecoder(strm, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default)<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> m <SPAN style="COLOR: blue">as</SPAN> BitmapMetadata = <SPAN style="COLOR: blue">CType</SPAN>(decoder.Frames(0).Metadata, BitmapMetadata)<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> output_jpgStream <SPAN style="COLOR: blue">as</SPAN> FileStream= <SPAN style="COLOR: blue">New</SPAN> FileStream(<SPAN style="COLOR: #a31515">"output.jpg"</SPAN>, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> jpgEncoder <SPAN style="COLOR: blue">As</SPAN> JpegBitmapEncoder = <SPAN style="COLOR: blue">New</SPAN> JpegBitmapEncoder()<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> jpgMetadata <SPAN style="COLOR: blue">as</SPAN> BitmapMetadata= <SPAN style="COLOR: blue">New</SPAN> BitmapMetadata(<SPAN style="COLOR: #a31515">"jpg"</SPAN>)<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">jpgMetadata.CameraManufacturer = m.CameraManufacturer<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> l() <SPAN style="COLOR: blue">As</SPAN> <SPAN style="COLOR: blue">String</SPAN> = {<SPAN style="COLOR: #a31515">"foo"</SPAN>, <SPAN style="COLOR: #a31515">"bar"</SPAN>}<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> col <SPAN style="COLOR: blue">As</SPAN> System.Collections.ObjectModel.ReadOnlyCollection(<SPAN style="COLOR: blue">of</SPAN> <SPAN style="COLOR: blue">String</SPAN>) = <SPAN style="COLOR: blue">New</SPAN> System.Collections.ObjectModel.ReadOnlyCollection(<SPAN style="COLOR: blue">Of</SPAN> <SPAN style="COLOR: blue">String</SPAN>)(<SPAN style="COLOR: blue">New</SPAN> List(<SPAN style="COLOR: blue">Of</SPAN> <SPAN style="COLOR: blue">String</SPAN>)(l))<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">jpgMetadata.Keywords = col<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">jpgMetadata.Comment = <SPAN style="COLOR: #a31515">"this is my comment!!!!!"<o:p></o:p></SPAN></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">jpgEncoder.Frames.Add(BitmapFrame.Create(decoder.Frames(0), <SPAN style="COLOR: blue">Nothing</SPAN>, jpgMetadata, <SPAN style="COLOR: blue">Nothing</SPAN>))<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">jpgEncoder.Save(output_jpgStream)<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">output_jpgStream.Flush()<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">output_jpgStream.Close()<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">strm.Close()</SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"></SPAN>&nbsp;</P><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><SPAN style="COLOR: black; FONT-FAMILY: Arial; mso-no-proof: yes"><FONT size=3>Here is the code to read the metadata from the saved file:</FONT></SPAN></P><SPAN style="COLOR: black; FONT-FAMILY: Arial; mso-no-proof: yes"> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"></SPAN>&nbsp;</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> strm <SPAN style="COLOR: blue">As</SPAN> FileStream = <SPAN style="COLOR: blue">New</SPAN> FileStream(<SPAN style="COLOR: #a31515">"..\Picture 0031.jpg"</SPAN>, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> decoder <SPAN style="COLOR: blue">As</SPAN> JpegBitmapDecoder = <SPAN style="COLOR: blue">New</SPAN> JpegBitmapDecoder(strm, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default)<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> frame = decoder.Frames(0)<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> metadata <SPAN style="COLOR: blue">As</SPAN> BitmapMetadata = <SPAN style="COLOR: blue">CType</SPAN>(frame.Metadata, BitmapMetadata)<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Dim</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> str <SPAN style="COLOR: blue">As</SPAN> <SPAN style="COLOR: blue">String</SPAN> = <SPAN style="COLOR: #a31515">""<o:p></o:p></SPAN></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">For</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> <SPAN style="COLOR: blue">Each</SPAN> s <SPAN style="COLOR: blue">In</SPAN> metadata.Keywords<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>str = str &amp; <SPAN style="COLOR: #a31515">" "</SPAN> &amp; s<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">Next<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">MsgBox(<SPAN style="COLOR: #a31515">"The Description metadata of this image is: "</SPAN> + str)</SPAN><SPAN style="FONT-FAMILY: Arial"><o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">&nbsp;</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><FONT size=3>Hope it helps</FONT></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><FONT size=3>Avner</FONT></SPAN></SPAN></P></SPAN> <P> <P>&nbsp;</P></P>Fri, 02 Feb 2007 02:15:00 Z2007-02-02T02:15:00Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#4d2276e0-51d6-4547-b709-2427eff95d00http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#4d2276e0-51d6-4547-b709-2427eff95d00RenRenhttp://social.msdn.microsoft.com/Profile/en-US/?user=RenRenReading and Writing image "Rating" metadata<p>Hello Avner.</p> <p>Yes, assigning to the properties of the BitmapMetadata object is one of the 3 possibilities and it's the simplest way, but if you want manipulate category and supplementalcategories (and many other), you have not corresponding properties in BitmapMetada object. See my previous post for sample.</p> <p>Sharing code and sample allways help. Thank you <img src="images/emoticons/smile_regular.gif"></p> <p>Jean-Luc</p> <p> </p>Fri, 02 Feb 2007 08:27:16 Z2007-02-02T08:27:16Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#81e63b0d-dd15-4281-bda1-b47be5e62afbhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#81e63b0d-dd15-4281-bda1-b47be5e62afbcode jockeyhttp://social.msdn.microsoft.com/Profile/en-US/?user=code%20jockeyReading and Writing image "Rating" metadata<p><font style="color:rgb(0, 0, 0)" size=2><span style="font-family:Geneva,Arial,Sans-serif">Avner - Thanks for your sample - but JL is correct - the properties exposed by the metadata object don't encompass all the metadata fields available that one may want to get and set. I for example want to be able to get and set the GPS coordinates in the EXIF headers. So the SetQuery/GetQuery methods are provided to make the library more flexible.</span></font></p><p style="font-family:Geneva,Arial,Sans-serif;color:rgb(0, 0, 0)"><font style="color:rgb(0, 0, 0)" size=2><span style="font-family:Geneva,Arial,Sans-serif">The other problem is that we should preserve all existing meta data in the image that we don't know about - so ideally we should use a clone of the source bitmapmeta data (as per the </span><span style="font-family:Geneva,Arial,Sans-serif" id="_ctl0_MainContent_PostFlatView"><span><font style="color:rgb(0, 128, 0);font-family:Courier New,Courier,Monospace">ModifyExistingData() <span style="font-family:Geneva,Arial,Sans-serif;color:rgb(0, 0, 0)">method in my prior sample).</span></font></span></span><br><span id="_ctl0_MainContent_PostFlatView"><span><font style="color:rgb(0, 128, 0);font-family:Courier New,Courier,Monospace">Otherwise we will be throwing away all the EXIF data that the camera inserted like focal length, etc if we use a simple BitmapMetadata constructor and don't explicitly copy all the values over.</font></span></span></font></p><p style="font-family:Geneva,Arial,Sans-serif;color:rgb(0, 0, 0)"><font style="color:rgb(0, 0, 0)" size=2><span id="_ctl0_MainContent_PostFlatView"><span></span></span></font></p><p><font style="color:rgb(0, 0, 0)" size=2><span style="font-family:Geneva,Arial,Sans-serif;color:rgb(0, 0, 0)" id="_ctl0_MainContent_PostFlatView"><span><font style="color:rgb(0, 128, 0);font-family:Courier New,Courier,Monospace"><span style="font-family:Geneva,Arial,Sans-serif">JL - How do you know what literals to put in the constructor for BitmapMetaData? The MSDN documentation (http://msdn2.microsoft.com/en-us/library/system.windows.media.imaging.bitmapmetadata.bitmapmetadata.aspx)</span> only explicitly lists </font></span></span><span style="font-family:Geneva,Arial,Sans-serif">&quot;gif&quot;, &quot;jpg&quot;, &quot;png&quot;, or &quot;tiff&quot; - but nothing else - but then the sample (in the MSDN page) then goes and uses &quot;exif&quot;! </span></font></p><p><font style="color:rgb(0, 0, 0)" size=2><span style="font-family:Geneva,Arial,Sans-serif">(I'm not saying you are wrong, I think you are right, just wondering how you know what are the correct values are?).</span></font></p><p><font style="color:rgb(0, 0, 0)" size=2><span style="font-family:Geneva,Arial,Sans-serif">At the end of the day although this is incredibly frustrating I think what we are trying to achieve is possible since the .NET code all wraps the new WIC library, and I suspect that is what Vista photo gallery uses - and I know it is what PhotoInfo uses....sigh.</span></font></p><p><span style="font-family:Geneva,Arial,Sans-serif">PS: JL - I just saw that recompression issue you mentioned before when I ran some test code. thats really bad. I suppose there must be a work around though.</span></p><p><span style="font-family:Geneva,Arial,Sans-serif">PPS: Sorry for the font craziness. The rich text editor doesn't seem to work so well after some cut and pastes.<br></span></p>Fri, 02 Feb 2007 11:46:08 Z2007-02-02T11:46:08Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#f5a8f80b-e749-4198-81b0-7cd50e04d966http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#f5a8f80b-e749-4198-81b0-7cd50e04d966RenRenhttp://social.msdn.microsoft.com/Profile/en-US/?user=RenRenReading and Writing image "Rating" metadata<P>Hello Code Jockey</P> <P>For litterals to put in BitmapMetadata constructor, I get&nbsp;them&nbsp;from <A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/DMD_Imag/htm/photo_metadata_policy__mvoo.asp" target=_blank><U>Photo Metadata Policy</U></A>&nbsp;page. For some system properties, in path column there&nbsp;are lines like "/xmp/&lt;<FONT color=#0000ff><STRONG>xmpbag</STRONG></FONT>&gt;dc:subject" or "/xmp/&lt;<FONT color=#0000ff><STRONG>xmpseq</STRONG></FONT>&gt;dc:creator"</P> <P>Jean-Luc</P>Fri, 02 Feb 2007 12:07:02 Z2007-02-02T12:07:02Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#9e14eca0-06cb-4528-ac6e-afc928ba66d2http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#9e14eca0-06cb-4528-ac6e-afc928ba66d2code jockeyhttp://social.msdn.microsoft.com/Profile/en-US/?user=code%20jockeyReading and Writing image "Rating" metadatadid anyone get anywhere with this?<br>I pretty much gave up - hoping for an MSDN article or something.<br>Mon, 26 Feb 2007 10:59:17 Z2007-02-26T10:59:17Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#2f27d0ca-e892-4388-b7e6-f395bb374f3ahttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#2f27d0ca-e892-4388-b7e6-f395bb374f3acode jockeyhttp://social.msdn.microsoft.com/Profile/en-US/?user=code%20jockeyReading and Writing image "Rating" metadataCan someone from MSFT confirm whether reading/writing metadata is actually possible in the framework? <br>Obviously its possible in WIC since Vista's Photo Gallery achieves it but I think someone has dropped the ball in interfacing it to .NET cause there is not a single working sample available.<br><br>Here is someone else who hasn't found a solution<br>http://bloggingabout.net/blogs/erwyn/archive/2007/03/18/diving-into-c-for-flickr-metadata-synchr-v0-6-0-0.aspx<br><br><br>Sat, 26 May 2007 00:25:50 Z2007-05-26T00:25:50Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#ac7dcd3a-0138-4b92-be36-0a90b3f599f3http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#ac7dcd3a-0138-4b92-be36-0a90b3f599f3DafEOhttp://social.msdn.microsoft.com/Profile/en-US/?user=DafEOReading and Writing image "Rating" metadata<p>Reading certainly seems possible.</p> <p>But writing is only possible if there's enought space in the Metadata area of the file and this is where most people, including myself are becoming unstuck.</p>Fri, 01 Jun 2007 16:27:51 Z2007-06-01T16:27:51Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#6b4d73dd-2aec-4519-af91-7922c29e37b7http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#6b4d73dd-2aec-4519-af91-7922c29e37b7code jockeyhttp://social.msdn.microsoft.com/Profile/en-US/?user=code%20jockeyReading and Writing image "Rating" metadatayes you are correct. I was ranting in my frustration. Reading the XMP works ok - its the writing that is busted.<br>Mon, 04 Jun 2007 09:59:23 Z2007-06-04T09:59:23Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#8732547c-91f0-4292-bd2c-8b5aecfc3802http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#8732547c-91f0-4292-bd2c-8b5aecfc3802SKJ08http://social.msdn.microsoft.com/Profile/en-US/?user=SKJ08Reading and Writing image "Rating" metadataHi I have just found this article, it doesn't contain a solution but kind of a good conclusion <img src="images/emoticons/smile_regular.gif"><br><br><a title="http://www.vsj.co.uk/articles/display.asp?id=649" href="http://www.vsj.co.uk/articles/display.asp?id=649">http://www.vsj.co.uk/articles/display.asp?id=649</a><br>Mon, 18 Jun 2007 21:42:02 Z2007-06-18T21:42:02Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#2277ba44-9a92-4ed9-81ed-d1459afea4c8http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#2277ba44-9a92-4ed9-81ed-d1459afea4c8Robert A. Wlodarczykhttp://social.msdn.microsoft.com/Profile/en-US/?user=Robert%20A.%20WlodarczykReading and Writing image "Rating" metadataPlease see my recent blog post: <a title="http://blogs.msdn.com/rwlodarc/archive/2007/07/18/using-wpf-s-inplacebitmapmetadatawriter.aspx" href="http://blogs.msdn.com/rwlodarc/archive/2007/07/18/using-wpf-s-inplacebitmapmetadatawriter.aspx">http://blogs.msdn.com/rwlodarc/archive/2007/07/18/using-wpf-s-inplacebitmapmetadatawriter.aspx</a>Thu, 19 Jul 2007 04:54:26 Z2007-07-19T04:54:50Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#a563f470-f83b-4a0f-ad0f-50958ac60bfbhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#a563f470-f83b-4a0f-ad0f-50958ac60bfbAnil Dhttp://social.msdn.microsoft.com/Profile/en-US/?user=Anil%20DReading and Writing image "Rating" metadata<p>Folks,</p> <p align=left>With the example above, I am getting Overflow exception?</p> <p align=left> </p> <p align=left>&quot;The image data generated an overflow during processing&quot;</p> <p align=left> </p> <p align=left>If you faced similar issue -could you please let me know - where the things may go wrong.</p> <p align=left> </p> <p align=left>Thanks And Regards,</p> <p align=left>Anil</p> <p align=left> </p> <p align=left><font face=Arial size=2></font> </p>Tue, 13 Nov 2007 12:59:35 Z2007-11-13T12:59:35Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#8ae461fc-d145-44dc-8294-d7449eacd09bhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#8ae461fc-d145-44dc-8294-d7449eacd09bJrw_99http://social.msdn.microsoft.com/Profile/en-US/?user=Jrw_99Reading and Writing image "Rating" metadata Hello ...<br><br>I see that this is an old thread... but I've encountered the exact same problem with the &quot;Cannot write to stream&quot; issue.  <br><br>I too spoke with Robert on getting my project to this point but the fact that there seems to be no reliable way to save the file is frustrating to say the least.<br><br>I saw 2 other postings about this and the solutions the other guys came up with were too 1) put the call to save inside of a method that is called in it's own thread marked with STAThread and 2) to dump trying to make it work directy from c# and directly access the Windows Vista Shell API using C++. (you can read about it here - <a href="http://bloggingabout.net/blogs/erwyn/archive/2007/03/18/diving-into-c-for-flickr-metadata-synchr-v0-6-0-0.aspx">http://bloggingabout.net/blogs/erwyn/archive/2007/03/18/diving-into-c-for-flickr-metadata-synchr-v0-6-0-0.aspx</a>)<br><br>I need this to work from c# without the need to rely on the vista shell and/or c++.  I didn't try rewriting the save portion in a separate thread but will be trying that next unless someone has already got this figured out???<br><br>cheers,<br>JonMon, 11 Aug 2008 22:34:04 Z2008-08-11T22:34:04Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#c3d59068-ee61-4922-bc0e-714354b9722ehttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#c3d59068-ee61-4922-bc0e-714354b9722eJon Millerhttp://social.msdn.microsoft.com/Profile/en-US/?user=Jon%20MillerReading and Writing image "Rating" metadata Is Microsoft ever going to fully implement this stuff in .NET? This stuff should NOT be rocket science. It should be as easy as opening a file, setting a property, saving it, and closing it. Dealing with metadata was supposed to be one of the great new features in Vista. Supposedly Vista's UI was going to be 95%+ in .NET. It looks like Microsoft did not follow through on that. I hope they fix this for NETFX 4.0. I don't know why Microsoft doesn't let COM die the death that it deserves.Sat, 13 Dec 2008 06:04:17 Z2008-12-13T06:04:17Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#684d6d4a-02f6-439d-b819-f73ac507bf82http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#684d6d4a-02f6-439d-b819-f73ac507bf82Felipe Ceottohttp://social.msdn.microsoft.com/Profile/en-US/?user=Felipe%20CeottoReading and Writing image "Rating" metadata Hello. I incurred with the same problems described here.<br><br>First, something I tried was the in-place metadata writer, which works fine. The kind of problem everyone here had, I sorted out by calling the TrySave method before each and every SetQuery, not just before the first time.<br><br>That only sorts out part of it, if the file does not have enough space for the metadata the SetQuery will fail. I found a nice example that sorts that out and guarantees a lossless transcoding, here is it: <a href="http://blogs.msdn.com/rwlodarc/archive/2007/07/18/using-wpf-s-inplacebitmapmetadatawriter.aspx">http://blogs.msdn.com/rwlodarc/archive/2007/07/18/using-wpf-s-inplacebitmapmetadatawriter.aspx</a><br><br>I hope this sorts it all out, it definitely worked for me.<br><br><br>Cheers,<br>Felipe.Thu, 12 Feb 2009 11:27:27 Z2009-02-12T11:27:27Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#5a349240-e9f5-4f90-856e-115e97fbc37ahttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#5a349240-e9f5-4f90-856e-115e97fbc37aStCroixSkipperhttp://social.msdn.microsoft.com/Profile/en-US/?user=StCroixSkipperReading and Writing image "Rating" metadata I agree the documentation is confusing.  Here is what I've discovered and some code that works with jpg files.  I think you should be able to adapt it to other fields and other image file types.  Good Luck<br><br> <div style="border-right:#7f9db9 1px solid;border-top:#7f9db9 1px solid;font-size:11px;overflow:auto;border-left:#7f9db9 1px solid;line-height:100%! important;border-bottom:#7f9db9 1px solid;font-family:Courier New;background-color:white"> <table style="border-top-width:0px;border-left-width:0px;margin:2px 0px;width:99%;border-bottom:#eee 0px solid;border-collapse:collapse;background-color:#fff;border-right-width:0px" cellspacing=0 cellpadding=0> <colgroup> <col style="padding-left:10px;font-size:11px;border-bottom:#f7f7f7 1px solid;font-family:Courier New;white-space:nowrap"> <tbody> <tr> <td><font style="font-size:11px">public ModifyJpgMetadata()  </font></td></tr> <tr> <td style="background-color:#f7f7f7">{  </td></tr> <tr> <td>    //  </td></tr> <tr> <td style="background-color:#f7f7f7">    // get the path to some jpg file  </td></tr> <tr> <td>    //  </td></tr> <tr> <td style="background-color:#f7f7f7">    string </font><font style="color:red">jpegPath</font><font style="font-size:11px"> = </font><font style="color:blue">&quot;C:\\users\\scott\\Pictures\\sample\\xxx.jpg&quot;</font><font style="font-size:11px">;  </font></td></tr> <tr> <td>    string </font><font style="color:red">jpegDirectory</font><font style="font-size:11px"> = </font><font style="color:blue">Path</font><font style="font-size:11px">.GetDirectoryName(jpegPath);  </font></td></tr> <tr> <td style="background-color:#f7f7f7">    string </font><font style="color:red">jpegFileName</font><font style="font-size:11px"> = </font><font style="color:blue">Path</font><font style="font-size:11px">.GetFileNameWithoutExtension(jpegPath);  </font></td></tr> <tr> <td>    string </font><font style="color:red">jpegExtension</font><font style="font-size:11px"> = </font><font style="color:blue">&quot;.jpg&quot;</font><font style="font-size:11px">;  </font></td></tr> <tr> <td style="background-color:#f7f7f7"> </td></tr> <tr> <td>    BitmapDecoder </font><font style="color:red">decoder</font><font style="font-size:11px"> = </font><font style="color:blue">null</font><font style="font-size:11px">;  </font></td></tr> <tr> <td style="background-color:#f7f7f7">    BitmapFrame </font><font style="color:red">bitmapFrame</font><font style="font-size:11px"> = </font><font style="color:blue">null</font><font style="font-size:11px">;  </font></td></tr> <tr> <td>    BitmapMetadata </font><font style="color:red">metadata</font><font style="font-size:11px"> = </font><font style="color:blue">null</font><font style="font-size:11px">;  </font></td></tr> <tr> <td style="background-color:#f7f7f7">    if (File.Exists(jpegPath))  </td></tr> <tr> <td>    {  </td></tr> <tr> <td style="background-color:#f7f7f7">        //  </td></tr> <tr> <td>        // load the jpg file with a JpegBitmapDecoder  </td></tr> <tr> <td style="background-color:#f7f7f7">        //  </td></tr> <tr> <td>        using (Stream </font><font style="color:red">jpegStreamIn</font><font style="font-size:11px"> = </font><font style="color:blue">File</font><font style="font-size:11px">.Open(jpegPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))  </font></td></tr> <tr> <td style="background-color:#f7f7f7">        {  </td></tr> <tr> <td>            </font><font style="color:red">decoder</font><font style="font-size:11px"> = </font><font style="color:blue">new</font><font style="font-size:11px"> JpegBitmapDecoder(jpegStreamIn, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);  </font></td></tr> <tr> <td style="background-color:#f7f7f7">        }  </td></tr> <tr> <td> </td></tr> <tr> <td style="background-color:#f7f7f7">        </font><font style="color:red">bitmapFrame</font><font style="font-size:11px"> = </font><font style="color:blue">decoder</font><font style="font-size:11px">.Frames[0];  </font></td></tr> <tr> <td>        </font><font style="color:red">metadata</font><font style="font-size:11px"> = (BitmapMetadata)bitmapFrame.Metadata;  </font></td></tr> <tr> <td style="background-color:#f7f7f7"> </td></tr> <tr> <td>        if (bitmapFrame != null)  </td></tr> <tr> <td style="background-color:#f7f7f7">        {  </td></tr> <tr> <td>            //  </td></tr> <tr> <td style="background-color:#f7f7f7">            // now get an InPlaceBitmapMetadataWriter, modify the metadata and try to save  </td></tr> <tr> <td>            //  </td></tr> <tr> <td style="background-color:#f7f7f7">            InPlaceBitmapMetadataWriter </font><font style="color:red">writer</font><font style="font-size:11px"> = </font><font style="color:blue">bitmapFrame</font><font style="font-size:11px">.CreateInPlaceBitmapMetadataWriter();  </font></td></tr> <tr> <td>            writer.SetQuery(&quot;/app1/ifd/exif:{</font><font style="color:red">uint</font><font style="font-size:11px">=</font><font style="color:blue">306</font><font style="font-size:11px">}&quot;, &quot;2001:01:01 01:01:01&quot;);  </font></td></tr> <tr> <td style="background-color:#f7f7f7">            if (!writer.TrySave() == true)  </td></tr> <tr> <td>            {  </td></tr> <tr> <td style="background-color:#f7f7f7">                //  </td></tr> <tr> <td>                // the size of the metadata has been increased and we can't save it  </td></tr> <tr> <td style="background-color:#f7f7f7">                //   </td></tr> <tr> <td>                uint </font><font style="color:red">padding</font><font style="font-size:11px"> = </font><font style="color:blue">2048</font><font style="font-size:11px">;  </font></td></tr> <tr> <td style="background-color:#f7f7f7"> </td></tr> <tr> <td>                BitmapMetadata </font><font style="color:red">metaData</font><font style="font-size:11px"> = (BitmapMetadata)bitmapFrame.Metadata.Clone();  </font></td></tr> <tr> <td style="background-color:#f7f7f7">                if (metaData != null)  </td></tr> <tr> <td>                {  </td></tr> <tr> <td style="background-color:#f7f7f7">                    //  </td></tr> <tr> <td>                    // Add padding  </td></tr> <tr> <td style="background-color:#f7f7f7">                    //  </td></tr> <tr> <td>                    metaData.SetQuery(&quot;/app1/ifd/PaddingSchema:Padding&quot;, padding);  </td></tr> <tr> <td style="background-color:#f7f7f7">                    //  </td></tr> <tr> <td>                    // modify the metadata  </td></tr> <tr> <td style="background-color:#f7f7f7">                    metaData.SetQuery(&quot;/app1/ifd/exif:{</font><font style="color:red">uint</font><font style="font-size:11px">=</font><font style="color:blue">36867</font><font style="font-size:11px">}&quot;, &quot;2003:03:03 03:04:03&quot;);  </font></td></tr> <tr> <td>                    metaData.SetQuery(&quot;/app1/ifd/exif:{</font><font style="color:red">uint</font><font style="font-size:11px">=</font><font style="color:blue">306</font><font style="font-size:11px">}&quot;, &quot;2001:01:01 01:01:01&quot;);  </font></td></tr> <tr> <td style="background-color:#f7f7f7">                    metaData.SetQuery(&quot;/app1/ifd/exif:{</font><font style="color:red">uint</font><font style="font-size:11px">=</font><font style="color:blue">36868</font><font style="font-size:11px">}&quot;, &quot;2002:02:02 02:02:02&quot;);  </font></td></tr> <tr> <td>                    //  </td></tr> <tr> <td style="background-color:#f7f7f7">                    // get an encoder to create a new jpg file with the addit'l metadata.  </td></tr> <tr> <td>                    //  </td></tr> <tr> <td style="background-color:#f7f7f7">                    JpegBitmapEncoder </font><font style="color:red">encoder</font><font style="font-size:11px"> = </font><font style="color:blue">new</font><font style="font-size:11px"> JpegBitmapEncoder();  </font></td></tr> <tr> <td>                    encoder.Frames.Add(BitmapFrame.Create(bitmapFrame, bitmapFrame.Thumbnail, metaData, bitmapFrame.ColorContexts));  </td></tr> <tr> <td style="background-color:#f7f7f7">                    string </font><font style="color:red">jpegNewFileName</font><font style="font-size:11px"> = </font><font style="color:blue">Path</font><font style="font-size:11px">.Combine(jpegDirectory, &quot;JpegTemp.jpg&quot;);  </font></td></tr> <tr> <td>                    using (Stream </font><font style="color:red">jpegStreamOut</font><font style="font-size:11px"> = </font><font style="color:blue">File</font><font style="font-size:11px">.Open(jpegNewFileName, FileMode.CreateNew, FileAccess.ReadWrite))  </font></td></tr> <tr> <td style="background-color:#f7f7f7">                    {  </td></tr> <tr> <td>                        encoder.Save(jpegStreamOut);  </td></tr> <tr> <td style="background-color:#f7f7f7">                    }  </td></tr> <tr> <td>                    //  </td></tr> <tr> <td style="background-color:#f7f7f7">                    // see if the metadata was really changed  </td></tr> <tr> <td>                    //  </td></tr> <tr> <td style="background-color:#f7f7f7">                    using (Stream </font><font style="color:red">jpegStreamIn</font><font style="font-size:11px"> = </font><font style="color:blue">File</font><font style="font-size:11px">.Open(jpegNewFileName, FileMode.Open, FileAccess.ReadWrite))  </font></td></tr> <tr> <td>                    {  </td></tr> <tr> <td style="background-color:#f7f7f7">                        </font><font style="color:red">decoder</font><font style="font-size:11px"> = </font><font style="color:blue">new</font><font style="font-size:11px"> JpegBitmapDecoder(jpegStreamIn, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);  </font></td></tr> <tr> <td>                        BitmapFrame </font><font style="color:red">frame</font><font style="font-size:11px"> = </font><font style="color:blue">decoder</font><font style="font-size:11px">.Frames[0];  </font></td></tr> <tr> <td style="background-color:#f7f7f7">                        BitmapMetadata </font><font style="color:red">bmd</font><font style="font-size:11px"> = (BitmapMetadata)frame.Metadata;  </font></td></tr> <tr> <td>                        string </font><font style="color:red">a1</font><font style="font-size:11px"> = (string)bmd.GetQuery(&quot;/app1/ifd/exif:{</font><font style="color:red">uint</font><font style="font-size:11px">=</font><font style="color:blue">36867</font><font style="font-size:11px">}&quot;);  </font></td></tr> <tr> <td style="background-color:#f7f7f7">                        string </font><font style="color:red">a2</font><font style="font-size:11px"> = (string)bmd.GetQuery(&quot;/app1/ifd/exif:{</font><font style="color:red">uint</font><font style="font-size:11px">=</font><font style="color:blue">306</font><font style="font-size:11px">}&quot;);  </font></td></tr> <tr> <td>                        string </font><font style="color:red">a3</font><font style="font-size:11px"> = (string)bmd.GetQuery(&quot;/app1/ifd/exif:{</font><font style="color:red">uint</font><font style="font-size:11px">=</font><font style="color:blue">36868</font><font style="font-size:11px">}&quot;);  </font></td></tr> <tr> <td style="background-color:#f7f7f7">                    }  </td></tr> <tr> <td>                }  </td></tr> <tr> <td style="background-color:#f7f7f7">            }  </td></tr> <tr> <td>        }  </td></tr> <tr> <td style="background-color:#f7f7f7">    }  </td></tr> <tr> <td>}  </td></tr> <tr> <td style="background-color:#f7f7f7"> <br><font style="font-size:12px" face=Verdana>You can step through this code and look at a1, a2 and a3 to verify they have been changed.<br><br>Just a note:<br>The documentation shows code like this:<br> <div style="border-right:#7f9db9 1px solid;border-top:#7f9db9 1px solid;font-size:11px;overflow:auto;border-left:#7f9db9 1px solid;line-height:100%! important;border-bottom:#7f9db9 1px solid;font-family:Courier New;background-color:white"> <table style="border-top-width:0px;border-left-width:0px;margin:2px 0px;width:99%;border-bottom:#eee 0px solid;border-collapse:collapse;background-color:#fff;border-right-width:0px" cellspacing=0 cellpadding=0> <colgroup> <col style="padding-left:10px;font-size:11px;border-bottom:#f7f7f7 1px solid;font-family:Courier New;white-space:nowrap"> <tbody> <tr> <td><font style="font-size:11px">Stream </font><font style="color:red">pngStream</font><font style="font-size:11px"> = </font><font style="color:blue">new</font><font style="font-size:11px"> System.IO.FileStream(&quot;smiley.png&quot;, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);  </font></td></tr> <tr> <td style="background-color:#f7f7f7">PngBitmapDecoder </font><font style="color:red">pngDecoder</font><font style="font-size:11px"> = </font><font style="color:blue">new</font><font style="font-size:11px"> PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);  </font></td></tr> <tr> <td>BitmapFrame </font><font style="color:red">pngFrame</font><font style="font-size:11px"> = </font><font style="color:blue">pngDecoder</font><font style="font-size:11px">.Frames[0];  </font></td></tr> <tr> <td style="background-color:#f7f7f7">InPlaceBitmapMetadataWriter </font><font style="color:red">pngInplace</font><font style="font-size:11px"> = </font><font style="color:blue">pngFrame</font><font style="font-size:11px">.CreateInPlaceBitmapMetadataWriter();  </font></td></tr> <tr> <td>if (pngInplace.TrySave() == true)  </td></tr> <tr> <td style="background-color:#f7f7f7">{ pngInplace.SetQuery(&quot;/Text/Description&quot;, &quot;Have a nice day.&quot;); }  </td></tr> <tr> <td>pngStream.Close(); </td></tr></tbody></table></div>Which can't work because pngInplace.TrySave() always returns true.  This makes sense because you haven't changed the metadata size.<br>The code should really look more like: <div style="border-right:#7f9db9 1px solid;border-top:#7f9db9 1px solid;font-size:11px;overflow:auto;border-left:#7f9db9 1px solid;line-height:100%! important;border-bottom:#7f9db9 1px solid;font-family:Courier New;background-color:white"> <table style="border-top-width:0px;border-left-width:0px;margin:2px 0px;width:99%;border-bottom:#eee 0px solid;border-collapse:collapse;background-color:#fff;border-right-width:0px" cellspacing=0 cellpadding=0> <colgroup> <col style="padding-left:10px;font-size:11px;border-bottom:#f7f7f7 1px solid;font-family:Courier New;white-space:nowrap"> <tbody> <tr> <td><font style="font-size:11px">Stream </font><font style="color:red">pngStream</font><font style="font-size:11px"> = </font><font style="color:blue">new</font><font style="font-size:11px"> System.IO.FileStream(&quot;smiley.png&quot;, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);  </font></td></tr> <tr> <td style="background-color:#f7f7f7">PngBitmapDecoder </font><font style="color:red">pngDecoder</font><font style="font-size:11px"> = </font><font style="color:blue">new</font><font style="font-size:11px"> PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);  </font></td></tr> <tr> <td>BitmapFrame </font><font style="color:red">pngFrame</font><font style="font-size:11px"> = </font><font style="color:blue">pngDecoder</font><font style="font-size:11px">.Frames[0];  </font></td></tr> <tr> <td style="background-color:#f7f7f7">InPlaceBitmapMetadataWriter </font><font style="color:red">pngInplace</font><font style="font-size:11px"> = </font><font style="color:blue">pngFrame</font><font style="font-size:11px">.CreateInPlaceBitmapMetadataWriter();  </font></td></tr> <tr> <td> </td></tr> <tr> <td style="background-color:#f7f7f7">pngInplace.SetQuery(&quot;/Text/Description&quot;, &quot;Have a nice day.&quot;);  </td></tr> <tr> <td>   </td></tr> <tr> <td style="background-color:#f7f7f7">if (pngInplace.TrySave() == true)  </td></tr> <tr> <td>{   </td></tr> <tr> <td style="background-color:#f7f7f7">   //  </td></tr> <tr> <td>   // add padding, change the metadata and save to a new file  </td></tr> <tr> <td style="background-color:#f7f7f7">   //  </td></tr> <tr> <td>}  </td></tr> <tr> <td style="background-color:#f7f7f7">pngStream.Close(); </td></tr></tbody></table></div></font></td></tr></tbody></table></div>Mon, 02 Mar 2009 00:16:08 Z2009-03-02T00:16:08Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#5b8c19ab-380d-4e7c-9d31-c048d0f57bd4http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#5b8c19ab-380d-4e7c-9d31-c048d0f57bd4jsmorelandhttp://social.msdn.microsoft.com/Profile/en-US/?user=jsmorelandReading and Writing image "Rating" metadataMuch of this thread, although not all of it, involves accessing a jpg's metadata in a way that you can modify it.  The simplest way to do this is to use: <span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><span style="font-size:x-small"><span style="font-size:x-small"><span style="font-size:x-small"> <p>BitmapFrame bitmapFrame = DecodeImage(imagePath);</p> </span></span></span> <p><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small">BitmapMetadata</span></span><span style="font-size:x-small"> metadata = (</span><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small">BitmapMetadata</span></span><span style="font-size:x-small">)bitmapFrame.Metadata.Clone();<span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"> <span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><span style="font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><font size=2 color="#2b91af"><font size=2 color="#2b91af"><font size=2> <p> <p> </p> </p> </font></font></font></span></span></span></span></span></span></span></span></span></span></span><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><span style="font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><font size=2 color="#2b91af"><font size=2 color="#2b91af"> <p> <p> </p> </p> </font></font></span></span></span></span></span></span></span></span></span></span></span><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><span style="font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small"><span style="font-size:x-small"><font size=2 color="#2b91af"> <p> <p> </p> </p> </font></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <p> <p> </p> </p> </span></span></span><span style="font-size:x-small">This gives you a BitmapMetadata object that is a copy of the original but is not frozen and can be modified.<br/><br/>Note: DecodeImage() is simply a function that determines what kind of image file it is and gets the appropriate decoder and decodes the image file into a BitmapFrame object.</span>Fri, 04 Sep 2009 17:35:14 Z2009-09-04T17:38:25Zhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#dec88a31-76ce-4a62-8f17-590c8cf2328bhttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f297b11-99ba-459c-b085-1ff3ae526487#dec88a31-76ce-4a62-8f17-590c8cf2328bjsmorelandhttp://social.msdn.microsoft.com/Profile/en-US/?user=jsmorelandReading and Writing image "Rating" metadata<span style="font-size:x-small"><span style="font-size:x-small"> <p> </p> </span></span> <p><span style="color:#0000ff;font-size:x-small"><span style="color:#0000ff;font-size:x-small">I got the <span style="color:#000000;font-size:small">0x88982F71 and &quot;Cannot write to the stream&quot; <span style="color:#0000ff;font-size:x-small">when I tried to call the jpeg bitmap encoder's Save() function from a BackgroundWorker thread.<br/><br/></span></span>void</span></span><span style="font-size:x-small"> UpdateImageTagsThread_DoWork(<span style="color:#0000ff"><span style="color:#0000ff">object</span></span> sender, <span style="color:#2b91af"><span style="color:#2b91af">DoWorkEventArgs</span></span> e)</span></p> <p><span style="font-size:x-small">{</span></p> <p><span style="font-size:x-small"><span style="color:#2b91af"><span style="color:#2b91af">    UpdateTagsEntry</span></span> entry = <span style="color:#0000ff"><span style="color:#0000ff">null</span></span>;</span></p> <p><span style="font-size:x-small"><span style="color:#0000ff"><span style="color:#0000ff">    while</span></span> (<span style="color:#0000ff"><span style="color:#0000ff">true</span></span> &amp;&amp; _cancel == <span style="color:#0000ff"><span style="color:#0000ff">false</span></span>)</span></p> <p><span style="font-size:x-small">    {</span></p> <p><span style="font-size:x-small"><span style="color:#0000ff"><span style="color:#0000ff">    while</span></span> (_updateTagsQueue.Count &gt; 0)</span></p> <p><span style="font-size:x-small">    {</span></p> <p><span style="font-size:x-small"><span style="color:#0000ff"><span style="color:#0000ff">        lock</span></span> (_updateTagsQueue)</span></p> <p><span style="font-size:x-small">        {</span></p> <p><span style="font-size:x-small">            entry = _updateTagsQueue.Dequeue();</span></p> <p><span style="font-size:x-small">        }</span></p> <p><span style="color:#0000ff"><span style="color:#0000ff"><span style="font-size:x-small">        try</span></span></span></p> <p><span style="font-size:x-small">        {</span></p> <p><span style="font-size:x-small"><span style="color:#0000ff"><span style="color:#0000ff">            </span></span></span><span style="color:#008000"><span style="color:#008000"><span style="font-size:x-small">SaveTagsToImageEntry(entry);</span></span></span></p> <p><span style="font-size:x-small">        }</span></p> <p><span style="font-size:x-small"><span style="color:#0000ff"><span style="color:#0000ff">        catch</span></span> (<span style="color:#2b91af"><span style="color:#2b91af">Exception</span></span> excptn)</span></p> <p><span style="font-size:x-small">        {</span></p> <p><span style="font-size:x-small"><span style="color:#2b91af"><span style="color:#2b91af">            Console</span></span>.WriteLine(<span style="color:#a31515"><span style="color:#a31515">&quot;Exception in SaveTagsToImageEntry() - {0}&quot;</span></span>, excptn.Message);</span></p> <p><span style="font-size:x-small">        }</span></p> <p><span style="font-size:x-small">    }</span></p> <p><span style="font-size:x-small"><span style="color:#2b91af"><span style="color:#2b91af">    Thread</span></span>.Sleep(100);</span></p> <p><span style="font-size:x-small">    }</span></p> <p><span style="font-size:x-small">}<br/><br/><span style="color:#0000ff">When I changed the call to </span><span style="color:#008000">SaveTagsToImageEntry(entry);</span><span style="color:#0000ff"> to:<br/> this<span style="color:#0000ff;font-size:x-small"><span style="color:#0000ff;font-size:x-small"><span style="color:#0000ff;font-size:x-small"><span style="color:#0000ff;font-size:x-small"><span style="color:#0000ff;font-size:x-small"><span style="color:#0000ff;font-size:x-small"><span style="color:#0000ff;font-size:x-small"></span></span></span><span style="color:#000000;font-size:x-small">.Dispatcher.Invoke(</span><span style="color:#0000ff;font-size:x-small"><span style="color:#0000ff;font-size:x-small">new</span></span><span style="color:#000000;font-size:x-small"> </span><span style="color:#2b91af;font-size:x-small"><span style="color:#2b91af;font-size:x-small">this.Dispatcher(UpdateImageTagsCallback</span></span><span style="font-size:x-small"><span style="color:#000000">(SaveTagsToImageEntry), entry);<br/><br/></span><span style="color:#0000ff">The error went away.<br/><br/>But it means I'm doing the encoding in the UI thread not in a background thread which was my intent.  I would dearly love to put this processing in a background thread.  Any ideas?</span></span></span></span></span></span></span></span></p>Fri, 04 Sep 2009 18:04:10 Z2009-09-04T18:08:16Z