2012-03-24 7 views
5

İstemci penceresine (aynı boyutta) 1027 * 768 bitmap oluşturmam gerekiyor ve bu görevi tamamlamak için 10-15 ms'dan fazla olmam gerekiyor. bufferedGraphicsContect nesnesinden ayrılmış bufferedGraphics nesnesini kullanıyorum ve yine de büyük performans sorunlarına dikkat edin.İşaretçi manupilasyonu aracılığıyla arabellek grafik yüzeyine yazma

benim kopyalama işlemleri ve bulundu inanılmaz sonuçlar gerçekleştirmek için güvensiz kod kullanıyorum. Graphics/BufferedGraphics nesnelerinin, numaralı bellekte çizim yüzeyinin bir çeşit olması gerektiğini biliyorum. Marshal ya da başka bir güvensiz düşük seviyeli yöntem kullanarak bu yüzeye nasıl yazılacağı konusunda bana doğru yönlendirilebileceğini merak ediyordum.

Daha eski bir C# grafik uygulaması gerçekleştirme aşamasındayım. C# 'nin ağır grafikler için tasarlanmadığını ve GDI +' dan daha iyi araçların olduğunu biliyorum, maalesef bu lükslere sahip değilim.

Şimdiye kadar geldiğim şey buydu ... Ne kadar büyük bir kavrayış var.

byte[] _argbs = null; 
static readonly Bitmap _bmUnderlay = Properties.Resources.bg; 
static Bitmap _bmpRender = new Bitmap(1024, 768, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 
int bmpHeight = Properties.Resources.bg.Height; 
int bmpWidth = Properties.Resources.bg.Width; 
static BufferedGraphicsContext _bgc = new BufferedGraphicsContext(); 

internal unsafe void FillBackBuffer(Point cameraPos) 
{ 
     // lock up the parts of the original image to read (parts of it) 
     System.Drawing.Imaging.BitmapData bmd = _bmUnderlay.LockBits(
      new Rectangle(cameraPos.X, cameraPos.Y, 1024, 768), 
      System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 
     // get the address of the first line. 
     IntPtr ptr = bmd.Scan0; 

     //if (_argbs == null || _argbs.Length != bmd.Stride * bmd.Height) 
     // _argbs = new byte[bmd.Stride * bmd.Height]; 
     if (_argbs == null || _argbs.Length != 1024 * 3 * 768) 
      _argbs = new byte[1024 * 3 * 768]; 

     // copy data out to a buffer 
     Marshal.Copy(ptr, _argbs, 0, 1024 * 3 * 768); 

     _bmUnderlay.UnlockBits(bmd); 

     // lock the new image to write to (all of it) 
     System.Drawing.Imaging.BitmapData bmdNew = _bmpRender.LockBits(
      new Rectangle(0, 0, 1024, 768), 
      System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 
     // copy data to new bitmap 
     Marshal.Copy(_argbs, 0, bmdNew.Scan0, 1024 * 3 * 768); 
     _bmpRender.UnlockBits(bmdNew); 
} 

private unsafe void _btnGo_Click(object sender, EventArgs e) 
{ 
    // less than 2 ms to complete!!!!!!!! 
    FillBackBuffer(new Point()); 

    using (BufferedGraphics bg = _bgc.Allocate(CreateGraphics(), ClientRectangle)) 
    { 
     System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); 
     sw.Start(); 
     ///// 
     /// 
     // This method takes over 17 ms to complete 
     bg.Graphics.DrawImageUnscaled(_bmpRender, new Point()); 
     // 
     /// 
     ///// 
     sw.Start(); 
     this.Text = sw.Elapsed.TotalMilliseconds.ToString(); 

     bg.Render(); 
    } 
} 

DÜZENLEME:

ben işaretçiler kullanarak, preferrably Grafik yüzey hafızasına yazma, Graphics.DrawImage() için düşük seviyeli bir alternatif arıyorum bahsetmek unuttunuz? Tekrar teşekkürler

+0

Kod girintisini düzenledim ve sonunda bir parantezli kaşlı ayraç var gibi görünüyor. Bu benim sorunumda bir sorun olsaydı, lütfen benim geri dönme – puk

+0

Yardım için teşekkürler, brace benim de benim vida bir parçası olduğunu düşünüyorum, üzgünüm :) – OverMars

cevap

3

Bitmap'in piksel biçimine dikkat edin. Standart 32bpp video donanımında, Format32bppPArgb diğerlerinden herhangi birine göre on kat daha hızlı çalışır. Çünkü piksellerin herhangi bir çeviri ihtiyacı yoktur. Kullandığınız 24bpp formatının artık 32bpp'ye genişletilmesi gerekiyor ve bu da ücretsiz gelmiyor. PArgb'nin P'sini atlamayın ve alfa değerini 255'e kodunuzda unutma.

BufferedGraphics kullanımı fishy btw'dir. OnPaint yönteminde her zaman ücretsiz olanı kullanmalısınız. Ve bu kadar hızlı karıştığınız için muhtemelen bir şeye ihtiyacınız yok. Bu otomatik 2x hızlanma.

+0

Bu beklenenden daha fazla yardımcı oldu, teşekkürler Ben bufferedGraphics kullanıyorum çünkü istemci penceresini doldurduktan sonra, birkaç başka bitmap katmanı ekliyorum! :(C# sooo bu anlama gelmez ... – OverMars

+0

Hmm, dil ile ilgili bir şey yok. Sadece ideal bir grafik kütüphanesi kullanıyorsunuz. GDI + çok uyumludur ama eğer isterseniz mükemmel bir Video belleğini yöneten kütüphane DirectX örneğin, SlimDX'in bunun için yönetilen bir sarıcı vardır. –