asweigart / pyautogui

A cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Incorrect screen size on Mac

luojxxx opened this issue · comments

Hi!

So I have a MacBook Pro retina running windows 8.1 on bootcamp.

And the actual screen resolution is 2880 x 1800, but pyautogii.size() returns 1920 x 1080.

I can't seem to find documentation about how to set these values nor have I been able to guess them.

I believe it has to do with the retina scaling, but as of right now the pointer is constantly thrown off.

Any help would be greatly appreciated!

Is this similar to issue #12 ? If so, this has been fixed and you should update pyautogui by running:

pip3 install -U pyautogui

Hmmm…. I’m using python 2.7 and it’s on the bootcamp Windows 8.1 side of a retina macbook pro. I’m not sure how that’d work out...

On May 14, 2015, at 12:59 AM, Al Sweigart notifications@github.com wrote:

Is this similar to issue #12 #12 ? If so, this has been fixed and you should update pyautogui by running:

pip3 install -U pyautogui

Reply to this email directly or view it on GitHub #33 (comment).

commented

Hey guys. I had a similar problem using this library on Windows 10 on a 4k display - In my case, I found it was related to DPI scaling not being accounted for.

I solved the issue by adding the following to my script:

from ctypes import windll
user32 = windll.user32
user32.SetProcessDPIAware()

There may be a similar bit of functionality for MacOS.

@starbadger You solved my issue, it works on Windows 10, thanks.

@starbadger Thank you, solved my issue on Windows 7 as well!

Just put the issue up on Pillow - ty for the fix @starbadger - worked a treat!

Pyautogui uses screencaps to find the location of stuff on the screen. The problem on macs with a retina display is that the screen output have double the number of pixels, to take advantage of the system’s greater pixel density for a crisper image.Therefore, when you take a screenshot, you get an image containing double the number of pixels than the same image from a non-retina Mac.
source

One work around is to change the yield of pyscreeze._locateAll_opencv and pyscreeze._locateAll_python (the pyautogui source code):

pyscreeze._locateAll_opencv:
change
yield (x, y, needleWidth, needleHeight) to

if subprocess.call("system_profiler SPDisplaysDataType | grep -i 'retina'", shell= True) == 0: 
    yield (int((matchx + region[0])*0.5), int((y + region[1])*0.5), int(needleWidth*0.5), int(needleHeight*0.5))
  else:
    yield (matchx + region[0], y + region[1], needleWidth, needleHeight)

pyscreeze._locateAll_python:
change
yield (matchx + region[0], y + region[1], needleWidth, needleHeight)
to

if subprocess.call("system_profiler SPDisplaysDataType | grep -i 'retina'", shell= True) == 0: 
    yield (int((matchx + region[0])*0.5), int((y + region[1])*0.5), int(needleWidth*0.5), int(needleHeight*0.5))
else:
    yield (matchx + region[0], y + region[1], needleWidth, needleHeight)

@kasperschnack I tried that fix, and got...

  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pyscreeze/__init__.py", line 272, in locateOnScreen
    retVal = locate(image, screenshotIm, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pyscreeze/__init__.py", line 256, in locate
    points = tuple(locateAll(needleImage, haystackImage, **kwargs))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pyscreeze/__init__.py", line 231, in _locateAll_python
    yield (int((matchx + region[0])*0.5), int((y + region[1])*0.5), int((needleWidth, needleHeight))*0.5)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'tuple'

@domluther try changing int((needleWidth, needleHeight))*0.5) (in both files) to int(needleWidth*0.5), int(needleHeight*0.5) - does that do the trick?

@kasperschnack Yes, it does! Thanks. Is there any particular reason why on one of them you've done the *0.5 inside the parentheses and the other outside??

@domluther that was a mistake - have fixed it now :)

commented

Hello !
Please, how do I modify pyscreeze._locateAll_opencv and pyscreeze._locateAll_python ?

Hello @jerb6.

You can modify the module directly.

If you're not sure where it is located you can find the location open the python repl in your terminal and run the following commands:

import pyscreeze
print(pyscreeze.__path__)

This should reveal the location of the .py file. Edit it, save it and you should be good to go :).

If you use an IDE like pycharm, you should be able to find the file by cmd+clicking on the import in your script.

commented

oh ! okay thank you very much @kasperschnack !!
Yes, I opened with pycharm.

But I have another problem.. Sorry for bothering you, I'm a complete beginner !
I can't modify yield (x, y, needleWidth, needleHeight) and yield (matchx + region[0], y + region[1], needleWidth, needleHeight)..

I says : failed to change read-only status for the following files :
/library/Frameworks/Python.frameworks/Versions/3.7/lib/python3.7/site-packages/pyscreeze/ __ init __ .py

@jerb6

It's wierd that your python packages/modules are installed in your /library directory I think. Normally they'd be installed in your $HOME-dir. I expect you're using the python installation that ships default with Mac OS. I believe that is the reason for the files being read-only. If you install Python with homebrew(which I would recommend you do) you probably wouldn't have this problem, although you might have to reinstall your packages.

You might be able to change it from the IDE though without doing any reinstalls
Open the file(/library/Frameworks/Python.frameworks/Versions/3.7/lib/python3.7/site-packages/pyscreeze/ __ init __ .py) in pycharm and do the following:
On the main menu, choose File -> Make File Writable.

commented

@kasperschnack I actually changed all directories on "read and write" because all was on "read only" !
Now it work ! And your modifications works too ! Thank you so much !

I changed the lines of source code like @kasperschnack suggested, but nothing different is happening. I tried changing 0.5 to different factors so see if it had any effect but I still have pyautogui.size returning half of my resolution 1280 x 800 (instead of 2560 x 1600). Maybe I changed the code incorrectly and did something wrong with the indentation (I'm new to programming) or it's the fact that I'm running OSX 10.14.1 Mojave. It's like none of the saved changes are applied.

The changed code looks like this:

schermafbeelding 2018-11-23 om 17 47 19

and:

schermafbeelding 2018-11-23 om 17 47 54

Hopefully anyone can help me solve this issue!

I have to admit it's been a long while since if looked at this issue - but isn't 1280 x 800 is what you want? Have you tried out moving the cursor around using the library to see if it behaves as you'd expect?

The problem is that I want to program python to take partial screenshots, which I program according to the pixel coordinates of my screen. For example, when using photoshop to find a specific spot on a full screenshot, the most right bottom pixel has coordinates 2560 x 1600. However, when I put my cursor at the right bottom of my screen and locate the coordinates with pyautogui it returns a value of 1280 x 800. I could work my way around it by dividing all coordinates by 2 for pyautogui functions, but your solution seemed more convenient for me. Unfortunately though I can not get it right.

commented

Unfortunately the check subprocess.call("system_profiler SPDisplaysDataType | grep -i 'retina' is not working on OSX Mojave 10.14.6
Any other ideas how to check if it is a retina?

i might be too late..
i suffer from the same issue with you guys..

i just solve this issue using the code below.

[problematic code]

pdf_con = pg.locateCenterOnScreen(
            f'{os.getcwd()[:-23]}/코드개발/pdf_loc5.png',
            # f'{os.getcwd()[:-23]}/코드개발/save.png', 
            grayscale=True,
            confidence=0.8
        )
pg.click(pdf_con)

[imporved code]

pdf_con = pg.locateCenterOnScreen(
            f'{os.getcwd()[:-23]}/코드개발/pdf_loc5.png',
            # f'{os.getcwd()[:-23]}/코드개발/save.png', 
            grayscale=True,
            confidence=0.8
        )
pg.click(pdf_con[0]/2, pdf_con[1]/2) # the reason of resolution

env
python 3.8
monitor: dell 4k (3840 x 2160)

i might be too late..
i suffer from the same issue with you guys..

i just solve this issue using the code below.

[problematic code]

pdf_con = pg.locateCenterOnScreen(
            f'{os.getcwd()[:-23]}/코드개발/pdf_loc5.png',
            # f'{os.getcwd()[:-23]}/코드개발/save.png', 
            grayscale=True,
            confidence=0.8
        )
pg.click(pdf_con)

[imporved code]

pdf_con = pg.locateCenterOnScreen(
            f'{os.getcwd()[:-23]}/코드개발/pdf_loc5.png',
            # f'{os.getcwd()[:-23]}/코드개발/save.png', 
            grayscale=True,
            confidence=0.8
        )
pg.click(pdf_con[0]/2, pdf_con[1]/2) # the reason of resolution

env
python 3.8
monitor: dell 4k (3840 x 2160)

Thanks so much, this worked for me!

I have the same problem here that I cannot solve. I'm using a Macbook as well, and when I run this code, it screenshots the whole screen. How do I make it so it is only a part of the screen? I understand this is a retina problem. I also ran this code to a windows computer and it worked fine when I changed to fit the pixels of the windows.

#Screenshot for Region pyautogui.screenshot(f"{region}_{tab}_SOM.png", region = (320,337,519,439))

Running into this on a MacBook now. How is this an open issue from 2015? 🤯