privatevoid 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"); })); } }
privateunsafevoid 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
privatevoid MainScreenThread() { ReadData();//reading data from socket. initial = bufferToJpeg();//first intial full screen image. pictureBox1.Paint+= pictureBox1_Paint;//activating the paint event. // The update action Action<Rectangle> updateAction = imageRect => { var viewRect = GetViewRect(); var scaleX =(float)viewRect.Width/ initial.Width; var scaleY =(float)viewRect.Height/ initial.Height; // Make sure the target rectangle includes the new block var targetRect = Rectangle.FromLTRB( (int)Math.Truncate(imageRect.X* scaleX), (int)Math.Truncate(imageRect.Y* scaleY), (int)Math.Ceiling(imageRect.Right* scaleX), (int)Math.Ceiling(imageRect.Bottom* scaleY)); pictureBox1.Invalidate(targetRect); pictureBox1.Update(); };
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.
// Invoke the update action, passing the updated block rectangle this.Invoke(updateAction, new Rectangle(x, y, block.Width, block.Height)); } }
privatevoid pictureBox1_Paint(object sender, PaintEventArgs e) { lock(initial) { var viewRect = GetViewRect(); var scaleX =(float)initial.Width/ viewRect.Width; var scaleY =(float)initial.Height/ viewRect.Height; var targetRect = e.ClipRectangle; var imageRect =new RectangleF(targetRect.X* scaleX, targetRect.Y* scaleY, targetRect.Width* scaleX, targetRect.Height* scaleY); e.Graphics.DrawImage(initial, targetRect, imageRect, GraphicsUnit.Pixel); } }
唯一棘手的部分是确定缩放的矩形,尤其是用于无效的矩形,因为需要进行浮点到 int 的转换,所以我们确保它最终比需要的大一点,但不能少。