Saturday 17 March 2012

Surface project - part 7 (Media metadata)

After showing pushpin in the latest demo, supervisors now want assign different metadata to image files so that when user put a pin on the map, the appearance of the pin would be changed based on the image metadata.

A lot of resource can be found online, but I some kind of lost the address of the best post I have seen so far.

The bitmap class provided by WPF has include the ability to edit image metadata. But some issue exists when in place update is not achievable. Thus, as a solution, if in place update not successful, then we need to overwrite the whole image file.

 using (FileStream originalFile = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                BitmapDecoder theDecoder = BitmapDecoder.Create(originalFile, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
                InPlaceBitmapMetadataWriter metadata = theDecoder.Frames[0].CreateInPlaceBitmapMetadataWriter();

metadata.Keywords = new ReadOnlyCollection<string>(tags);

if (!metadata.TrySave())
                {
                    OverwriteImageMedia(filePath, tags);
                }
            }

 private static void OverwriteImageMedia(string filePath, Collection<string> tags)
       {
           using (FileStream originalFile = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
           {
               BitmapDecoder original = BitmapDecoder.Create(originalFile, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
               BitmapEncoder encoder;
               string extension = Path.GetExtension(filePath);
               if (extension == ".jpeg" || extension == ".jpg")
                   encoder = new JpegBitmapEncoder();
               else if (extension == ".png")
                   encoder = new PngBitmapEncoder();
               else
                   return;
               if (original.Frames[0] != null && original.Frames[0].Metadata != null)
               {
                   uint paddingAmount = 2048;
                   BitmapMetadata metadata = original.Frames[0].Metadata.Clone() as BitmapMetadata;
                   metadata.SetQuery("/app1/ifd/PaddingSchema:Padding", paddingAmount);
                   metadata.SetQuery("/app1/ifd/exif/PaddingSchema:Padding", paddingAmount);
                   metadata.SetQuery("/xmp/PaddingSchema:Padding", paddingAmount);
                   metadata.Keywords = new ReadOnlyCollection<string>(tags);
                   encoder.Frames.Add(BitmapFrame.Create(original.Frames[0], original.Frames[0].Thumbnail, metadata, original.Frames[0].ColorContexts));
               }
               originalFile.Close();
               using (Stream outputFile = File.Open ( filePath, FileMode.Create, FileAccess.ReadWrite,FileShare.ReadWrite))
               {
                   encoder.Save(outputFile);
               }
           }
       }

No comments:

Post a Comment