WPF图像停止重新绘制

Epi*_*lle 9 c# wpf graphics mvvm

使用WPF和MVVM我试图将相机图像显示为Image.每个帧相机都有一个回调叫做:

视图模型

public void OnNewFrame(object sender, EventArgs e)
{
    Camera camera = sender as MyCamera;
    camera.ToBitmap(out _bmpImage);
    RaisePropertyChanged("BMPImage");
}
Run Code Online (Sandbox Code Playgroud)

每一帧,我更新变量_bmpImage:

视图模型

private Bitmap _bmpImage;
public Bitmap BMPImage
{
    get
    { return _bmpImage; }
    private set
    { _bmpImage = value; RaisePropertyChanged("BMPImage"); }
}
Run Code Online (Sandbox Code Playgroud)

为了转换BitmapBitmapImage我使用转换器:

变流器

public class ImageToSource : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter,
                System.Globalization.CultureInfo culture)
        {
            Image image = value as Image;
            if (image != null)
            {
                MemoryStream ms = new MemoryStream();
                image.Save(ms, ImageFormat.Bmp);
                ms.Seek(0, SeekOrigin.Begin);
                BitmapImage bi = new BitmapImage();
                bi.BeginInit();
                bi.StreamSource = ms;
                bi.EndInit();
                return bi;
            }
            return null;
        }

        public object ConvertBack(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
  }
Run Code Online (Sandbox Code Playgroud)

Finnaly绑定到我的观点:

 <Image Source="{Binding Main.BMPImage, Converter={StaticResource ImageToSource}}"></Image>
Run Code Online (Sandbox Code Playgroud)

这是第15秒的好工作,但在这个延迟之后:我Image变成了白色.在转换器中,image永远不会null让相机运行良好.问题是组件Image停止重新绘制.
当它Image是白色时,我可以调整窗口大小或移动它,因为Image重新绘制图像变得很好.

我做错了什么?
有一种方法可以强制Image重画吗?
为什么要Image停止重新涂漆?

谢谢

EDIT1:

经过一些验证后,当图像变白时,所有ui都会冻结(因此我的按钮不可点击,直到我调整大小或移动窗口)

EDIT2

正如丹尼斯在评论中提出的那样,我试图在我的ViewModel中进行转换:

为此,我添加了一个表示转换后图像的属性:

 private BitmapImage _testImage;
 public BitmapImage TestImage
 {
      get
      { return _testImage; }
      private set
      { _testImage = value; RaisePropertyChanged("TestImage"); }
 }
Run Code Online (Sandbox Code Playgroud)

_bmpImage直接转换成OnNewFrame :

public void OnNewFrame(object sender, EventArgs e)
    {
        Camera camera = sender as MyCamera;
        camera.ToBitmap(out _bmpImage);
        //RaisePropertyChanged("BMPImage");
        if (_bmpImage != null)
        {
              // Convertion
              MemoryStream ms = new MemoryStream();
              _bmpImage.Save(ms, ImageFormat.Bmp);
              ms.Seek(0, SeekOrigin.Begin);
              _testImage = new BitmapImage();
              _testImage.BeginInit();
              _testImage.StreamSource = ms;
              _testImage.EndInit();
              RaisePropertyChanged("TestImage");
        }
    }
Run Code Online (Sandbox Code Playgroud)

并直接绑定TestImage我的Image
视图

<Image Source="{Binding Main.TestImage}" />
Run Code Online (Sandbox Code Playgroud)

使用此代码我有例外:

Must create DependencySource on same Thread as the DependencyObject
Run Code Online (Sandbox Code Playgroud)

编辑3

我考虑过你的评论,这是我的新代码:

if (_bmpImage != null)
            {

                // Convertion
                Console.WriteLine("ok");
                MemoryStream ms = new MemoryStream();
                _bmpImage.Save(ms, ImageFormat.Bmp);
                ms.Seek(0, SeekOrigin.Begin);
                _testImage = new BitmapImage();
                _testImage.BeginInit();
                _testImage.StreamSource = ms;
                _testImage.EndInit();

                ms.Dispose();

                System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                {
                    RaisePropertyChanged("TestImage");
                }));

            }
Run Code Online (Sandbox Code Playgroud)

我也有同样的例外 RaisePropertyChanged("TestImage");

Juste注意到Edit2和Edit3是一个测试,并没有回答我原来的问题

对不起,很长的帖子

Epi*_*lle 0

我终于找到了解决办法。我使用其他方法来转换我的位图(可能更快)

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
{
    Bitmap bmp = value as Bitmap;

    if (bmp != null)
    {
        IntPtr hBitmap = bmp.GetHbitmap(); 
        var drawable = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
              hBitmap,
              IntPtr.Zero,
              Int32Rect.Empty,
              BitmapSizeOptions.FromEmptyOptions());

        DeleteObject(hBitmap);
        bmp.Dispose();
        return drawable;
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)