2012-03-11 73 views
1

我们正在建设一个图形应用程序,我们要画在画布上的背景点,因为我们有像捕捉到的特征电网当然绘制大量点的最佳方式是什么?

中,用户可以设置捕捉点之间的距离,所以,如果我们有一个大小为1024 x 1024的画布,每个点之间有5个像素,我们将有大约41775个点!

在画布上渲染大量点的建议方法是什么?我们需要它尽可能快。

回答

4

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); 
     } 
    } 
} 
相关问题