I am trying to build a simple graphics application in WPF C#. The purpose is to draw 10000*10000 rectangles of size 4 pixels each.
I have modified the OnRender method of the canvas to draw the rectangles. Drawings are performed for smaller number of rectangles (say 50*50 or 100*100 rectangles of 4 pixel each) but it is slowing down as I am increasing the no. of rectangles.
Following is my code:
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
FillCells(dc);
if (_ShowGrids)
{
DrawGrid(dc); // draw grid lines
}
}
void FillCells(DrawingContext dc)
{
int cellSize=4;
for (int i = 0; i < MaxRow; i++)
{
for (int j = 0; j < MaxColumn; j++)
{
dc.DrawRectangle(GetRectBrush(i,j), GetRectPen(i,j), new Rect(j * cellSize , i * cellSize , cellSize - 1, cellSize - 1));
}
}
}
The above code takes more than a minute to draw 1000*1000 rectangles.
Is there any method to make this process faster? Is there any other thing I can use in place of this?
Thanks.
The purpose is to draw 10000*10000 rectangles of size 4 pixels each.
Do NOT draw them. That simple. This would be 40k to 40k pixels.
Most will not be visible. So they must not bee drawn. Basically only draw those that are visible in the canvas. When resizing or scrolling you repaint anyway, then do the same - only draw those that are visible.
Virtualization is the key to performance here. Take things out of the drawing loop as early as possible. Stuff not visible per definition does not need to be drawn at all.
Next alternative would be not to use a canvas. Try a bitmap. Prepare it on a separate thread, then draw this one at once.
You should try StreamGeometry then. http://msdn.microsoft.com/en-us/library/system.windows.media.streamgeometry.aspx
For complex geometries that don’t need to be modified after they are created, you should consider using StreamGeometry rather than PathGeometry as a performance optimization. StreamGeometry works like PathGeometry, except that it can only be filled via procedural code. Its odd name refers to an implementation detail: To use less memory (and less of the CPU), its PathFigures and PathSegments are stored as a compact byte stream rather than a graph of .NET objects.
Quoted from Adam Nathan's book WPF Unleashed.
You don't need to recreate the brush for each iteration of the loop, since they use the same color over and over:
SolidColorBrush blueBrush = new SolidColorBrush(Colors.Blue)
SolidColorPen bluePen = new SolidColorPen(blueBrush)
for (int i = 0; i < MaxRow; i++)
{
for (int j = 0; j < MaxColumn; j++)
{
dc.DrawRectangle(blueBrush, bluePen, 1), new Rect(j * cellSize , i * cellSize , cellSize - 1, cellSize - 1));
}
}
This may speed up the loop a bit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With