2012-03-09 46 views
13

sau một ngày toàn bộ thử nghiệm tôi đã đưa ra mã này, mà chụp màn hình hiện tại sử dụng DirectX (SlimDX) và lưu nó vào một tập tin:Saving Surface to Bitmap và tối ưu hóa chụp ảnh màn hình DirectX trong C#

Device d; 

public DxScreenCapture() 
{ 
    PresentParameters present_params = new PresentParameters(); 
    present_params.Windowed = true; 
    present_params.SwapEffect = SwapEffect.Discard; 
    d = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.SoftwareVertexProcessing, present_params); 
} 

public Surface CaptureScreen() 
{ 
    Surface s = Surface.CreateOffscreenPlain(d, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, Format.A8R8G8B8, Pool.Scratch); 
    d.GetFrontBufferData(0, s); 
    return s; 
} 

sau đó, tôi làm như sau:

DxScreenCapture sc = new DxScreenCapture(); 

..code đây

private void button1_Click(object sender, EventArgs e) 
    { 

     Stopwatch stopwatch = new Stopwatch(); 

     // Begin timing 
     stopwatch.Start(); 

     Surface s = sc.CaptureScreen(); 
     Surface.ToFile(s, @"c:\temp\test.png", ImageFileFormat.Png); 

     s.Dispose(); 

     stopwatch.Stop(); 

     textBox1.Text = ("Elapsed:" + stopwatch.Elapsed.TotalMilliseconds); 
    } 

các kết quả là:

0. khi tôi không lưu bề mặt: avg. thời gian trôi qua: 80-90ms

1. khi tôi cũng lưu bề mặt thành tệp BMP: định dạng: ImageFileFormat.Bmp, avg. thời gian trôi qua: 120 mili giây, kích thước tệp: 7mb

2. khi tôi cũng lưu bề mặt vào tệp PNG: định dạng: ImageFileFormat.Png, avg. thời gian trôi qua: 800ms, kích thước: 300KB

Các câu hỏi là:

1. Có thể tối ưu hóa khả năng chụp ảnh hiện tại? Theo bài viết này - Chụp ảnh màn hình Directx phải nhanh hơn GDI. Đối với tôi, GDI thường mất 20ms để có được một "Bitmap", trong khi phải mất 80ms để có được "Surfare" bằng cách sử dụng DX (cả hai mà không lưu).

http://www.codeproject.com/Articles/274461/Very-fast-screen-capture-using-DirectX-in-Csharp

2a. Làm thế nào để lưu Surface thành định dạng hình ảnh PNG nhanh hơn? Khi tôi lưu bề mặt thành tệp BMP 7MB, thời gian sẽ mất gần 6 lần ít hơn, khi tôi lưu cùng một bề mặt vào tệp PNG 300kb ..

2b. Có thể lưu Bề mặt trực tiếp vào Bitmap để không phải tạo các tệp tạm thời không?

Vì vậy, tôi không phải làm như sau: Bề mặt -> tệp hình ảnh; tệp hình ảnh mở -> bitmap;, nhưng thay vào đó: Bề mặt -> bitmap

là tất cả bây giờ. Tôi sẽ sẵn sàng chấp nhận bất kỳ lời khuyên nào, cảm ơn!

Edit:

Chỉ cần giải quyết 2b bằng cách thực hiện:

Bitmap bitmap = new Bitmap(SlimDX.Direct3D9.Surface.ToStream(s, SlimDX.Direct3D9.ImageFileFormat.Bmp)); 

Edit2:

Surface.ToFile(s, @"C:\temp\test.bmp", ImageFileFormat.Bmp); 
Bitmap bitmap = new Bitmap(@"C:\temp\test.bmp"); 

nhanh hơn:

Bitmap bitmap = new Bitmap(SlimDX.Direct3D9.Surface.ToStream(s, SlimDX.Direct3D9.ImageFileFormat.Bmp)); 

bởi 100 ms !!!Vâng, tôi không thể tin vào mắt mình nữa;) Tôi không thích ý tưởng tạo tập tin tạm thời, nhưng tăng hiệu suất 50% (100-200ms thay vì 200-300 +) là một điều rất tốt.

+0

Tôi nghĩ png có thể nén nhanh hơn 800 mili giây. Hãy thử nếu nó là nhanh hơn nếu bạn lần đầu tiên ghi vào một bộ nhớ. –

Trả lời

0

nếu bạn không muốn sử dụng thư viện SlimDX bạn cũng có thể thử

public Bitmap GimmeBitmap(Surface s) 
{ 
    GraphicsStream gs = SurfaceLoader.SaveToStream(ImageFileFormat.Bmp, s); 
    return new Bitmap(gs); 
} 

và thử tương tự cho .png - Tôi không thử nghiệm hiệu suất nhưng nó phải thể nhanh hơn so với sử dụng đĩa tạm thời nộp :)

và như đối với câu hỏi 1 - cố gắng một lần duy nhất tạo bề mặt và hơn trên tất cả các ảnh chụp màn hình chỉ đưa vào dữ liệu đệm nó thành thiết bị và tạo bitmap

d.GetFrontBufferData(0, s); 
return new Bitmap(SurfaceLoader.SaveToStream(ImageFileFormat.Bmp, s)); 

điều này sẽ giúp bạn tiết kiệm thời gian :)

+0

SlimDX không hoạt động theo cách đó .. Tôi nhận được rất nhiều lỗi với "SurfaceLoader" (Tên 'SurfaceLoader' không tồn tại trong ngữ cảnh hiện tại). Tôi nghĩ rằng tôi có một cái gì đó để làm với "Managed DirectX" thư viện, mà không được hỗ trợ trong .net 4 vì vậy tôi không thể thêm tài liệu tham khảo. Nó giống như C# VisualStudion không biết những gì "SurfaceLoader" và "GraphicsStream" là .. – Alex

+0

P.S. Tôi đã cài đặt DX SDK nhưng không may là không có tham chiếu "Managed DX" trong VS2010. Sau khi một số đào tôi phát hiện ra rằng chúng tôi không còn (tháng 6 năm 2010 SDK +) có thể sử dụng DX, tất cả những gì còn lại là SlimDX (wrapper) hoặc XNA (được sử dụng chủ yếu cho game dev). – Alex

+1

SurfaceLoader không có trong SlimDX nhưng trong bản gốc DirectX (Microsoft.DirectX.Direct3D.SurfaceLoader) và nó hoạt động trên .NET4 ... Và nếu bạn không thể tìm thấy dll cho mã được quản lý hãy xem "C: \ Windows \ Microsoft.NET \ DirectX cho mã được quản lý ". – Runaurufu

Các vấn đề liên quan