I'm having a problem with the computer screen stream with C #, I already did the software where the server created a TCP socket and the client sent a print of it in Bitmap form. But the problem with this method was that with a lot of client connected (5 or more) the software was reading a lot, besides, there was a lot of delay. I tried with UDP also with the same failure. Is there any method to accomplish this project somehow with C #, or only with lower level language like C and C ++?
EDIT 01:
Following the idea of a colleague ai Gypsy Morrison Mendez I decided to do a test where I take several screenshot with DirectX because it is much faster than a method that I used previously. I modified a code that I found on the net to get only what changes in the second print, because what I found it combined the differences and made a very strange image. The problem I have now is how I do using only what was changed in the image to update the server image. For if I send the PictureBox to display only what changed the screen would be mostly white.
using SlimDX.Direct3D9;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StreamScreen
{
public partial class Form1 : Form
{
DxScreenCapture sc;
Thread _t1;
Bitmap older;
public Form1(){
InitializeComponent();
sc = new DxScreenCapture();
/*Surface s = sc.CaptureScreen();
Bitmap _b1 = new Bitmap(SlimDX.Direct3D9.Surface.ToStream(s, SlimDX.Direct3D9.ImageFileFormat.Bmp));
Thread.Sleep(1000);
s = sc.CaptureScreen();
Bitmap _b2 = new Bitmap(SlimDX.Direct3D9.Surface.ToStream(s, SlimDX.Direct3D9.ImageFileFormat.Bmp));
Bitmap diff = PixelDiff(_b1, _b2);
setImage(diff, _b1, _b2);*/
Surface s = sc.CaptureScreen();
older = new Bitmap(SlimDX.Direct3D9.Surface.ToStream(s, SlimDX.Direct3D9.ImageFileFormat.Bmp));
_t1 = new Thread(new ThreadStart(capture));
_t1.Start();
}
private void setImage(Bitmap bitmap, Bitmap _b1, Bitmap _b2)
{
if(pictureBox1.InvokeRequired){
this.Invoke((MethodInvoker)delegate{
pictureBox1.Image = bitmap;
pictureBox2.Image = _b1;
pictureBox3.Image = _b2;
});
}else{
pictureBox1.Image = bitmap;
pictureBox2.Image = _b1;
pictureBox3.Image = _b2;
}
}
private void capture() {
while(true){
Surface s = sc.CaptureScreen();
Bitmap _b1 = new Bitmap(SlimDX.Direct3D9.Surface.ToStream(s, SlimDX.Direct3D9.ImageFileFormat.Bmp));
Bitmap diff = PixelDiff(older, _b1);
setImage(diff, _b1, older);
older = _b1;
//setImage(new Bitmap(SlimDX.Direct3D9.Surface.ToStream(s, SlimDX.Direct3D9.ImageFileFormat.Bmp)));
}
}
unsafe Bitmap PixelDiff(Bitmap a, Bitmap b){
Bitmap output = new Bitmap(a.Width, a.Height, PixelFormat.Format32bppArgb);
Rectangle rect = new Rectangle(Point.Empty, a.Size);
using (var aData = a.LockBitsDisposable(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb))
using (var bData = b.LockBitsDisposable(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb))
using (var outputData = output.LockBitsDisposable(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb))
{
byte* aPtr = (byte*)aData.Scan0;
byte* bPtr = (byte*)bData.Scan0;
byte* outputPtr = (byte*)outputData.Scan0;
int len = aData.Stride * aData.Height;
for (int i = 0; i < len; i++){
// For alpha use the average of both images (otherwise pixels with the same alpha won't be visible)
/*if ((i + 1) % 4 == 0){
//*outputPtr = (byte)((*aPtr + *aPtr) / 2);
*outputPtr = (byte)~(*aPtr ^ *bPtr);
}else{
*outputPtr = (byte)(*aPtr ^ *bPtr);
}*/
/* inicio da adaptacao tecnica */
byte bb = (byte)~(*aPtr ^ *bPtr);
if (bb != ((byte)~(*aPtr ^ *aPtr))){
*outputPtr = *bPtr;
}else
*outputPtr = (byte)~(*aPtr ^ *bPtr);
/*fim da adaptacao tecnica */
outputPtr++;
aPtr++;
bPtr++;
}
}
return output;
}
}
}
static class Extensions
{
public static DisposableImageData LockBitsDisposable(this Bitmap bitmap, Rectangle rect, ImageLockMode flags, PixelFormat format)
{
return new DisposableImageData(bitmap, rect, flags, format);
}
public class DisposableImageData : IDisposable
{
private readonly Bitmap _bitmap;
private readonly BitmapData _data;
internal DisposableImageData(Bitmap bitmap, Rectangle rect, ImageLockMode flags, PixelFormat format)
{
//bitmap.("bitmap");
_bitmap = bitmap;
_data = bitmap.LockBits(rect, flags, format);
}
public void Dispose()
{
_bitmap.UnlockBits(_data);
}
public IntPtr Scan0
{
get { return _data.Scan0; }
}
public int Stride
{
get { return _data.Stride; }
}
public int Width
{
get { return _data.Width; }
}
public int Height
{
get { return _data.Height; }
}
public PixelFormat PixelFormat
{
get { return _data.PixelFormat; }
}
public int Reserved
{
get { return _data.Reserved; }
}
}
}
EDIT 02:
I was able to merge two images using the following command.
Bitmap diff = PixelDiff(_b1, _b2);
using (Graphics grfx = Graphics.FromImage(_b1)){
grfx.DrawImage(diff, new System.Drawing.Rectangle(0, 0, _b1.Width, _b1.Height));
}
But I found another problem, the image that brings only what has different is with the white background, and when I draw over white replace what has not changed yet. Does anyone know how to turn this white into transparent?