C # Atualizar bitmap na caixa de imagem
Estou trabalhando em um projeto de compartilhamento de tela e recebo pequenos blocos de imagem de umSocket
constantemente e precisa atualizá-los em um determinado bitmap dekstop inicial que eu tenho.
Basicamente, leio constantemente dados do soquete (dados armazenados como imagem jpeg), usandoImage.FromStream()
recuperar a imagem e copiar os pixels do bloco recebidos para o bitmap primário completo (em uma posição específicaX
eY
que também recebo do soquete) - é assim que a imagem inicial é atualizada. Mas então vem a parte em que eu preciso exibi-lo em umPicturebox
Eu manejo oPaint
evento e redesenhar tudo de novo - toda a imagem inicial, que é bem grande (1920X1080 no meu caso).
Este é o meu código:
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
}
}
Como estou visando um desempenho de alta velocidade (é um projeto em tempo real), gostaria de saber se não existe um método para desenhar a corrente que recebeu o bloco na caixa de imagem em vez de desenhar o todoinitial
bitmap novamente - o que me parece muito ineficiente ... Esse é o meu método de desenho (funciona extremamente rápido, copiando bloco commemcpy
):
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);
}
}
Aqui estão alguns exemplos de um bitmap primário completo e outros pequenos blocos que estou recebendo e preciso desenhar sobre o completo.
Bitmap completo: bloco pequeno:
bloco pequeno:
Estou recebendo uma grande quantidade de pequenos blocos por segundo (30 ~ 40) às vezes seus limites são muito pequenos (retângulo de 100X80 pixels, por exemplo), portanto, não é necessário redesenhar todo o bitmap novamente ... Atualizar rapidamente uma imagem em tela cheia mataria o desempenho ...
Espero que minha explicação seja clara.
Ansioso por uma resposta.
Obrigado.