请教UDP分块发送图片问题(Delphi XE+Indy 10)
Delphi XE的IDE有个Bug,因此IdUDPServer控件及OnUDPRead事件只好在运行时生成。请不要见怪。
我是想通过UDP将Img1中修改的部分发送到服务端,并重画在Img2上。现在能做的是,可以获得需要发送的最小矩形,使用SendBuffer命令以TMemoryStream方式将其划分成最大1024个字节大小进行发送。
客户端以'_STARTIMG_'为表示开始,‘_END__IMG_'表示发送结束;
服务端接收到“_STARTIMG_”之后开始接收数据,每次直接通过MemRec.Write(Adata, size)写入全局变量MemRec(TMemoryStream)。
当服务端收到‘_END__IMG_'之后结束结果,将MemRec内容画到IMG2上。
现在,的问题是MemRec无法画到IMG2上,而MemOld则可以。但通过CompareMem命令发现,两者的内容是相同的。这一点实在就想不通了。
由于这是一个还没理清头绪的程序,我的表述可能很不清楚。如有需要,请跟贴,我再做详细说明。
//发送程序procedure TForm1.btn1Click(Sender: TObject);var mem: TMemoryStream; Buf: array [0..1023] of Char; pos, len: Integer; RecStr: String; TmpImg1, TmpImg2: TImage; BitBuf: TBytes;begin RectNew.Top:=0; RectNew.Left:=0; RectNew.Bottom:=rect.Bottom-rect.Top; RectNew.Right:=rect.Right-rect.Left; form1.Caption:=''; mem:= TMemoryStream.Create; TmpImg1:=TImage.Create(self); TmpImg1.Picture.Bitmap.Width:=RectNew.Right; TmpImg1.Picture.Bitmap.Height:=RectNew.Bottom; TmpImg1.Canvas.CopyRect(RectNew, img1.Canvas, rect); TmpImg1.Picture.Bitmap.SaveToStream(mem); MemOld.Free; MemOld:=TMemoryStream.Create; TmpImg2:=TImage.Create(self); TmpImg1.Picture.Bitmap.SaveToStream(MemOld); //mem 和 MemOld的内容均正确// MemOld.Position:=0; //通过下面三句可以把画正确地画到IMG2中// TmpImg2.Picture.Bitmap.LoadFromStream(MemOld); //为了与传输结果比较,此处的MemOld为一全局变量// img2.Canvas.CopyRect(rect, TmpImg2.Canvas, rectnew); if mem.Size>0 then begin idpclnt1.Send('_STARTIMG_'); pos:=0; while pos<mem.Size do begin len:=1024; if mem.Size-pos<1024 then len:=mem.Size-pos; mem.Read(buf, len); SetLength(BitBuf, len); Move(buf[1], BitBuf[0], Len); idpclnt1.SendBuffer(BitBuf); inc(pos, len); end; idpclnt1.Send('_END__IMG_'); end; Form1.Caption:=Form1.Caption+' end'; mem.Free; TmpImg1.Free; TmpImg2.Free;end;//接收程序procedure Tform1.UDPRead(AThread: TIdUDPListenerThread; AData: TArray<Byte>; ABinding: TIdSocketHandle);var str, str1, str2: string; size, i, flag: Integer; tmp: TImage; NewRect: TRect; just: Boolean;begin NewRect.Top:=0; NewRect.Left:=0; NewRect.Bottom:=rect.Bottom-rect.Top; NewRect.Right:=rect.Right-rect.Left; Flag:=1; Size:=Length(AData); if size=10 then begin SetLength(str, 10); for i := 1 to 10 do str[i]:=Char(AData[i-1]); if str='_STARTIMG_' then begin flag:=0; form1.Tag:=1; end; if str='_END__IMG_' then begin flag:=2; form1.Tag:=0; end; end; case flag of 0: begin form1.Caption:=Form1.Caption+'S_'; MemRec:=TMemoryStream.Create; form1.Caption:=Form1.Caption+'S_'; end; 2: begin form1.Caption:=Form1.Caption+'_E'; tmp:=TImage.Create(self); try MemRec.Position:=0; Form1.mmo1.Lines.Add(IntToStr(MemRec.Size)+ ' '+inttostr(MemOld.Size)) ; MemOld.Position:=0; //用MemOld可以正确地将需要的部分画到IMG2中 tmp.Picture.Bitmap.LoadFromStream(MemOld); img2.Canvas.CopyRect(rect, tmp.Canvas, NewRect);// MemRec.Position:=0; //用MemRec 不能 需要的部分画到IMG2中// tmp.Picture.Bitmap.LoadFromStream(MemRec);// img2.Canvas.CopyRect(rect, tmp.Canvas, NewRect); just:=CompareMem(MemRec.Memory,MemOld.Memory, MemOld.Size); //但内存比较的结果是MemOld与MemRec的内容完全相同 if just then form1.mmo1.Lines.Add(IntToStr(1)) else form1.mmo1.Lines.Add(IntToStr(0)); finally tmp.Free; MemRec.Free; end; form1.img2.Canvas.MoveTo(0, 0); form1.img2.Canvas.LineTo(30, 30); end; 1: if form1.tag=1 then begin MemRec.Write(Adata, size); form1.Caption:=Form1.Caption+' - '+inttostr(MemRec.Size); end; end;end;