我正在开发一个屏幕共享项目,不断地从Socket
接收小块图像数据,并需要将它们更新到我已经拥有的某个初始桌面位图上。
基本上,我不断地从socket中读取数据(存储为jpeg图像),使用Image.FromStream()
来获取这些图像,然后将接收到的块像素复制到完整的主位图上(在特定位置X
和Y
,我也从socket中获得)-这就是初始图像如何更新的。但之后我需要将其显示在Picturebox
上。
我处理了Paint
事件并重新绘制了整个初始图像,这相当大(在我的情况下为1920X1080)。
这是我的代码:
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
}
}
因为我追求高速性能(这是一个实时项目),我想知道除了重新绘制整个initial
位图(对我来说似乎非常低效)之外,是否有一种方法可以在picturebox上直接绘制当前接收到的块本身。 这是我的绘图方法(使用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);
}
}
以下是完整主位图和其他我正在获取并需要在完整主位图上绘制的小块的一些示例。
小块:
我每秒会获得大量的小块(30~40),有时它们的范围非常小(例如100X80像素的矩形),因此不必重新绘制整个位图...快速刷新全屏图像会影响性能...
希望我的说明清楚了。
期待回答。
谢谢。