Jump to content

Pixel Search


Hypnotix
 Share

Recommended Posts

Well I am going to start off my first post on this forum with a question,(Yeah thats typical I know) Please accommodate me though.

I am using pixelsearch to find colors. (Im keeping this question as general as possible) When i use pixelsearch, it finds the color i want it to, but It fixates on that same instance of the color every time it is called (I want it to find unique instances of the color each time) Is this possible?

Thanks in advance!

Edited by Hypnotix
Link to comment
Share on other sites

Hypnotix

Welcome to these forums.

Recently, I created the function _PixelSearchNextInstance() for NoHAX who was looking for a way to get the position of the second instance of a colour using PixelSearch().

Your enquiry prompted me to create _PixelSearchNthInstance() function which continuously calls _PixelSearchNextInstance() function until the required number of instances of the colour are found.

#include <Array.au3>
#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <ScreenCapture.au3>

Opt("PixelCoordMode", 0) ;1=absolute, 0=relative, 2=client

Local $i_ColourToFind = 0xFF7F27 ; In RGB hex format(0xRRGGBB)
Local $i_ShadeVariation = 0x30 ; ±30 of each colour channel of 0xFF7F27
Local $i_FindInstance = 10 ; -1     ; ( -1 for every instance)

_GDIPlus_Startup()

; ===== Load specific image file ======
;Local $var = @ScriptDir & "\banner_160x400.png"
;Local $hImage = _GDIPlus_ImageLoadFromFile($var)

; or

;#cs ; ===== Select image file  ======
Local $var = FileOpenDialog("Select image", @ScriptDir & "\", "Images (*.gif;*.png;*.jpg;*.bmp)|All (*.*)", 1 + 2)
If @error Then
    MsgBox(0, "", "No File(s) chosen", 2)
    Exit
EndIf
Local $hImage = _GDIPlus_ImageLoadFromFile($var)
;#ce

; or ===== Screen capture =====
;Local $var = _ScreenCapture_Capture("", 0, 0, 200, 200, False)
;Local $hImage = _GDIPlus_BitmapCreateFromHBITMAP($var)


Local $iX = _GDIPlus_ImageGetWidth($hImage)
Local $iY = _GDIPlus_ImageGetHeight($hImage)

Local $hWhnd = GUICreate("", $iX, $iY, 0, 0, $WS_POPUPWINDOW, $WS_EX_TOPMOST)

Local $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWhnd)
GUIRegisterMsg($WM_PAINT, "MY_WM_PAINT")
GUISetState()

$aPixelPos = _PixelSearchNthInstance(0, 0, $iX, $iY, $i_ColourToFind, $i_ShadeVariation, $i_FindInstance)

If @error Then
    MsgBox(0, "Results", $aPixelPos[0][0] & " instances of 0x" & Hex($i_ColourToFind, 6) & " found.")
Else
    MsgBox(0, "Results", $aPixelPos[0][0] & " instance of 0x" & Hex($i_ColourToFind, 6) & _
            " found at X, Y coordinadtes " & $aPixelPos[$aPixelPos[0][0]][0] & ", " & $aPixelPos[$aPixelPos[0][0]][1])
EndIf

_ArrayDisplay($aPixelPos)

; Clean up resources
_WinAPI_DeleteObject($var)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()


; Description: Will fill an array up to the nth instance (or the number of instances if less than nth instance) of a colour's
;                               x, y coordinates and the actual colour at those coordinates.
; Parameters:-
; $iLeft, $iTop, $iRight, $iBottom, $iColor, and $iShadeVariation are same as PixelSearch() function
; $iInstance - (Default 1) Finds the $iInstance instance of the $iColor with $iShadeVariation variation.
;                               "-1" returns all instances found
; Returns:
;           A 2D array of pixel's coordinates. (Array[1 ..n][0] = x, Array[1 ..n][1] = y, Array[1 ..n][2] = Actual pixel coour found)
;               with the number of matching pixels found in Array[0][0].
;   Success: Last row of elements in array contain the requested instance of the colour with @error = 0
; Failure: Sets @error to 1 if requested instance is not found. Array contain all instance that were found.
; Requires function  _PixelSearchNextInstance()
;
Func _PixelSearchNthInstance($iLeft, $iTop, $iRight, $iBottom, $iColor, $iShadeVariation = 0, $iInstance = 1)
    Local $aNextPixelPos
    Local $aCoord1stFind = PixelSearch($iLeft, $iTop, $iRight, $iBottom, $i_ColourToFind, $i_ShadeVariation); First instance of colour
    If Not @error Then
        If $iInstance = 1 Then Return SetError(0, 0, $aCoord1stFind)
    Else
        Local $aCoord1stFind[1][3] = [[0, 0, 0]]
        Return SetError(1, 0, $aCoord1stFind); If colour not found set error = 1
    EndIf
    If $iInstance = -1 Then $iInstance = Abs($iLeft - $iRight) * Abs($iTop - $iBottom)
    Local $aPixels[$iInstance + 1][3] = [[$iInstance, 0, "Colors Found"],[$aCoord1stFind[0], $aCoord1stFind[1], "0x" & Hex(PixelGetColor($aCoord1stFind[0], $aCoord1stFind[1]), 6)]]
    Local $aTemp = $aCoord1stFind
    For $i = 2 To $iInstance
        $aNextPixelPos = _PixelSearchNextInstance($aTemp, $iLeft, $iTop, $iRight, $iBottom, $i_ColourToFind, $i_ShadeVariation)
        If Not @error Then
            $aPixels[$i][0] = $aNextPixelPos[0]
            $aPixels[$i][1] = $aNextPixelPos[1]
            $aPixels[$i][2] = "0x" & Hex(PixelGetColor($aNextPixelPos[0], $aNextPixelPos[1]), 6)
            $aTemp = $aNextPixelPos
        Else
            $aPixels[0][0] = $i - 1
            ReDim $aPixels[$i][3]
            Return SetError(1, 0, $aPixels) ; Error = 1 required instance not found.
        EndIf
    Next
    Return SetError(0, 0, $aPixels)
EndFunc   ;==>_PixelSearchNthInstance

; Parameters:-
;   $aCoord1stFind - Array containing X,Y coordinates of previous pixel found.
;   $iLeft      - Left coordinate of rectangle.
;   $iTop       - Top coordinate of rectangle.
;   $iRight     - Right coordinate of rectangle.
;   $iBottom  - Bottom coordinate of rectangle.
;   $iColor     - Colour value of pixel to find (in decimal or hex).
;   $iShadeVariation [optional] - A number between 0 and 255 to indicate the allowed number of shades of
;                       variation of the red, green, and blue components of the colour. Default is 0 (exact match).
; http://www.autoitscript.com/forum/topic/123583-pixelsearch-problem/page__view__findpost__p__858571
Func _PixelSearchNextInstance($aCoord1stFind, $iLeft, $iTop, $iRight, $iBottom, $iColor, $iShadeVariation = 0)

    ; Check the rest of the line for 2nd instance of $iColor
    Local $coord = PixelSearch($aCoord1stFind[0] + 1, $aCoord1stFind[1], $iRight, $aCoord1stFind[1], $iColor, $iShadeVariation)
    If Not @error Then
        Return SetError(0, 0, $coord)
    Else ; 2nd instance Not on same line.

        ; Check all remaining lines for 2nd instance
        Local $coord = PixelSearch($iLeft, $aCoord1stFind[1] + 1, $iRight, $iBottom, $iColor, $iShadeVariation)
        If Not @error Then
            Return SetError(0, 0, $coord)
        Else ;Could not find 2nd instance of pixel.
            Return SetError(1, 0, 1); Set error to 1
        EndIf
    EndIf
EndFunc   ;==>_PixelSearchNextInstance

; Draw PNG image
Func MY_WM_PAINT($hWnd, $Msg, $wParam, $lParam)
    _WinAPI_RedrawWindow($hWhnd, 0, 0, $RDW_UPDATENOW)
    _GDIPlus_GraphicsDrawImage($hGraphic, $hImage, 0, 0)
    _WinAPI_RedrawWindow($hWhnd, 0, 0, $RDW_VALIDATE)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_WM_PAINT
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...