我有一个从某些输入文件生成图形的应用程序。用户可以选择从这些图形生成图像。该图是使用外部库创建的,该库可绘制到自定义视觉对象(继承自Canvas)中。
我创建了一个自定义功能,可以在此画布上创建图像,并且到目前为止效果很好。当需要从非常大的图形中生成图像时,我遇到的问题与其性能有关。
此功能生成的图像一直很大,为了能够生成这些大图像,我生成了较小的“块”(可配置,但当前为2000x2000px,较大的块会丢失质量,较小的块会较慢)。创建这些“块”之后,我使用另一个外部库将它们合并(这最后一个工作正常,而且速度很快,问题不在这里)。
正在发生的问题是,原始视觉效果越大,每个块渲染所花费的时间就越长。
问题在于图像越大,每个“块”渲染花费的时间越长。我将稍后在此处发布代码,但是我注意到使用“ DrawingVisual”(带有块信息)时的“ RenderTargetBitmap.Render()”方法。例如,此方法调用在Canvas为 74052.75px x 1119.4px ;整个图像创建时间大约需要20秒。
并没有那么糟,但是有一个要求,即必须创建一个大(更大)的图像,并且每个块需要5分钟的时间来生成,所以我估计是大约需要 60天。
这是我在每个“块”循环中使用的代码。修改了代码,以删除一些取消令牌和进度报告调用。我还添加了一条注释,以突出显示耗时400毫秒以上的呼叫。
for (int i = 0; i < rowCount; i++)
{
for (int j = 0; j < colCount; j++)
{
int row = i, col = j; //this is done because task start could have a modified value on call
Rect rect = new Rect(
col * maxWidth,
row * maxHeight,
col + 1 < colCount ? maxWidth :
surfaceWidth - (colCount - 1) * maxWidth,
row + 1 < rowCount ? maxHeight :
surfaceHeight - (rowCount - 1) * maxHeight);
DrawingVisual visual = new DrawingVisual();
using (var dc = visual.RenderOpen())
{
VisualBrush brush = new VisualBrush(element)
{
Viewbox = rect,
ViewboxUnits = BrushMappingMode.Absolute,
Stretch = Stretch.None
};
dc.DrawRectangle(brush,
null,
new Rect(0, 0, rect.Width, rect.Height));
}
RenderTargetBitmap bitmap = new RenderTargetBitmap(
(int)(rect.Width * (imgdpi / DEFAULT_DPI)),
(int)(rect.Height * (imgdpi / DEFAULT_DPI)),
imgdpi,
imgdpi,
PixelFormat);
//***********************//
//THIS IS THE CALL THAT TAKES 400+ms
//***********************//
bitmap.Render(visual);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
MemoryStream ms = new MemoryStream();
encoder.Save(ms);
//... Some additional code to work with the chunk asynchronously
}
}
我尝试了几件事:
由于我不太确定此Render功能在内部如何工作(并且我已经搜索了这些信息,但是我发现充其量只是肤浅的),所以我不确定原因是表面较大还是曲面中控件的数量(或两者的组合)。因此,以下是有关测试用例的其他信息,每个渲染用时为400ms:
此外,由于不会产生如此大的图像,因此对普通用户也不会如此。我不介意所提供的解决方案是否牺牲了UI响应能力。
非常感谢您能提供的帮助。
谢谢!