Page 1 of 4
Having looked at working with raw pixel data we turn our attention to formattted image files and how to code and decode both the pixel data and the meta data they contain.
WPF can read in bitmaps from a range of sources and in a range of formats and usually automatically decode them to raw pixel data that can then be further processed or rendered. Occasionally, however, you need to take control of the formatting of a bitmap and this is where the encoder/decoder classes and BitmapFrame enter the picture. Using standard formats like JPEG or TIFF also brings with it the opportunity to work with photos and image files that store additional information such as camera name, author, keywords and so on. Dealing with this metadata is an art all of its own and to make it easier we take a close look at the BitmapMetadata object.
BitmapFrame inherits directly from BitmapSource and as such represents a BitmapSource with a few additional capabilities. The BitmapFrame is also closely associated with the WPF decoder/encoder classes. Even the online documentation states:
"Represents image data returned by a decoder and accepted by encoders".
For this reason it is tempting to see it as something special and different from the other classes descended from BitmapSource but it really is just another bitmap class with a few extras that are generally needed by encoders and decoders.
Specifically a BitmapFrame works in the same way as a BitmapSource but it also has a Thumbnail property and better support for the Metadata property. Both of these are needed if you are going to completely decode or encode image formats that store thumbnails and metadata. There is also the slight complication that some image formats support multiple bitmaps and hence their corresponding encoders/decoders work with arrays of BitmapFrames. However all of this shouldn't distract you from the simple fact that this is just another BitmapSource that can be used in more or less the same way and in addition can be used with encoders/decoders.
The BitmapFrame has a constructor but instances are created using the Create static method as for the BitmapSource. For example, to use a BitmapFrame we first create a suitable Bitmap using in this case a RenderTargetBitmap and some vector drawing commands in conjunction with a DrawingVisual:
DrawingVisual MyDrawingVisual =
DrawingContext MyDC =
new Pen(Brushes.Yellow, 1),
new Point(34, 67),
new Point(120, 0));
= new RenderTargetBitmap(
Don't worry if you don't follow this because all that really matters is that at this point we have a bitmap stored in MyRenderTargetBitmap which also decends from BitmapImageSource. Now we can use one of the Create methods to convert this into a BitMapFrame:
BitmapFrame MyBMF = BitmapFrame.
Once we have MyBMF we can use it in the same way as any BitmapSource derived class and, for example, show it in an Image control:
image1.Source = MyBMF;
If you put all of the above to work the result is a bitmap displaying a single yellow line.
There static methods that allow you to create a BitmapFrame from another BitmapSource, a stream and a URI. In addition there are also methods specific to the class that allow you to specify a thumbnail image and metadata.
Notice that you can't set the Thumbnail or Metadata property to associate a thumbnail or metadata with a new BitmapFrame - as these are read only.
The Thumbnail is just a standard BitmapSource and as such has no additional characteristics. The Metadata property references and instance of a class derived from ImageMetadata. Obviously ImageMetadata has to be customized depending on the type of image format in use and hence it is an abstract class that acts as the base class for all metadata storage. If you want to change an images metadata then you have to use an InPlaceBitmapMetadataWriter - and this can be tricky see later.