Jump to content

Anything faster than Pixelgetcolor ?


Recommended Posts

Currently writing a bot to peridically check 100 pixels

Turns out its kinda slow .

Friend wrote something similiar in c# and get can get 280 pixels in 0.1 sec

I get my 100 done in about 1 sec...

Dont get me wrong , it works its just 10x slower.

Pixelsearch only returns the first pixel encountered so its not what i need.

Pixelchecksum is not 100% secure so i passed on that...

Thanks

Link to comment
Share on other sites

Currently writing a bot to peridically check 100 pixels

Turns out its kinda slow .

Friend wrote something similiar in c# and get can get 280 pixels in 0.1 sec

I get my 100 done in about 1 sec...

Dont get me wrong , it works its just 10x slower.

Pixelsearch only returns the first pixel encountered so its not what i need.

Pixelchecksum is not 100% secure so i passed on that...

Thanks

You can change the pixelsearch step, more step == faster searching.

Link to comment
Share on other sites

You can change the pixelsearch step, more step == faster searching.

Thanks but like i said its not what i need

pixel search returns one , the first pixel , with the color tested.

I kinda need to check all 100 pixels for 5 diferent colours and take action on that.

If pixel search returned an array of locations in a rectangle where that colour could be found it might help but it doesnt

Link to comment
Share on other sites

Thanks but like i said its not what i need

pixel search returns one , the first pixel , with the color tested.

I kinda need to check all 100 pixels for 5 diferent colours and take action on that.

If pixel search returned an array of locations in a rectangle where that colour could be found it might help but it doesnt

Well, you can run 5 pixelsearches, but as you said thats not optimal.

I have a code in Pascal that searches for any 256 colours in a rectangle and returns the needed coordinates in an array. Unfortunately it can't be transfered to Autoit.

I guess the only thing you could do is make your own, maybe a more experienced Autoit user will prove me wrong though.

#Edit: I just remmebered this script I made.

$File = FileOpen("Test.txt", 1);Or any other name.txt
For $i = 0 to 100 step 1;Search from X=0 to X=10
    For $j = 0 to 150 step 1;Search from Y=0 to Y=150
$I_Found_This_Pixel = PixelGetColor( $i, $j )
FileWrite ( $file, "X is: " & $i & ", Y is: " & $j & $I_Found_This_Pixel & @CRLF )
Next
Next

It will search for any colours in a certain range. Then it will write them to a .txt file for your observing.

You can modify it to write to .ini files, this will make accesing results easier.

Edited by Qousio
Link to comment
Share on other sites

Well, you can run 5 pixelsearches, but as you said thats not optimal.

I have a code in Pascal that searches for any 256 colours in a rectangle and returns the needed coordinates in an array. Unfortunately it can't be transfered to Autoit.

I guess the only thing you could do is make your own, maybe a more experienced Autoit user will prove me wrong though.

#Edit: I just remmebered this script I made.

$File = FileOpen("Test.txt", 1);Or any other name.txt
For $i = 0 to 100 step 1;Search from X=0 to X=10
    For $j = 0 to 150 step 1;Search from Y=0 to Y=150
$I_Found_This_Pixel = PixelGetColor( $i, $j )
FileWrite ( $file, "X is: " & $i & ", Y is: " & $j & $I_Found_This_Pixel & @CRLF )
Next
Next

It will search for any colours in a certain range. Then it will write them to a .txt file for your observing.

You can modify it to write to .ini files, this will make accesing results easier.

Heres sample of code

for $n = 1 to 280 step +1

$here = PixelGetColor(63+$n , 848)

If $here == 0 then

$straring = $straring & "A"

ElseIf $here == 4671303 then

$straring = $straring & "B"

ElseIf $here == 15458991 Then

$straring = $straring & "C"

ElseIf $here == 2171169 then

$straring = $straring & "D"

Else

$straring = $straring & "E"

EndIf

Next

The string gets added to a dictionary and actions are taken based on the look up of that string in that dictionary in run time.

$oDictionary.ADD ($straring, $key)

There are 2 dictionaries and 20k variants on strings.

Code works

Problem is it takes 2 secs to run those 10 lines of code.

And those lines are run ... "alot"

Is there any way to import or include c# code to au3 ? Can i run c# getpixel in an au3 script ?

For those just checking this topic now , aparently c# getpixel is 10x faster.

Thanks again.

Link to comment
Share on other sites

Heres sample of code

for $n = 1 to 280 step +1

$here = PixelGetColor(63+$n , 848)

If $here == 0 then

$straring = $straring & "A"

ElseIf $here == 4671303 then

$straring = $straring & "B"

ElseIf $here == 15458991 Then

$straring = $straring & "C"

ElseIf $here == 2171169 then

$straring = $straring & "D"

Else

$straring = $straring & "E"

EndIf

Next

The string gets added to a dictionary and actions are taken based on the look up of that string in that dictionary in run time.

$oDictionary.ADD ($straring, $key)

There are 2 dictionaries and 20k variants on strings.

Code works

Problem is it takes 2 secs to run those 10 lines of code.

And those lines are run ... "alot"

Is there any way to import or include c# code to au3 ? Can i run c# getpixel in an au3 script ?

For those just checking this topic now , aparently c# getpixel is 10x faster.

Thanks again.

The DirectX's pixel warp is even faster :)

Anyhow, we should let the professional Autoiters read this topic. I'm also interested in this.

Link to comment
Share on other sites

Is there any way to import or include c# code to au3 ? Can i run c# getpixel in an au3 script ?

For those just checking this topic now , aparently c# getpixel is 10x faster.

Thanks again.

Of course YES.

Look at DllCall() and/or PluginOpen().

You can make your speed optimized PixelGet function in C++ or assembler or whatever else and compile it as DLL.

Then call this from AutoIt by DllCall().

Edited by Zedna
Link to comment
Share on other sites

$straring=""
$timer=TimerInit()
for $n = 1 to 280 step +1
$here = PixelGetColor(63+$n , 848)
If $here == 0 then 
$straring &= "A" 
ElseIf $here == 4671303 then 
$straring &= "B"
ElseIf $here == 15458991 Then 
$straring &= "C"
ElseIf $here == 2171169 then 
$straring &= "D"
Else 
$straring &=  "E"
EndIf
Next
$td=TimerDiff($timer)
ConsoleWrite($td)

this took 4.55464 milliseconds

Link to comment
Share on other sites

  • Moderators

Just note: AutoIt uses GetPixel Win32 API function

http://msdn.microsoft.com/en-us/library/dd144909(VS.85).aspx

I don't think that's true any longer. I think Valik re-wrote them using bitblt.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

This way of getting pixel colours appears to be faster than your friend's getting 280 pixels in 0.1 sec.

On my XP on a 10x28 image (280 pixels),the results are 0.0111secs getting the pixels, and a further 0.0026secs getting info out of the pixel data.

Also appears to be faster than the tests conducted at

http://www.autoitscript.com/forum/index.ph...st&p=658071

Comparative results are

_ImageGetPixels (All Pixels)320x240

100%: 644.033808766198 milliseconds

Average: 0.00838655529776364 milliseconds per pixel

All results are written to console.

;
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <Misc.au3>
; http://www.autoitscript.com/forum/index.php?s=&showtopic=91755&view=findpost&p=663576
Opt('MustDeclareVars', 1)

Global $width, $height, $hGUI1, $hImage, $hGraphic1
Global $iX, $iY, $sAllPixels, $GuiX = 320, $GuiY = 240, $init, $sStr
; Search colours are white, black, yellow, blue, and red in order, and in hex BBGGRRAA format.
Global $aSearchCols[5][2] = [["FFFFFFFF", 0],["000000FF", 0],["00FFFFFF", 0], _
        ["FF0000FF", 0],["0000FFFF", 0]]

_Main()

Func _Main()
; Capture top left corner of the screen
    _ScreenCapture_Capture(@MyDocumentsDir & "\GDIPlus_Image.png", 0, 0, $GuiX, $GuiY)

; Create a GUI for the original image
    $hGUI1 = GUICreate("Original", 400, 300, 0, 0)
    GUISetState()
    GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
; Initialize GDI+ library and load image
    _GDIPlus_Startup()
    $hImage = _GDIPlus_ImageLoadFromFile(@MyDocumentsDir & "\GDIPlus_Image.png")
    $iX = _GDIPlus_ImageGetWidth($hImage)
    $iY = _GDIPlus_ImageGetHeight($hImage)

; Draw original image
    $hGraphic1 = _GDIPlus_GraphicsCreateFromHWND($hGUI1)
    _GDIPlus_GraphicsDrawImage($hGraphic1, $hImage, 0, 0)

    $init = TimerInit()

; All pixels of image are in variable, $sAllPixels, inthe format:-
; BBGGRRAA BBGGRRAA BBGGRRAA ...
    $sAllPixels = _ImageGetPixels($hImage)
    ConsoleWrite("_ImageGetPixels (All Pixels)" & $GuiX & "x" & $GuiY & @CRLF & "100%: " & _
            TimerDiff($init) & @CRLF & "Average: " & TimerDiff($init) / ($GuiX * $GuiY) & @CRLF & @CRLF)

    $init = TimerInit()

; Find specific colours and the number of times each colour is occurring in image
    Local $sStr = ""
    For $x = 0 To UBound($aSearchCols) - 1
        StringReplace($sAllPixels, $aSearchCols[$x][0], $aSearchCols[$x][0])
        $aSearchCols[$x][1] = @extended
        $sStr &= $aSearchCols[$x][0] & " appears " & $aSearchCols[$x][1] & " times " & @CRLF
    Next

; Finds the RGB colour at X, Y position. This example $x,$y position are desktop coordinates.
    Local $x = 54, $y = 60, $col, $ColRGB
    $col = StringMid($sAllPixels, ($y * $GuiX + $x) * 9 + 1, 8);
    $ColRGB = "0x" & StringRegExpReplace($col, "(.{2})(.{2})(.{2})(.{2})", "\3\2\1")
;ConsoleWrite($x & ", " & $y & " $col = " & $ColRGB &  @CRLF)

    ConsoleWrite("Doing things with the pixel data time " & $GuiX & "x" & $GuiY & @CRLF & _
            "Play time: " & TimerDiff($init) & @CRLF & _
            "coordinates (x, y) " & $x & ", " & $y & " $col = " & $ColRGB & @CRLF & $sStr)

; Loop until user exits
    Do

    Until GUIGetMsg() = $GUI_EVENT_CLOSE

; Release resources
    _GDIPlus_GraphicsDispose($hGraphic1)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
EndFunc  ;==>_Main

Func _ImageGetPixels($hImage)
    Local $Reslt, $stride, $format, $Scan0, $iIW, $iIH, $hBitmap1
    Local $v_BufferA, $AllPixels, $sREResult1, $sResult

    $iIW = _GDIPlus_ImageGetWidth($hImage)
    $iIH = _GDIPlus_ImageGetHeight($hImage)

    $hBitmap1 = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iIW, $iIH, $GDIP_PXF32ARGB)

; Locks a portion of a bitmap for reading or writing
    $Reslt = _GDIPlus_BitmapLockBits($hBitmap1, 0, 0, $iIW, $iIH, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB)

;Get the returned values of _GDIPlus_BitmapLockBits ()
    $width = DllStructGetData($Reslt, "width")
    $height = DllStructGetData($Reslt, "height")
    $stride = DllStructGetData($Reslt, "stride")
    $format = DllStructGetData($Reslt, "format")
    $Scan0 = DllStructGetData($Reslt, "Scan0")

    $v_BufferA = DllStructCreate("byte[" & $height * $width * 4 & "]", $Scan0); Create DLL structure for all pixels
    $AllPixels = DllStructGetData($v_BufferA, 1)
;ConsoleWrite("$AllPixels, raw data, first 9 colours = " & StringRegExpReplace($AllPixels, "(.{98})(.*)", "\1") & @CRLF)

; Searches on this string - $sREResult1 whch has the prefix "0x"  removed, and a space put between pixels 8 characters long.
    $sREResult1 = StringRegExpReplace(StringTrimLeft($AllPixels, 2), "(.{8})", "\1 ")
;ConsoleWrite("$AllPixels, raw data, first 9 colours = " & StringRegExpReplace($sREResult1, "(.{98})(.*)", "\1") & @CRLF)

    _GDIPlus_BitmapUnlockBits($hBitmap1, $Reslt); releases the locked region
    Return $sREResult1
EndFunc  ;==>_ImageGetPixels

Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGUI1 Then _GDIPlus_GraphicsDrawImageRect($hGraphic1, $hImage, 0, 0, $width, $height)
    Return $GUI_RUNDEFMSG
EndFunc  ;==>MY_PAINT
;
Edited by Malkey
Link to comment
Share on other sites

  • Moderators

I looked into public AutoIt 3.1.0 sources.

Indeed, PixelGetColor() is using GetPixel() while PixelSearch() is using GetDIBits(). It wouldn't be required to get all the bits just to get a specific coordinate's pixel color.

If it still is horribly slow in Vista with Aero enabled, then ya'll are probably right.

@Authenticity.. Not sure if PixelSearch() uses GetDIBits() or GetDIBitSection(), but the confidence you had in that statement, you've probably read it somewhere (Or you're an incognito developer).

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...