Monday, November 8, 2010

Error setting image source in silverlight from a memory stream

Have you received the following error? "catastrophic failure exception from hresult 0x8000ffff e_unexpected" while trying to set a bitmap image source from a memorystream?

I battled this all weekend and wanted to share. My basic scenario is to use the fileopendialog in Silverlight. Pick a jpg, for a profile picture. Show the picture then upload the picture to Azure Table Storage.

I'm using a WCF service.

The error probably isn't in the way your putting the retrieved memory stream into your bitmap image. It's how your converting you stream to a byte array when you first open it up.

I'm not going to try to get into lots of code here. Here's the basic file open code. Mine might look different, but if you get you code open, and are having success putting your image up, don't worry about the differences.

What I found out when I started looking is that in putting the stream into the bitmap sets the position in the stream to the last byte. Converting the stream to the byte array at that point runs fine, but all bytes are set to 0. Storing and retriving that byte array causes the catastropic fail.

You can put a break point on the code after the conversion and see the bytes are all {0}. Also check the stream.Position. I'll lay odds it's at the end.

If this is the case add the line of code highlighted in red. It sets the position back to 0, and the conversion code starts at the beginning.


private void cmdFileOpen_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openDialog = new OpenFileDialog();
openDialog.Filter = "JPEG Files (*.jpg;*.jpeg)*.jpg;*.jpeg";

if (openDialog.ShowDialog().GetValueOrDefault(false))
{

using (FileStream stream = openDialog.File.OpenRead())
{

BitmapImage bi = new BitmapImage();

bi.SetSource(stream);
imgProfile.Source = bi;
stream.Position = 0;

// Now read s into a byte buffer.
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);

//Get the service reference for the wcf service.
UserSVCClient client = App.GetUserClient();
client.UpdateProfileImageCompleted += new EventHandler(client_UpdateProfileImageCompleted);
client.UpdateProfileImageAsync(App.UserInfo.UserID, bytes);

}
}
}

No comments: