I'm using this custom method to convert a Bitmapsource to a Bitmap:
public Bitmap BitmapFromSource(BitmapSource bitmapsource) {
using (MemoryStream outStream = new MemoryStream()) {
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(outStream);
using (var tempBitmap = new Bitmap(outStream)) {
return new Bitmap(tempBitmap);
} } }
this method is called several times in my code and it works great. But when I'm calling it with a mouse click event or a key down event, i get the handler is invalid error.
I don't have any clue on how to proceed. any suggestion?
In the code I have a list of bitframes:
List<BitmapFrame> myImages = new List<BitmapFrame>();
initially the method works when I show each frame in to several pictureboxes:
var handler = new EventHandler(pictureBoxClick);
for (int i = 0; i < (decoder.Frames.Count); i++) {
var picture = new MyPictureBox {
Name = "pictureBoxFrame" + i,
Width = (int)newWidth,
Height = (int)newHeight,
SizeMode = PictureBoxSizeMode.Zoom,
Location= loc,
Image = BitmapFromSource(myImages[i]), };
Controls[i].Click += handler;
splitContainer1.Panel1.Controls.Add(picture);
}
then when I click one of these pictureboxes:
void pictureBoxClick (object sender , EventArgs e) {
var selectedPictureBox = (PictureBox)sender;
int idx = Controls.IndexOf(selectedPictureBox);
pictureBox1.Image = BitmapFromSource(myImages[idx]);
}
I get the error...
From what I can see from your code, you are quite probably a victim of the "Stream".
Meaning that, when you are loading a resource from a FileStream, the stream must be available (not disposed) for the lifespan of that resource.
This applies to the image resource referenced by a BitmapDecoder, too.
If you dispose the stream used to initialize the
BitmapDecoder, it's Frames collection will be set to 1 frame of 1x1 size.Since leaving the stream open is not a good idea, it is usually copied to a MemoryStream (the raw byte array) and disposed right after.
Having loaded an image resource from a stream, the
BitmapDecodercan be initialized this way:This way, the
BitmapFramesof theBitmapDecoderwill have a valid handle, because the underlying stream is still alive.When you load a new image, the
MemoryStreamwill be updated using a newFileStream.To test the result of what has been written here and in the comments (those suggestions are relevant too), I've built a Test Form class.
You can download the source code from PasteBin.