Я работаю над проектом совместного использования экрана, и я получаю небольшие блоки изображения из Socket
постоянно и должен обновлять их на определенном исходном растровом растровом, который у меня есть.
В основном я постоянно читаю данные из сокета (данные, которые хранятся как jpeg-изображение), используя Image.FromStream()
для извлечения изображения и копирования получаемых пикселов блока в полную первичную растровую карту (в определенной позиции X
и Y
который я также получаю из сокета) - то, как обновляется исходное изображение. Но затем приходит часть, где мне нужно отобразить ее на 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 bounds
}
}
Поскольку я нацелен на высокую скорость работы (это как проект в реальном времени), я хотел бы знать, нет ли какого-либо метода для того, чтобы нарисовать текущий полученный блок на картинке вместо того, чтобы рисовать весь initial
растровое изображение снова, что кажется мне очень неэффективным...
Это мой метод рисования (работает очень быстро, копируя блок с помощью 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 пикселей, например), поэтому перерисовка всего растрового изображения снова не требуется... Быстро Обновление полного экрана изображение убьет производительность...
Надеюсь, мое объяснение было ясным.
Ожидаем ответа.
Спасибо.