Skip to content

Commit

Permalink
Updates for 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
asweigart committed Aug 20, 2024
1 parent 9c767e0 commit 93f2775
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 22 deletions.
2 changes: 2 additions & 0 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Jon Winsley https://github.com/glitchassassin
Julien Schueller https://github.com/jschueller
Lauritz Thaulow https://github.com/LauritzThaulow
Rob Putt https://github.com/robputt796
Samik Saraswat https://github.com/samik3301
Shaheer Sarfaraz https://github.com/DaKheera47
socal-nerdtastic https://github.com/socal-nerdtastic
vorstrelok https://github.com/vorstrelok
zerocewl https://github.com/zerocewl
57 changes: 53 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,121 +6,170 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [Unreleased] - 2023-10-16

## [Unreleased]
### Added

- Added allScreens argument for Windows only for now.

### Changed
### Changed

- Set `USE_IMAGE_NOT_FOUND_EXCEPTION` to `True` by default. This is a backwards-compatibility breaking change. Set `USE_IMAGE_NOT_FOUND_EXCEPTION = False` to get the original behavior and have locate functions return None when they can't find an image.
- Renamed CHANGES.txt to CHANGELOG.md and using a changelog template.


- Made screenshot functions more restrictive and force the region arg to a tuple of four ints, instead of converting them to ints.
- Fix for the region argument not working on macOS.
- Fix for PILLOW_VERSION not being correctly translated. #98 #101
- Fix readme example using click() #91

## [0.1.28] - 2021-09-13

## Changed

Fix for DC Release error that happened when calling pixel() after calling screenshot() on Windows.


## [0.1.22] - 2019-06-27

## Added

Added -z to scrot to silence the beep.


## [0.1.21] - 2019-05-17

## Changed

Fix memory leak at pixel(). Fix to pixel function. Fix cropped image saving on Linux and Mac. Fix UnboundLocalError (img_cv won't be assigned) when img is a true-color array.


## [0.1.18] - 2018-07-19

## Changed

Fixing MANIFEST.in to include readme, which cause installation failure.


## [0.1.17] - 2018-07-18

## Changed

Adjusted setup.py to include the long description.


## [0.1.16] - 2018-07-18

## Changed

Adjusted setup.py to include the long description.


## [0.1.15] - 2018-07-18

## Changed

Fixed a bug involving the generator for locateAll().


## [0.1.14] - 2018-03-02

## Added

Added check for Pillow installation when calling screenshot() on Windows.


## [0.1.13] - 2017-06-13

## Changed

Fixed RGB ordering bug for pixel() in 0.1.12


## [0.1.12] - 2017-06-12

## Changed

Used the win32 GetPixel() function to speed up the pixel() function 2x.


## [0.1.11] - 2017-06-11

## Changed

Have setup.py pull version info from file, which fixes several issues.


## [0.1.10] - 2017-06-11

## Changed

Fixed Google App Engine failure, fix RGB/RGBA bug in pixelMatchesColor()


## [0.1.9] - 2017-01-19

## Changed

Put imports into a try/except, to prevent errors if PIL is not present.


## [0.1.8] - 2015-06-02

## Added

Add more error handling for OpenCV


## [0.1.7] - 2015-05-29

## Added

Exposed confidence setting for OpenCV, added "min search time"


## [0.1.6] - 2015-01-10

## Changed

OpenCV integration, fix for limit keyword argument


## [0.1.5] - 2014-12-15

## Changed

Actual fix for the region issue.


## [0.1.4] - 2014-12-14

## Changed

Updated features for region parameter to several functions.


## [0.1.3] - 2014-12-11

## Changed

Fix for Linux issues from github.com/LauritzThaulow


## [0.1.2] - 2014-10-19

## Changed

Fix for locateCenterOnScreen() bug.


## [0.1.1] - 2014-10-19

## Changed

Fix for issue #3 on the PyAutoGUI project.


## [0.1.0] - 2014-09-16

## Changed

Initial release.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
PyScreeze
=========

PyScreeze is a simple, cross-platform screenshot module for Python 2 and 3.
PyScreeze is a simple, cross-platform screenshot module for Python 3.

About
-----

PyScreeze can take screenshots, save them to files, and locate images within the screen. This is useful if you have a small image of, say, a button that needs to be clicked and want to locate it on the screen.
PyScreeze can take screenshots, save them to files, and locates images within the screen. This is useful if you have a small image of, say, a button that needs to be clicked and want to locate it on the screen.

NOTE - PyScreeze depends on Pillow, whose older versions have security issues. The only secure versions of Pillow are 8.3.2 and later. However, Pillow 8.3.2 only supports Python as far back as Python 3.6. If you are installing PyScreeze for Python 3.5 or earlier, be aware that there may be security issues with the version of Pillow it uses.
NOTE - PyScreeze depends on Pillow for screenshots, whose older versions have security issues. The only secure versions of Pillow are 8.3.2 and later. However, Pillow 8.3.2 only supports Python as far back as Python 3.6. If you are installing PyScreeze for Python 3.5 or earlier, be aware that there may be security issues with the version of Pillow it uses.

Screenshot functionality requires the Pillow module. OS X uses the `screencapture` command, which comes with the operating system. Linux uses the `scrot` command, which can be installed by running `sudo apt-get install scrot`.
If Pillow is unavailable, there are fallback methods for each OS (screencapture for macOS, gnome-screenshot for Linux, etc.)

Special Notes About Ubuntu
==========================

Unfortunately, Ubuntu seems to have several deficiencies with installing Pillow. PNG and JPEG support are not included with Pillow out of the box on Ubuntu. The following links have more information
If your Ubuntu system uses the older X11 window system, you must install Xlib by running `sudo apt install python3-xlib`. This will require the admin password for your computer.

The screenshot() Function
=========================
Expand All @@ -36,22 +36,22 @@ There is also an optional `region` keyword argument, if you do not want a screen
The Locate Functions
====================

You can visually locate something on the screen if you have an image file of it. You can call the `locateOnScreen('calc7key.png')` function to get the screen coordinates of the 7 button for a calculator app. The return value is a 4-integer tuple: (left, top, width, height). This tuple can be passed to `center()` to get the X and Y coordinates at the center of this region. If the image can't be found on the screen, `locateOnScreen()` returns `None`.
You can visually locate something on the screen if you have an image file of it. You can call the `locateOnScreen('calc7key.png')` function to get the screen coordinates of the 7 button for a calculator app. The return value is a 4-integer tuple: (left, top, width, height). This tuple can be passed to `center()` to get the X and Y coordinates at the center of this region. If the image can't be found on the screen, `locateOnScreen()` returns `None`. (PyAutoGUI is a module that simulates mouse clicks.)

>>> import pyscreeze
>>> import pyscreeze, pyautogui
>>> button7location = pyscreeze.locateOnScreen('calc7key.png')
>>> button7location
(1416, 562, 50, 41)
>>> button7x, button7y = pyscreeze.center(button7location)
>>> button7x, button7y
(1441, 582)
>>> pyscreeze.click(button7x, button7y) # clicks the center of where the 7 button was found
>>> pyautogui.click(button7x, button7y) # clicks the center of where the 7 button was found

The `locateCenterOnScreen()` function is probably the one you want to use most often:

>>> import pyscreeze
>>> import pyscreeze, pyautogui
>>> x, y = pyscreeze.locateCenterOnScreen('calc7key.png')
>>> pyscreeze.click(x, y)
>>> pyautogui.click(x, y)

On a 1920 x 1080 screen, the locate function calls take about 1 or 2 seconds. This may be too slow for action video games, but works for most purposes and applications.

Expand Down
37 changes: 29 additions & 8 deletions pyscreeze/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,16 +529,16 @@ def showRegionOnScreen(region, outlineColor='red', filename='_showRegionOnScreen
screenshotIm.save(filename)


def _screenshot_win32(imageFilename=None, region=None):
def _screenshot_win32(imageFilename=None, region=None, allScreens=False):
"""
TODO
"""
# TODO - Use the winapi to get a screenshot, and compare performance with ImageGrab.grab()
# https://stackoverflow.com/a/3586280/1893164
im = ImageGrab.grab()
im = ImageGrab.grab(all_screens=allScreens)
if region is not None:
assert len(region) == 4, 'region argument must be a tuple of four ints'
region = [int(x) for x in region]
assert isinstance(region[0], int) and isinstance(region[1], int) and isinstance(region[2], int) and isinstance(region[3], int), 'region argument must be a tuple of four ints'
im = im.crop((region[0], region[1], region[2] + region[0], region[3] + region[1]))
if imageFilename is not None:
im.save(imageFilename)
Expand All @@ -563,7 +563,7 @@ def _screenshot_osx(imageFilename=None, region=None):

if region is not None:
assert len(region) == 4, 'region argument must be a tuple of four ints'
region = [int(x) for x in region]
assert isinstance(region[0], int) and isinstance(region[1], int) and isinstance(region[2], int) and isinstance(region[3], int), 'region argument must be a tuple of four ints'
im = im.crop((region[0], region[1], region[2] + region[0], region[3] + region[1]))
os.unlink(tmpFilename) # delete image of entire screen to save cropped version
im.save(tmpFilename)
Expand All @@ -575,7 +575,11 @@ def _screenshot_osx(imageFilename=None, region=None):
os.unlink(tmpFilename)
else:
# Use ImageGrab.grab() to get the screenshot if Pillow version 6.3.2 or later is installed.
im = ImageGrab.grab()
if region is not None:
im = ImageGrab.grab(bbox=(region[0], region[1], region[2] + region[0], region[3] + region[1]))
else:
# Get full screen for screenshot
im = ImageGrab.grab()
return im


Expand Down Expand Up @@ -607,7 +611,7 @@ def _screenshot_linux(imageFilename=None, region=None):
else:
# Return just a region of the screenshot.
assert len(region) == 4, 'region argument must be a tuple of four ints' # TODO fix this
region = [int(x) for x in region]
assert isinstance(region[0], int) and isinstance(region[1], int) and isinstance(region[2], int) and isinstance(region[3], int), 'region argument must be a tuple of four ints'
im = im.crop((region[0], region[1], region[2] + region[0], region[3] + region[1]))
return im
elif RUNNING_X11 and SCROT_EXISTS: # scrot only runs on X11, not on Wayland.
Expand All @@ -629,7 +633,7 @@ def _screenshot_linux(imageFilename=None, region=None):

if region is not None:
assert len(region) == 4, 'region argument must be a tuple of four ints'
region = [int(x) for x in region]
assert isinstance(region[0], int) and isinstance(region[1], int) and isinstance(region[2], int) and isinstance(region[3], int), 'region argument must be a tuple of four ints'
im = im.crop((region[0], region[1], region[2] + region[0], region[3] + region[1]))
os.unlink(tmpFilename) # delete image of entire screen to save cropped version
im.save(tmpFilename)
Expand Down Expand Up @@ -705,6 +709,15 @@ def pixelMatchesColor(x, y, expectedRGBColor, tolerance=0):
Return True if the pixel at x, y is matches the expected color of the RGB
tuple, each color represented from 0 to 255, within an optional tolerance.
"""

# TODO DEPRECATE THIS FUNCTION

# Note: Automate the Boring Stuff 2nd edition documented that you could call
# pixelMatchesColor((x, y), rgb) instead of pixelMatchesColor(x, y, rgb).
# Lets correct that for the 1.0 release.
if isinstance(x, collections.abc.Sequence) and len(x) == 2:
raise TypeError('pixelMatchesColor() has updated and no longer accepts a tuple of (x, y) values for the first argument. Pass these arguments as two separate arguments instead: pixelMatchesColor(x, y, rgb) instead of pixelMatchesColor((x, y), rgb)')

pix = pixel(x, y)
if len(pix) == 3 or len(expectedRGBColor) == 3: # RGB mode
r, g, b = pix[:3]
Expand All @@ -728,8 +741,16 @@ def pixelMatchesColor(x, y, expectedRGBColor, tolerance=0):

def pixel(x, y):
"""
Return an RGB tuple, each color represented from 0 to 255, of the pixel at x, y.
Returns the color of the screen pixel at x, y as an RGB tuple, each color represented from 0 to 255.
"""

# Note: Automate the Boring Stuff 2nd edition documented that you could call
# pixel((x, y), rgb) instead of pixel(x, y, rgb).
# Lets correct that for the 1.0 release.
if isinstance(x, collections.abc.Sequence) and len(x) == 2:
raise TypeError('pixel() has updated and no longer accepts a tuple of (x, y) values for the first argument. Pass these arguments as two separate arguments instead: pixel(x, y) instead of pixel((x, y))')


if sys.platform == 'win32':
# On Windows, calling GetDC() and GetPixel() is twice as fast as using our screenshot() function.
with __win32_openDC() as hdc: # handle will be released automatically
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",

This comment has been minimized.

Copy link
@Avasam

Avasam Aug 21, 2024

@asweigart Pillow is still missing from install_requires for Python 3.12

This comment has been minimized.

Copy link
@injust

injust Aug 21, 2024

#115 should fix this

"Programming Language :: Python :: 3 :: Only",
],
)

0 comments on commit 93f2775

Please sign in to comment.