Wednesday, March 10, 2010 Register    Login
Blog_List
  Print    

Blog_Archive
  Print    

Search_Blog
  Print    

Using an embedded resource Image from code in a WPF application.
Location: BlogsVB.Net Code ExamplesWPF VB.Net Development    
Posted by: Ibrahim 5/24/2009 4:23 PM

Using an embedded resource Image from code in a WPF application.

In WinForms or standard ASP.Net coding getting a reference to an embedded resource image is as simple as “My.Resources.ImageName” but alas this is not the case in WPF or even in Silverlight. You can access the Image resource in code using the previous examples, but as the saying  goes, you can’t get there from here. What you will get is a Bitmap reference that is just not usable by the ImageSource object.

There are many examples of how to use an embedded resource image directly in the XAML script such as ImageSource="/{AssemblyName};component/Images/MyImage.png" where {Assemblyname} is the name of the containing assembly.  But what if your requirements include the need to set these image properties during runtime in the Visueal Basic code instead of during XAML design time?

What you are going to have to do is use reflection to extract the embedded resource file from the containing assembly and stream it into a decoder object and then pass the decoder’s frame object to the ImageSource object and you are done.   Below is a code example that retrieves A PNG image from the assembly’s embedded resources.  The method takes the name of the image as an argument including the root namespace of the assembly and the file extension of the image as an argument. As written this method is specifically designed for a PNG type of image file since the image decoders are specific to an image type. The steps include getting a reference to the containing assembly, opening a memory stream that points to the image resource and decode the stream using a BitMapDecoder that is specific to an image type to decode the image into a System.Windows.Media.ImageSource object. You extract the Image Source from Frame(0) of the decoder.  Why is the image source placed in a frame array? Because in some cases such as an animated GIF, you will have several frames that make up the animation. In such a case you will have to create a method that returns an array of ImageSource objects.

    '''

    ''' Given a valid resource image name that includes [namespace].[imagename].[extension]

    ''' this function returns an PNG image source that can be programatically used as a

    ''' WPF ImageSource object.

    '''

    '''

    '''

    '''

    '''

    Public Shared Function GetPNGResourceImage(ByVal Imagename As String) _

                                               As ImageSource

 

        Dim MyStream As System.IO.Stream = Nothing

        Dim MyDecoder As PngBitmapDecoder = Nothing

        Dim MyImage As ImageSource = Nothing

        Dim MyAssembly As System.Reflection.Assembly = Nothing

 

        Try

            'get a reference to the containing assembly

            MyAssembly = System.Reflection.Assembly.GetExecutingAssembly

            'get a memory stream of the embedded image

            MyStream = MyAssembly.GetManifestResourceStream(Imagename)

            'make sure we have a valid stream instance

            If MyStream IsNot Nothing Then

 

                'decode the image into a imagesource object

                MyDecoder = New PngBitmapDecoder(MyStream, _

                                                 BitmapCreateOptions.PreservePixelFormat, _

                                                 BitmapCacheOption.Default)

                MyImage = MyDecoder.Frames(0)

 

            End If

 

        Catch ex As Exception

            ’handle your exceptions here

        Finally

            MyStream.Close()

        End Try

 

        Return MyImage

 

    End Function

 

 

.

The code above extracts a PNG type of image from an assembly’s resource cache.  For this to work properly you have to set the resource image’s Build Action property to Embedded Resource.  To call the function you might do something like this:

Me.Logo.Source = Utilities.GetPNGResourceImage(Me, "PPCSalesManagement.PPCSpider.png")

 The above function method works fine if all of your images are of PNG type.  That is not always the case and perhaps a more flexible method would be in order to accommodate any of the image types. You can approach it many ways but in the example below I use an enumerator in the argument for selecting the image type and then a select case to instantiate an image type specific decoder from the generic base class declaration.

   

    Public Enum eImageType

        PNG = 0

        JPG = 1

        BMP = 2

        GIF = 3

        Icon = 4

        WMF = 5

        TIFF = 6

    End Enum

 

 

    '''

    '''  Given a valid resource image name that includes [namespace].[imagename].[extension]

    '''  and the proper image type selection this function returns an image source that can be 

    '''  prgramatically used as a WPF ImageSource object.

    '''

    '''

    '''

    '''

    ''' Given a valid resource image name that includes [namespace].[imagename].[extension]

    '''  and the proper image type selection this function returns an image source that can be 

    '''  prgramatically used as a WPF ImageSource object.

    Public Shared Function GetResourceImage(ByVal ImageNameIn As String, ByVal TypeIn As eImageType) As ImageSource

 

        Dim MyStream As System.IO.Stream = Nothing

        Dim MyDecoder As BitmapDecoder = Nothing 'PngBitmapDecoder = Nothing

        Dim MyImage As ImageSource = Nothing

        Dim MyAssembly As System.Reflection.Assembly = Nothing

 

        Try

 

            'get a reference to the containing assembly

            MyAssembly = System.Reflection.Assembly.GetExecutingAssembly

            'get a memory stream of the embedded image

            MyStream = MyAssembly.GetManifestResourceStream(ImageNameIn)

            'make sure we have a valid stream instance

            If MyStream IsNot Nothing Then

 

                'get the appropriate decoder

                Select Case TypeIn

 

                    Case eImageType.BMP

                        MyDecoder = New BmpBitmapDecoder(MyStream, _

                                                 BitmapCreateOptions.PreservePixelFormat, _

                                                 BitmapCacheOption.Default)

                    Case eImageType.GIF

                        MyDecoder = New GifBitmapDecoder(MyStream, _

                                                 BitmapCreateOptions.PreservePixelFormat, _

                                                 BitmapCacheOption.Default)

 

                    Case eImageType.Icon

                        MyDecoder = New IconBitmapDecoder(MyStream, _

                                                 BitmapCreateOptions.PreservePixelFormat, _

                                                 BitmapCacheOption.Default)

 

                    Case eImageType.JPG

                        MyDecoder = New JpegBitmapDecoder(MyStream, _

                                                 BitmapCreateOptions.PreservePixelFormat, _

                                                 BitmapCacheOption.Default)

 

                    Case eImageType.PNG

                        MyDecoder = New PngBitmapDecoder(MyStream, _

                                                 BitmapCreateOptions.PreservePixelFormat, _

                                                 BitmapCacheOption.Default)

 

                    Case eImageType.TIFF

                        MyDecoder = New TiffBitmapDecoder(MyStream, _

                                                 BitmapCreateOptions.PreservePixelFormat, _

                                                 BitmapCacheOption.Default)

 

                    Case eImageType.WMF

                        MyDecoder = New WmpBitmapDecoder(MyStream, _

                                                 BitmapCreateOptions.PreservePixelFormat, _

                                                 BitmapCacheOption.Default)

 

                End Select

 

                MyImage = MyDecoder.Frames(0)

 

            End If

 

        Catch ex As Exception

            ProcessException(ex, eExceptionsOptions.ShowMessageAndLog)

        Finally

            MyStream.Close()

        End Try

 

        Return MyImage

 

    End Function

 

A call to this function is would look like the example below:

Me.HeaderBorder.Background = New ImageBrush(Utilities.GetResourceImage("PPCSalesManagement.ppcBanner1.png", Utilities.eImageType.PNG))

Well, that wraps up this article.  If you have comments or suggestions please feel free to post them here.

Ibrahim

 

Copyright ©2009 Ibrahim Malluf
Permalink |  Trackback