还是图片取色的问题,有句代码看不懂是啥意思
本帖最后由 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
**** Hidden Message *****
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:09
**** 本内容被作者隐藏 ****
完美!高手啊,你竟然看懂这个
我看不懂的那段,你都直接去掉了,我还在学习上一段代码呢!
等我再理解一下你的代码!一脸懵逼啊! 现在论坛很厉害啊!以前我提的问题基本上都是自问自答,现在竟然有人回答,感动到流泪!
{:1_203:} 本帖最后由 heavenm 于 2019-8-5 23:42 编辑
zghwelcome 发表于 2019-8-5 22:09
**** 本内容被作者隐藏 ****
我主要想实现,某个区域范围内的图片随机抓取色点,对比画面是否在指定界面,抓取的色点最好颜色不要同一种
坐标点格式是,[顶部,左距,底部下,底部右],(用uiautomatorviewer读取出来的)
高手能直接帮我改出成品不,请你抽包烟:face (25):
没想到会有人回答,我以为得自问自答呢!
本来我手工抓色点的,结果发现每部不一样的手机,色点位置都不一样,直接懵逼了,每个不同的手机要抓一次色点,好麻烦!
所以想弄个自动抓取色点,然后在对比 你的项目太高深,我搞不懂啊 zghwelcome 发表于 2019-8-6 13:15
你的项目太高深,我搞不懂啊
没事没事,我自己改改,最关键的部分你已经帮我完成了!3Q 和图片像素一样结果是正确的,如果只截取部分,就不对了!
#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
我看说明_GDIPlus_BitmapLockBits写得是读取部分位图啊,咋不行呢! _GDIPlus_BitmapLockBits 的X,Y值可以定位起始坐标,
矩形宽度和高度是定义不了的,怎么取值都会按顺序来读取,并不会按矩形来读取图片内容!
,好吧!换个方法,是我呆了,我发现这句根本没用!
afan 发表于 2019-8-6 22:00
还是有用的,只是这里用处不大,帮你改了部分,试下
咦!感觉好像是这样子!我明天研究研究!我去,我都准备放弃了,受到鼓励!!感谢
快快留个联系方式,我请你喝奶茶!
本帖最后由 heavenm 于 2019-8-7 09:47 编辑
比较大的图片,如果 x,y 不为0 AU3会崩溃{:1_203:}
Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')
Local $sAllPixels = DllStructGetData($v_BufferA, 1)在这一句挂掉了