2009-02-26 3 views
7

Ho pubblicato diverse domande relative a questo problema che sto avendo e sto iniziando a credere che questo non possa essere fatto. Ecco la storia precedente.Rendering di un'immagine al runtime in WPF

Ho un'applicazione ASP.NET da cui voglio generare un'immagine .png. Questa immagine .png deve essere costruita da XAML o da una struttura visuale WPF. Per questo motivo, devo generare l'immagine .png in un thread STA. Tutto funziona bene fino a quando la mia struttura visiva XAML/WPF include un'immagine (come in System.Windows.Controls.Image). Il mio file .png viene generato correttamente, tranne che l'elemento Immagine non mostra l'immagine di riferimento. L'immagine di riferimento si trova su un URL remoto. Non vengono emessi errori o eccezioni.

Come si crea un'immagine .png da una struttura ad albero XAML/WPF che include un elemento System.Windows.Controls.Image? Il risultato .png deve includere l'immagine a cui si fa riferimento nell'elemento Immagine. Ho provato il seguente codice in vari modi:

string address = "http://imgtops.sourceforge.net/bakeoff/o-png24.png"; 

WebClient webClient = new WebClient(); 
byte[] imageContent = webClient.DownloadData(address); 

Image image = new Image(); 
using (MemoryStream memoryStream = new MemoryStream(imageContent)) 
{ 
    BitmapImage imageSource = new BitmapImage(); 
    imageSource.BeginInit(); 
    imageSource.StreamSource = memoryStream; 
    imageSource.EndInit(); 
    image.Source = imageSource; 
} 

// Set the size 
image.Height = 200; 
image.Width = 300; 

// Position the Image within a Canvas 
image.SetValue(Canvas.TopProperty, 1.0); 
image.SetValue(Canvas.LeftProperty, 1.0); 

Canvas canvas = new Canvas(); 
canvas.Height = 200; 
canvas.Width = 300; 
canvas.Background = new SolidColorBrush(Colors.Purple); 
canvas.Children.Add(image); 

// Create the area 
Size availableSize = new Size(300, 200); 
frameworkElement.Measure(availableSize); 
frameworkElement.Arrange(new Rect(availableSize)); 

// Convert the WPF representation to a PNG file    
BitmapSource bitmap = RenderToBitmap(frameworkElement); 
PngBitmapEncoder encoder = new PngBitmapEncoder(); 
encoder.Frames.Add(BitmapFrame.Create(bitmap)); 

// Generate the .png 
FileStream fileStream = new FileStream(filename, FileMode.Create); 
encoder.Save(fileStream); 


public BitmapSource RenderToBitmap(FrameworkElement target) 
{ 
    int actualWidth = 300; 
    int actualHeight = 200; 

    Rect boundary = VisualTreeHelper.GetDescendantBounds(target); 
    RenderTargetBitmap renderBitmap = new RenderTargetBitmap(actualWidth, actualHeight, 96, 96, PixelFormats.Pbgra32); 

    DrawingVisual drawingVisual = new DrawingVisual(); 
    using (DrawingContext context = drawingVisual.RenderOpen()) 
    { 
    VisualBrush visualBrush = new VisualBrush(target); 
    context.DrawRectangle(visualBrush, null, new Rect(new Point(), boundary.Size)); 
    } 

    renderBitmap.Render(drawingVisual); 
    return renderBitmap; 
} 

Grazie per il vostro aiuto.

+1

Mi piace quando trovo la risposta alla mia domanda senza dover chiedere - grazie per aver incontrato la stessa domanda che ho avuto e aiutarmi a risolvere i miei problemi! –

risposta

14

Si sta visualizzando correttamente la bitmap di output, è solo la bitmap di input che si sta facendo clic :).

BitmapImage richiede l'accesso alla proprietà StreamSource finché non scocca l'evento DownloadCompleted, ma il blocco "using"s di MemoryStream prima che abbia una possibilità! Potresti semplicemente scartare il MemoryStream dal blocco using e lasciare che il GC lo gestisca (se lo fai, ti consiglio di impostare BitmapImage.CacheOption su BitmapCacheOption.None, in modo che usi lo stream direttamente, piuttosto che una copia), ma vorrei utilizzare la proprietà UriSource e attendere l'evento DownloadComplete prima del rendering.

+1

Grazie mille! Questo ha completamente risolto il mio problema. Stavo impazzendo. – user70192

+0

perfetto! grazie per aver fornito questa risposta! –