Jump to content

AutoItX AU3_PixelSearch Access Violation


CultOfSun
 Share

Go to solution Solved by Andreik,

Recommended Posts

 

#include <iostream>
#include "AutoItX3_DLL.h"

int main()
{
    HINSTANCE dllHandle = LoadLibrary(TEXT("C:\\Users\\ccjen\\Desktop\\AutoX\\AutoItX3_x64.dll"));

    if (dllHandle) {

        POINT coords{};

        RECT searchCoords{};
        searchCoords.left = 688;
        searchCoords.top = 10;
        searchCoords.right = 762;
        searchCoords.bottom = 78;

        AU3_PixelSearch(&searchCoords, 0x000000, 0, 1, &coords);
        AU3_MouseMove(coords.x, coords.y);
        

        FreeLibrary(dllHandle);

    }
}

 

Link to comment
Share on other sites

Just now, TheDcoder said:

Did you check the result of PixelSearch? coords may not be properly initialized because it failed.

Could you inform me on how to properly do that? My original belief was that the result was being sent to the POINT struct "coords". I'm new to c++ if it's something simple I apologize, I appreciate the help.

Link to comment
Share on other sites

I'm not sure how AutoIt's DLL interface works (can't even find the documentation) but the PixelSearch function in the scripting language itself "sets the @error flag to 1" during failure. So you'd have to check for that somehow.

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

1 minute ago, Danp2 said:

@TheDcoder There's a help file under the AutoItX subdirectory.

I do recall something like that, but sadly I don't have quick access to it as I have AutoIt installed in my work VM. I searched for it on the internet and couldn't find it... maybe we can add it to the website just like the main help file?

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

The version I'm using is 3.3.16.1. Also I messed around with the code again. 

#include <iostream>
#include "AutoItX3_DLL.h"

int main()
{
    HINSTANCE dllHandle = LoadLibrary(TEXT("C:\\Users\\ccjen\\Desktop\\AutoX\\AutoItX3_x64.dll"));

    if (dllHandle) {

        POINT coords{};

        RECT searchCoords{};
        searchCoords.left = 688;
        searchCoords.top = 10;
        searchCoords.right = 762;
        searchCoords.bottom = 78;

        AU3_PixelSearch(&searchCoords, 0x000000, 0, 1, &coords);
        std::cout << AU3_error() << std::endl;

        //AU3_MouseMove(coords.x, coords.y);
        

        FreeLibrary(dllHandle);

    }
}

So I believed I may have narrowed it down. Every time I block the search area with visual studio it prints 1 in the console but when I unblock the search area it gives me the access violation. So could it be having trouble storing the coords in the POINT structure?

Link to comment
Share on other sites

Link to comment
Share on other sites

4 minutes ago, Nine said:

You need to pass individual coord not a structure. It is not returning a Point Structure but rather a 2 elements array.  Please see AutoItX help file for more informations.

AU3_API void WINAPI AU3_PixelSearch(LPRECT lpRect, int nCol, /*default 0*/int nVar, /*default 1*/int nStep, LPPOINT pPointResult);

This is from the header file 

Link to comment
Share on other sites

We may not speaking of the same thing :

Quote

PixelSearch

Searches a rectangle of pixels for the pixel color provided

PixelSearch left, top, right, bottom, color [, shade-variation] [, step]]

Parameters

left left coordinate of rectangle.
top top coordinate of rectangle.
right right coordinate of rectangle.
bottom bottom coordinate of rectangle.
color color value of pixel to find (in decimal or hex).
shade-variation 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 color. Default is 0 (exact match).
step Optional: Instead of searching each pixel use a value larger than 1 to skip pixels (for speed). E.g. A value of 2 will only check every other pixel. Default is 1.

Return Value

Success: Returns a 2 element array containing the pixel's coordinates
Failure: Sets oAutoIt.error to 1 if color is not found.

Remarks

The search is performed top-to-bottom, left-to-right, and the first match is returned.

Performing a search of a region can be time consuming, so use the smallest region you are able to reduce CPU load.

Related

PixelChecksum, PixelCoordMode (Option), PixelGetColor

Example

 
Set oAutoIt = WScript.CreateObject("AutoItX3.Control")

value = oAutoIt.PixelSearch(0,0, 100, 100, 0)
If oAutoIt.error = 1 Then
  WScript.Echo "Color not found"
Else
  WScript.Echo "Color found at: " & value(0) & "," & value(1)
End If


 

Link to comment
Share on other sites

1 minute ago, Nine said:

We may not speaking of the same thing :

 

Yeah this is autoitx for c++, you pass a pointer to the POINT struct. When I cover up the search area it prints 1 because it didn't find what it was looking for, when I uncover the area it gives an access violation for whatever reason my guess is it's not able to write the coords to the struct.

Link to comment
Share on other sites

@CultOfSun At this point I think you're better off implementing PixelSearch on your own, it doesn't look like a hard task to me. Certainly not harder than figuring out what's going wrong since there's lack of documentation as well as source code for inspection.

 

Alternatively one of the devs might be able to take a look but I won't count on that. You can ping jpm or Jos if desperate.

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

1 minute ago, TheDcoder said:

@CultOfSun At this point I think you're better off implementing PixelSearch on your own, it doesn't look like a hard task to me. Certainly not harder than figuring out what's going wrong since there's lack of documentation as well as source code for inspection.

 

Alternatively one of the devs might be able to take a look but I won't count on that. You can ping jpm or Jos if desperate.

I may ping them just to inform them, I've made a pixelsearch function it's just very slow. Thank you for your time! I'm gonna look into different ways I can speed up this pixel search function.

Link to comment
Share on other sites

I haven't seen it before but there might be GPL source code of AutoIt out there, so try looking for it and copy the code from there :)

Actually, nevermind. Just use this.

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

  • Solution

Your structure it's just fine and it's easy to test with AU3_MouseGetPos() that require the same POINT structure (example below)

#include <iostream>
#include "AutoItX3_DLL.h"

int main()
{
    POINT coords{};

    AU3_MouseGetPos(&coords);

    std::cout << coords.x << std::endl;
    std::cout << coords.y << std::endl;
    return 0;
}

I am not sure what is broken with AU3_PixelSearch(). Sometimes it works and sometimes I get segmentation faults and the only thing I changed in these cases is the color.

Based on an older version of AutoIt I suspect that AU3_PixelSearch() last parameter might not be a pointer to a POINT structure so this is why I get random segmentation faults but I cannot be sure without seeing the actual implementation. Anyway, here is an adaptation of PixelSearch() based on a previous AutoIt version. Note that current version might have been implemented this function in a different way.

#include <iostream>
#include "AutoItX3_DLL.h"

#define AUT_COORDMODE_WINDOW    0
#define AUT_COORDMODE_SCREEN    1
#define AUT_COORDMODE_CLIENT    2

void Util_RGBtoBGR(int &nCol)
{
    int nR = (nCol & 0xff0000) >> 16;
    int nG = (nCol & 0x00ff00);
    int nB = (nCol & 0x0000ff) << 16;
    nCol = nR | nG | nB;
}

void ConvertCoords(int nCoordMode, POINT &pt)
{
    HWND    hFore = GetForegroundWindow();
    RECT    rect;

    if (nCoordMode == AUT_COORDMODE_WINDOW)
    {
        GetWindowRect(hFore, &rect);
        pt.x = rect.left;
        pt.y = rect.top;
    }
    else if (nCoordMode == AUT_COORDMODE_CLIENT)
    {
        pt.x = 0;
        pt.y = 0;
        ClientToScreen(hFore, &pt);
    }
    else
    {
        pt.x = 0;
        pt.y = 0;
    }
}

int PixelSearch(LPRECT lpRect, int nCol, int nVar, int nStep, LPPOINT pPointResult, int nCoordPixelMode = AUT_COORDMODE_SCREEN) {
    int         q,r;
    int         col;
    BYTE        red, green, blue;
    BYTE        red_low, red_high, green_low, green_high, blue_low, blue_high;
    HDC         hdc;
    RECT        relrect;
    POINT       ptOrigin;
    bool        m_bColorModeBGR = false;

    relrect.left = lpRect->left;
    relrect.top = lpRect->top;
    relrect.right = lpRect->right;
    relrect.bottom = lpRect->bottom;

    ConvertCoords(nCoordPixelMode, ptOrigin);
    relrect.left += ptOrigin.x;
    relrect.top += ptOrigin.y;
    relrect.right += ptOrigin.x;
    relrect.bottom += ptOrigin.y;

    col = nCol;
    if (m_bColorModeBGR == false)
        Util_RGBtoBGR(col);

    red     = GetRValue(col);
    green   = GetGValue(col);
    blue    = GetBValue(col);

    if ( nVar < 0 )
        nVar = 0;
    else if ( nVar > 0xff )
        nVar = 0xff;

    if (nVar == 0)
    {
        red_low = red_high = red;
        green_low = green_high = green;
        blue_low = blue_high = blue;
    }
    else
    {
        red_low = (nVar > red) ? 0 : red - nVar;
        green_low = (nVar > green) ? 0 : green - nVar;
        blue_low = (nVar > blue) ? 0 : blue - nVar;
        red_high = (nVar > 0xFF - red) ? 0xFF : red + nVar;
        green_high = (nVar > 0xFF - green) ? 0xFF : green + nVar;
        blue_high = (nVar > 0xFF - blue) ? 0xFF : blue + nVar;
    }

    hdc = GetDC(NULL);
    for( q=relrect.left; q<=relrect.right; q = q + nStep)
    {
        for( r=relrect.top; r<=relrect.bottom; r = r + nStep)
        {
            col     = GetPixel(hdc, q, r);
            red     = GetRValue(col);
            green   = GetGValue(col);
            blue    = GetBValue(col);

            if (red >= red_low && red <= red_high && green >= green_low && green <= green_high
                    && blue >= blue_low && blue <= blue_high)
            {
                q -= ptOrigin.x;
                r -= ptOrigin.y;
                pPointResult->x = q;
                pPointResult->y = r;
                ReleaseDC(NULL,hdc);
                return 0;
            }
        }
    }
    ReleaseDC(NULL,hdc);
    return 0;
}

int main()
{
    POINT coords {0, 0};
    RECT searchCoords{688, 10, 762, 78};

    PixelSearch(&searchCoords, 0x000000, 0, 1, &coords);

    std::cout << coords.x << std::endl;
    std::cout << coords.y << std::endl;
    return 0;
}

BTW you can avoid LoadLibrary() if you compile using the static library.

Edited by Andreik

When the words fail... music speaks.

Link to comment
Share on other sites

2 hours ago, Andreik said:

Your structure it's just fine and it's easy to test with AU3_MouseGetPos() that require the same POINT structure (example below)

#include <iostream>
#include "AutoItX3_DLL.h"

int main()
{
    POINT coords{};

    AU3_MouseGetPos(&coords);

    std::cout << coords.x << std::endl;
    std::cout << coords.y << std::endl;
    return 0;
}

I am not sure what is broken with AU3_PixelSearch(). Sometimes it works and sometimes I get segmentation faults and the only thing I changed in these cases is the color.

Based on an older version of AutoIt I suspect that AU3_PixelSearch() last parameter might not be a pointer to a POINT structure so this is why I get random segmentation faults but I cannot be sure without seeing the actual implementation. Anyway, here is an adaptation of PixelSearch() based on a previous AutoIt version. Note that current version might have been implemented this function in a different way.

#include <iostream>
#include "AutoItX3_DLL.h"

#define AUT_COORDMODE_WINDOW    0
#define AUT_COORDMODE_SCREEN    1
#define AUT_COORDMODE_CLIENT    2

void Util_RGBtoBGR(int &nCol)
{
    int nR = (nCol & 0xff0000) >> 16;
    int nG = (nCol & 0x00ff00);
    int nB = (nCol & 0x0000ff) << 16;
    nCol = nR | nG | nB;
}

void ConvertCoords(int nCoordMode, POINT &pt)
{
    HWND    hFore = GetForegroundWindow();
    RECT    rect;

    if (nCoordMode == AUT_COORDMODE_WINDOW)
    {
        GetWindowRect(hFore, &rect);
        pt.x = rect.left;
        pt.y = rect.top;
    }
    else if (nCoordMode == AUT_COORDMODE_CLIENT)
    {
        pt.x = 0;
        pt.y = 0;
        ClientToScreen(hFore, &pt);
    }
    else
    {
        pt.x = 0;
        pt.y = 0;
    }
}

int PixelSearch(LPRECT lpRect, int nCol, int nVar, int nStep, LPPOINT pPointResult, int nCoordPixelMode = AUT_COORDMODE_SCREEN) {
    int         q,r;
    int         col;
    BYTE        red, green, blue;
    BYTE        red_low, red_high, green_low, green_high, blue_low, blue_high;
    HDC         hdc;
    RECT        relrect;
    POINT       ptOrigin;
    bool        m_bColorModeBGR = false;

    relrect.left = lpRect->left;
    relrect.top = lpRect->top;
    relrect.right = lpRect->right;
    relrect.bottom = lpRect->bottom;

    ConvertCoords(nCoordPixelMode, ptOrigin);
    relrect.left += ptOrigin.x;
    relrect.top += ptOrigin.y;
    relrect.right += ptOrigin.x;
    relrect.bottom += ptOrigin.y;

    col = nCol;
    if (m_bColorModeBGR == false)
        Util_RGBtoBGR(col);

    red     = GetRValue(col);
    green   = GetGValue(col);
    blue    = GetBValue(col);

    if ( nVar < 0 )
        nVar = 0;
    else if ( nVar > 0xff )
        nVar = 0xff;

    if (nVar == 0)
    {
        red_low = red_high = red;
        green_low = green_high = green;
        blue_low = blue_high = blue;
    }
    else
    {
        red_low = (nVar > red) ? 0 : red - nVar;
        green_low = (nVar > green) ? 0 : green - nVar;
        blue_low = (nVar > blue) ? 0 : blue - nVar;
        red_high = (nVar > 0xFF - red) ? 0xFF : red + nVar;
        green_high = (nVar > 0xFF - green) ? 0xFF : green + nVar;
        blue_high = (nVar > 0xFF - blue) ? 0xFF : blue + nVar;
    }

    hdc = GetDC(NULL);
    for( q=relrect.left; q<=relrect.right; q = q + nStep)
    {
        for( r=relrect.top; r<=relrect.bottom; r = r + nStep)
        {
            col     = GetPixel(hdc, q, r);
            red     = GetRValue(col);
            green   = GetGValue(col);
            blue    = GetBValue(col);

            if (red >= red_low && red <= red_high && green >= green_low && green <= green_high
                    && blue >= blue_low && blue <= blue_high)
            {
                q -= ptOrigin.x;
                r -= ptOrigin.y;
                pPointResult->x = q;
                pPointResult->y = r;
                ReleaseDC(NULL,hdc);
                return 0;
            }
        }
    }
    ReleaseDC(NULL,hdc);
    return 0;
}

int main()
{
    POINT coords {0, 0};
    RECT searchCoords{688, 10, 762, 78};

    PixelSearch(&searchCoords, 0x000000, 0, 1, &coords);

    std::cout << coords.x << std::endl;
    std::cout << coords.y << std::endl;
    return 0;
}

BTW you can avoid LoadLibrary() if you compile using the static library.

Thank you! You saved me a huge amount of time. 

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...