Click to Rate and Give Feedback
MSDN
MSDN Library
.NET Development
.NET Framework 3.5
 SetQuery Method
Collapse All/Expand All Collapse All
This page is specific to
Microsoft Visual Studio 2008/.NET Framework 3.5

Other versions are also available for the following:
.NET Framework Class Library
BitmapMetadata..::.SetQuery Method

Provides access to a metadata query writer that can write metadata to a bitmap image file.

Namespace:  System.Windows.Media.Imaging
Assembly:  PresentationCore (in PresentationCore.dll)
Visual Basic (Declaration)
Public Sub SetQuery ( _
    query As String, _
    value As Object _
)
Visual Basic (Usage)
Dim instance As BitmapMetadata
Dim query As String
Dim value As Object

instance.SetQuery(query, value)
C#
public void SetQuery(
    string query,
    Object value
)
Visual C++
public:
void SetQuery(
    String^ query, 
    Object^ value
)
JScript
public function SetQuery(
    query : String, 
    value : Object
)
XAML
You cannot use methods in XAML.

Parameters

query
Type: System..::.String
Identifies the location of the metadata to be written.
value
Type: System..::.Object
The value of the metadata to be written.

Metadata that is associated with an image is data that describes the image but that is not necessary for display of the image. Each supported bitmap image format handles metadata differently, but the facility for reading and writing metadata is the same.

Windows Presentation Foundation (WPF) supports the following image metadata schemas: Exchangeable image file (Exif), tEXt (PNG Textual Data), image file directory (IFD), International Press Telecommunications Council (IPTC), and Extensible Metadata Platform (XMP).

The following code example demonstrates how to use the SetQuery method to write metadata to a Portable Network Graphics (PNG) file.

Visual Basic
Dim pngStream As New System.IO.FileStream("smiley.png", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)
Dim pngDecoder As New PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default)
Dim pngFrame As BitmapFrame = pngDecoder.Frames(0)
Dim pngInplace As InPlaceBitmapMetadataWriter = pngFrame.CreateInPlaceBitmapMetadataWriter()
If pngInplace.TrySave() = True Then
    pngInplace.SetQuery("/Text/Description", "Have a nice day.")
End If
pngStream.Close()
C#
Stream pngStream = new System.IO.FileStream("smiley.png", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
PngBitmapDecoder pngDecoder = new PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapFrame pngFrame = pngDecoder.Frames[0];
InPlaceBitmapMetadataWriter pngInplace = pngFrame.CreateInPlaceBitmapMetadataWriter();
if (pngInplace.TrySave() == true)
{ pngInplace.SetQuery("/Text/Description", "Have a nice day."); }
pngStream.Close();
Visual C++
Stream^ pngStream = gcnew FileStream("smiley.png", FileMode::Open, FileAccess::ReadWrite, FileShare::ReadWrite);
PngBitmapDecoder^ pngDecoder = gcnew PngBitmapDecoder(pngStream, BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::Default);
BitmapFrame^ pngFrame = pngDecoder->Frames[0];
InPlaceBitmapMetadataWriter^ pngInplace = pngFrame->CreateInPlaceBitmapMetadataWriter();
if (pngInplace->TrySave() == true)
{
   pngInplace->SetQuery("/Text/Description", "Have a nice day.");
}
pngStream->Close();

After the metadata is written, the GetQuery method is used to read that data and emit it as a text string.

Visual Basic
' Add the metadata of the bitmap image to the text block.
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "The Description metadata of this image is: " + pngInplace.GetQuery("/Text/Description").ToString()
C#
// Add the metadata of the bitmap image to the text block.
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "The Description metadata of this image is: " + pngInplace.GetQuery("/Text/Description").ToString();
Visual C++
// Add the metadata of the bitmap image to the text block.
TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "The Description metadata of this image is: " + pngInplace->GetQuery("/Text/Description")->ToString();

Windows 7, Windows Vista, Windows XP SP2, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

.NET Framework

Supported in: 3.5, 3.0
Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Better Examples      Kyle A Reed   |   Edit   |   Show History

One note about the above example, the InPlaceMetadataWriter WILL NOT WORK unless there's enough padding in the header of your image. If you are creating a new Metadata block, it will not work either. You may try the example above but TrySave will likely return false on any image other than a PNG. In that situation, you need to create a new BitmapFrame so that the Metadata block is not frozen. See the following examples.

The above example is fairly anemic here are some more fleshed out examples. Also, see this page for better resources on data tags: http://msdn.microsoft.com/en-us/library/bb643802.aspx

The following example shows the way to "Un-Freeze" the metadata block. This will cause the image to be re-encoded but that's the price that must be paid to add metadata if there isn't enough room in the header. Follow this pattern for other image types.

// Get the source image stream
using (FileStream imageFileStream =
    new FileStream("test.jpg", FileMode.Open))
{
    // Load the image in the decoder
    JpegBitmapDecoder decoder = new JpegBitmapDecoder(imageFileStream,
        BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
    
    // Make a copy of the frame, this will also unlock the metadata
    BitmapFrame frameCopy = BitmapFrame.Create(decoder.Frames[0]);
 
    // Now we have a metadata object that is unfrozen
    BitmapMetadata copyMetadata = (BitmapMetadata)frameCopy.Metadata;
 
    // Set your metadata here, metadata in the source frame
    // will be rewritten to the output frame and any changes
    // will overwrite the metadata in the source frame.
    copyMetadata.Title = "Test Title";
 
    // Create a new encoder and add the copied frame to it
    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
    encoder.Frames.Add(frameCopy);
 
    // Save the new file with the new metadata
    using (FileStream imageFileOutStream =
        new FileStream("testOutput.jpg", FileMode.Create))
    {
        encoder.Save(imageFileOutStream);
    }
}
 
// If you want to add a brand new metadata block, you must create
// the metadata block first and then pass the metadata to the
// BitmapFrame.Create method so it's written to the frame
 
// Get the source image stream
using (FileStream imageFileStream =
    new FileStream("test.jpg", FileMode.Open))
{
    // Create new metadata first, here we are making an IPTC block in a JPG
    // NOTE: IPTC tags do not get parsed correctly on Windows 7
    BitmapMetadata jpgData = new BitmapMetadata("jpg");
    jpgData.SetQuery("/app13/irb/8bimiptc/iptc/object name", "Test Title");
    jpgData.SetQuery("/app13/irb/8bimiptc/iptc/keywords", "Test Tag");
    jpgData.SetQuery("/app13/irb/8bimiptc/iptc/date created", "20090512");
    jpgData.SetQuery("/app13/irb/8bimiptc/iptc/time created", "115300-0800");
    jpgData.SetQuery("/app13/irb/8bimiptc/iptc/caption", "Test Comment");
    jpgData.SetQuery("/app13/irb/8bimiptc/iptc/by-line", "Test Author");
    jpgData.SetQuery("/app13/irb/8bimiptc/iptc/copyright notice", "Copyright 2009");
 
    // Load the image in the decoder
    JpegBitmapDecoder decoder = new JpegBitmapDecoder(imageFileStream,
        BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
 
    // Make a copy of the frame and also pass in the new metadata
    BitmapFrame frameCopy = BitmapFrame.Create(decoder.Frames[0],
        null /* thumbnail */,
        jpgData /* new metadata */,
        decoder.ColorContexts);
 
    // Now we have the image frame that has a fresh IPTC metadata block
 
    // Create a new encoder and add the frame to it
    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
    encoder.Frames.Add(frameCopy);
 
    // Save the new file with the new metadata
    using (FileStream imageFileOutStream =
        new FileStream("testOutput2.jpg", FileMode.Create))
    {
        encoder.Save(imageFileOutStream);
    }
}
 
// Example of TIFF with EXIF
BitmapMetadata tiffData = new BitmapMetadata("tiff");
tiffData.SetQuery("/ifd/{ushort=40091}",
    UnicodeEncoding.Unicode.GetBytes("Test Title".ToCharArray()));
tiffData.SetQuery("/ifd/{ushort=40094}",
    UnicodeEncoding.Unicode.GetBytes("Test Tag".ToCharArray()));
tiffData.SetQuery("/ifd/exif/{uint=36867}", "2009:05:12 11:53:00");
tiffData.SetQuery("/ifd/{ushort=40092}",
    UnicodeEncoding.Unicode.GetBytes("Test Comment".ToCharArray()));
tiffData.SetQuery("/ifd/{ushort=40093}",
    UnicodeEncoding.Unicode.GetBytes("Test Author".ToCharArray()));
tiffData.SetQuery("/ifd/{ushort=33432}", "Copyright 2009");

// Example of WDP (Windows Media Photo) with XMP // NOTE: This does not work (throws COM Exception) on x64 wdpMetadata = new BitmapMetadata("wmphoto"); // With XMP, you need to create the XMP nodes before you use them // The BitmapMetadata constructor will accept metadata block types as // well as image types as shown below wdpMetadata.SetQuery("/ifd/xmp", new BitmapMetadata("xmp")); wdpMetadata.SetQuery("/ifd/xmp/dc:title", new BitmapMetadata("xmpalt")); wdpMetadata.SetQuery("/ifd/xmp/exif:UserComment", new BitmapMetadata("xmpalt")); wdpMetadata.SetQuery("/ifd/xmp/dc:rights", new BitmapMetadata("xmpalt")); wdpMetadata.SetQuery("/ifd/xmp/dc:creator", new BitmapMetadata("xmpseq")); wdpMetadata.SetQuery("/ifd/xmp/dc:subject", new BitmapMetadata("xmpbag")); // XMP Alt has a default value x-default where you can set the value wdpMetadata.SetQuery("/ifd/xmp/dc:title/x-default", "Test Title"); wdpMetadata.SetQuery("/ifd/xmp/exif:UserComment/x-default", "Test Comment"); wdpMetadata.SetQuery("/ifd/xmp/dc:rights/x-default", "Copyright 2009"); // XMP Seq/XMP Bag are indexed. You can set multiple values using {ulong=<offset>} wdpMetadata.SetQuery("/ifd/xmp/dc:creator/{ulong=0}", "Test Author 1"); wdpMetadata.SetQuery("/ifd/xmp/dc:creator/{ulong=1}", "Test Author 2"); wdpMetadata.SetQuery("/ifd/xmp/dc:subject/{ulong=0}", "Test Tag"); // This value is at the root of the XMP block using the XMP date format wdpMetadata.SetQuery("/ifd/xmp/xmp:CreateDate", "2009-05-12T12:05:05");
Windows 7 and 64 Bit problems      Kyle A Reed ... Thomas Lee   |   Edit   |   Show History

IPTC tags are not correctly parsed in Windows 7. For example the comments tag gets assigned to the title tag when viewing the properties in Windows Explorer.

Also, either XMP, WMPhoto or a combination of the two causes COM Expections on 64 bit machines.

Processing
© 2009 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement | Site Feedback
Page view tracker