2012-03-11 90 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); 
     } 
    } 
} 
相關問題