DrawingContext到Bitmap文件

Lad*_*gic 10 .net c# wpf rendertargetbitmap drawingcontext

我有一个DrawingContext(Visual或DrawingGroup的一部分),我在其中绘制一堆矩形和/或1位图像.可以将其视为屏蔽1位图像.我想将其转换为位图图像文件.

使用RenderTargetBitmap不是一个选项,因为它只能以32位像素格式渲染,所以如果我必须渲染一个20MB的1位图像,我的堆上最终会得到640MB(20*32)的内存.这当然会产生宏伟的LOH碎片,并且应用程序在第二次拍摄时会耗尽内存.

所以,我基本上需要一种方法来有效地从绘图上下文中写入1位位图文件.任何想法/建议/替代方法将不胜感激.

Col*_*ith 7

一些想法,有些是有点复杂的......

打印到XPS然后提取位图

您可以打印Visual到XPS文档.

如果你很幸运,那么它将合并你在其中绘制的1bit图像,DrawingContext并在XPS文件中生成单个位图.

对于矩形,它可以将矩形保持为XPS中的基于矢量的信息(基于"形状" Rectangle或者DrawingContext DrawRectangle可能都这样做)....如果发生这种情况,则创建一个位图,在其中绘制矩形部分并将该位图绘制到上下文.

一旦你有了XPS文件,你就可以解析它并提取"图像",如果你幸运的话就是它产生的内容.(XPS只是一个ZIP文件,它使用XAML来描述内容并使用子目录来存储位图图像数据文件,字体等).

(我认为您可以使用Package该类访问XPS文档的原始部分,或者XpsDocument更高级别的解释).

或者只是在XPS查看器中显示XPS,如果您的目的只是提供一种方法,允许在不同的上下文中查看组合的1位图像.

使用提供"打印到图像"功能的打印机驱动程序

这并不理想......尤其是因为您必须在机器上安装打印机驱动程序.....但您可以使用"打印到图像"打印机驱动程序然后使用它来生成位图.以下是一些建议:

创建一个GDI + HBITMAP并使用GDI +调用进行绘制...然后将其包装以供WPF使用...或保存到磁盘.

[1]首先创建一个足够大的GDI +位图来保存你的合成渲染

(有几种不同的方法可以做到这一点......一种方法是使用WriteableBitmap来提供后备缓冲器位/存储......如果你想要访问内存中的位...在你的情况下我不会认为你做/需要).

var bmp = new System.Drawing.Bitmap( pixelwidth, pixelheight, System.Drawing.Imaging.Format1bppIndexed );
Run Code Online (Sandbox Code Playgroud)

或者这种方式,如果你想要WriteableBitmap访问.

[2]将任何WPF BitmapSource转换为GDI + Bitmaps,以便您可以使用DrawImage将它们绘制到GDI + Graphics上下文中.

您可以使用CopyPixels在BitmapSource上执行此操作.

对于矩形,您只需使用GDI + DrawRectangle渲染命令即可.

[3]将GDI +位图保存到磁盘

使用System.Image.Bitmap上的.Save方法将其另存为位图.

[4]使用保存的图像作为Image元素的Source

(注意,当它加载你的图像时,它可能会使用大量的内存,即使它是1bpp ...因为WPF渲染路径都是32bpp).

[4]或者包装GDI + Bitmap以便在WPF中使用

您可以使用InteropBitmap来包装基于GDI +的位图,以便您可以将其用作WPF中的BitmapSource.(注意它可能必须是32bpp ......如果必须......那么你回到了1号方......但是无论如何都要尝试).

创建位图"服务"

创建另一个充当服务的进程(不一定是NT服务......可能只是你开始的子进程)来渲染你的组合1bpp图像....有各种方法与它进行通信给出它是渲染命令.

当内存消耗过高/ LOH碎片化时,您可以重新启动此服务.

其他想法

您可以使用OpenGL进行渲染(例如使用OpenTK或SharpGL),或使用DirectX渲染...通过3D路径使用D3DImage或Direct2D(无论这个行为与内存使用方面的RenderTargetBitmap相同......都可以找到).

尝试使用NET 4.5,因为LOH堆有很多改进:


mle*_*may 0

像素格式怎么样

编辑:(感谢安德斯·古斯塔夫森)

较低的是PixelFormats.BlackWhite,每像素 1 位。

这样,您就可以将任何 BitmapImage 转换为 FormatConvertedBitmap,在其中您可以将格式修改为较低的 bpp。