I'm working on a screen sharing project ,and i recieve a small blocks of image from a Socket constantly and need to update them on a certain initial dekstop bitmap i have.
Basically i constantly read data from socket(data which is stored as jpeg image) ,using Image.FromStream() to retrieve the image and copying the recieved block pixels to the full primary bitmap(at a specific position X and Y which i also get from the socket)- that's how the initial image gets updated. But then comes the part where i need to display it on a Picturebox
I handle the Paint event and redrawing it all again-the entire inital image,which is pretty big(1920X1080 in my case).
This is my code:
private void MainScreenThread()
{
ReadData();//reading data from socket.
initial = bufferToJpeg();//first intial full screen image.
pictureBox1.Paint += pictureBox1_Paint;//activating the paint event.
while (true)
{
int pos = ReadData();
x = BlockX();//where to draw :X
y = BlockY();//where to draw :Y
Bitmap block = bufferToJpeg();//constantly reciving blocks.
Draw(block, new Point(x, y));//applying the changes-drawing the block on the big initial image.using native memcpy.
this.Invoke(new Action(() =>
{
pictureBox1.Refresh();//updaing the picturebox for seeing results.
// this.Text = ((pos / 1000).ToString() + "KB");
}));
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
lock (initial)
{
e.Graphics.DrawImage(initial, pictureBox1.ClientRectangle); //draws at picturebox's bounds
}
}
Because i'm aiming at high speed performance(it's kind of a real-time project) , i would like to know if there isn't any method to draw current recieved the block itself on the picturebox instead of drawing the whole initial bitmap again-which seems very inefficient to me...
This is my drawing method(works extremly fast, copying block with memcpy):
private unsafe void Draw(Bitmap bmp2, Point point)
{
lock (initial)
{
BitmapData bmData = initial.LockBits(new Rectangle(0, 0, initial.Width, initial.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, initial.PixelFormat);
BitmapData bmData2 = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp2.PixelFormat);
IntPtr scan0 = bmData.Scan0;
IntPtr scan02 = bmData2.Scan0;
int stride = bmData.Stride;
int stride2 = bmData2.Stride;
int Width = bmp2.Width;
int Height = bmp2.Height;
int X = point.X;
int Y = point.Y;
scan0 = IntPtr.Add(scan0, stride * Y + X * 3);//setting the pointer to the requested line
for (int y = 0; y < Height; y++)
{
memcpy(scan0, scan02 ,(UIntPtr)(Width * 3));//copy one line
scan02 = IntPtr.Add(scan02, stride2);//advance pointers
scan0 = IntPtr.Add(scan0, stride);//advance pointers//
}
initial.UnlockBits(bmData);
bmp2.UnlockBits(bmData2);
}
}
Here are some examples of a full primary bitmap,and other small blocks i'm getting and need to draw over the full one.
small block:
I'm getting large amount of small blocks per second(30~40) somtimes their bounds are really small(rectangle of 100X80 pixels for example) so redrawing the entire bitmap again is not necessary...Rapidly Refreshing a full screen image would kill the performance...
I hope my explaination was clear.
Looking forward for an answer.
Thanks.




Control.CreateGraphicsto get the graphics from the picture box and then draw on top of it withGraphics.DrawImage(image, x, y)so you avoid redrawing the intial image. But I don't know how efficient it is, it might be blitting it anyway under the hood. Might be worth doing some performance testing. - Stefano d'Antonio