Wednesday, April 13, 2016

C# CopyFromScreen Problems

Leave a Comment

for starters, i know there are already threads about this, but i cannot seem to find an answer which fits my needs and after about 4 months of research i have decided to ask a question here.

For a project i need to make screenshots cyclical. These screenshots are made based on the user parameters whether to use a display or not or the area the screenshot is taken from. (This means that it could be that the screenshot is only made from the half of the display or so.)

The thing is, its slow... Yes i know, if i want to do it faster i have to use this library or that directx and so on. But: Neither do i know directx, nor i could find an opensource lirary that is capable of returning a bitmap-data-stripe (and realy is faster). Also i have tried out some tutorials for making screenshots with directx but wasn't able to get it to run properly.

About the performance thing, when using only 1 display, the performance isn't actually that bad. (Taking a screenshot is about 40ms for 1440p resolution)

The realy bad thing is DWM. (I guess its dwm). When making screenshots everything acts normaly except when draging around windows. Like, watching a video on youtube is fine. But when i start to move around windows, its slow as hell. Is seems that the draging animation is blocked while i take a screenshot.

Now for to my question (or questions):

  • Someone does know this behavior and/or has an solution?
  • What are my alternatives (serious alternatives. i mean like 3x 1440p in 30ms alternatives)

Edit: This is the method i use to make screenshots

public void makeScreenshot(int i) {     if (DisplayList[i].UseDisplay)     {         // copy from screen into graphics         this.graphicsList[i].CopyFromScreen(Screen.AllScreens[DisplayList[i].DisplayNo].Bounds.X, AreaTop[i], 0, 0, sizeList[i], CopyPixelOperation.SourceCopy);         // bitmapData is filled with LockBits from Screenshotted Bmp         bitmapData[i] = this.bitmapList[i].LockBits(rect[i], ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);         // Pointer set to first pixel of Bitmap data         Iptr[i] = bitmapData[i].Scan0;         // Now Marshalcopy bitmapData to Pixel Array         Marshal.Copy(Iptr[i], Pixels[i], 0, Pixels[i].Length);         // Finaly unlock bits of Bitmap for next run         this.bitmapList[i].UnlockBits(bitmapData[i]);     } } 

1 Answers

Answers 1

There is a quite simple and stable solution I've used for screen capturing and live streaming, but it do use an external library. May be you can spend several minutes to look at this. I got 6-15ms for 1600x900 screen capture. So, u need -

  1. Mirage Driver, that you can get here: http://www.demoforge.com/dfmirage.htm
  2. this sample application: http://www.demoforge.com/sdk/MirrSharp.zip

I have modified the code for the sample solution to display the screen in PictureBox control every time the desktop changed event is fired. Something like this:

private void _mirror_DesktopChange(object sender, DesktopMirror.DesktopChangeEventArgs e)     {         Trace.WriteLine(string.Format("Changed rect is {0},{1} ; {2}, {3} ({4})", new object[] { e.x1, e.y1, e.x2, e.y2, e.type }));          var perf = new Stopwatch();         perf.Start();         var bitmap = _mirror.GetScreen();         perf.Stop();          label1.Invoke(new Action<Int64>(i =>         {             pictureBox1.Image = bitmap;             label1.Text = i.ToString();         }), perf.ElapsedMilliseconds);     } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment