después de todo un día de pruebas me ocurrió con este código, que captura la pantalla actual usando DirectX (SlimDX) y lo guarda en un archivo:Ahorro de superficie de mapa de bits y la optimización de la captura de pantalla de DirectX en 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;
}
entonces hago lo siguiente:
DxScreenCapture sc = new DxScreenCapture();
..code aquí
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);
}
el los resultados son:
0. cuando no guardo la superficie: avg. tiempo transcurrido: 80-90ms
1. cuando también guardo el archivo Surface to BMP: formato: ImageFileFormat.Bmp, avg. tiempo transcurrido: 120ms, tamaño de archivo: 7mb
2. cuando también guardo el archivo Surface to PNG: format: ImageFileFormat.Png, avg. Tiempo transcurrido: 800ms, tamaño de archivo: 300 KB
Las preguntas son:
1. ¿Es posible optimizar la captura de la imagen actual? Según este artículo, la captura de pantalla de Directx debe ser más rápida que GDI. Para mí, GDI usualmente toma 20 ms para obtener un "Bitmap", mientras que toma 80ms para obtener "Surfare" usando DX (ambos sin guardar).
http://www.codeproject.com/Articles/274461/Very-fast-screen-capture-using-DirectX-in-Csharp
2a. ¿Cómo guardar formato de imagen de Superficie a PNG más rápido? Cuando guardo la superficie en un archivo BMP de 7mb, me lleva casi 6 veces menos tiempo que cuando guardo la misma superficie en un archivo PNG de 300 kb ..
2b. ¿Es posible guardar Surface directamente en Bitmap para que no tenga que crear archivos temporales?
Así que no tengo que hacer lo siguiente: Superficie -> archivo de imagen; archivo de imagen abierto -> mapa de bits;, pero en su lugar: Superficie -> mapa de bits
eso es todo por ahora. Acepto gustosamente cualquier consejo, ¡gracias!
Editar:
Sólo resuelto 2b haciendo:
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");
es más rápido que:
Bitmap bitmap = new Bitmap(SlimDX.Direct3D9.Surface.ToStream(s, SlimDX.Direct3D9.ImageFileFormat.Bmp));
por 100 ms !!!Sí, no podía creer lo que veía también;) No me gusta la idea de creación temporal de archivos, pero un 50% de aumento en el rendimiento (100-200 ms en vez de 200-300 +) es algo muy bueno.
Creo que png puede comprimir más rápido que 800 ms. Pruebe si es más rápido si primero escribe en un flujo de memoria. –