PyAutoGUI Region Parameter Not Working, The Entire Screen is Taken Instead

610 Views Asked by At

I'm new to Python and trying to figure out how to take a screenshot of just a specific region with pyautogui. Here's what I have:

import pyautogui

IM = pyautogui.screenshot(region=(20, 20, 500, 500))
IM.save('screen.png')

The region parameter does not work and it screenshots my entire screen every time. I am on MacOS. Thank you for your help!

2

There are 2 best solutions below

0
Dez64ru On

Yep, this is a bug for macos, they just forgot to add logic for the crop (and also save)

I`m a novice (literally learning python only the second day, bc I can miss something, but i this can helps for ppls who find this response)

I could create a PR, but as I see, the library is completely abandoned

old lib code:

def _screenshot_osx(imageFilename=None, region=None):
    """
    TODO
    """
    # TODO - use tmp name for this file.

    

    if tuple(PIL__version__) < (6, 2, 1):
        # Use the screencapture program if Pillow is older than 6.2.1, which
        # is when Pillow supported ImageGrab.grab() on macOS. (It may have
        # supported it earlier than 6.2.1, but I haven't tested it.)
        if imageFilename is None:
            tmpFilename = 'screenshot%s.png' % (datetime.datetime.now().strftime('%Y-%m%d_%H-%M-%S-%f'))
        else:
            tmpFilename = imageFilename
        subprocess.call(['screencapture', '-x', tmpFilename])
        im = Image.open(tmpFilename)

        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]
            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)
        else:
            # force loading before unlinking, Image.open() is lazy
            im.load()

        if imageFilename is 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()

    return im

Fixed code:

def _screenshot_osx(imageFilename=None, region=None):
    """
    TODO
    """
    # TODO - use tmp name for this file.

    

    if tuple(PIL__version__) < (6, 2, 1):
        # Use the screencapture program if Pillow is older than 6.2.1, which
        # is when Pillow supported ImageGrab.grab() on macOS. (It may have
        # supported it earlier than 6.2.1, but I haven't tested it.)
        if imageFilename is None:
            tmpFilename = 'screenshot%s.png' % (datetime.datetime.now().strftime('%Y-%m%d_%H-%M-%S-%f'))
        else:
            tmpFilename = imageFilename
        subprocess.call(['screencapture', '-x', tmpFilename])
        im = Image.open(tmpFilename)

        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]
            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)
        else:
            # force loading before unlinking, Image.open() is lazy
            im.load()

        if imageFilename is 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:
            assert len(region) == 4, 'region argument must be a tuple of four ints'
            region = [int(x) for x in region]
            im = im.crop((region[0], region[1], region[2] + region[0], region[3] + region[1]))

        if imageFilename is not None:
            im.save(imageFilename)

    return im
0
Al Sweigart On

This bug has been fixed in 0.1.30, so all you need to do is upgrade PyScreeze (which PyAutoGUI uses) by running pip3 install -U pyscreeze