Search code examples
c#wpfwriteablebitmapwriteablebitmapex

Weird WriteableBitmap FromStream issue


I am desperately trying to load a WriteableBitmap with the FromStream extension method.

The code below throws a System.InvalidOperationException at the FromStream() call with the following information:

BitmapImage has not been initialized. Call the BeginInit method, set the appropriate properties, and then call the EndInit method.

I verified that the image exists and it's build action is set to Resource. The image is valid (I loaded it into a BitmapImage) and the stream has the correct length.

var sri = Application.GetResourceStream(new Uri("dummy.jpg", UriKind.RelativeOrAbsolute));
if (sri != null)
{
    using (var stream = sri.Stream)
    {
        // creates the bitmap, part of the writeablebitmapextensions on WPF
        var wb = BitmapFactory.New(1, 1); 
        wb.FromStream(stream); // <--- Exception
    }
}

The error seems to indicate the extension method uses a BitmapImage internally in an incorrect way, which I find hard to belive. I'm using WriteableBitmapEx.Wpf 1.0.14.0

What could be causing this exception? There is no other code running in my application.


Solution

  • The FromStream method in WriteableBitmapConvertExtensions.cs, line 367, seems to be broken. It is missing the BeginInit and EndInit calls on the BitmapImage:

    public static WriteableBitmap FromStream(this WriteableBitmap bmp, Stream stream)
    {
        var bmpi = new BitmapImage();
    #if SILVERLIGHT
        bmpi.SetSource(stream);
        bmpi.CreateOptions = BitmapCreateOptions.None;
    #elif WPF
        bmpi.StreamSource = stream;
    #endif
        bmp = new WriteableBitmap(bmpi);
        return bmp;
    }
    

    It should look like this:

    public static WriteableBitmap FromStream(this WriteableBitmap bmp, Stream stream)
    {
        var bmpi = new BitmapImage();
    #if SILVERLIGHT
        bmpi.SetSource(stream);
        bmpi.CreateOptions = BitmapCreateOptions.None;
    #elif WPF
        bmpi.BeginInit();
        bmpi.StreamSource = stream;
        bmpi.EndInit();
    #endif
        bmp = new WriteableBitmap(bmpi);
        return bmp;
    }