heavenm 发表于 2019-8-5 20:41:02

还是图片取色的问题,有句代码看不懂是啥意思

本帖最后由 heavenm 于 2019-8-5 20:42 编辑

#include <GDIPlus.au3>
#include <String.au3>
#include <Array.au3>

$FileErrPNG = FileRead(FileOpen('test.png', 16))
MsgBox(0, '', _bitmapGetColor($FileErrPNG, 9,9))



Func _bitmapGetColor($_hBitmap, $_iX, $_iY) ;成功则返回数组.失败返回0.
      Local $__begin_time = TimerInit()
      ;定义子程序必须的变量
      Local $BitmapData, $Scan0, $pixelData, $s_BMPData, $i_Stride
      ;初始化GDI+库
      _GDIPlus_Startup()
      ;如果调用函数时候没有指定宽和高, 则调用API获取宽和高.

      ;调用函数获取指定窗体的位图句柄.
;~         $hBMP = _WinCapture($hand, $iWidth, $iHeight)
      ;从位图句柄创建Bitmap对象
      $_hBitmap = _GDIPlus_BitmapCreateFromMemory($_hBitmap)
;~         $hBitmap = _GDIPlus_BitmapCreateFromFile($hBitmap)

;~         $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)
      ;如果未创建成功,则直接退出.未创建成功可能是因为无效的图形句柄
      If @error Then
                _GDIPlus_Shutdown()
                Return 0
      EndIf
      ;获取位图句柄的宽和高.
      $iWidth = $_iX + 5
      $iHeight = $_iY + 5
      ;锁定位图句柄中用于输入输出的部分. 将位图句柄中的数据格式格式化成24位的RGB格式.
      $BitmapData = _GDIPlus_BitmapLockBits($_hBitmap, 0, 0, $_iX, $_iY, $GDIP_ILMREAD, $GDIP_PXF24RGB)
      ;以下几句可能是BMP的数据格式, 我不懂. 这是大牛阿福给的
      $i_Stride = DllStructGetData($BitmapData, "Stride")
      $Scan0 = DllStructGetData($BitmapData, "Scan0")
      $pixelData = DllStructCreate("ubyte lData[" & (Abs($i_Stride) * $iHeight) & "]", $Scan0)
      $s_BMPData = DllStructGetData($pixelData, "lData")
      $s_BMPData = StringTrimLeft($s_BMPData, 2)
      ;解锁BMP位图数据区块.
      _GDIPlus_BitmapUnlockBits($_hBitmap, $BitmapData)
      ;销毁位图句柄
      _GDIPlus_ImageDispose($_hBitmap)
      ;删除位图对象.
      _WinAPI_DeleteObject($_hBitmap)
      ;关闭GDI库
      _GDIPlus_Shutdown()
      ;定义变量.
      Local $a_return[$iWidth][$iHeight], $s
      ;从位图数据中取出指定的那行.
;~         Local $a_return[$i_width][$i_height], $x = $i_width - 5, $y = $i_height - 5, $s
;~         $s = StringMid($s_BMPData, $y * ($i_Stride * 2) + 1, $i_width * 6)
      $s = StringMid($s_BMPData, $_iY * ($i_Stride * 2) + 1, $iWidth * 6)

      ;从该行中读出指定的那个坐标.
      $a_return[$_iX][$_iY] = StringMid($s, $_iX * 6 + 1, 6)
      ;BGR转RGB.
      $a_return[$_iX][$_iY] = StringRight($a_return[$_iX][$_iY], 2) & StringMid($a_return[$_iX][$_iY], 3, 2) & StringLeft($a_return[$_iX][$_iY], 2)
      
      ConsoleWrite(StringFormat('%s ][ %s \n', '_bitmapGetColor', TimerDiff($__begin_time)))
      Return StringLower($a_return[$_iX][$_iY])
EndFunc   ;==>_bitmapGetColor



我想实现把所有的颜色都写到数组里面,现在的代码只会把指定坐标的颜色输出
有些代码看不懂,比如这句
$_iY * ($i_Stride * 2) + 1

zghwelcome 发表于 2019-8-5 22:09:39

**** Hidden Message *****

afan 发表于 2019-8-6 22:00:37

heavenm 发表于 2019-8-6 20:52
_GDIPlus_BitmapLockBits 的X,Y值可以定位起始坐标,
矩形宽度和高度是定义不了的,怎么取值都会按顺序来读 ...

还是有用的,只是这里用处不大,帮你改了部分,试下
#include <GDIPlus.au3>

Local $sImageFile = @ScriptDir & '\6x6.png'
;~ Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')
Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')

$Form1 = GUICreate('Form1', 600, 600)
For $i = 0 To UBound($aAryImage) - 1;行
        For $x = 0 To UBound($aAryImage, 2) - 1
                $Label1 = GUICtrlCreateLabel($aAryImage[$i][$x], $x * 82, $i * 82, 80, 80)
                GUICtrlSetBkColor(-1, '0x' & $aAryImage[$i][$x])
                GUICtrlSetColor(-1, 0xffffff)
        Next
Next
GUISetState()
While GUIGetMsg() <> -3
WEnd

Func _BitmapGetColorToArray($__hBitmap, $__coordinate)
        Local $__begin_time = TimerInit()
        $__coordinate = StringRegExp($__coordinate, '\[(.+?)\]', 3)
        Local $__posi = StringSplit($__coordinate, ',', 2)
        Local $__size = StringSplit($__coordinate, ',', 2)

        _GDIPlus_Startup()
        Local $hImage = _GDIPlus_ImageLoadFromFile($__hBitmap)
        If @error Then
                _GDIPlus_Shutdown()
                Return SetError(1)
        EndIf

        Local $i_Width = _GDIPlus_ImageGetWidth($hImage)
        Local $i_Height = _GDIPlus_ImageGetHeight($hImage)
        Local $__x = $__posi
        Local $__y = $__posi
        Local $iIW = $__size - $__posi
        Local $iIH = $__size - $__posi
        ConsoleWrite(StringFormat('%s ][ x=%s y=%s w=%s h=%s \n', '_bitmapGetColor', $__x, $__y, $iIW, $iIH))

        Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage, $__x, $__y, 1, 1, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
        Local $Scan0 = DllStructGetData($tBitmapData, 'Scan0')
        Local $v_BufferA = DllStructCreate('byte[' & $i_Width * $i_Height * 4 & ']', $Scan0)
        Local $sAllPixels = DllStructGetData($v_BufferA, 1)
        $v_BufferA = 0
        _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
        _GDIPlus_ImageDispose($hImage)
        _GDIPlus_Shutdown()

        $sAllPixels = StringTrimLeft($sAllPixels, 2)
        $sAllPixels = StringRegExpReplace($sAllPixels, '(..)(..)(..)(..)', '${3}${2}${1}')
        $sAllPixels = StringMid($sAllPixels, 1, $i_Width * 6 * $iIH)
        $sAllPixels = StringRegExpReplace($sAllPixels, '(.{' & $i_Width * 6 & '})', '${1}' & @CRLF)
        $sAllPixels = StringRegExpReplace($sAllPixels, '(?m)^(.{' & $iIW * 6 & '}).*\v+', '${1}')
        Local $aReg = StringRegExp($sAllPixels, '(.{6})', 3)
        If @error Then Return SetError(2)
        If UBound($aReg) <> $iIH * $iIW Then Return SetError(4)
        Local $aRet[$iIH][$iIW], $h = 0, $w = 0
        For $i = 0 To UBound($aReg) - 1
                $aRet[$h][$w] = $aReg[$i]
                $w += 1
                If $w > $iIW - 1 Then
                        $w = 0
                        $h += 1
                EndIf
        Next
        ReDim $aReg
        $aReg = 0
        ConsoleWrite(StringFormat('%s ][ %s \n', '_bitmapGetColor', TimerDiff($__begin_time)))
        Return $aRet
EndFunc   ;==>_BitmapGetColorToArray

zghwelcome 发表于 2019-8-5 22:04:02

你确定你取的对应坐标的颜色值对吗

heavenm 发表于 2019-8-5 22:59:08

zghwelcome 发表于 2019-8-5 22:09
**** 本内容被作者隐藏 ****

完美!高手啊,你竟然看懂这个
我看不懂的那段,你都直接去掉了,我还在学习上一段代码呢!

等我再理解一下你的代码!一脸懵逼啊!

heavenm 发表于 2019-8-5 23:20:48

现在论坛很厉害啊!以前我提的问题基本上都是自问自答,现在竟然有人回答,感动到流泪!
{:1_203:}

heavenm 发表于 2019-8-5 23:40:05

本帖最后由 heavenm 于 2019-8-5 23:42 编辑

zghwelcome 发表于 2019-8-5 22:09
**** 本内容被作者隐藏 ****
我主要想实现,某个区域范围内的图片随机抓取色点,对比画面是否在指定界面,抓取的色点最好颜色不要同一种

坐标点格式是,[顶部,左距,底部下,底部右],(用uiautomatorviewer读取出来的)


高手能直接帮我改出成品不,请你抽包烟:face (25):
没想到会有人回答,我以为得自问自答呢!

heavenm 发表于 2019-8-5 23:46:20

本来我手工抓色点的,结果发现每部不一样的手机,色点位置都不一样,直接懵逼了,每个不同的手机要抓一次色点,好麻烦!
所以想弄个自动抓取色点,然后在对比

zghwelcome 发表于 2019-8-6 13:15:31

你的项目太高深,我搞不懂啊

heavenm 发表于 2019-8-6 16:11:18

zghwelcome 发表于 2019-8-6 13:15
你的项目太高深,我搞不懂啊

没事没事,我自己改改,最关键的部分你已经帮我完成了!3Q

heavenm 发表于 2019-8-6 19:59:23

和图片像素一样结果是正确的,如果只截取部分,就不对了!

#include <GDIPlus.au3>
#include <String.au3>
#include <Array.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Local $sImageFile = @ScriptDir & '\6x6.png'
Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')
;~ If Not @error Then _ArrayDisplay($aAryImage)

$Form1 = GUICreate("Form1", 600, 600)
For $i = 0 To UBound($aAryImage) - 1;行
        For $x=0 To UBound($aAryImage, 2) - 1
                $Label1 = GUICtrlCreateLabel($aAryImage[$i][$x], $x * 82,$i* 82, 80, 80)
                GUICtrlSetBkColor(-1, '0x' & $aAryImage[$i][$x])
                GUICtrlSetColor (-1, 0xffffff )
        Next
Next

GUISetState(@SW_SHOW)
While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit

        EndSwitch
WEnd

;~ MsgBox(0, '', _bitmapGetColor($FileErrPNG, 1, 1))
Func _BitmapGetColorToArray($__hBitmap, $__coordinate)
        Local $__begin_time = TimerInit()
        $__coordinate = _StringBetween($__coordinate, '[', ']');坐标组
        $__posi = StringSplit($__coordinate, ',', 2)
        $__size = StringSplit($__coordinate, ',', 2)
       
        _GDIPlus_Startup()
        Local $hImage = _GDIPlus_ImageLoadFromFile($__hBitmap)
        If @error Then
                _GDIPlus_Shutdown()
                Return SetError(1)
        EndIf
        Local $Scan0, $iIW, $iIH, $aReg
      Local $v_BufferA, $sAllPixels,$tBitmapData
;~         $iIW = _GDIPlus_ImageGetWidth($hImage)
;~         $iIH = _GDIPlus_ImageGetHeight($hImage)
        $__x = $__posi
        $__y = $__posi
        $iIW = $__size - $__posi
        $iIH = $__size - $__posi
        ConsoleWrite(StringFormat('%s ][ x=%s y=%s w=%s h=%s \n', '_bitmapGetColor', $__x, $__y, $iIW, $iIH))

        $tBitmapData = _GDIPlus_BitmapLockBits($hImage, $__x, $__y, $iIW, $iIH, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB)
        $Scan0 = DllStructGetData($tBitmapData, "Scan0")
        $v_BufferA = DllStructCreate("byte[" & $iIH * $iIW * 4 & "]", $Scan0)
        $sAllPixels = DllStructGetData($v_BufferA, 1)
        $v_BufferA = 0
        _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
        _GDIPlus_ImageDispose($hImage)
        _GDIPlus_Shutdown()

        $sAllPixels = StringTrimLeft($sAllPixels, 2)
        $sAllPixels = StringRegExpReplace($sAllPixels, "(.{2})(.{2})(.{2})(.{2})", "${3}${2}${1}")
        $aReg = StringRegExp($sAllPixels, '(.{6})', 3)
        If @error Then Return SetError(2)
        If UBound($aReg) <> $iIH * $iIW Then Return SetError(4)
        Local $aRet[$iIH][$iIW], $h = 0, $w = 0
        For $i = 0 To UBound($aReg) - 1
                $aRet[$h][$w] = $aReg[$i]
                $w += 1
                If $w > $iIW - 1 Then
                        $w = 0
                        $h += 1
                EndIf
        Next
        ReDim $aReg
        $aReg = 0
        ConsoleWrite(StringFormat('%s ][ %s \n', '_bitmapGetColor', TimerDiff($__begin_time)))
        Return $aRet
EndFunc   ;==>_BitmapGetColorToArray


heavenm 发表于 2019-8-6 20:12:33

我看说明_GDIPlus_BitmapLockBits写得是读取部分位图啊,咋不行呢!

heavenm 发表于 2019-8-6 20:52:56

_GDIPlus_BitmapLockBits 的X,Y值可以定位起始坐标,
矩形宽度和高度是定义不了的,怎么取值都会按顺序来读取,并不会按矩形来读取图片内容!
,好吧!换个方法,是我呆了,我发现这句根本没用!

heavenm 发表于 2019-8-7 02:32:13

afan 发表于 2019-8-6 22:00
还是有用的,只是这里用处不大,帮你改了部分,试下
咦!感觉好像是这样子!我明天研究研究!我去,我都准备放弃了,受到鼓励!!感谢
快快留个联系方式,我请你喝奶茶!

heavenm 发表于 2019-8-7 09:46:06

本帖最后由 heavenm 于 2019-8-7 09:47 编辑

比较大的图片,如果 x,y 不为0 AU3会崩溃{:1_203:}

Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')

Local $sAllPixels = DllStructGetData($v_BufferA, 1)在这一句挂掉了
页: [1] 2 3
查看完整版本: 还是图片取色的问题,有句代码看不懂是啥意思