在DLL上使用WPF动态创建映像(而不是GDI +)

我需要动态生成一个图像,在我阅读这里的教程之后,我意识到我可以使用WPF中的所有控件和布局来生成渲染,然后将其保存为JPG。 我们的想法是使用它代替GDI +,这是非常原始的。

问题是,如何创建一个以编程方式生成WPFcanvas的常规dll文件,然后我可以向其添加控件然后将其输出到图像文件。 请记住,它将由ASP.NET应用程序使用。

有人的想法吗?

这个例子有一个良好的开端,但我发现它有很多不必要的垃圾。 主要的是你不需要一个单独的WPF项目。

这是做什么的:

  • 在您的Web项目中引用PresentationCore,PresentationFramework和WindowsBase。
  • 在STA线程中以编程方式创建Canvas和其他WPF对象。
  • 在它们上面调用一些特殊方法,以确保它们在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(); } } }