原神用FindText做当前血量图像识别【1080P】

原神用FindText做当前血量图像识别【1080P】

#NoEnv
#SingleInstance Force
#KeyHistory 0
SetBatchLines -1
ListLines Off
CoordMode Mouse
CoordMode ToolTip
CoordMode Pixel

Gosub 原神血量数字二值化数据

; 由于当前血量和总血量之间有/比较难识别处理,所有就显示当前血量了
; 也可以划定范围分开识别【1.当前血量、2.总血量】
; FindText().OCR(ok).Text 是OCR血量数据,可以用于低血量识别操作之类的

F1::
if (onoff := !onoff)
    SetTimer 原神血量显示, 10
  else {
    SetTimer 原神血量显示, off
	SetTimer Sc996, -150
 }
Return

Sc996::ToolTip

原神血量显示:
; if (ok:=FindText(X, Y,1431, 983, 1557, 1017, , , Text))
if (ok:=FindText(X, Y, 894, 999, 952, 1023, , , Text))
	ToolTip % FindText().OCR(ok).Text, 925, 958
 else
	ToolTip
Return


原神血量数字二值化数据:
Text:="|<1>##0$0/0/E7E7E7,-1/1/E1E1E1,-1/-1/FFFFFF,0/-1/FFFFFF,0/-2/FFFFFF,-1/-2/FFFFFF,-1/-3/FFFFFF,0/-3/FFFFFF,0/-4/FFFFFF,-1/-4/FFFFFF,-1/-5/FFFFFF,0/-5/FFFFFF,0/-6/FFFFFF,-1/-6/FFFFFF,-1/-7/FFFFFF,0/-7/FFFFFF,0/-8/FFFFFF,-1/-8/FFFFFF,-1/-9/FFFFFF,0/-9/FFFFFF,-2/-9/FFFFFF,-3/-9/FDFDFB"

Text.="|<1>##0$0/0/FFFFFF,1/0/FFFFFF,2/0/FFFFFF,2/1/FFFFFF,2/2/FFFFFF,2/3/FFFFFF,2/4/FFFFFF,2/5/FFFFFF,2/6/FFFFFF,2/7/FFFFFF,2/8/FFFFFF"

Text.="|<8>##0$0/0/FFFFFF,0/1/FFFFFF,0/2/FFFFFF,-1/2/FFFFFF,1/3/FFFFFF,0/3/FFFFFF,1/4/FFFFFF,2/4/FFFFFF,3/4/FFFFFF,4/4/FFFFFF,4/3/FFFFFF,5/3/FFFFFF,5/2/FFFFFF,6/2/FFFFFF,6/1/FFFFFF,6/0/FFFFFF,6/7/FFFFFF,7/7/FFFFFF,-1/7/FFFFFF,0/6/FFFFFF,4/5/FFFFFF"

Text.="|<8>##0$0/0/FFFFFF,0/1/FFFFFF,0/2/FFFFFF,1/2/FFFFFF,1/3/FFFFFF,2/3/FFFFFF,5/3/FFFFFF,6/1/FFFFFF,5/4/FFFFFF,4/4/FFFFFF,3/4/FFFFFF,2/4/FFFFFF,1/4/FEFFFE,0/8/FFFFFF,0/7/FFFFFF,0/6/FFFFFF,6/6/FFFFFF,6/7/FFFFFF,6/8/FFFFFF,7/8/FFFFFF"


Text.="|<3>##0$0/0/FFFFFF,0/1/FFFFFF,6/1/FFFFFF,7/1/FFFFFF,6/0/FFFFFF,6/2/FFFFFF,3/4/FFFFFF,6/6/FFFFFF,7/6/FFFFFF,7/7/FFFFFF,6/7/FFFFFF,6/8/FFFFFF,7/8/FFFFFF,0/8/FFFFFF,0/7/FFFFFF"

Text.="|<3>##0$0/0/FFFFFF,0/1/FFFFFF,-1/1/FFFFFF,6/0/FFFFFF,6/1/FFFFFF,6/2/FFFFFF,4/4/FFFFFF,3/4/FFFFFF,6/7/FFFFFF,0/8/FFFFFF,-1/8/FFFFFF,-1/7/FFFFFF"


Text.="|<2>##0$0/0/E7E7E7,1/0/E7E7E7,1/-1/FFFFFF,0/-1/FFFFFF,1/-2/FFFFFF,3/-4/FFFFFF,5/-6/FFFFFF,5/-9/FFFFFF,6/-9/FFFFFF,0/-8/FFFFFF,0/-9/FFFFFF"

Text.="|<2>##0$0/0/E7E7E7,-1/0/E7E7E7,-1/-1/FFFFFF,0/-1/FFFFFF,0/-2/FFFFFF,1/-2/FFFFFF,5/-7/FFFFFF,5/-9/FFFFFF,-1/-8/FFFFFF,-1/-9/FFFFFF"


Text.="|<4>##0$0/0/EFEFEF,0/1/FFFFFF,0/2/FFFFFF,0/3/FFFFFF,0/4/FFFFFF,0/5/FFFFFF,0/6/FFFFFF,0/7/FFFFFF,0/8/FFFFFF,0/9/FFFFFF,0/10/E7E7E7,-6/8/FFFFFF,-5/8/FFFFFF,-4/8/FFFFFF,-3/8/FFFFFF,-2/8/FFFFFF,-1/8/FFFFFF,1/8/FFFFFF,2/8/FFFFFF,3/8/FFFFFF,4/8/FFFFFF"

Text.="|<5>##0$0/0/FFFFFF,6/0/FFFFFF,7/-1/FFFFFF,6/-1/FFFFFF,6/-2/FFFFFF,7/-2/FFFFFF,6/-3/FFFFFF,6/-4/FFFFFF,5/-4/FFFFFF,3/-5/FFFFFF,0/-6/FFFFFF,1/-8/FFFFFF"

Text.="|<5>##0$0/0/FFFFFF,0/1/FFFFFF,0/2/FFFFFF,0/3/FFFFFF,5/5/FFFFFF,5/6/FFFFFF,5/7/FFFFFF,5/8/FFFFFF,6/7/FFFFFF,6/6/FFFFFF,6/5/FFFFFF,-1/7/FFFFFF,-1/8/FFFFFF,6/8/FFFFFF"


Text.="|<6>##0$0/0/FFFFFF,0/1/FFFFFF,-1/1/FFFFFF,-1/2/FFFFFF,0/2/FFFFFF,4/1/FFFFFF,5/2/FFFFFF,6/2/FFFFFF,6/3/FFFFFF,6/4/FFFFFF,6/5/FFFFFF,6/6/FFFFFF,0/6/FFFFFF,0/5/FFFFFF,0/4/FFFFFF,0/3/FFFFFF,-1/4/FFFFFF"

Text.="|<6>##0$0/0/FFFFFF,-1/1/FFFFFF,-1/2/FFFFFF,-2/2/FFFFFF,-2/3/FFFFFF,-1/3/FFFFFF,-1/4/FFFFFF,-2/5/FFFFFF,-2/6/FFFFFF,-2/7/FFFFFF,-2/8/FFFFFF,4/5/FFFFFF,4/6/FFFFFF,4/7/FFFFFF,4/8/FFFFFF"


Text.="|<9>##0$0/0/FFFFFF,0/1/FFFFFF,0/-1/FFFFFF,1/3/FFFFFF,0/3/FFFFFF,3/4/FFFFFF,2/4/FFFFFF,6/4/FFFFFF,6/3/FFFFFF,6/2/FFFFFF,6/1/FFFFFF,6/0/FFFFFF,7/0/FFFFFF,7/1/FFFFFF,7/2/FFFFFF,7/3/FFFFFF,7/4/FFFFFF,5/7/FFFFFF,6/6/FFFFFF"

Text.="|<9>##0$0/0/FFFFFF,1/0/FFFFFF,1/1/FFFFFF,1/2/FFFFFF,1/3/FFFFFF,0/1/FFFFFF,0/2/FFFFFF,0/3/FFFFFF,7/0/FFFFFF,7/1/FFFFFF,7/2/FFFFFF,7/3/FFFFFF,7/4/FFFFFF,6/4/FEFEFD,6/5/FFFFFF,7/5/FFFFFF,7/6/FFFFFF,6/6/FFFFFF,6/7/FFFFFF"

Text.="|<9>##0$0/0/FFFFFF,-1/0/FFFFFF,-2/0/FFFFFF,-3/-5/FFFFFF,-3/-4/FFFFFF,-3/-3/FFFFFF,-4/-2/FFFFFF,-4/-5/FFFFFF,3/-5/FFFFFF,3/-3/FFFFFF,3/-2/FFFFFF,2/2/FFFFFF"


Text.="|<0>##0$0/0/FFFFFF,0/1/FFFFFF,0/2/FFFFFF,0/3/FFFFFF,0/4/FFFFFF,0/5/FFFFFF,0/6/FFFFFF,7/1/FFFFFF,7/2/FFFFFF,7/3/FFFFFF,7/4/FFFFFF,7/5/FFFFFF,7/6/FFFFFF"


Text.="|<7>##0$0/0/FFFFFF,1/0/FFFFFF,1/1/FFFFFF,0/1/FFFFFF,0/2/FFFFFF,1/2/FEFEFD,0/3/FFFFFF,-1/2/FFFFFF,-1/3/FFFFFF,-1/4/FFFFFF,0/4/FFFFFF,0/5/FFFFFF,-1/5/FFFFFF"

Text.="|<7>##0$0/0/FFFFFF,-1/1/FFFFFF,-1/2/FFFFFF,-1/3/FFFFFF,-2/3/FFFFFF,-2/4/FFFFFF,-2/5/FFFFFF,-3/5/FFFFFF,-3/6/FFFFFF,-3/7/FFFFFF,-3/8/FFFFFF,-4/8/FFFFFF,-4/7/FFFFFF"

Text.="|<7>##0$0/0/FFFFFF,-1/2/FFFFFF,-1/3/FFFFFF,-2/3/FFFFFF,-2/4/FFFFFF,-2/5/FFFFFF,-2/6/FFFFFF,-2/7/FFFFFF,-3/5/FFFFFF,-3/6/FFFFFF,-3/7/FFFFFF,-3/8/FFFFFF,-3/9/E7E7E7,-4/9/E7E7E7"


Text.="|<7>##0$0/0/FFFFFF,0/1/FFFFFF,-1/2/FFFFFF,-1/3/FFFFFF,-2/3/FFFFFF,-2/4/FFFFFF,-2/5/FFFFFF,-2/6/FFFFFF,-2/7/FFFFFF,-3/7/FFFFFF,-3/6/FFFFFF"
Return

;/*
;===========================================
;  FindText - 屏幕抓字生成字库工具与找字函数
;  https://autohotkey.com/boards/viewtopic.php?f=6&t=17834
;
;  脚本作者 : FeiYue
;  最新版本 : 8.6
;  更新时间 : 2021-09-12
;
;  用法:  (需要最新版本 AHK v1.1.31+)
;  1. 将本脚本保存为“FindText.ahk”并复制到AHK程序的Lib子目录中
;  2. 抓图并生成调用FindText()的代码
;     2.1 方式一:直接点击“抓图”按钮
;     2.2 方式二:先设定截屏热键,使用热键截屏,再点击“截屏抓图”按钮
;  3. 测试一下调用的代码是否成功:直接点击“测试”按钮
;  4. 复制调用的代码到自己的脚本中
;     4.1 方式一:直接点击“复制”按钮,然后粘贴到自己的脚本中(不推荐)
;     4.2 方式二:取消“附加FindText()函数”的选框,然后点击“复制”按钮,
;         然后粘贴到自己的脚本中,然后在自己的脚本开头加上一行:
;         #Include <FindText>  ; Lib目录中必须有FindText.ahk
;  5. 多色查找模式可以一定程度上适应图像的放大缩小,也可以找图
;  6. 这个库还可以用于快速截屏、获取颜色、写入颜色、编辑后另存图片
;  7. 如果要调用FindTextClass类中的函数,请用无参数的FindText()获取默认对象
;
;===========================================
;*/


if (!A_IsCompiled and A_LineFile=A_ScriptFullPath)
  FindText().Gui("Show")


;===== Copy The Following Functions To Your Own Code Just once =====


;--------------------------------
;  FindText - 屏幕找字函数
;--------------------------------
;  返回变量 := FindText(
;      OutputX --> 保存返回的X坐标的变量名称
;    , OutputY --> 保存返回的Y坐标的变量名称
;    , X1 --> 查找范围的左上角X坐标
;    , Y1 --> 查找范围的左上角Y坐标
;    , X2 --> 查找范围的右下角X坐标
;    , Y2 --> 查找范围的右下角Y坐标
;    , err1 --> 文字的黑点容错百分率(0.1=10%)
;    , err0 --> 背景的白点容错百分率(0.1=10%)
;    , Text --> 由工具生成的查找图像的数据,可以一次查找多个,用“|”分隔
;    , ScreenShot --> 是否截屏,为0则使用上一次的截屏数据
;    , FindAll --> 是否搜索所有位置,为0则找到一个位置就返回
;    , JoinText --> 是否组合图像,为1则多个数据组合为一幅图来查找
;    , offsetX --> 组合图像的每个字和前一个字的最大横向间隔
;    , offsetY --> 组合图像的每个字和前一个字的最大高低间隔
;    , dir --> 查找的方向,有上、下、左、右、中心9种
;  )
;
;  返回变量 --> 如果没找到结果会返回0。否则返回一个二级数组,
;      第一级是每个结果对象,第二级是结果对象的具体信息数组:
;      { 1:左上角X, 2:左上角Y, 3:图像宽度W, 4:图像高度H
;        , x:中心点X, y:中心点Y, id:图像识别文本 }
;  坐标都是相对于屏幕,颜色使用RGB格式
;
; 如果 OutputX 等于 "wait" 或 "wait1" 意味着等待图像出现,
; 如果 OutputX 等于 "wait0" 意味着等待图像消失
; 此时 OutputY 设置等待时间的秒数,如果小于0则无限等待
; 如果超时则返回0,意味着失败,如果等待图像出现成功,则返回位置数组
; 如果等待图像消失成功,则返回 1
; 例1: FindText("wait",3, 0,0,0,0,0,0,Text)   ; 等待3秒等图像出现
; 例2: FindText("wait0",-1, 0,0,0,0,0,0,Text) ; 无限等待等图像消失
;--------------------------------

FindText(ByRef x:="FindTextObject", ByRef y:="", args*)
{
  static obj:=new FindTextClass()
  if (x=="FindTextObject")
    return obj
  else
    return obj.FindText(x, y, args*)
}

Class FindTextClass
{  ;// Class Begin

static bind:=[], bits:=[], Lib:=[], Cursor:=0

__New()
{
  this.bind:=[], this.bits:=[], this.Lib:=[], this.Cursor:=0
}

__Delete()
{
  if (this.bits.hBM)
    DllCall("DeleteObject", "Ptr",this.bits.hBM)
}

FindText(ByRef OutputX:="", ByRef OutputY:=""
  , x1:=0, y1:=0, x2:=0, y2:=0, err1:=0, err0:=0
  , text:="", ScreenShot:=1, FindAll:=1
  , JoinText:=0, offsetX:=20, offsetY:=10, dir:=1)
{
  local
  if RegExMatch(OutputX, "i)^\s*wait[10]?\s*$")
  {
    found:=!InStr(OutputX,"0"), time:=OutputY
    , timeout:=A_TickCount+Round(Abs(time)*1000)
    , OutputX:=OutputY:=""
    Loop
    {
      ok:=this.FindText(OutputX, OutputY
        , x1, y1, x2, y2, err1, err0
        , text, ScreenShot, FindAll
        , JoinText, offsetX, offsetY, dir)
      if (found and ok)
        return ok
      else if (!found and !ok)
        return 1
      if (time>=0 and A_TickCount>=timeout)
        Break
      Sleep, 100
    }
    return 0
  }
  SetBatchLines, % (bch:=A_BatchLines)?"-1":"-1"
  centerX:=Round(x1+x2)//2, centerY:=Round(y1+y2)//2
  if (x1*x1+y1*y1+x2*x2+y2*y2<=0)
    n:=150000, x:=y:=-n, w:=h:=2*n
  else
    x:=Min(x1,x2), y:=Min(y1,y2), w:=Abs(x2-x1)+1, h:=Abs(y2-y1)+1
  bits:=this.GetBitsFromScreen(x,y,w,h,ScreenShot,zx,zy,zw,zh)
  , info:=[]
  Loop Parse, text, |
    if IsObject(j:=this.PicInfo(A_LoopField))
      info.Push(j)
  if (w<1 or h<1 or !(num:=info.Length()) or !bits.Scan0)
  {
    SetBatchLines, %bch%
    return 0
  }
  arr:=[], ini:={zx:zx, zy:zy, zw:zw, zh:zh
    , sx:x-zx, sy:y-zy, sw:w, sh:h, comment:""}, k:=0
  For i,j in info
    k:=Max(k, j[2]*j[3]), ini.comment .= j[11]
  VarSetCapacity(s1, k*4), VarSetCapacity(s0, k*4)
  , VarSetCapacity(ss, 2*(w+2)*(h+2))
  , FindAll:=(dir=9 ? 1 : FindAll)
  , JoinText:=(num=1 ? 0 : JoinText)
  , allpos_max:=(FindAll or JoinText ? 10240 : 1)
  , VarSetCapacity(allpos, allpos_max*8)
  Loop 2
  {
    if (err1=0 and err0=0) and (num>1 or A_Index>1)
      err1:=0.05, err0:=0.05
    Loop % JoinText ? 1 : num
    {
      this.PicFind(arr, ini, info, A_Index, err1, err0
        , FindAll, JoinText, offsetX, offsetY, dir
        , bits, ss, s1, s0, allpos, allpos_max)
      if (!FindAll and arr.Length())
        Break
    }
    if (err1!=0 or err0!=0 or arr.Length() or info[1][12])
      Break
  }
  if (dir=9)
    arr:=this.Sort2(arr, centerX, centerY)
  SetBatchLines, %bch%
  if (arr.Length())
  {
    OutputX:=arr[1].x, OutputY:=arr[1].y
    return arr
  }
  return 0
}

PicFind(arr, ini, info, index, err1, err0
  , FindAll, JoinText, offsetX, offsetY, dir
  , bits, ByRef ss, ByRef s1, ByRef s0
  , ByRef allpos, allpos_max)
{
  local
  static MyFunc:=""
  if (!MyFunc)
  {
    x32:=""
    . "5557565383EC648B6C247883FD050F84AB0800008BB424BC000000C744240C00"
    . "00000085F60F8E1A0D000031FF31C0896C2478C74424080000000031C9C74424"
    . "1400000000897C241089C5908D7426008B5C24108BBC24B80000008B7424148B"
    . "54240C01DF89D829DE8B9C24B800000003B424B400000085DB7E58893C2489EB"
    . "89D7EB198BAC24B000000083C70483C00189548D0083C1013904247429837C24"
    . "780389FA0F45D0803C063175D78BAC24AC00000083C70483C00189549D0083C3"
    . "0139042475D78BB424B80000000174241489DD83442408018BBC24A00000008B"
    . "442408017C24108B9C248C000000015C240C398424BC0000000F8551FFFFFF89"
    . "6C24088B6C2478894C240C31C08B74240839B424C00000008B7C240C0F4DF039"
    . "BC24C4000000897424080F4CC739C68944240C0F4DC683FD038904240F848E08"
    . "00008B84248C0000008BB424980000000FAF84249C000000C1E6028974243401"
    . "F08BB4248C000000894424308B8424A0000000F7D885ED8D0486894424200F85"
    . "800300008B44247CC744241C00000000C744242400000000C1E8100FB6E88B44"
    . "247C0FB6C4894424100FB644247C894424148B8424A0000000C1E0028944242C"
    . "8B8424A400000085C00F8EC60000008B7C24048B442430896C24188BAC24A000"
    . "000085ED0F8E8D0000008BB424880000008B6C242403AC24A800000001C60344"
    . "242C8944242803842488000000894424040FB67E028B4C24180FB6160FB64601"
    . "2B5424142B44241089FB01CF29CB8D8F000400000FAFC00FAFCBC1E00B0FAFCB"
    . "BBFE05000029FB0FAFDA01C10FAFD301CA399424800000000F93450083C60483"
    . "C5013B74240475A98B9C24A0000000015C24248B4424288344241C0103442420"
    . "8B74241C39B424A40000000F854AFFFFFF897C24048B8424A00000002B8424B8"
    . "000000C644244B00C644244A00C744245000000000C744245C00000000894424"
    . "548B8424A40000002B8424BC000000894424388B84248400000083E80183F807"
    . "0F87BC05000083F803894424400F8EB70500008B44245C8B7424508944245089"
    . "74245C8B742454397424500F8F410A00008B4424548B742408C744242C000000"
    . "00894424588B8424AC0000008D04B08B7424408944244C89F083E00189442444"
    . "89F08BB4248800000083E003894424608B44245C8B7C243839F80F8F7E010000"
    . "837C2460018B4C24500F4F4C2458897C24288944241C894C243C8DB600000000"
    . "8B7C24448B44242885FF0F4444241C837C244003894424200F8FC2020000807C"
    . "244A008B44243C894424248B4424240F85CA020000807C244B000F8570030000"
    . "0FAF8424A00000008B14248B5C242085D28D2C180F8E850000008BBC24C40000"
    . "008B9424A800000031C08B9C24C0000000896C24308B4C24088974241801EA89"
    . "7C24148B2C248B7C240C895C2410669039C17E1C8B9C24AC0000008B348301D6"
    . "803E00750B836C2410010F885004000039C77E1C8B9C24B00000008B348301D6"
    . "803E00740B836C2414010F883004000083C00139E875B98B6C24308B7424188B"
    . "44240885C074278BBC24A80000008B8424AC0000008B5C244C8D0C2F8D742600"
    . "8B1083C00401CA39D8C6020075F28B442420038424980000008B5C242C8BBC24"
    . "C80000008904DF8B4424240384249C0000008944DF0483C3013B9C24CC000000"
    . "895C242C7D308344241C01836C2428018B44241C394424380F8DA2FEFFFF8344"
    . "245001836C2458018B442450394424540F8D5AFEFFFF8B44242C83C4645B5E5F"
    . "5DC2580083FD010F847207000083FD020F84DB0400008B44247C0FB67C247CC7"
    . "44242800000000C744242C00000000C1E8100FB6D08B44247C89D50FB6DC8B84"
    . "2480000000C1E8100FB6C88B84248000000029CD01D1896C243889DD894C2410"
    . "0FB6F40FB684248000000029F501DE896C241489FD8974241829C501F8894424"
    . "248B8424A0000000896C241CC1E002894424348B8424A400000085C00F8EF3FC"
    . "FFFF8B4C24308B6C24388B8424A000000085C00F8E880000008B842488000000"
    . "8B54242C039424A800000001C8034C243489CF894C243003BC2488000000EB34"
    . "395C24107C3D394C24147F37394C24187C3189F30FB6F33974241C0F9EC33974"
    . "24240F9DC183C00483C20121D9884AFF39C7741E0FB658020FB648010FB63039"
    . "DD7EBD31C983C00483C201884AFF39C775E28BB424A00000000174242C8B4C24"
    . "308344242801034C24208B442428398424A40000000F854FFFFFFFE935FCFFFF"
    . "8B442420807C244A00894424248B44243C894424208B4424240F8436FDFFFF0F"
    . "AF84248C0000008B1C248B4C242085DB8D2C880F8EF5FDFFFF8BBC24C0000000"
    . "31C9896C24108D76008DBC27000000008B8424AC0000008B5C2410031C888B84"
    . "24B00000008B2C880FB6441E0289EAC1EA100FB6D229D00FB6541E010FB61C1E"
    . "0FAFC03B4424047F2789E80FB6C429C20FAFD23B5424047F1789E80FB6C029C3"
    . "0FAFDB3B5C24047E108DB4260000000083EF010F887701000083C1013B0C2475"
    . "8F896C247CE964FDFFFF8DB6000000000FAF84248C0000008B4C24208D048889"
    . "4424100344247C0FB64C06010FB67C06020FB60406894C24148B0C2489442418"
    . "85C90F8E26FDFFFF8B8424C400000031DB894424348B8424C000000089442430"
    . "8B442404897C2404908DB42600000000395C24087E658B8424AC0000008B4C24"
    . "108B7C2404030C980FB6440E020FB6540E010FB60C0E2B5424142B4C241889C5"
    . "01F829FD8DB8000400000FAFD20FAFFDC1E20B0FAFFDBDFE05000029C50FAFE9"
    . "01FA0FAFCD01D1398C2480000000730B836C2430010F889E000000395C240C7E"
    . "618B8424B00000008B4C24108B7C2404030C980FB6440E020FB6540E010FB60C"
    . "0E2B5424142B4C241889C501F829FD8DB8000400000FAFD20FAFFDC1E20B0FAF"
    . "FDBDFE05000029C50FAFE901FA0FAFCD01D1398C24800000007207836C243401"
    . "783783C3013B1C240F8522FFFFFF89442404E917FCFFFF89F68DBC2700000000"
    . "8B742418E93DFCFFFF8DB42600000000896C247CE92DFCFFFF89442404E924FC"
    . "FFFFC7442440000000008B4424388B7424548944245489742438E944FAFFFF8B"
    . "84248000000031C931F631FF8904248B44247CC744247C000000000FAFC08944"
    . "24048B8424B40000000FB6108D5801EB2789FA8B8C24AC0000000FB7FFC1EA10"
    . "0FAF94248C0000008D14BA31FF8914B10FB61389C183C3010FBEC285C0743A8D"
    . "50D083FA0977078D14BF8D7C50D083F82F74070FB61384D275DB89C883F00185"
    . "C974AE8B8C24B0000000893CB189C10FB61383C60131FFEBBC897C247C83FD05"
    . "8B8424A00000000F9444244A83FD030F9444244B038424980000002B8424B800"
    . "0000894424548B84249C000000038424A40000002B8424BC000000894424388B"
    . "84249C000000C784249C00000000000000894424508B842498000000C7842498"
    . "000000000000008944245CE903F9FFFF8B44247C31D2F7B424B80000000FAF84"
    . "248C0000008D04908944247CE96CFFFFFF8B8424A00000008BB4249C0000000F"
    . "AF8424A400000083EE01038424A800000089742410894424188B8424A0000000"
    . "038424980000008944241C8B84249C000000038424A400000039F00F8C080100"
    . "008BB4249800000083C0012BAC2498000000894424288B44241CC74424240000"
    . "000083EE018974242C8B74241001C50FAFB4248C0000008D7801896C24308974"
    . "24208B44242C3944241C0F8C9B0000008B4C24108B5C24208B742424035C2434"
    . "2BB42498000000039C2488000000C1E91F03742418894C2414EB50908D742600"
    . "398424900000007E4B807C24140075448B4C2410398C24940000007E370FB64B"
    . "FE0FB653FD83C3040FB66BF86BD24B6BC92601D189EAC1E20429EA01CAC1FA07"
    . "8854060183C00139F8741889C2C1EA1F84D274ACC64406010083C00183C30439"
    . "F875E88B7424300174242483442410018B9C248C0000008B442410015C242039"
    . "4424280F8539FFFFFF8B8424A00000008B8C24A400000083C00285C98944241C"
    . "0F8E2FF7FFFF8B8424A40000008B6C2418036C241CC744241801000000C74424"
    . "200000000083C001894424248B8424A0000000896C241483C004894424288B84"
    . "24800000008B9424A000000085D20F8EA40000008B4424148B5C24208B742428"
    . "039C24A800000089C12B8C24A000000089C201C6894C2410908DB42600000000"
    . "0FB642010FB62ABF010000000344247C39E8723D0FB66A0239E872358B4C2410"
    . "0FB669FF39E872290FB66EFF39E872210FB669FE39E872190FB62939E872120F"
    . "B66EFE39E8720A0FB63E39F80F92C189CF89F9834424100183C201880B83C601"
    . "83C3018B4C2410394C241475938BBC24A0000000017C242083442418018B5C24"
    . "1C8B742418015C2414397424240F8532FFFFFF89842480000000E916F6FFFF8B"
    . "44247C8BB424A400000031EDC7442414000000008D48018B8424A0000000C1E1"
    . "07C1E00285F6894C247C894424180F8EE1F5FFFF896C24108B4424308B6C247C"
    . "8B9C24A000000085DB7E5F8B8C24880000008B5C2414039C24A800000001C103"
    . "4424188944241C0384248800000089C70FB651020FB641010FB6316BC04B6BD2"
    . "2601C289F0C1E00429F001D039C50F970383C10483C30139F975D58BBC24A000"
    . "0000017C24148B44241C8344241001034424208B74241039B424A40000007580"
    . "E950F5FFFFC744240800000000E9B9F3FFFFC744242C00000000E997F7FFFF90"
    x64:=""
    . "4157415641554154555756534881EC88000000488BBC24F0000000488BB42430"
    . "01000083F90589542468448944240844898C24E8000000488B9C243801000048"
    . "8BAC24400100000F84300900008B8424580100004531ED4531E485C00F8EDC00"
    . "0000448974240C448BB4245001000031D231C04889BC24F00000004889B42430"
    . "0100004531FF4531ED4531E4C704240000000089D789C6660F1F840000000000"
    . "4585F67E6548631424478D1C3E4489F848039424480100004189F8EB1F0F1F00"
    . "83C0014D63D54183C0044183C5014883C2014139C346894C9500742A83F90345"
    . "89C1440F45C8803A3175D583C0014D63D44183C0044183C4014883C2014139C3"
    . "46890C9375D64401342483C6014403BC242001000003BC24F800000039B42458"
    . "0100000F8577FFFFFF448B74240C488BBC24F0000000488BB4243001000031C0"
    . "4439A42460010000440F4DE04439AC2468010000440F4DE84539EC4589EF450F"
    . "4DFC83F9030F84270900008B8424F80000008B9424100100000FAF8424180100"
    . "008D04908B9424F8000000894424208B842420010000F7D885C98D0482890424"
    . "0F85C40300008B4C24684889C84189CB0FB6C441C1EB1089C20FB6C1450FB6DB"
    . "4189C28B84242801000085C00F8E370100008B842420010000448964242831C9"
    . "44896C24304889B42430010000448B6C2420448B6424088BB42420010000C1E0"
    . "0244897C24184889BC24F00000004889AC24400100004189CFC744240C000000"
    . "008944241089D748899C24380100004489D585F60F8E8A000000488B9C24F000"
    . "00004963C54531D24C8D4C030248635C240C48039C2430010000660F1F440000"
    . "450FB631410FB651FE410FB641FF29EA4489F14501DE4189D0418D9600040000"
    . "4429D929F80FAFD10FAFC00FAFD1C1E00B8D0402BAFE0500004429F2410FAFD0"
    . "410FAFD001D04139C4420F9304134983C2014983C1044439D67FA544036C2410"
    . "0174240C4183C70144032C244439BC24280100000F8558FFFFFF448B7C241844"
    . "8B642428448B6C2430488BBC24F0000000488BB42430010000488B9C24380100"
    . "00488BAC24400100008B8424200100002B842450010000C644245700C644244C"
    . "00C744246C00000000C744247800000000894424708B8424280100002B842458"
    . "010000894424408B8424E800000083E80183F8070F870606000083F803894424"
    . "480F8E010600008B4424788B4C246C8944246C894C24788B4C2470394C246C0F"
    . "8F350B00008B4424708B4C244848899C24380100004889AC24400100004489ED"
    . "4589E5C74424300000000089442474418D4424FF4C8BA42440010000488D4483"
    . "044889F3488BB42438010000488944246089C883E0018944245089C883E00389"
    . "44247C4489F04589FE4189C78B4424788B4C244039C80F8F3E010000837C247C"
    . "018B54246C0F4F542474894C2428890424895424448B44245085C08B4424280F"
    . "440424837C2448038944240C0F8FCF020000807C244C008B442444894424100F"
    . "85D7020000807C2457000F85700300008B4C24100FAF8C2420010000034C240C"
    . "4585F67E59448B942468010000448B8C246001000031C0660F1F840000000000"
    . "4139C589C27E184189C84403048642803C0300750A4183E9010F888500000039"
    . "D57E1289CA41031484803C130074064183EA01786F4883C0014139C67FC24585"
    . "ED741E4C8B4424604889F00F1F44000089CA03104883C0044C39C0C604130075"
    . "EF8B4C24308B54240C039424100100004C8B94247001000089C801C048984189"
    . "14828B54241003942418010000418954820489C883C0013B8424780100008944"
    . "24307D2E83042401836C2428018B0424394424400F8DDBFEFFFF8344246C0183"
    . "6C2474018B44246C394424700F8D9AFEFFFF8B4424304881C4880000005B5E5F"
    . "5D415C415D415E415FC383F9010F847108000083F9020F84370500008B542468"
    . "448B542408C744241000000000C74424180000000089D0440FB6C2C1E810440F"
    . "B6C84889D00FB6CC4489D04589CBC1E810894C240C0FB6D04C89D00FB6C44129"
    . "D34401CA89C18B44240C29C8034C240C89442430410FB6C24589C24129C24401"
    . "C0448B8424280100008944240C8B842420010000C1E0024585C0894424280F8E"
    . "05FDFFFF448974243C44896C244448899C2438010000448B742420448B6C2430"
    . "8B9C242001000044897C243844896424404189CF4889AC24400100004189D444"
    . "89D585DB7E784C635424184963C631D2488D4407024901F2EB37660F1F440000"
    . "4539C47C3E4139CD7F394139CF7C344439CD410F9EC044394C240C0F9DC14883"
    . "C0044421C141880C124883C20139D37E24440FB6000FB648FF440FB648FE4539"
    . "C37EBD31C94883C00441880C124883C20139D37FDC4403742428015C24188344"
    . "241001440334248B442410398424280100000F856AFFFFFF448B7C2438448B74"
    . "243C448B642440448B6C2444488B9C2438010000488BAC2440010000E908FCFF"
    . "FF8B44240C807C244C00894424108B4424448944240C0F8429FDFFFF8B442410"
    . "8B4C240C0FAF8424F80000004585F6448D14880F8EA8FDFFFF448B8C24600100"
    . "004531C04989DB660F1F840000000000428B1486438B1C844401D289D98D4202"
    . "C1E9100FB6C948980FB6040729C88D4A014863D20FAFC00FB614174863C90FB6"
    . "0C0F4439F87F1A0FB6C729C10FAFC94439F97F0D0FB6C329C20FAFD24439FA7E"
    . "0A4183E9010F88950100004983C0014539C67F9C895C24684C89DBE921FDFFFF"
    . "8B4424108B4C240C0FAF8424F80000008D048889C1034424684585F68D500248"
    . "63D2440FB614178D500148980FB604074863D20FB614170F8EE4FCFFFF448B9C"
    . "246801000048895C24584531C948897424184C8964242089CB89C64189D44489"
    . "5C243C448B9C246001000044895C24384539CD4589C87E6E488B442418428B14"
    . "8801DA8D42024898440FB63C078D42014863D20FB6141748980FB604074589FB"
    . "4501D7418D8F000400004529D329F2410FAFCB4429E00FAFC0410FAFCB41BBFE"
    . "050000C1E00B4529FB440FAFDA01C8410FAFD301C239542408730B836C243801"
    . "0F88A60000004439C57E6A488B442420428B148801DA8D42024898440FB63C07"
    . "8D42014863D20FB6141748980FB604074589F84501D7418D8F000400004529D0"
    . "29F2410FAFC84429E00FAFC0410FAFC841B8FE050000C1E00B4529F8440FAFC2"
    . "01C8410FAFD001C2395424087207836C243C0178374983C1014539CE0F8F0EFF"
    . "FFFF488B5C2458488B7424184C8B642420E9ABFBFFFF662E0F1F840000000000"
    . "895C24684C89DBE9D8FBFFFF488B5C2458488B7424184C8B642420E9C4FBFFFF"
    . "C7442448000000008B4424408B4C247089442470894C2440E9FAF9FFFF8B4424"
    . "68448B7C24084531C04531DB4531C94189C6440FAFF0488B8424480100000FB6"
    . "104C8D5001EB2B4489CA450FB7C94D63C3C1EA100FAF9424F8000000428D148A"
    . "4531C942891483410FB6124189C04983C2010FBEC285C074418D50D083FA0977"
    . "09438D1489448D4C50D083F82F7408410FB61284D275D74489C083F0014585C0"
    . "74A54963D34189C04183C30144894C95004531C9410FB612EBB444894C246883"
    . "F9058B8424200100000F9444244C83F9030F94442457038424100100002B8424"
    . "50010000894424708B842418010000038424280100002B842458010000894424"
    . "408B842418010000C7842418010000000000008944246C8B842410010000C784"
    . "24100100000000000089442478E9B5F8FFFF8B44246831D2F7B424500100000F"
    . "AF8424F80000008D049089442468E96CFFFFFF8B8424200100008B9424180100"
    . "000FAF842428010000448D5AFF48984801F0488904248B842420010000038424"
    . "100100008944240C8B842418010000038424280100004439D80F8C610100008B"
    . "94241001000083C001448B9424F8000000894424282B8C241001000044896424"
    . "48448BA4240001000083EA01C74424180000000044897C24408D049500000000"
    . "895424384489742444450FAFD344896C244C48899C2438010000894424204898"
    . "48894424308B44240C448954241001C1448D5001894C243C8B4424383944240C"
    . "0F8CA40000008B4C24108B5424204589DE488B5C24304C6344241841C1EE1F4C"
    . "03042401CA4C63F94863D24C8D0C174829D3EB514139C47E554584F675504439"
    . "9C24080100007E46410FB64902410FB6510183C0014983C0016BD24B6BC92601"
    . "D14A8D140B4983C104460FB62C3A4489EAC1E2044429EA01D1C1F907418848FF"
    . "4139C2741D89C2C1EA1F84D274A683C00141C600004983C1044983C0014139C2"
    . "75E38B5C243C015C24184183C3018B9C24F8000000015C241044395C24280F85"
    . "34FFFFFF448B7C2440448B742444448B642448448B6C244C488B9C2438010000"
    . "8B842420010000448B94242801000083C0024585D20F8E8EF6FFFF488B0C2448"
    . "9844897C24384889442410448B7C246848899C2438010000C704240100000048"
    . "8D440101C744240C00000000448974243C4889C18B8424280100004889CB83C0"
    . "01894424184863842420010000488D500348F7D048894424288B842420010000"
    . "48895424208B54240883E8014883C0014889442430448B8C24200100004585C9"
    . "0F8EAD000000488B44242048634C240C4C8D0C18488B4424284801F14C8D0418"
    . "488B4424304C8D34184889D80F1F40000FB610440FB650FF41BB010000004401"
    . "FA4439D2724A440FB650014439D27240450FB650FF4439D27236450FB651FF44"
    . "39D2722C450FB650FE4439D27222450FB6104439D27219450FB651FE4439D272"
    . "0F450FB6114439D2410F92C30F1F40004883C0014488194983C1014883C10149"
    . "83C0014C39F075888B8C2420010000014C240C8304240148035C24108B042439"
    . "4424180F852CFFFFFF448B7C2438448B74243C89542408488B9C2438010000E9"
    . "25F5FFFF8B8424200100008B5424684531DBC744240C00000000C1E00283C201"
    . "894424108B842428010000C1E2078954246885C00F8EEFF4FFFF44897C241848"
    . "899C2438010000448B7C2468448B9424200100008B5C242044897424284585D2"
    . "7E504C6374240C4863C34531C0488D4C07024901F60FB6110FB641FF440FB649"
    . "FE6BC04B6BD22601C24489C8C1E0044429C801D04139C7430F9704064983C001"
    . "4883C1044539C27FCC035C2410440154240C4183C301031C2444399C24280100"
    . "00759A448B7C2418448B742428488B9C2438010000E94FF4FFFFC74424300000"
    . "0000E98BF6FFFF909090909090909090"
    this.MCode(MyFunc, A_PtrSize=8 ? x64:x32)
  }
  num:=info.Length(), j:=info[index]
  , text:=j[1], w:=j[2], h:=j[3]
  , e1:=(!j[12] ? Floor(j[4]*err1) : j[6])
  , e0:=(!j[12] ? Floor(j[5]*err0) : j[7])
  , mode:=j[8], color:=j[9], n:=j[10], comment:=j[11]
  , sx:=ini.sx, sy:=ini.sy, sw:=ini.sw, sh:=ini.sh
  if (JoinText and index>1)
  {
    x:=ini.x, y:=ini.y, sw:=Min(x+offsetX+w,sx+sw), sx:=x, sw-=sx
    , sh:=Min(y+offsetY+h,sy+sh), sy:=Max(y-offsetY,sy), sh-=sy
  }
  ok:=!bits.Scan0 ? 0 : DllCall(&MyFunc
    , "int",mode, "uint",color, "uint",n, "int",dir
    , "Ptr",bits.Scan0, "int",bits.Stride
    , "int",ini.zw, "int",ini.zh
    , "int",sx, "int",sy, "int",sw, "int",sh
    , "Ptr",&ss, "Ptr",&s1, "Ptr",&s0
    , "AStr",text, "int",w, "int",h, "int",e1, "int",e0
    , "Ptr",&allpos, "int",allpos_max)
  pos:=[]
  Loop % ok
    pos[A_Index]:=NumGet(allpos, 8*A_Index-8, "uint")
      | NumGet(allpos, 8*A_Index-4, "uint")<<32
  Loop % ok
  {
    x:=pos[A_Index], y:=x>>32, x:=x&0xFFFFFFFF
    if (!JoinText)
    {
      x1:=x+ini.zx, y1:=y+ini.zy
      , arr.Push( {1:x1, 2:y1, 3:w, 4:h
      , x:x1+w//2, y:y1+h//2, id:comment} )
    }
    else if (index=1)
    {
      ini.x:=x+w, ini.y:=y, ini.minY:=y, ini.maxY:=y+h
      Loop % num-1
        if !this.PicFind(arr, ini, info, A_Index+1, err1, err0
        , FindAll, JoinText, offsetX, offsetY, 5
        , bits, ss, s1, s0, allpos, 1)
          Continue, 2
      x1:=x+ini.zx, y1:=ini.minY+ini.zy
      , w1:=ini.x-x, h1:=ini.maxY-ini.minY
      , arr.Push( {1:x1, 2:y1, 3:w1, 4:h1
      , x:x1+w1//2, y:y1+h1//2, id:ini.comment} )
    }
    else
    {
      ini.x:=x+w, ini.y:=y
      , (y<ini.minY && ini.minY:=y)
      , (y+h>ini.maxY && ini.maxY:=y+h)
      return 1
    }
    if (!FindAll and arr.Length())
      return
  }
}

GetBitsFromScreen(ByRef x, ByRef y, ByRef w, ByRef h
  , ScreenShot:=1, ByRef zx:="", ByRef zy:=""
  , ByRef zw:="", ByRef zh:="")
{
  local
  bits:=this.bits
  if (!ScreenShot)
  {
    zx:=bits.zx, zy:=bits.zy, zw:=bits.zw, zh:=bits.zh
    if IsByRef(x)
      w:=Min(x+w,zx+zw), x:=Max(x,zx), w-=x
      , h:=Min(y+h,zy+zh), y:=Max(y,zy), h-=y
    return bits
  }
  bch:=A_BatchLines, cri:=A_IsCritical
  Critical
  if (id:=this.BindWindow(0,0,1))
  {
    WinGet, id, ID, ahk_id %id%
    WinGetPos, zx, zy, zw, zh, ahk_id %id%
  }
  if (!id)
  {
    SysGet, zx, 76
    SysGet, zy, 77
    SysGet, zw, 78
    SysGet, zh, 79
  }
  bits.zx:=zx, bits.zy:=zy, bits.zw:=zw, bits.zh:=zh
  , w:=Min(x+w,zx+zw), x:=Max(x,zx), w-=x
  , h:=Min(y+h,zy+zh), y:=Max(y,zy), h-=y
  if (zw>bits.oldzw or zh>bits.oldzh or !bits.hBM)
  {
    hBM:=bits.hBM
    , bits.hBM:=this.CreateDIBSection(zw, zh, bpp:=32, ppvBits)
    , bits.Scan0:=(!bits.hBM ? 0:ppvBits)
    , bits.Stride:=((zw*bpp+31)//32)*4
    , bits.oldzw:=zw, bits.oldzh:=zh
    , DllCall("DeleteObject", "Ptr",hBM)
  }
  if (w<1 or h<1 or !bits.hBM)
  {
    Critical, %cri%
    SetBatchLines, %bch%
    return bits
  }
  if IsFunc(k:="GetBitsFromScreen2")
    and %k%(bits, x-zx, y-zy, w, h)
  {
    zx:=bits.zx, zy:=bits.zy, zw:=bits.zw, zh:=bits.zh
    Critical, %cri%
    SetBatchLines, %bch%
    return bits
  }
  mDC:=DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
  oBM:=DllCall("SelectObject", "Ptr",mDC, "Ptr",bits.hBM, "Ptr")
  if (id)
  {
    if (mode:=this.BindWindow(0,0,0,1))<2
    {
      hDC2:=DllCall("GetDCEx", "Ptr",id, "Ptr",0, "int",3, "Ptr")
      DllCall("BitBlt","Ptr",mDC,"int",x-zx,"int",y-zy,"int",w,"int",h
        , "Ptr",hDC2, "int",x-zx, "int",y-zy, "uint",0xCC0020|0x40000000)
      DllCall("ReleaseDC", "Ptr",id, "Ptr",hDC2)
    }
    else
    {
      hBM2:=this.CreateDIBSection(zw, zh)
      mDC2:=DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
      oBM2:=DllCall("SelectObject", "Ptr",mDC2, "Ptr",hBM2, "Ptr")
      DllCall("PrintWindow", "Ptr",id, "Ptr",mDC2, "uint",(mode>3)*3)
      DllCall("BitBlt","Ptr",mDC,"int",x-zx,"int",y-zy,"int",w,"int",h
        , "Ptr",mDC2, "int",x-zx, "int",y-zy, "uint",0xCC0020|0x40000000)
      DllCall("SelectObject", "Ptr",mDC2, "Ptr",oBM2)
      DllCall("DeleteDC", "Ptr",mDC2)
      DllCall("DeleteObject", "Ptr",hBM2)
    }
  }
  else
  {
    win:=DllCall("GetDesktopWindow", "Ptr")
    hDC:=DllCall("GetWindowDC", "Ptr",win, "Ptr")
    DllCall("BitBlt","Ptr",mDC,"int",x-zx,"int",y-zy,"int",w,"int",h
      , "Ptr",hDC, "int",x, "int",y, "uint",0xCC0020|0x40000000)
    DllCall("ReleaseDC", "Ptr",win, "Ptr",hDC)
  }
  if this.CaptureCursor(0,0,0,0,0,1)
    this.CaptureCursor(mDC, zx, zy, zw, zh)
  DllCall("SelectObject", "Ptr",mDC, "Ptr",oBM)
  DllCall("DeleteDC", "Ptr",mDC)
  Critical, %cri%
  SetBatchLines, %bch%
  return bits
}

CreateDIBSection(w, h, bpp:=32, ByRef ppvBits:=0, ByRef bi:="")
{
  VarSetCapacity(bi, 40, 0), NumPut(40, bi, 0, "int")
  , NumPut(w, bi, 4, "int"), NumPut(-h, bi, 8, "int")
  , NumPut(1, bi, 12, "short"), NumPut(bpp, bi, 14, "short")
  return DllCall("CreateDIBSection", "Ptr",0, "Ptr",&bi
    , "int",0, "Ptr*",ppvBits:=0, "Ptr",0, "int",0, "Ptr")
}

PicInfo(text)
{
  local
  static info:=[]
  if !InStr(text,"$")
    return
  key:=(r:=StrLen(text))<1000 ? text
    : DllCall("ntdll\RtlComputeCrc32", "uint",0
    , "Ptr",&text, "uint",r*(1+!!A_IsUnicode), "uint")
  if (info[key])
    return info[key]
  v:=text, comment:="", seterr:=e1:=e0:=0
  ; You Can Add Comment Text within The <>
  if RegExMatch(v,"<([^>\n]*)>",r)
    v:=StrReplace(v,r), comment:=Trim(r1)
  ; You can Add two fault-tolerant in the [], separated by commas
  if RegExMatch(v,"\[([^\]\n]*)]",r)
  {
    v:=StrReplace(v,r), r:=StrSplit(r1, ",")
    , seterr:=1, e1:=r[1], e0:=r[2]
  }
  color:=StrSplit(v,"$")[1], v:=Trim(SubStr(v,InStr(v,"$")+1))
  mode:=InStr(color,"##") ? 5
    : InStr(color,"-") ? 4 : InStr(color,"#") ? 3
    : InStr(color,"**") ? 2 : InStr(color,"*") ? 1 : 0
  color:=RegExReplace(color, "[*#\s]")
  if (mode=5)
  {
    if (v~="[^\s\w/]") and FileExist(v)  ; ImageSearch
    {
      if !(hBM:=LoadPicture(v))
        return
      this.GetBitmapWH(hBM, w, h)
      if (w<1 or h<1)
        return
      hBM2:=this.CreateDIBSection(w, h, 32, Scan0)
      this.CopyHBM(hBM2, 0, 0, hBM, 0, 0, w, h)
      DllCall("DeleteObject", "Ptr",hBM)
      if (!Scan0)
        return
      c1:=NumGet(Scan0+0,"uint")&0xFFFFFF
      c2:=NumGet(Scan0+(w-1)*4,"uint")&0xFFFFFF
      c3:=NumGet(Scan0+(w*h-w)*4,"uint")&0xFFFFFF
      c4:=NumGet(Scan0+(w*h-1)*4,"uint")&0xFFFFFF
      if (c1!=c2 or c1!=c3 or c1!=c4)
        c1:=-1
      VarSetCapacity(v, w*h*18*(1+!!A_IsUnicode)), i:=-4, n:=0
      SetFormat, IntegerFast, d
      Loop %h%
      {
        y:=A_Index-1
        Loop %w%
          if (c:=NumGet(Scan0+(i+=4),"uint")&0xFFFFFF)!=c1
            v.=((A_Index-1)|y<<16) "/" c "/", n++
      }
      DllCall("DeleteObject", "Ptr",hBM2)
    }
    else
    {
      v:=Trim(StrReplace(RegExReplace(v,"\s"),",","/"),"/")
      r:=StrSplit(v,"/"), n:=r.Length()//3
      if (!n)
        return
      VarSetCapacity(v, n*18*(1+!!A_IsUnicode))
      x1:=x2:=r[1], y1:=y2:=r[2]
      SetFormat, IntegerFast, d
      Loop % n + (i:=-2)*0
        x:=r[i+=3], y:=r[i+1]
        , (x<x1 && x1:=x), (x>x2 && x2:=x)
        , (y<y1 && y1:=y), (y>y2 && y2:=y)
      Loop % n + (i:=-2)*0
        v.=(r[i+=3]-x1)|(r[i+1]-y1)<<16 . "/"
        . Floor("0x" StrReplace(r[i+2],"0x"))&0xFFFFFF . "/"
      w:=x2-x1+1, h:=y2-y1+1
    }
    len1:=n, len0:=0
  }
  else
  {
    r:=StrSplit(v,"."), w:=r[1]
    , v:=this.base64tobit(r[2]), h:=StrLen(v)//w
    if (w<1 or h<1 or StrLen(v)!=w*h)
      return
    if (mode=4)
    {
      r:=StrSplit(StrReplace(color,"0x"),"-")
      , color:=Round("0x" r[1]), n:=Round("0x" r[2])
    }
    else
    {
      r:=StrSplit(color,"@")
      , color:=r[1], n:=Round(r[2],2)+(!r[2])
      , n:=Floor(512*9*255*255*(1-n)*(1-n))
    }
    StrReplace(v,"1","",len1), len0:=StrLen(v)-len1
  }
  e1:=Floor(len1*e1), e0:=Floor(len0*e0)
  return info[key]:=[v, w, h, len1, len0, e1, e0
    , mode, color, n, comment, seterr]
}

GetBitmapWH(hbm, ByRef w, ByRef h)
{
  local
  VarSetCapacity(bm, size:=(A_PtrSize=8 ? 32:24), 0)
  r:=DllCall("GetObject", "Ptr",hbm, "int",size, "Ptr",&bm)
  w:=NumGet(bm,4,"int"), h:=Abs(NumGet(bm,8,"int"))
  return r
}

CopyHBM(hBM1, x1, y1, hBM2, x2, y2, w2, h2)
{
  local
  mDC1:=DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
  oBM1:=DllCall("SelectObject", "Ptr",mDC1, "Ptr",hBM1, "Ptr")
  mDC2:=DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
  oBM2:=DllCall("SelectObject", "Ptr",mDC2, "Ptr",hBM2, "Ptr")
  DllCall("BitBlt", "Ptr",mDC1
    , "int",x1, "int",y1, "int",w2, "int",h2, "Ptr",mDC2
    , "int",x2, "int",y2, "uint",0xCC0020)
  DllCall("SelectObject", "Ptr",mDC2, "Ptr",oBM2)
  DllCall("DeleteDC", "Ptr",mDC2)
  DllCall("SelectObject", "Ptr",mDC1, "Ptr",oBM1)
  DllCall("DeleteDC", "Ptr",mDC1)
}

CopyBits(Scan01,Stride1,x1,y1,Scan02,Stride2,x2,y2,w2,h2,Reverse:=0)
{
  local
    p1:=Scan01+(y1-1)*Stride1+x1*4
  , p2:=Scan02+(y2-1)*Stride2+x2*4, w2*=4
  if (Reverse)
    p2+=(h2+1)*Stride2, Stride2:=-Stride2
  Loop % h2
    DllCall("RtlMoveMemory","Ptr",p1+=Stride1,"Ptr",p2+=Stride2,"Ptr",w2)
}

; 绑定窗口从而可以后台查找这个窗口的图像
; 相当于始终在前台。解绑窗口使用 FindText().BindWindow(0)

BindWindow(bind_id:=0, bind_mode:=0, get_id:=0, get_mode:=0)
{
  local
  bind:=this.bind
  if (get_id)
    return bind.id
  if (get_mode)
    return bind.mode
  if (bind_id)
  {
    bind.id:=bind_id, bind.mode:=bind_mode, bind.oldStyle:=0
    if (bind_mode & 1)
    {
      WinGet, oldStyle, ExStyle, ahk_id %bind_id%
      bind.oldStyle:=oldStyle
      WinSet, Transparent, 255, ahk_id %bind_id%
      Loop 30
      {
        Sleep, 100
        WinGet, i, Transparent, ahk_id %bind_id%
      }
      Until (i=255)
    }
  }
  else
  {
    bind_id:=bind.id
    if (bind.mode & 1)
      WinSet, ExStyle, % bind.oldStyle, ahk_id %bind_id%
    bind.id:=0, bind.mode:=0, bind.oldStyle:=0
  }
}

; 使用 FindText().CaptureCursor(1) 设置抓图时捕获鼠标
; 使用 FindText().CaptureCursor(0) 取消抓图时捕获鼠标

CaptureCursor(hDC:=0, zx:=0, zy:=0, zw:=0, zh:=0, get_cursor:=0)
{
  local
  if (get_cursor)
    return this.Cursor
  if (hDC=1 or hDC=0) and (zw=0)
  {
    this.Cursor:=hDC
    return
  }
  VarSetCapacity(mi, 40, 0), NumPut(16+A_PtrSize, mi, "int")
  DllCall("GetCursorInfo", "Ptr",&mi)
  bShow   := NumGet(mi, 4, "int")
  hCursor := NumGet(mi, 8, "Ptr")
  x := NumGet(mi, 8+A_PtrSize, "int")
  y := NumGet(mi, 12+A_PtrSize, "int")
  if (!bShow) or (x<