2015-06-05 13 views
9

Utilizzo di WPF e MVVM Sto tentando di visualizzare le immagini della fotocamera in un Image. Ogni telecamera telaio ottenuto, un callback si chiama:Arresto dell'immagine WPF ridisegno

viewmodel

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

Ogni telaio, aggiorno il _bmpImage variabile:

ViewModel

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

Per convertire lo Bitmap in BitmapImage Io uso un convertitore:

Converter

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 legarsi al mio punto di vista:

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

E 'un lavoro buono il primo 15 secondi, ma dopo questo ritardo: la mia Image diventa bianco . Nel convertitore, image non è mai null, quindi la fotocamera funziona bene. Il problema è che il componente Image smette di ridipingere.
Quando il Image è bianco, posso ridimensionare la finestra o spostarla e l'immagine diventa buona perché Image è ridipinta.

C'è qualcosa che faccio di sbagliato?
C'è un modo per forzare la riverniciatura di Image?
Perché Image smettere di riverniciare?

Grazie

Edit1:

Dopo un po 'di verifica, quando l'immagine diventa bianco, tutti ui congelamento (quindi il mio tasto non sono cliccabili fino a quando ho ridimensionare o spostare la finestra)

EDIT2

come Dennis nel commento mi ha suggerito, ho provato a fare la conversione nel mio ViewModel:

Per questo, aggiungo una proprietà che rappresentano l'immagine convertita:

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

E ho convertito _bmpImage direttamente in 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"); 
     } 
    } 

e legare direttamente il TestImage sul mio Image
View

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

E con questo codice ho eccezione:

Must create DependencySource on same Thread as the DependencyObject 

EDIT 3

ho considerato le sue osservazioni ed è il mio nuovo codice:

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

      } 

ho la stessa eccezione su RaisePropertyChanged("TestImage");

Juste n ota che Edit2 e Edit3 sono un test e non risponde alla mia domanda iniziale

Ci scusiamo per il lungo post

+0

Qual è il nome di tipo completo per 'Bitmap'?Hai provato a eseguire la conversione nel modello di visualizzazione ed esporre la proprietà 'ImageSource' dalla VM invece di' Bitmap'? – Dennis

+0

Il tipo completo è 'System.Drawing.Bitmap'. Dare una prova – Epitouille

+0

Si sta lentamente trasformando in una sessione di debug. I post su Stack Overflow dovrebbero contenere una singola domanda (non aiutarmi nel debug) e non cambiare troppo nel tempo. Forse puoi ottenere aiuto tramite chat: http://chat.stackoverflow.com/ e risolvere la domanda dopo aver risolto il problema. –

risposta

0

Ho finalmente trovato una soluzione. Uso un altro metodo per convertire la mia Bitmap (probabilmente più veloce)

[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

Scommetto Il tuo metodo OnNewFrame non viene eseguito sul thread dell'interfaccia utente.

Nel codice, modificare questa riga in modo che viene eseguito sul thread UI acquistare chiamando Invoke o BeginInvoke sulla proprietà Dispatcher della finestra/controllo:

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

Questa buona idea, ma nel mio modello di vista, non ho ui così no 'windowOrControl' – Epitouille

+0

Ma stai usando WPF - e hai una finestra, giusto? Hai creato un'immagine e alcuni altri elementi dell'interfaccia utente, quindi è in esecuzione un thread dell'interfaccia utente. Puoi anche provare Application.Current.Dispatcher ... –

+0

È quello che ho fatto :) controlla il mio "Modifica 3" – Epitouille

0

controllare l'utilizzo della memoria dell'applicazione.

Se le bitmap prendere un sacco di memoria e l'applicazione non dispone delle immagini e buffer

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

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

L'applicazione potrebbe essere spesa il suo tempo sulla raccolta dei rifiuti invece di aggiornare l'interfaccia utente.

Problemi correlati