随笔 - 7  文章 - 57  trackbacks - 0
<2011年7月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

常用链接

留言簿(3)

随笔分类

随笔档案

文章分类

文章档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

续上文:
QQ美女找茬(外挂)学习笔记(一)截图的实现与保存
http://www.cppblog.com/ArthasLee/archive/2010/11/18/134022.html

比较两幅图片的不同过程中,笔者直接用了 == 来比较,尽管XOR会效率高点。
以下是笔者的代码,非完全原创,有参考,至于具体URL,在上一篇已经跟大家公布过:

 1
void CZhaoChaV30Dlg::CompareBMP( DWORD*& pBuffer, DWORD* pLeft, DWORD* pRight )
 2{
 3    if!pBuffer )   
 4    {   
 5        delete []pBuffer;   
 6        pBuffer = NULL;   
 7    }
   
 8
 9    pBuffer = new DWORD[ nWidth * nHeight ];   
10    //比较两幅图,数据相同的设置为白色,不同的为红色。  
11    for (DWORD i = 0; i < (DWORD)nWidth * nHeight; i++ )   
12    {   
13        if( pLeft[ i ] != pRight[ i ] )    
14            pBuffer[ i ] = RGB( 0,0,255 );    
15        else  
16            pBuffer[ i ] = pLeftBuffer[ i ] ;    
17    }

18
19    //转换图片数据,使图片按正常顺序显示。(BMP格式与窗口图像存放竖坐标相反)  
20    //笔者开始一直不是很明白该位blog主的意思,为什么要倒转y坐标;
21    //因此就把下面的注释掉,从windows图片浏览器观察位图,发现位图显示出来的时候并没有倒转;
22    //直至在后来要把位图显示到窗口上才真切理解“BMP格式与窗口图像存放竖坐标相反”这个事实;
23    //要注意,不然日后要写全自动WG,直接由机器发送鼠标消息模拟点击的时候就杯具了。
24    int width = nWidth;   
25    for ( DWORD i = 0; i < (DWORD)(nHeight / 2); i++ )   
26    {   
27        for ( DWORD j = 0; j < (DWORD)width; j++ )   
28        {   
29            DWORD temp;   
30            temp = *( pBuffer + i * width + j );   
31            *( pBuffer + i * width + j ) = *( pBuffer + width * ( nHeight - 1 - i ) + j );   
32            *( pBuffer + width * ( nHeight - 1 - i ) + j ) = temp;   
33        }
   
34    }
  
35
36}

37
传入三个pBuffer,然后对后面两个参数的内容进行比较,然后把比较结果写入第一个pBuffer指向的内存空间中。这段代码笔者还是好好学习了下,大家留意注释。

比较完成以后,当然是要把比较的成果显示到程序主窗口的客户区中。不然之前一切的努力也就白费了。
 1void CZhaoChaV30Dlg::BMPToWnd( void )   
 2{    
 3    CBitmap bm; 
 4    CDC* pDC;
 5
 6    bm.CreateBitmap( nWidth, nHeight, 132, pBuffer );   
 7    CBrush brush;   
 8    brush.CreatePatternBrush( &bm );   
 9
10    pDC = GetDC();
11    CBrush* pOldBrush = (CBrush*)pDC -> SelectObject( &brush );   
12
13    pDC->FillRect( &CRect( 00, nWidth, nHeight ), &brush );   
14
15    pDC->SelectObject( pOldBrush );   
16
17    brush.DeleteObject();   
18    bm.DeleteObject();   
19    ReleaseDC(pDC);   
20}
   
在上面的代码中,有个函数是CreateBitmap,与之前截图用到的CreateCompatableBitmap有点相似,笔者有点好奇,拜了google大神后,找到了以下的文章:
http://hi.baidu.com/550189285/blog/item/3742cfd4f8c9f30ba08bb775.html
PS:尽管随便贴URL是不道德滴,但是学习资料不保留下来更加不道德~


一般来说,WG来到这里,就差不多了。因为我们的基本目标已经达到。
but。。。
其余的细节呢?
要不要令这个WG更自动化,让“它”自己“玩”游戏呢?
又该如何实现呢???


以下是笔者在编码过程中遇到的问题和解决心得:
再次声明,此乃笔记,不具有普适性,有错误和改进,欢迎指出~

问题3:比较图片和一个奇怪的现象?

 

背景:

捕获了图片之后开始对两幅相同的图像进行比较,可以选取每个像素点进行比较,方法有二:直接用 == 比较,或者将两个点进行Xor运算。但是由此比较出来的图片,却出现了“重影现象”;

如下图所示:

 

子问题:什么原因导致此现象?

 

解决方案:

分析:笔者对比了几个失败样本之后,发现重影多数是出现在X方向上Y方向上则没有明显现象。如果这种现象是由色差这样微小的非肉眼能识别的区别而造成的,那么应该整张图也出现重影,而不应该在某一个方向上出现特别显著的重影。

 

结论:

两幅图在X坐标上有1个像素的偏移,笔者没有自己通过任何技术手段去获取两幅图片左上角的确切坐标,只是google了一下,就找到了相关的文章:

http://student.csdn.net/space.php?uid=110891&do=blog&id=38571

这个链接在笔者的上一篇文章已经提到过。

 

关键的数字们~

x1 = 8;

y1 = 193;

x2 = 516 + 1; //左右两副图本身有偏移个像素,去掉偏移的,只比较共有的部分

y2 = 193;

nWidth = 498 - 1;//左右两副图本身有偏移个像素,去掉偏移的,只比较共有的部分

nHeight = 448;

 

感想:

遇到问题的时候,google很重要。

 

 

 

问题4:将比较结果显示到更新了的窗口上:

 

背景:

位图信息被保存在pBuffer上,为了整个程序可以仅仅透过pBuffer来沟通,放弃了之前的hdcWindowhBitMap等变量的使用(让它们在截图函数返回前就被销毁)。因此,MSDN上的那段关于截图的代码的后半部分就不能再用。

 

子问题:

在位图内容已经存在的情况下,通过pBuffer,如何把位图显示到窗口上?

 

解决方案:

创建一个滑刷,CBrush brush;然后把pBuffer里面的像素填充进去。但是注意填充之前要保证pBuffer里面的纵坐标被倒转一下再显示到窗口中,不然会出现倒转,详见笔者在上面的代码,有中文注释。

 

 

 

问题5:隐藏窗口时的延迟性造成截图干扰

 

背景:

按下display按钮进行找茬之后,需要隐藏窗口再进行截图,不知道是机器原因还是别的问题,窗口还没有隐藏好,可能截图操作就已经完成了,这是截下的图就会是包含了“窗口残像”的图,再进行比较当然毫无意义。

 

例如出现了这样的“灵异事件”:


 

分析:

显然是窗口还没有完全隐藏,截图就进行了,so……

详情见代码:

 1void CZhaoChaV30Dlg::OnBnClickedButtonDisplay()
 2{
 3    // TODO: 在此添加控件通知处理程序代码
 4    ShowWindow( SW_HIDE );
 5    Sleep( 500 );// Good code!
 6
 7    pBuffer = NULL;
 8#ifdef DEBUG_CODE
 9    CaptureImage( pLeftBuffer, x1, y1, nWidth, nHeight );
10    SaveBMP( pLeftBuffer, _T("Debug_1.bmp") );
11    CaptureImage( pRightBuffer, x2, y2, nWidth, nHeight );
12    SaveBMP( pRightBuffer, _T("Debug_2.bmp") );
13    CompareBMP( pBuffer, pLeftBuffer, pRightBuffer );
14    SaveBMP( pBuffer, _T("Result.bmp") );
15#else
16    CaptureImage( pLeftBuffer, x1, y1, nWidth, nHeight );
17    CaptureImage( pRightBuffer, x2, y2, nWidth, nHeight );
18    CompareBMP( pBuffer, pLeftBuffer, pRightBuffer );
19#endif
20    ShowWindow( SW_SHOW );
21
22    //RetSetWnd();
23    BMPToWnd();    
24}

 

解决方案:

隐藏窗口代码后加一行:Sleep 500 ;

让程序“休息”一下,这样就可以等窗口完全隐藏过后才开始截图。

 

感想:

Sleep真神奇~
理想状态下一切都很理想,但实际操作的时候,还是会出现某些非理论性延迟。这时需要
coder们灵活变通,处理一下这个延迟了的“消息”~

 

鸣谢:
jingzhongrong——提供了不少测试样例和分析案例,从反面促使笔者尽快完成此文;
vczh——从正面鼓励笔者尽快完成此文;
vczh:http://www.cppblog.com/vczh/

posted on 2010-11-24 00:02 ArthasLee 阅读(3518) 评论(14)  编辑 收藏 引用 所属分类: windows应用层编程

FeedBack:
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 00:53 长沙
学习了。。。很牛逼  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 09:07 潘孙友
写得不错,加油!

期待后续文章 :)  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 09:37 睡觉没床
兄弟,这也叫外挂?  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 10:25 放屁阿狗
我在5173的时候有个同事是用vb做游戏图像识别的,当时觉得很土,但还是比较有效  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 10:26 陈梓瀚(vczh)
@睡觉没床
因为有了差你就可以控制鼠标去点了吧,我觉得基本上可以构成一个外挂了——虽然目标游戏比较简单。  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 11:27 尤里卡
呵呵,我理解的话,一般将代码注入其他程序进程的东西才称为外挂(比较形象吧?)。这种的话,我一般称之为辅助工具、或作弊程序。
楼主加油。  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 16:49 陈梓瀚(vczh)
@尤里卡
这是病毒- -b  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示[未登录] 2010-11-24 17:12 niino
@陈梓瀚(vczh)
那是病毒...  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 19:13 ArthasLee
@潘孙友
多谢支持,也打算写后续文章。不过都是那句:这两篇文章都是我的笔记性质居多,因此不具有普适性。  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 19:14 ArthasLee
@放屁阿狗
本人才疏学浅,这个哪里是什么图像识别,只不过是单纯比较像素点罢了,呵呵!  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 19:18 ArthasLee
@陈梓瀚(vczh)
vczh兄正解~目标游戏那是相当简单,要我以现在的水平弄个星际蟑螂流战术算法评估器,估计成功率跟我在有生之年看到人类实现超光速飞行的概率差不多。
例如这些:http://sc2.plu.cn/tactical/2010-11-04/22450.html
不过可能也不能叫做外挂吧?  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-24 19:22 ArthasLee
@尤里卡
将代码注入其他进程啊?呵呵,听闻过。不过现在还不会呢。有机会的话希望兄台指点指点~
多谢支持先。  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-26 14:22 feixuwu
楼主这种办法比较耗CPU吧?另外,刷新也会是个问题,不过探索精神应该赞一个。原来也为朋友做过这个外挂,当时用的一个办法是挂钩directDraw,直接操作缓冲区,效率会比较高,另外显示上也会更好。  回复  更多评论
  
# re: QQ美女找茬(外挂)学习笔记(二)图片的比较与显示 2010-11-26 15:18 ArthasLee
@feixuwu
哇!长见识了!今晚去了解了解。谢谢兄台给的建议!  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理