快速“美女找茬”(辅助工具)

            最近和小徒弟玩QQ游戏中的“美女找茬”,这个游戏也就是给你两幅差不多的图片,让你找出几个不同的地方(一般是五个)。可惜我老眼昏花比较反应迟钝,总是输,被小徒弟取笑。不禁一时心血来潮,既然作为普通玩家赢不了,何不...!于是我琢磨了一下,不过就是两幅图片比较一下吗,对计算机来说当然很简单。也不需要考虑什么算法。

            所以我就做了这样一个小程序,纯属贪图好玩。我首先找到游戏窗口,然后把这个窗口“截屏”下来,在内存里判断两幅图片的不同之处,然后把结果输出到一个半透明窗口上,并且把这个半透明窗口准确的覆盖到左侧图片上。这个半透明窗口的背景是一个白色矩形,两幅图不同的地方用红色填充出来。

            判断两幅图片之前,我们做一些准备工作。先用SPY++查询出游戏窗口的窗口类和窗口标题。我在 Photoshop 里精确测量了两幅图在窗口中的起始坐标和长度宽度,很庆幸的一点是在游戏里这些值是固定的!现在为了简单起见,我们先把这些值 hard code 在程序里(如果考虑更周到,我们应该把这些信息存到一个 ini 配置文件里)。

            那么截图并且找到不同处的代码如下所示。为了考虑容错性,我还尝试了以 3*3 和 2*2 的像素矩形块为基本单位进行检测,但经过测试后我发现意义不大,实际上仅对单个像素进行检测就足够了,所以下面的代码就是逐个像素检测。

 

Code_FindDifference
//When user click the icon , then Let's GO !!! 
BOOL FindDifference(HWND hParentDlg)
{
    RECT rc, rc2;

    //hide layer wnd
    ShowWindow(m_wndLayer, SW_HIDE);

    m_wndGame = FindWindow(CLASSNAME, WINDOWNAME);

    if(m_wndGame == NULL)
    {
        MessageBox(hParentDlg, "没找到游戏窗口哇!还没进入房间吧?", "帮你找茬", MB_OK |MB_ICONINFORMATION);
        return FALSE;
    }

    GetWindowRect(m_wndGame, &rc);
    GetWindowRect(m_wndLayer,&rc2);
    int width = rc.right -rc.left;
    int height = rc.bottom - rc.top;
    int width2 = rc2.right - rc2.left;
    int height2 = rc2.bottom - rc2.top;

    HDC gameDC = GetDC(m_wndGame);
    HDC layDC = GetDC(m_wndLayer);

    HDC memDC = CreateCompatibleDC(gameDC);
    HDC memDC2= CreateCompatibleDC(layDC);
    
    //create game bitmap (for the first call)
    if(m_bmGame == NULL)
        m_bmGame = CreateCompatibleBitmap(gameDC, width, height); 
    if(m_bmLayer == NULL)
        m_bmLayer = CreateCompatibleBitmap(layDC, width, height);
    
    //把截图复制到内存DC
    HGDIOBJ hOld1 = SelectObject(memDC, m_bmGame);
    HGDIOBJ hOld2 = SelectObject(memDC2, m_bmLayer);

    BitBlt(memDC, 0 , 0, rc.right-rc.left, rc.bottom-rc.top, 
        gameDC, 0, 0, SRCCOPY);

    //把图层填充白色
    Rectangle(memDC2, 0 , 0, width2, height2);

    //现在我们从起始点查找
    int i, j, diff;
    BYTE r1, g1, b1, r2, g2, b2;
    COLORREF color1, color2;

    for(j = 0; j < IMG_HEIGHT; j++)
    {
        for(i = 0; i < IMG_WIDTH; i++)
        {
            //单像素检测
            color1 = GetPixel(memDC, IMG_X1 + i, IMG_Y + j);
            color2 = GetPixel(memDC, IMG_X2 + i, IMG_Y + j);

            r1 = GetRValue(color1);
            g1 = GetGValue(color1);
            b1 = GetBValue(color1);

            r2 = GetRValue(color2);
            g2 = GetGValue(color2);
            b2 = GetBValue(color2);

            diff = abs(r1-r2) + abs(g1-g2) + abs(b1-b2);

            if(diff > m_Threshold)
            {
                SetPixel(memDC2, i, j, RGB(255, 0, 0));
            }
        }
    }
    
    SelectObject(memDC, hOld1);
    SelectObject(memDC2, hOld2);
    DeleteDC(memDC);
    DeleteDC(memDC2);

    ReleaseDC(m_wndGame, gameDC);
    ReleaseDC(m_wndLayer, layDC);

    //把窗口移动到指定位置
    SetWindowPos(m_wndLayer, HWND_TOPMOST, 
        rc.left + IMG_X1, rc.top + IMG_Y, 0, 0, 
        SWP_NOACTIVATE | SWP_NOSIZE | SWP_SHOWWINDOW
        );

    InvalidateRect(m_wndLayer, NULL, TRUE);
    return TRUE;
}

 

            这个函数的效率不是很高,检测不同的时候需要等大概一秒钟的时间(我的电脑配置是 2.67GHz * 2 CPU, 3.24G 内存)。我想如果改进为直接用指针访问位图的数据块会比这种方法的效率好很多,所以它还可以改进,不过目前的处理时间对于我来说也还是可以接受的。

            然后我们需要给用户一个接口去调用上面的函数,因此我在通知栏(Tray:系统托盘)放置了一个图标,只要用户用左键单击通知栏图标,就会调用上面的函数,也就是执行一次查找,并把半透明窗口和游戏窗口进行对齐。通过鼠标右键,可以选择显示或者隐藏半透明窗口。

 

            【注意】如果游戏窗口被其他窗口遮挡,或者游戏窗口有屏幕以外,或者游戏窗口上有动态元素(例如游戏的倒计时提示等),请注意这时候获取到的窗口截图是有问题的,那么查找结果也会出现不准确的情况。 

 

             

 

            如图所示,我在左侧图上叠加了一个半透明窗口,它只是一个普通对话框(上面什么控件也没有),当然我们还需要把这个半透明窗口设置成顶层窗口,还要使其“鼠标穿透”,也就是说它自身不想接收鼠标事件,而是让鼠标“穿透”它传送给其下面的窗口,这是通过设置窗口样式来完成的。在初始化对话框时,我们用下面的代码即可:

 

Code_设置鼠标穿透
//窗口过程局部:
switch(message)
{
case WM_INITDIALOG:
    {
    //设置图层窗口,不透明度
    SetWindowLong(hDlg, GWL_EXSTYLE, 
            GetWindowLong(hDlg, GWL_EXSTYLE) | 
            WS_EX_TRANSPARENT | //鼠标穿透
            WS_EX_LAYERED        //图层窗口
            );
    //BYTE alpha = 120;
    SetLayeredWindowAttributes(hDlg,0, 120, LWA_ALPHA);
    return TRUE;
    }
    break;

//其他消息。。。

}

 

 

            【注意】VC6.0提供的PLATFORM SDK(1998年的)并不支持图层窗口相关的API,因此编译时会提示找不到相应函数。要正确编译,解决方法是在 winuser.h 文件中补充相关的定义,并用高版本的Visual Studio(例如VS2003, VS2005 )中的 user32.lib 覆盖VC中的相应文件。

             我增加了一个设置对话框如下图所示,用于设置 FindDifference 函数中使用的全局参数 m_Threshold 的值。可以修改这个值的大小然后观察这个值的大小对输出结果中红色区域形状的影响,这个值越小,则输出结果的红色区域越接近为“矩形”(这个形状主要是基于游戏中使用的图片),即对差异的检验越严格。这个值越大,则输出结果的红色区域会产生收缩,使其更接近差异的“实际形状”,即使“容许误差”增加(把灰度变化较小的部分过滤,仅标示灰度差异明显的地方)。当然这个值如果设置的过大,则红色区域会减少到“完全消失”。

 

            

 

             这里是源代码的下载链接:(于 2014 年 2 月 17 日 被我撤除)

             http://files.cnblogs.com/hoodlum1980/FindIt.rar

            最后我要特别提示的是,游戏的本质是娱乐,不要为了追求浮云而失去游戏的本意。

 

    【补充】by hoodlum1980 @ 2011-11-19

    其实对于这个工具来说,仅仅是比较两幅位图,找出不同之处。其实就很简单了,我们只要两张图的位图数据块做异或就可以得到差异结果,相当于在 photoshop 中的图层模式设置为“差值”,就可以看到两个图层之间的差异。大致方法如下:

    为了加快效率,用 uint32* 类型的指针,分别指向两个位图的数据块。一般我们截图的结果是 bpp = 24,也就是说每 3 个字节为一个像素,但我们依然可以每 4 个字节一组进行异或,异或结果就是结果(同样,可以对异或结果不为0的结果像素用显著颜色标识),把结果图片呈现出来就达到和本文中相同的效果。这种方法会比我之前实现的方式速度快很多。

    但如果我们要推算出像素位置,则还需要进行一次换算,假设截图为 24 bpp,则数据排列如下:

    |   0   |    1   |   2   |

    |B G R B|G R B G|R ...

           |    0      |   1      | .....

    

    设 pDest 为结果图片的数据块指针,pSrc1和pSrc2分别是要比较的图片(注意实际上可使用同一个位图,只是水平方向上有不同偏移的定位) 

    *pDest = *pSrc1 ^ *pSrc2;

    设 uint32* p0 为数据块起始点:假设在 p1 处发现不为 0,则距离起始点的距离是:

    (p1 - p0) * sizeof(uint), 即 (p1-p0)*4;

    然后换成成像素坐标:

    stride = (width * bpp + 31)/32 * 4;

    y = (height - 1) - (p1-p0)*sizeof(uint) / stride;  //如果扫描行为逆序

    x = (((p1 - p0) * sizeof(uint)) % stride) / 3;

    注意实际上这里涵盖了两个相邻像素(x,y)和(x+1,y)组成的(由于数据块用int32对齐,所以一定在同一扫描行内),可能是 BGR|B, GR|BG, R|BGR 三种情况之一:所以我们还应该分析除以 3 以后的余数。

    令余数 k = (((p1-p0)*sizeof(uint)) % stride) % 3;

    k = 0: BGR|B   (x, y) ,     (x+1, y)的B

    k = 1: GR|BG   (x,y)的GR,   (x+1,y)的BG

    k = 2: R|BGR   (x,y)的R,    (x+1,y)

 

    如果我们需要更精确的知道到底似乎是那个像素不同导致的,我们还需要对这四个字节扫描一下,然后按照上诉情况分析不同的值位于(x,y)还是(x+1,y)。当然一般来说如果是在差异区域内部实际没必要区分。

 

    【对以上补充的补充说明:】

    由于我已经采用更佳方法(参见:http://www.cnblogs.com/hoodlum1980/p/3536444.html),所以以上补充说明已不再有效。-- hoodlum1980, on 2014-2-17。

 

 

时间: 2024-09-21 21:51:32

快速“美女找茬”(辅助工具)的相关文章

VB实现的《QQ美女找茬游戏》作弊器实例_vb

本文实例讲述了VB实现的<QQ美女找茬游戏>作弊器.分享给大家供大家参考.具体如下: 比较无聊哈,原理很简单,用VB速度比较慢,但是实现很容易. Option Explicit Private Type sPOINT x As Long y As Long End Type Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function Get

5月14日蚕豆网不推荐的Android应用:《美女找茬》

前言:如雨后春笋般杂乱滋生的Android app遍布于网络中.下载平台中.用户的手机中,目前由于监管不严.开放性过大这些应用的安全性便成了当前Android手机最大问题.通讯录被复制.私人照片丢失.信息被公开等等事件的出现,其罪魁祸首当属那些存在安全隐患.内藏恶意代码的Android手机应用.鉴于此情况, 蚕豆网联合<安全管家>定 期为大家审查Android应用的安全性,尽我们最大力量来帮助用户来认清app.选择app,把最安全.最稳定的Android环境奉献给广大用户.应用名称:美女找茬M

[发布] QQGame 连连看辅助工具(限制功能版)

前几天想起了这个想法,然后最近两天开发了这个工具,就是用于 QQGame 中的连连看的辅助工具.本来是想把全部代码都公开的,但是我在调试程序的时候注意到腾讯在qqgame中宣传卖那些游戏道具.所以我的想法就改变了下,不想影响腾讯卖这些道具来赚钱,所以我把原来完整功能版的版本又加上了一些限制. 辅助工具实现的功能包括:全自动点击,自动重排(当方块无解时),显示可点击方块提示(相当于官方的指南针功能),模拟单步点击. 首先进入 QQGame,连连看,开始游戏后如下图所示:   启动工具后的界面如下图

分享一个LiteDB做的简单考试系统辅助工具

    凌晨,被安排在公司值班,因为台风"灿鸿"即将登陆,风力太大,办公楼,车间等重要部分需要关注.所以无聊,那就分享一下,今天给朋友临时做的一个小的考试系统辅助工具吧.其实非常小,需求也很简单,但是可以根据实际需要进行扩充,暂时只实现了一些核心功能.界面丑了点,无所谓,凑合着用吧. 1.考试系统辅助需求     上午10点一个朋友紧急求助,单位要进行在线测评,开卷考试,题库以及答案已经发给他们了,但是太多,好几百道题目,翻资料都来不及.问我能不能做一个软件,能够快速填充答案或者找到题

全新361应用工场内测上线 开启有奖找茬活动广征建议

中介交易 SEO诊断 淘宝客 云主机 技术大厅 近日,国内知名的移动建站平台361应用工场(http://361.w.cn/)全新内测上线,为移动开发者.企业商家提供快速生成手机版网站和APP应用服务.361应用工场具备快速生成.自选功能.数据同步三大特色功能.可以帮助移动开发者和企业商家快速提升移动流量,并针对不同用户的需求展开定制,实现流量变现. 记者了解到通过361应用工场,不久后将实现3-5分钟内快速把pc端站点转换成适合浏览的手机版网站,并生成APP程序包给用户使用.除此之外,361手

《AutoCAD全套园林图纸绘制自学手册》一2.7 绘图辅助工具

2.7 绘图辅助工具 AutoCAD全套园林图纸绘制自学手册 要快速顺利地完成图形绘制工作,有时要借助一些辅助工具,比如用于准确确定绘制位置的精确定位工具和调整图形显示范围与方式的显示工具等.下面将简略介绍这两种非常重要的辅助绘图工具. 2.7.1 精确定位工具 在绘制图形时,可以使用直角坐标和极坐标精确定位点,但是有些点(如端点.中心点等)的坐标我们是不知道的,又想精确的指定这些点,可想而知是很难的,有时甚至是不可能的.幸好AutoCAD 2013已经很好地为我们解决了这个问题.AutoCAD

十个好用的iOS开发辅助工具与资源

「工欲善其事,必先利其器」为了开发出更好.更有创意又高质感的 iOS 应用程式,方便又大腕的辅助工具以及免费资源是绝对少不了的!这边让我们来介绍一些常用又简单的免费小工具吧. 1. Resizer 将 Retina 使用的图档(档名为 @2x 或 -hd 的图档)快速且完美地产生普通屏幕的图档尺寸. 2. LifeView 透过 Wifi 使用 iPhone 或是 iPad 直接预览电脑画面,方便检视图片在 Retina 屏幕中的效果. 3. Icon Viewer 线上快速预览你精心製作的 A

Linr PS toolkit(Photoshop开发人员辅助工具)

来自(vickey)的肖软件~ github地址:https://github.com/Linrstudio/LinrPSToolkit  Linr PS toolkit(Photoshop开发人员辅助工具) 一键导图:快速输出选区为Web所用格式;若当前图层被锁定则只输出当前图层的当前选区;  快速获取信息:快速获取图像选区尺寸(若无选区则获取图像完整尺寸); 快速获取前景色.背景色.边框设置; 生成CSS:当前图层为文本图层时获取文本样式并生成CSS;并将每个空格或换行符相间的文本转成超链接

全能QQ辅助工具——拉拉QQ助手

硅谷网6月7日讯 目前有超过3亿的人在用QQ,对于大多 数人来说,打开电脑的第一件事就是先登录自己的QQ,它的方便快捷.简答实用让无数人为之青睐.可是QQ应用的设置需要你一个一个的设置,十分繁琐,对于快节奏的现代人来说已经不能满足要求了.小编在这里体验 一款超强的QQ应用功能的辅助工具--拉拉QQ助手(WWW.5qq.COM). 拉拉QQ助手在同行业中具有了划时代的意义.拉拉QQ助手与市面上其他的QQ辅助功能有着明显的差别,QQ各种资源功能超强一键,海量QQ应用资源,一站式云管理技术等, 这些技