hook gdi绘图API函数的方法或者差值传输图像的算法(200分)

  • 主题发起人 主题发起人 zhaokaien
  • 开始时间 开始时间
Z

zhaokaien

Unregistered / Unconfirmed
GUEST, unregistred user!
能提供线索的50分
能提供流程的100分
能提供demo的200分

邮箱:xyzw-0016@163.com
qq:99292746
 
两张图片比较,一般都使用的象素遍历吧~不过象素遍历有好几种方法,有快有慢
 
楼上的兄弟能提供点代码吗??
 
楼主是用在远程抓屏吗?
 
对,网中戏能否提供点资料
 
如果远程传输,跑不掉要使用分块处理
 
能否给点代码!!
 
偶简单写了个两张图片象素遍历的函数,GetImg(旧图,新图)返回一个处理过的图

const
MaxPixelCount=32768;
type
PRGBArray=^TRGBArray;
TRGBArray=array [0..MaxPixelCount] of TRGBTriple;

function GetImg(ImgOld,ImgNew:TBitmap):TBitmap;
var
i,j:Integer;
TmpBmp1:TBitmap;
Row1,Row2,DestRow:PRGBArray;
begin
Result:=TBitmap.Create;
TmpBmp1:=TBitmap.Create;
try
TmpBmp1.Width:=ImgOld.Width;
TmpBmp1.Height:=ImgOld.Height;
ImgOld.PixelFormat:=pf24bit;
TmpBmp1.PixelFormat:=ImgOld.PixelFormat;

for i:=0 to TmpBmp1.Height-1 do
begin
Row1:=ImgOld.ScanLine;
Row2:=ImgNew.ScanLine;
DestRow:=TmpBmp1.ScanLine;
for j:=0 to TmpBmp1.Width-1 do
begin
if (Row1[j].rgbtBlue<>Row2[j].rgbtBlue) or
(Row1[j].rgbtGreen<>Row2[j].rgbtGreen) or
(Row1[j].rgbtRed<>Row2[j].rgbtRed) then
begin
DestRow[j].rgbtBlue:=Row2[j].rgbtBlue;
DestRow[j].rgbtGreen:=Row2[j].rgbtGreen;
DestRow[j].rgbtRed:=Row2[j].rgbtRed;
end;
end;
end;
Result.Assign(TmpBmp1);
img3.Stretch:=True;
finally
TmpBmp1.Free;
end;
end;
 
cb2000已经可以得到50分了,
还有给代码的吗
 
我也来看看。
 
TO
cb20000
你的差图也是位图。大小不变。怎样压缩啊
 
网中戏 说的有道理,
不知道网中戏有没有什么可以提示的代码,我知道一些原理,可操作性上有待提高
 
这个有一个比较图像的简单方案:用scanline得到行指针,然后给你提供一个函数来比较行的差别,是用MMX指令优化过的。

function GetDataDifferenceMMX(SData:array of pbyteArray;Sx0,Sy0,Width,Height:integer;
TData:array of pbyteArray;Tx0,Ty0:integer):integer;
var
i,j : integer;
Ps,pt : pbyteArray;
width8 : integer;
width8sub24 : integer;
width24 : integer;
begin

result:=0;
width8:=(width div 8);
width24:=(width div 24);
width8sub24:=width8-width24*3;

if width24>0 then
begin
for i:=0 to Height -1 do
begin
ps:= Pointer(integer(Sdata[i+Sy0])+Sx0);
pt:= Pointer(integer(TData[i+Ty0])+Tx0);

asm

push ebx
push esi
push edi

xor eax,eax
mov esi,ps
mov edi,pt
pxor mm3,mm3

mov ecx,width24
@@StartFor:

//{按24字节边界对齐处理
movq mm0,[esi]
movq mm1,[edi]

movq mm2,mm0
psubusb mm0,mm1
psubusb mm1,mm2
por mm0,mm1

movq mm4,[esi+8]
movq mm5,[edi+8]

movq mm2,mm4
psubusb mm4,mm5
psubusb mm5,mm2
por mm4,mm5

movq mm6,[esi+16]
movq mm7,[edi+16]

movq mm2,mm6
psubusb mm6,mm7
psubusb mm7,mm2
por mm6,mm7

//add all
movq mm1,mm0
punpcklbw mm0,mm3
punpckhbw mm1,mm3
pmaddwd mm0,mm0
pmaddwd mm1,mm1
paddd mm0,mm1

movq mm5,mm4
punpcklbw mm4,mm3
punpckhbw mm5,mm3
pmaddwd mm4,mm4
pmaddwd mm5,mm5
paddd mm4,mm5

movq mm7,mm6
punpcklbw mm6,mm3
punpckhbw mm7,mm3
pmaddwd mm6,mm6
pmaddwd mm7,mm7
paddd mm6,mm7

//
paddd mm0,mm4
paddd mm0,mm6

movd edx,mm0
punpckhdq mm0,mm3
add eax,edx
movd ebx,mm0
add eax,ebx

add esi,24
add edi,24
//}

dec ecx
jnz @@StartFor
@@EndFor:

add result,eax

pop edi
pop esi
pop ebx

end;
end;

end;

//(*
if width8sub24>0 then
begin
for i:=0 to Height -1 do
begin
ps:= Pointer(integer(Sdata[i+Sy0])+Sx0+width24*24);
pt:= Pointer(integer(TData[i+Ty0])+Tx0+width24*24);

asm

push ebx
push esi
push edi

xor eax,eax
mov esi,ps
mov edi,pt
pxor mm3,mm3

mov ecx,width8sub24
@@StartFor:
//{按8字节边界对齐处理
movq mm0,[esi]
movq mm1,[edi]

//abs(a-b)
movq mm2,mm0
psubusb mm0,mm1
psubusb mm1,mm2
por mm0,mm1

//add all
movq mm1,mm0
punpcklbw mm0,mm3
punpckhbw mm1,mm3
pmaddwd mm0,mm0
pmaddwd mm1,mm1
paddd mm0,mm1

movd edx,mm0
punpckhdq mm0,mm3
add eax,edx
movd ebx,mm0
add eax,ebx

add esi,8
add edi,8
//}

dec ecx
jnz @@StartFor
@@EndFor:

add result,eax

pop edi
pop esi
pop ebx
end;
end;
//*)

end;

if width8*8<width then
begin
for i:=0 to Height -1 do
begin
ps:= Pointer(integer(Sdata[i+Sy0])+Sx0);
pt:= Pointer(integer(TData[i+Ty0])+Tx0);
for j:=width8*8 to Width -1 do
begin
result:=result+(sqr(ps[j]-pt[j]));
end;
end;
end;

asm
emms //
end;
//MMX处理结束

end;
 
不错,我知道这个代码的,
爱元元的哥哥可以拿到50分了,

还有没有大虾过来指教的,我这里还有分,够大家拿的,说话算数,绝对给分!!
 
我也正在做远程控制的软件,作来作去发现耗时的并不是比较、传送、压缩,而是截屏,截屏在我的集成显卡电脑上要占去 180 ms 的时间,可以说大部分时间都浪费在截屏上。
最好的办法还是钩子够住重画消息,只截要求重画的部分。我又针对这个问题发贴、查资料,连续好几天了,无果!郁闷!
 
据我观察,这中间耗时的有三部分,1.抓屏幕 2。压缩 3。传输
当然他们也是有关联的,比如压缩和传输有很大的关联,要求压得又快又好(这里的好当然是说压缩比高),对于抓屏幕这一块你说说的用hook api的确是很好的思路,但是难度较高,关键是可靠性,稳定性问题,压缩方面来说delphi自带zlib压缩的还算快,压缩比也还好,传输上就要看你传的数据包的大小和网络情况了,从现在的情况来看,后两者的确到了一定的时候提升的空间不大了,关键就看抓屏幕,关键是电脑刷新的原理要搞清楚,另外,据陈经韬的经验,他利用mirro驱动得到了很好的效果,具体原理不清楚,
 
这个还需要说啊,本来如果抓的屏幕范围大,那肯定就耗时,同时内容也就大了,那么做压缩的时候,肯定耗时,传输的内容同样大了,是一个连锁的反应.谁找到这个代码,贴出来共享一下,嘿嘿,大家都想要哦.
 
如果只是比较是否发生了变化,可以考虑用指纹算法,就是分别计算两个图像的MD5值,然后比较两个指纹是否改变。
不知道我的理解是否正确?
 
你说的MD5是一个摘要散列算法,前提条件是已经建立好了指纹的资料(即指纹的数据的散列),在进行图象的比较的时候可以考虑,只不过这里的图象要比指纹复杂,可能散列函数不好定义啊,
 
抓图比较容易可以使用directx方式抓图,我测试过的确可以快很多。
抓完了图,可以使用一些简单的图像比较方法找出变动区域并形成差异图形。
最后使用RLE方式压缩进行传输即可。
客户端使用对基色异或的方式绘制即可。
以上方法在具体处理上要注意细节方面的技巧。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部