我需要动态生成图像,在阅读教程后here我意识到我可以使用 WPF 中的所有控件和布局来生成渲染,然后将其另存为 JPG。
这个想法是使用它来代替 GDI+,这是相当原始的。
问题是,如何创建一个常规 dll 文件,该文件将以编程方式生成 WPF 画布,以便我可以向其中添加控件,然后将其输出到图像文件。请记住,它将由 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();
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)