我们正在建设一个图形应用程序,我们要画在画布上的背景点,因为我们有像捕捉到的特征电网当然绘制大量点的最佳方式是什么?
中,用户可以设置捕捉点之间的距离,所以,如果我们有一个大小为1024 x 1024的画布,每个点之间有5个像素,我们将有大约41775个点!
在画布上渲染大量点的建议方法是什么?我们需要它尽可能快。
我们正在建设一个图形应用程序,我们要画在画布上的背景点,因为我们有像捕捉到的特征电网当然绘制大量点的最佳方式是什么?
中,用户可以设置捕捉点之间的距离,所以,如果我们有一个大小为1024 x 1024的画布,每个点之间有5个像素,我们将有大约41775个点!
在画布上渲染大量点的建议方法是什么?我们需要它尽可能快。
WPF没有直接的方法在画布上绘制像素。实现它的最佳方法是使用Image和WriteableBitmap源代码。看看下面的代码。它有两个函数:drawGrid1和drawGrid2。在我的机器上,第一个函数(绘制椭圆元素)需要6秒。后者的功能需要50毫秒。
下面的代码仅用于说明。您可以缓存WritebaleBitmap,并且您应该敏感(如果您的场景需要)更改宽度或高度(或者,只需创建一个非常大的位图)。如果你需要更多的性能,并且你可以使用不安全的代码,你可以调用WritebaleBitmap.Lock,然后获得WriteableBitmap.BackBuffer,并手动修改后台缓冲区。最后,调用WriteableBitmap.AddDirtyBuffer来使整个矩形失效。如果你的Grid只有两种颜色,你也可以通过使用调色板来获得更高的性能。
更多WriteableBitmap的:http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap(VS.85).aspx
XAML:
<Window
x:Class="SO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="1000" Width="1000"
Title="SO Sample"
Loaded="Window_Loaded"
>
<Canvas x:Name="x_canvas">
<Border Canvas.Left="4" Canvas.Right="4" Width="120" Height="32" Background="White" >
<TextBlock x:Name="x_txt" VerticalAlignment="Center" />
</Border>
</Canvas>
</Window>
代码背后:
private void Window_Loaded(object sender, RoutedEventArgs e) {
DateTime start = DateTime.Now;
//drawGrid1();
drawGrid2();
DateTime end = DateTime.Now;
TimeSpan span = end - start;
x_txt.Text = span.ToString();
}
private void drawGrid2() {
// Create a new image
Image img = new Image();
RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.NearestNeighbor);
RenderOptions.SetEdgeMode(img, EdgeMode.Aliased);
// Add this image to the canvas
x_canvas.Children.Add(img);
int width = (int)x_canvas.ActualWidth;
int height = (int)x_canvas.ActualHeight;
// Create the bitmap, and set
WriteableBitmap wb = new WriteableBitmap(
width,
height,
96, 96,
PixelFormats.Bgra32,
null
);
img.Source = wb;
img.Stretch = Stretch.None;
img.HorizontalAlignment = HorizontalAlignment.Left;
img.VerticalAlignment = VerticalAlignment.Top;
Canvas.SetZIndex(img, -100);
// Each "dot" is 2x2 rectangle
Int32Rect rect = new Int32Rect(0, 0, 2, 2);
int size = rect.Width * rect.Height * 4;
byte[] pixels = new byte[ size ];
// Setup the pixel array
for(int i=0; i<rect.Height*rect.Width; ++i) {
pixels[ i*4 + 0 ] = 255; // Blue
pixels[ i*4 + 1 ] = 0; // Green
pixels[ i*4 + 2 ] = 0; // Red
pixels[ i*4 + 3 ] = 255; // Alpha
}
wb.WritePixels(rect, pixels, rect.Width*4, 0);
int step = 5;
for(int r = 0; r<height; r+=step) {
for(int c = 0; c<width; c+=step) {
rect.X = c;
rect.Y = r;
wb.WritePixels(rect, pixels, rect.Width*4, 0);
}
}
}
private void drawGrid1() {
int step = 10;
for(int i=0; i<1024; i+=step) {
for(int j=0; j<1024; j+=step) {
Ellipse l = new Ellipse();
if(i%100==0 && j%100==0) {
l.Width = 4;
l.Height = 4;
}
else {
l.Width = 2;
l.Height = 2;
}
l.Fill = new SolidColorBrush(Colors.Black);
Canvas.SetTop(l, i);
Canvas.SetLeft(l, j);
Canvas.SetZIndex(l, -100);
this.x_canvas.Children.Add(l);
}
}
}