2009-02-26 6 views
7

Я опубликовал несколько вопросов, связанных с этой проблемой, которые у меня возникают, и я начинаю верить, что этого не может быть сделано. Вот предыстория.Предоставление изображения во время выполнения в WPF

У меня есть приложение ASP.NET, из которого я хочу сгенерировать .png изображение. Это .png изображение должно быть построено либо из XAML, либо из Visual Tree. Из-за этого я должен сгенерировать .png изображение в потоке STA. Все работает нормально, пока мое визуальное дерево XAML/WPF не включает изображение (как в System.Windows.Controls.Image). Файл .png генерируется правильно, за исключением того, что элемент Image не показывает ссылку. Ссылка на изображение находится на удаленном URL-адресе. Ошибок и исключений не выбрасывают.

Как создать изображение .png из некоторого визуального дерева XAML/WPF, содержащего элемент System.Windows.Controls.Image? В результате .png должен включать изображение, указанное в элементе Image. Я пробовал следующий код различными способами:

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

Благодарим за помощь.

+1

Мне нравится, когда я нахожу ответ на свой вопрос, не спрашивая - спасибо за то, что я столкнулся с тем же вопросом, который у меня был, и помогал мне в решении моих проблем! –

ответ

14

Вы визуализируете выходное растровое изображение правильно, это всего лишь входной растровый рисунок, который вы завинчиваете :).

BitmapImage требует доступа к свойству StreamSource до тех пор, пока он не запустит событие DownloadCompleted, а блок «using» Dispose() s из MemoryStream, прежде чем у него появится шанс! Вы могли бы просто развернуть MemoryStream из блока использования и позволить GC обрабатывать его (если это так, я бы рекомендовал установить BitmapImage.CacheOption в BitmapCacheOption.None, поэтому он использует поток напрямую, а не копию), но я бы используйте свойство UriSource и дождитесь события DownloadComplete перед рендерингом.

+1

Большое вам спасибо! Это полностью решило мою проблему. Я сходил с ума. – user70192

+0

безупречный! спасибо за предоставление этого ответа! –