首页 > 解决方案 > 处理程序在 BitmapEncoder.Frames.Add 调用中无效

问题描述

我正在使用此自定义方法将 Bitmapsource 转换为 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);
            } } }

这个方法在我的代码中被调用了几次,效果很好。但是当我用鼠标单击事件或按键事件调用它时,我得到处理程序无效错误。

我不知道如何进行。有什么建议吗?

在代码中,我有一个位帧列表:

List<BitmapFrame> myImages = new List<BitmapFrame>();

最初,当我将每一帧显示到几个图片框中时,该方法有效:

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);
}

然后当我单击这些图片框之一时:

void pictureBoxClick (object sender , EventArgs e) {
    var selectedPictureBox = (PictureBox)sender;
    int idx = Controls.IndexOf(selectedPictureBox);
    pictureBox1.Image = BitmapFromSource(myImages[idx]);
}

我得到错误...

标签: c#bitmapsource

解决方案


从我从您的代码中可以看出,您很可能是“流”的受害者。
这意味着,当您从FileStream加载资源时,该流必须在该资源的生命周期内可用(未释放)。这也适用于BitmapDecoder
引用的图像资源。 如果您处理用于初始化的流,它的 Frames 集合将设置为 1x1 大小的 1 帧。 由于让流保持打开状态并不是一个好主意,因此通常会将其复制到MemoryStream(原始字节数组)并在之后立即处理。
BitmapDecoder

无论您可能读过或听到什么,MemoryStream都不需要处理 a (至少不需要立即处理),因为它并没有真正使用任何重要资源。

从流中加载图像资源后,BitmapDecoder可以这样初始化:

MemoryStream memstream = new MemoryStream();
stream.CopyTo(memstream);
memstream.Position = 0;
BitmapDecoder bitmapDecoder = BitmapDecoder.Create(memstream,
                                            BitmapCreateOptions.PreservePixelFormat,
                                            BitmapCacheOption.Default);

这样,BitmapFramesBitmapDecoder将有一个有效的句柄,因为底层流仍然是活动的。
当您加载新图像时,MemoryStream将使用新的FileStream.

为了测试这里和评论中所写内容的结果(这些建议也很相关),我构建了一个测试表单类。
您可以从 PasteBin下载源代码。


推荐阅读