2009-05-04 47 views
3

我需要動態生成圖像,在閱讀教程here後,我意識到我可以使用WPF中的所有控件和佈局來生成我的渲染,並且然後將其另存爲JPG。 這個想法是用這個代替GDI +,這是相當原始的。在DLL上使用WPF動態創建圖像(而不是GDI +)

的問題是,如何創建,將產生一個編程WPF畫布這樣的話我就可以添加控件,然後輸出中,爲圖像文件常規DLL文件。請記住,它將被ASP.NET應用程序使用。

任何想法有人?

+0

我發現這個鏈接 http://www.codeproject.com/KB/WPF/WPF-Image-to-WebPage.aspx 我會看看它是否工作.... – federubin 2009-05-04 02:01:13

+0

似乎爲我工作,但誰知道他爲什麼使用jpeg中間格式。 – RandomEngy 2009-05-04 16:58:36

回答

9

這個例子有一個良好的開端,但我發現它有很多不必要的垃圾隨之。主要的是你不需要有一個單獨的WPF項目。

這裏是做什麼:

  • 參考PresentationCore,PresentationFramework和WindowsBase在Web項目。
  • 創建一個畫布和其他WPF在STA線程編程對象。
  • 呼籲他們一些特殊的方法,以確保他們更新一個WPF應用程序的上下文之外。
  • 使用RenderTargetBitmap將它們渲染爲圖像。
  • 關閉線程的調度程序。
  • 設置MIME類型並使用ASP.NET輸出圖像。

爲了提高效率,您可以重複使用同一個線程,而不是爲每個圖像創建一個新線程。在這種情況下,只需在關閉線程時清理調度程序。

下面是完整的工作代碼,我有:

using System; 
using System.Web; 
using System.Threading; 
using System.IO; 
using System.Windows; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Controls; 
using System.Windows.Documents; 

public partial class _Default : System.Web.UI.Page 
{ 
    private byte[] imageBuffer; 

    public void Page_Load(object sender, EventArgs e) 
    { 
     this.RenderImage(); 

     Response.Clear(); 
     Response.ContentType = @"image/png"; 
     Response.BufferOutput = true; 
     Response.BinaryWrite(this.imageBuffer); 
     Response.Flush(); 
    } 

    public void RenderImage() 
    { 
     Thread worker = new Thread(new ThreadStart(this.RenderImageWorker)); 
     worker.SetApartmentState(ApartmentState.STA); 
     worker.Name = "RenderImageWorker"; 
     worker.Start(); 
     worker.Join(); 
    } 

    public void RenderImageWorker() 
    { 
     Canvas imageCanvas = new Canvas { Width = 600, Height = 200, Background = Brushes.Azure }; 

     TextBlock tb = new TextBlock(); 
     tb.Width = (double)400; 
     //tb.Height = (double)200; 
     tb.TextAlignment = TextAlignment.Center; 
     tb.Inlines.Add(new Run("This is ")); 
     tb.Inlines.Add(new Bold(new Run("bold"))); 
     tb.Inlines.Add(new Run(" text.")); 
     tb.FontSize = 30; 
     tb.Foreground = Brushes.Blue; 

     imageCanvas.Children.Add(tb); 

     // Update layout 
     imageCanvas.Measure(new Size(imageCanvas.Width, imageCanvas.Height)); 
     imageCanvas.Arrange(new Rect(new Size(imageCanvas.Width, imageCanvas.Height))); 

     RenderTargetBitmap bitmapRenderer = new RenderTargetBitmap((int)imageCanvas.ActualWidth, (int)imageCanvas.ActualHeight, 96, 96, PixelFormats.Pbgra32); 
     bitmapRenderer.Render(imageCanvas); 

     PngBitmapEncoder png = new PngBitmapEncoder(); 
     png.Frames.Add(BitmapFrame.Create(bitmapRenderer)); 

     using (MemoryStream memoryStream = new MemoryStream()) 
     { 
      png.Save(memoryStream); 
      this.imageBuffer = memoryStream.ToArray(); 
     } 

     if (bitmapRenderer.Dispatcher.Thread.IsAlive) 
     { 
      bitmapRenderer.Dispatcher.InvokeShutdown(); 
     } 
    } 
}