2015-06-05 43 views
9

Sử dụng WPF và MVVM Tôi đang cố hiển thị hình ảnh camera thành Image. Mỗi camera khung có, một callback được gọi là:Dừng hình ảnh WPF

ViewModel

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

Mỗi khung, tôi cập nhật _bmpImage biến:

ViewModel

private Bitmap _bmpImage; 
public Bitmap BMPImage 
{ 
    get 
    { return _bmpImage; } 
    private set 
    { _bmpImage = value; RaisePropertyChanged("BMPImage"); } 
} 

Để để chuyển đổi Bitmap thành BitmapImage tôi sử dụng một bộ chuyển đổi:

Chuyển đổi

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

finnaly liên kết với quan điểm của tôi:

<Image Source="{Binding Main.BMPImage, Converter={StaticResource ImageToSource}}"></Image> 

Đó là công việc tốt trong 15 giây đầu tiên, nhưng sau khi sự chậm trễ này: Image của tôi trở nên trắng . Trong Bộ chuyển đổi, image không bao giờ là null vì vậy máy ảnh hoạt động tốt. Vấn đề là thành phần Image ngừng sơn lại.
Khi Image có màu trắng, tôi có thể đổi kích thước cửa sổ hoặc di chuyển nó và hình ảnh trở nên tốt vì Image đang sơn lại.

Có điều gì đó tôi làm sai?
Có cách nào để buộc Image sơn lại?
Tại sao Image ngừng sơn lại?

Cảm ơn

EDIT1:

Sau khi một số xác minh, khi hình ảnh trở nên trắng, tất cả ui đóng băng (vì vậy nút của tôi không thể nhấp cho đến khi tôi thay đổi kích thước hay di chuyển cửa sổ)

EDIT2

như Dennis trong nhận xét đã gợi ý cho tôi, tôi đã cố gắng thực hiện chuyển đổi trong ViewModel của mình:

Đối với đó, tôi thêm một tài sản mà đại diện cho hình ảnh chuyển đổi:

private BitmapImage _testImage; 
public BitmapImage TestImage 
{ 
     get 
     { return _testImage; } 
     private set 
     { _testImage = value; RaisePropertyChanged("TestImage"); } 
} 

Và tôi chuyển _bmpImage trực tiếp vào 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"); 
     } 
    } 

và ràng buộc trực tiếp TestImage trên tôi Image
Xem

<Image Source="{Binding Main.TestImage}" /> 

Và với mã này tôi đã ngoại trừ:

Must create DependencySource on same Thread as the DependencyObject 

EDIT 3

Tôi đã xem xét những nhận xét của bạn và nó là mã mới của tôi:

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

      } 

Tôi đã cùng một ngoại lệ trên RaisePropertyChanged("TestImage");

Juste n ote rằng Edit2 và Edit3 là một thử nghiệm và không trả lời cho câu hỏi ban đầu của tôi

Xin lỗi cho đăng bài dài

+0

Tên đầy đủ cho 'Bitmap' là gì?Bạn đã thử thực hiện chuyển đổi trong mô hình xem và hiển thị thuộc tính 'ImageSource' từ VM thay vì' Bitmap'? – Dennis

+0

Kiểu đầy đủ là 'System.Drawing.Bitmap'. Tôi sẽ thử – Epitouille

+0

Điều này đang dần biến thành một phiên gỡ lỗi. Bài đăng trên Stack Overflow nên chứa một câu hỏi (không giúp tôi gỡ lỗi) và không thay đổi quá nhiều theo thời gian. Có lẽ bạn có thể nhận trợ giúp bằng cách sử dụng trò chuyện: http://chat.stackoverflow.com/ và khắc phục sự cố sau khi nhận được sự cố. –

Trả lời

0

Cuối cùng tôi đã tìm được giải pháp. Tôi sử dụng một phương pháp khác để chuyển đổi Bitmap của tôi (có thể nhanh hơn)

[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; 
} 
2

Tôi sẽ đặt cược phương pháp OnNewFrame của bạn không chạy trên thread UI.

Trong code của bạn, thay đổi dòng này để nó chạy trên thread UI mua gọi Gọi hoặc BeginInvoke về tài sản Dispatcher của cửa sổ/kiểm soát của bạn:

windowOrControlDispatcher.BeginInvoke((Action) (() => 
{ 
    RaisePropertyChanged("TestImage"); 
})); 
+0

Ý tưởng hay đó, nhưng trong mô hình khung nhìn của tôi, tôi không có ui nên không có 'windowOrControl' – Epitouille

+0

Nhưng bạn đang sử dụng WPF - và bạn có một cửa sổ, phải không? Bạn đã tạo một hình ảnh và một số thành phần giao diện người dùng khác - vì vậy có một chuỗi giao diện người dùng đang chạy. Bạn thậm chí có thể thử Application.Current.Dispatcher ... –

+0

Là những gì tôi đã làm :) kiểm tra "Chỉnh sửa 3" – Epitouille

0

Kiểm tra mức tiêu thụ bộ nhớ của ứng dụng.

Nếu bitmap mất rất nhiều bộ nhớ và các ứng dụng không xử lý hình ảnh và bộ đệm

camera.ToBitmap(out _bmpImage); 
// does this clean up the old _bmpImage? 

MemoryStream ms = new MemoryStream(); 
// no dispose! 

Ứng dụng này có thể dành thời gian của mình vào việc thu thập rác thay vì cập nhật giao diện người dùng.

Các vấn đề liên quan