Question solved!

PIL.ImageGrab.grab(bbox=None, include_layered_windows=False, all_screens=True)

And it captures every screen.

Answer from Qiasm on Stack Overflow
🌐
GitHub
github.com › python-pillow › Pillow › issues › 1547
ImageGrab fails with multiple monitors · Issue #1547 · python-pillow/Pillow
November 20, 2015 - When calling ImageGrab.grab() passing in a bounding box that is outside the area of my primary monitor, I just get black. For example, my primary monitor is 1920x1200, flanked on either side by monitors running at 1600x1200, making my to...
Author   chilimangoes
🌐
GitHub
github.com › python-pillow › Pillow › issues › 7898
ImageGrab.grab() unable to capture screenshot with bounding box coordinates on main screen when external monitor is attached · Issue #7898 · python-pillow/Pillow
March 23, 2024 - What did you do? I used PIL.ImageGrab.grab() to capture screenshot by specifying the bounding box coordinates based on two mouse clicks. These clicks corresponded to the top left and bottom right corners while an external monitor was con...
Author   rockyko
Discussions

ImageGrab range error when capturing multi-screen shots and the parameter 'left' is negative
The issue with multi-monitor screenshot capturing is that when the secondary monitor is positioned to the left of the primary monitor, and in ImageGrab.grab(bbox=(left, top, width, height)), left i... More on github.com
🌐 github.com
1
June 9, 2024
Hacktober opportunity: Add multimonitor support to pyautogui for windows
Something I might finally be able to help with on here! I don't think this has been added to the main branch yet, but with some help I wrote a fix for multi-monitor support. I haven't looked at the screenshot function but I'll include the link to my post below as maybe it will help you out here too! https://github.com/asweigart/pyautogui/issues/9#issuecomment-527236475 More on reddit.com
🌐 r/learnpython
5
20
October 23, 2020
PyAutoGUI with multiple monitors
2 years later UPDATE: The latest version of PIL (v 8.0.1) now supports this, so this solution is no longer needed. Instead add these 3 lines to the top of your code to enable all monitor screengrabs in Windows: from PIL import ImageGrab from functools import partial ImageGrab.grab = partial(ImageGrab.grab, all_screens=True) And then use pyautogui normally. Yes, I solved this problem by using a different screenshot program. Here is my solution, assuming you are using Windows: Save the following in file named "chilimangos.py": #!/usr/bin/env python # -*- coding: utf-8 -*- # chilimangoes.py # from ctypes import windll, c_int, c_uint, c_char_p, c_buffer from struct import calcsize, pack from PIL import Image gdi32 = windll.gdi32 screen_size = (10000, 10000) #optimistic until we know better # Win32 functions CreateDC = gdi32.CreateDCA CreateCompatibleDC = gdi32.CreateCompatibleDC GetDeviceCaps = gdi32.GetDeviceCaps CreateCompatibleBitmap = gdi32.CreateCompatibleBitmap BitBlt = gdi32.BitBlt SelectObject = gdi32.SelectObject GetDIBits = gdi32.GetDIBits DeleteDC = gdi32.DeleteDC DeleteObject = gdi32.DeleteObject # Win32 constants NULL = 0 HORZRES = 8 VERTRES = 10 SRCCOPY = 13369376 HGDI_ERROR = 4294967295 ERROR_INVALID_PARAMETER = 87 #from http://www.math.uiuc.edu/~gfrancis/illimath/windows/aszgard_mini/movpy-2.0.0-py2.4.4/movpy/lib/win32/lib/win32con.py SM_XVIRTUALSCREEN = 76 SM_YVIRTUALSCREEN = 77 SM_CXVIRTUALSCREEN = 78 SM_CYVIRTUALSCREEN = 79 SM_CMONITORS = 80 def grab_screen(region=None): """ Grabs a screenshot. This is a replacement for PIL's ImageGrag.grab() method that supports multiple monitors. (SEE: https://github.com/python-pillow/Pillow/issues/1547) Returns a PIL Image, so PIL library must be installed. param region is in the format (left, top, width, height), which is the same format returned by pyscreeze Usage: im = grab_screen() # grabs a screenshot of all monitors im = grab_screen([0, 0, -1600, 1200]) # grabs a 1600 x 1200 screenshot to the left of the primary monitor im.save('screencap.jpg') """ bitmap = None try: screen = CreateDC(c_char_p('DISPLAY'),NULL,NULL,NULL) screen_copy = CreateCompatibleDC(screen) if region: left,top,width,height = region else: left = windll.user32.GetSystemMetrics(SM_XVIRTUALSCREEN) top = windll.user32.GetSystemMetrics(SM_YVIRTUALSCREEN) width = windll.user32.GetSystemMetrics(SM_CXVIRTUALSCREEN) height = windll.user32.GetSystemMetrics(SM_CYVIRTUALSCREEN) bitmap = CreateCompatibleBitmap(screen, width, height) if bitmap == NULL: print('grab_screen: Error calling CreateCompatibleBitmap. Returned NULL') return hobj = SelectObject(screen_copy, bitmap) if hobj == NULL or hobj == HGDI_ERROR: print('grab_screen: Error calling SelectObject. Returned {0}.'.format(hobj)) return if BitBlt(screen_copy, 0, 0, width, height, screen, left, top, SRCCOPY) == NULL: print('grab_screen: Error calling BitBlt. Returned NULL.') return bitmap_header = pack('LHHHH', calcsize('LHHHH'), width, height, 1, 24) bitmap_buffer = c_buffer(bitmap_header) bitmap_bits = c_buffer(' ' * (height * ((width * 3 + 3) & -4))) got_bits = GetDIBits(screen_copy, bitmap, 0, height, bitmap_bits, bitmap_buffer, 0) if got_bits == NULL or got_bits == ERROR_INVALID_PARAMETER: print('grab_screen: Error calling GetDIBits. Returned {0}.'.format(got_bits)) return image = Image.frombuffer('RGB', (width, height), bitmap_bits, 'raw', 'BGR', (width * 3 + 3) & -4, -1) if not region: #if this was a full screen grab then set the size for future use. global screen_size screen_size = image.size return image finally: if bitmap is not None: if bitmap: DeleteObject(bitmap) DeleteDC(screen_copy) DeleteDC(screen) Then, in your program add this to the pyautogui import: import pyautogui import chilimangoes pyautogui.screenshot = chilimangoes.grab_screen pyautogui.pyscreeze.screenshot = chilimangoes.grab_screen pyautogui.size = lambda: chilimangoes.screen_size More on reddit.com
🌐 r/learnpython
9
6
August 22, 2018
python - PIL ImageGrab fails on 2nd virtual monitor of VirtualBox - Stack Overflow
If I had to guess, I'd assume that ImageGrab is getting its coordinates from the SM_SCREEN flag, which gives the coordinates of the primary monitor only, rather than the SM_VIRTUALSCREEN, which gives the entire virtual screen (I haven't looked through the source though, so just a guess). That said, it's easy enough to get around this by interacting directly with the Windows API, then converting its bitmap output into a more usable PIL ... More on stackoverflow.com
🌐 stackoverflow.com
June 4, 2014
🌐
GitHub
github.com › python-pillow › Pillow › issues › 8120
ImageGrab range error when capturing multi-screen shots and the parameter 'left' is negative · Issue #8120 · python-pillow/Pillow
June 9, 2024 - The issue with multi-monitor screenshot capturing is that when the secondary monitor is positioned to the left of the primary monitor, and in ImageGrab.grab(bbox=(left, top, width, height)), left i...
Author   burning-star-x
🌐
Reddit
reddit.com › r/learnpython › hacktober opportunity: add multimonitor support to pyautogui for windows
r/learnpython on Reddit: Hacktober opportunity: Add multimonitor support to pyautogui for windows
October 23, 2020 -

I came across a problem today that could be solved by a beginner / intermediate python programmer and a little time. Anyone want to take on a challenge?

The pyautogui.screenshot() function on Windows does not support multiple monitors. This has been a problem for many years, but recently the PIL ImageGrab module (which pyautogui depends on) added the all_screens option.

# primary monitor only 
import pyautogui
im = pyautogui.screenshot() 

# all monitors
from PIL import ImageGrab
im = ImageGrab.grab(all_screens=True)

This new feature just needs to be added to pyautogui / pyscreeze. Easy(ish). You would learn a lot, get listed as a contributor to a popular open source project (great for resumes), and it would count toward a hacktoberfest tshirt!

Here's the issue you would close: https://github.com/asweigart/pyautogui/issues/9

Here's the offending line at the core of what needs to be updated: https://github.com/asweigart/pyscreeze/blob/master/pyscreeze/init.py#L427

🌐
PyPI
pypi.org › project › Desktopmagic
Client Challenge
JavaScript is disabled in your browser · Please enable JavaScript to proceed · A required part of this site couldn’t load. This may be due to a browser extension, network issues, or browser settings. Please check your connection, disable any ad blockers, or try using a different browser
🌐
Pillow Documentation
pillow.readthedocs.io › en › stable › reference › ImageGrab.html
ImageGrab module - Pillow (PIL Fork) 12.2.0 documentation
Capture all monitors. Windows OS only. Added in version 6.2.0. ... X11 Display address. Pass None to grab the default system screen. Pass "" to grab the default X11 screen on Windows or macOS. You can check X11 support using PIL.features.check_feature() with feature="xcb".
🌐
Reddit
reddit.com › r/learnpython › pyautogui with multiple monitors
r/learnpython on Reddit: PyAutoGUI with multiple monitors
August 22, 2018 -

Just wondering if anyone else has run into problems using pyautogui.locateCenterOnScreen with multiple monitors and if so, did you find any solution to help the function. I keep getting a None value returned when the image is clearly on the screen.

Thanks

Top answer
1 of 3
6
2 years later UPDATE: The latest version of PIL (v 8.0.1) now supports this, so this solution is no longer needed. Instead add these 3 lines to the top of your code to enable all monitor screengrabs in Windows: from PIL import ImageGrab from functools import partial ImageGrab.grab = partial(ImageGrab.grab, all_screens=True) And then use pyautogui normally. Yes, I solved this problem by using a different screenshot program. Here is my solution, assuming you are using Windows: Save the following in file named "chilimangos.py": #!/usr/bin/env python # -*- coding: utf-8 -*- # chilimangoes.py # from ctypes import windll, c_int, c_uint, c_char_p, c_buffer from struct import calcsize, pack from PIL import Image gdi32 = windll.gdi32 screen_size = (10000, 10000) #optimistic until we know better # Win32 functions CreateDC = gdi32.CreateDCA CreateCompatibleDC = gdi32.CreateCompatibleDC GetDeviceCaps = gdi32.GetDeviceCaps CreateCompatibleBitmap = gdi32.CreateCompatibleBitmap BitBlt = gdi32.BitBlt SelectObject = gdi32.SelectObject GetDIBits = gdi32.GetDIBits DeleteDC = gdi32.DeleteDC DeleteObject = gdi32.DeleteObject # Win32 constants NULL = 0 HORZRES = 8 VERTRES = 10 SRCCOPY = 13369376 HGDI_ERROR = 4294967295 ERROR_INVALID_PARAMETER = 87 #from http://www.math.uiuc.edu/~gfrancis/illimath/windows/aszgard_mini/movpy-2.0.0-py2.4.4/movpy/lib/win32/lib/win32con.py SM_XVIRTUALSCREEN = 76 SM_YVIRTUALSCREEN = 77 SM_CXVIRTUALSCREEN = 78 SM_CYVIRTUALSCREEN = 79 SM_CMONITORS = 80 def grab_screen(region=None): """ Grabs a screenshot. This is a replacement for PIL's ImageGrag.grab() method that supports multiple monitors. (SEE: https://github.com/python-pillow/Pillow/issues/1547) Returns a PIL Image, so PIL library must be installed. param region is in the format (left, top, width, height), which is the same format returned by pyscreeze Usage: im = grab_screen() # grabs a screenshot of all monitors im = grab_screen([0, 0, -1600, 1200]) # grabs a 1600 x 1200 screenshot to the left of the primary monitor im.save('screencap.jpg') """ bitmap = None try: screen = CreateDC(c_char_p('DISPLAY'),NULL,NULL,NULL) screen_copy = CreateCompatibleDC(screen) if region: left,top,width,height = region else: left = windll.user32.GetSystemMetrics(SM_XVIRTUALSCREEN) top = windll.user32.GetSystemMetrics(SM_YVIRTUALSCREEN) width = windll.user32.GetSystemMetrics(SM_CXVIRTUALSCREEN) height = windll.user32.GetSystemMetrics(SM_CYVIRTUALSCREEN) bitmap = CreateCompatibleBitmap(screen, width, height) if bitmap == NULL: print('grab_screen: Error calling CreateCompatibleBitmap. Returned NULL') return hobj = SelectObject(screen_copy, bitmap) if hobj == NULL or hobj == HGDI_ERROR: print('grab_screen: Error calling SelectObject. Returned {0}.'.format(hobj)) return if BitBlt(screen_copy, 0, 0, width, height, screen, left, top, SRCCOPY) == NULL: print('grab_screen: Error calling BitBlt. Returned NULL.') return bitmap_header = pack('LHHHH', calcsize('LHHHH'), width, height, 1, 24) bitmap_buffer = c_buffer(bitmap_header) bitmap_bits = c_buffer(' ' * (height * ((width * 3 + 3) & -4))) got_bits = GetDIBits(screen_copy, bitmap, 0, height, bitmap_bits, bitmap_buffer, 0) if got_bits == NULL or got_bits == ERROR_INVALID_PARAMETER: print('grab_screen: Error calling GetDIBits. Returned {0}.'.format(got_bits)) return image = Image.frombuffer('RGB', (width, height), bitmap_bits, 'raw', 'BGR', (width * 3 + 3) & -4, -1) if not region: #if this was a full screen grab then set the size for future use. global screen_size screen_size = image.size return image finally: if bitmap is not None: if bitmap: DeleteObject(bitmap) DeleteDC(screen_copy) DeleteDC(screen) Then, in your program add this to the pyautogui import: import pyautogui import chilimangoes pyautogui.screenshot = chilimangoes.grab_screen pyautogui.pyscreeze.screenshot = chilimangoes.grab_screen pyautogui.size = lambda: chilimangoes.screen_size
2 of 3
2
I’ve had similar issues. I wrote a gui app on a laptop and had external monitor, but using the locate centre onscreen only found the image if it was on the screen where the icon screenshot was originally taken. I believe it has to do with the screen resolution, so the locate centre on screen command will be looking for an image of a certain size, but if on a different screen then the image is rendered at a different size to what autogui is searching for.
Find elsewhere
Top answer
1 of 3
2

I've faced this same issue. If I had to guess, I'd assume that ImageGrab is getting its coordinates from the SM_SCREEN flag, which gives the coordinates of the primary monitor only, rather than the SM_VIRTUALSCREEN, which gives the entire virtual screen (I haven't looked through the source though, so just a guess).

That said, it's easy enough to get around this by interacting directly with the Windows API, then converting its bitmap output into a more usable PIL object.

Some Code:

def _get_screen_buffer(self, bounds=None):
                # Grabs a DC to the entire virtual screen, but only copies to 
                # the bitmap the the rect defined by the user. 

                SM_XVIRTUALSCREEN = 76  # coordinates for the left side of the virtual screen. 
                SM_YVIRTUALSCREEN = 77  # coordinates for the right side of the virtual screen.  
                SM_CXVIRTUALSCREEN = 78 # width of the virtual screen
                SM_CYVIRTUALSCREEN = 79 # height of the virtual screen

                hDesktopWnd = windll.user32.GetDesktopWindow() #Entire virtual Screen

                left = windll.user32.GetSystemMetrics(SM_XVIRTUALSCREEN)
                top = windll.user32.GetSystemMetrics(SM_YVIRTUALSCREEN)
                width = windll.user32.GetSystemMetrics(SM_CXVIRTUALSCREEN)
                height = windll.user32.GetSystemMetrics(SM_CYVIRTUALSCREEN)

                if bounds:
                        left, top, right, bottom = bounds
                        width = right - left 
                        height = bottom - top
                
                hDesktopDC = windll.user32.GetWindowDC(hDesktopWnd)
                if not hDesktopDC: print 'GetDC Failed'; sys.exit()
                
                hCaptureDC = windll.gdi32.CreateCompatibleDC(hDesktopDC)
                if not hCaptureDC: print 'CreateCompatibleBitmap Failed'; sys.exit()

                hCaptureBitmap = windll.gdi32.CreateCompatibleBitmap(hDesktopDC, width, height)
                if not hCaptureBitmap: print 'CreateCompatibleBitmap Failed'; sys.exit()
                
                windll.gdi32.SelectObject(hCaptureDC, hCaptureBitmap)

                SRCCOPY = 0x00CC0020
                windll.gdi32.BitBlt(
                        hCaptureDC, 
                        0, 0, 
                        width, height, 
                        hDesktopDC, 
                        left, top, 
                        0x00CC0020
                )
                return hCaptureBitmap

        def _make_image_from_buffer(self, hCaptureBitmap):
                import Image
                bmp_info = BITMAPINFO()
                bmp_header = BITMAPFILEHEADER()
                hdc = windll.user32.GetDC(None)

                bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER)

                DIB_RGB_COLORS = 0
                windll.gdi32.GetDIBits(hdc, 
                        hCaptureBitmap, 
                        0,0, 
                        None, byref(bmp_info), 
                        DIB_RGB_COLORS
                )

                bmp_info.bmiHeader.biSizeImage = bmp_info.bmiHeader.biWidth *abs(bmp_info.bmiHeader.biHeight) * (bmp_info.bmiHeader.biBitCount+7)/8;
                size = (bmp_info.bmiHeader.biWidth, bmp_info.bmiHeader.biHeight )
                print size
                pBuf = (c_char * bmp_info.bmiHeader.biSizeImage)()

                windll.gdi32.GetBitmapBits(hCaptureBitmap, bmp_info.bmiHeader.biSizeImage, pBuf)

                return Image.frombuffer('RGB', size, pBuf, 'raw', 'BGRX', 0, 1)

The first function gets a bitmap of the screen, and the second guy converts it to a PIL object.

If you don't want to figure out the coordinates of the other monitors yourself, I've got a small module called PyRobot which has functions for targeting specific monitors and whatnot. And it's pure Python, so no need to install PyWin32 :)

2 of 3
0

Audionautics / chriskiehl !

I took your post and some of your library and re-write it for python 3 ! I hope you're okay with it. It works for me using PILLOW (PIL) and the python 3.4 engine.

I just called the file duelMonitory.py containing:

# https://github.com/chriskiehl/pyrobot
# started from Audionautics code on http://stackoverflow.com/questions/3585293/pil-imagegrab-fails-on-2nd-virtual-monitor-of-virtualbox
# updated for PILLOW and Python 3 by Alan Baines (Kizrak)


from PIL import *
#from ctypes import windll, Structure, byref, c_uint
#import ctypes

import ctypes
from ctypes import *
from ctypes.wintypes import *

def get_screen_buffer(bounds=None):
    # Grabs a DC to the entire virtual screen, but only copies to 
    # the bitmap the the rect defined by the user. 

    SM_XVIRTUALSCREEN = 76  # coordinates for the left side of the virtual screen. 
    SM_YVIRTUALSCREEN = 77  # coordinates for the right side of the virtual screen.  
    SM_CXVIRTUALSCREEN = 78 # width of the virtual screen
    SM_CYVIRTUALSCREEN = 79 # height of the virtual screen

    hDesktopWnd = windll.user32.GetDesktopWindow() #Entire virtual Screen

    left = windll.user32.GetSystemMetrics(SM_XVIRTUALSCREEN)
    top = windll.user32.GetSystemMetrics(SM_YVIRTUALSCREEN)
    width = windll.user32.GetSystemMetrics(SM_CXVIRTUALSCREEN)
    height = windll.user32.GetSystemMetrics(SM_CYVIRTUALSCREEN)

    if bounds:
        left, top, right, bottom = bounds
        width = right - left 
        height = bottom - top

    hDesktopDC = windll.user32.GetWindowDC(hDesktopWnd)
    if not hDesktopDC:
        print ('GetDC Failed')
        sys.exit()

    hCaptureDC = windll.gdi32.CreateCompatibleDC(hDesktopDC)
    if not hCaptureDC:
        print ('CreateCompatibleBitmap Failed')
        sys.exit()

    hCaptureBitmap = windll.gdi32.CreateCompatibleBitmap(hDesktopDC, width, height)
    if not hCaptureBitmap:
        print ('CreateCompatibleBitmap Failed')
        sys.exit()

    windll.gdi32.SelectObject(hCaptureDC, hCaptureBitmap)

    SRCCOPY = 0x00CC0020
    windll.gdi32.BitBlt(
        hCaptureDC, 
        0, 0, 
        width, height, 
        hDesktopDC, 
        left, top, 
        0x00CC0020
    )
    return hCaptureBitmap

def make_image_from_buffer(hCaptureBitmap):
    from PIL import Image
    bmp_info = BITMAPINFO()
    bmp_header = BITMAPFILEHEADER()
    hdc = windll.user32.GetDC(None)

    bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER)

    DIB_RGB_COLORS = 0
    windll.gdi32.GetDIBits(hdc, 
        hCaptureBitmap, 
        0,0, 
        None, byref(bmp_info), 
        DIB_RGB_COLORS
    )

    bmp_info.bmiHeader.biSizeImage = int( bmp_info.bmiHeader.biWidth *abs(bmp_info.bmiHeader.biHeight) * (bmp_info.bmiHeader.biBitCount+7)/8 );
    size = (bmp_info.bmiHeader.biWidth, bmp_info.bmiHeader.biHeight )
    print (size)
    pBuf = (c_char * bmp_info.bmiHeader.biSizeImage)()

    windll.gdi32.GetBitmapBits(hCaptureBitmap, bmp_info.bmiHeader.biSizeImage, pBuf)

    return Image.frombuffer('RGB', size, pBuf, 'raw', 'BGRX', 0, 1)


class BITMAPFILEHEADER(ctypes.Structure):
    _fields_ = [
        ('bfType', ctypes.c_short),
        ('bfSize', ctypes.c_uint32),
        ('bfReserved1', ctypes.c_short),
        ('bfReserved2', ctypes.c_short),
        ('bfOffBits', ctypes.c_uint32)
    ]


class BITMAPINFOHEADER(ctypes.Structure):
    _fields_ = [
        ('biSize', ctypes.c_uint32),
        ('biWidth', ctypes.c_int),
        ('biHeight', ctypes.c_int),
        ('biPlanes', ctypes.c_short),
        ('biBitCount', ctypes.c_short),
        ('biCompression', ctypes.c_uint32),
        ('biSizeImage', ctypes.c_uint32),
        ('biXPelsPerMeter', ctypes.c_long),
        ('biYPelsPerMeter', ctypes.c_long),
        ('biClrUsed', ctypes.c_uint32),
        ('biClrImportant', ctypes.c_uint32)
    ]


class BITMAPINFO(ctypes.Structure):
    _fields_ = [
        ('bmiHeader', BITMAPINFOHEADER),
        ('bmiColors', ctypes.c_ulong * 3)
    ]

And my test code was duelMonitor.test.py containing:

from PIL import *

from duelMonitor import *

hCaptureBitmap = get_screen_buffer()

pimage = make_image_from_buffer(hCaptureBitmap)

pimage.save("Hello.png","PNG")

Basically just combination of Audionautics post and his library from https://github.com/chriskiehl/pyrobot webpage and conversion to Python 3 (and PILLOW).

Have fun!

(PS. I would have posted as comment, but I don't have enough points /sadface)

🌐
GitHub
github.com › python-pillow › Pillow › blob › main › docs › reference › ImageGrab.rst
Pillow/docs/reference/ImageGrab.rst at main · python-pillow/Pillow
.. versionadded:: 6.1.0 :param all_screens: Capture all monitors. Windows OS only. .. versionadded:: 6.2.0 :param xdisplay: X11 Display address. Pass :data:`None` to grab the default system screen. Pass ``""`` to grab the default X11 screen on Windows or macOS. You can check X11 support using :py:func:`PIL.features.check_feature` with ``feature="xcb"``. ..
Author   python-pillow
🌐
GitHub
github.com › ludios › Desktopmagic
GitHub - ludios/Desktopmagic: Robust multi-monitor screenshot grabbing library for Python 2.x/3.x on Windows
Desktopmagic can take a screenshot of all monitors. You can: Take a screenshot of the entire virtual screen. Take a screenshot of the entire virtual screen, split into one PIL Image per display. Take a screenshot of just one display. Take a screenshot of an arbitrary region of the virtual screen. ... ImageGrab leaks memory if you try to take a screenshot when the workstation is locked (as of 2011-01).
Starred by 57 users
Forked by 11 users
Languages   Python 100.0% | Python 100.0%
🌐
GitHub
github.com › python-pillow › Pillow › issues › 6144
ImageGrab.grab(bbox=) fails on Mac with Retina screen, or on secondary monitor · Issue #6144 · python-pillow/Pillow
March 20, 2022 - ImageGrab.grab() is failing to account for the 144 DPI (not 72 DPI "virtual pixels") image generated by screencapture for my Retina display, so the bbox passed to the crop function needs to be scaled by 2 (all 4 parameters). Secondary problem: this all fails completely when the app window is on a secondary monitor.
Author   resnbl
🌐
Pillow
pillow.readthedocs.io › en › latest › releasenotes › 6.2.0.html
6.2.0 (2019-10-01) - Pillow (PIL Fork) 12.0.0.dev0 documentation
These flags would be used by default if building libwebp without debugging, and using them fixes a significant decrease in speed when a wheel-installed copy of Pillow performs libwebp operations. On this page · 6.2.0 (2019-10-01) Security · Buffer overruns · CVE 2019-16865: Fix DOS attack · API changes · Image.getexif · Deprecations · Image.frombuffer · API additions · Text stroking · ImageGrab on multi-monitor Windows ·
🌐
GitHub
github.com › python-pillow › Pillow › issues › 3293
ImageGrab on mac ( coordinate problem ? ) · Issue #3293 · python-pillow/Pillow
August 5, 2018 - from PIL import ImageGrab import os import time def screenGrab(): x = 351 y = 237 im = ImageGrab.grab((x,y,x+645,y+484)) im.save(os.getcwd() + "\\full_snap_" + str(int(time.time()) ) + ".png", "PNG") if __name__ == '__main__': screenGrab() Normally the program should be doing this : But for whatever reason he took this instead : As you can see, the coordinates does not correspond to what I've wrote and it looks like he zoom on the screen too..
Author   jerb6
🌐
Python
mail.python.org › pipermail › image-sig › 2008-June › 005054.html
[Image-SIG] PIL ImageGrab with multi-monitors.
September 5, 2013 - I have no problem programmatically creating and moving Tkinter windows to any screen, as MS Windows and Tcl/Tk support multiple monitors. Since PIL has been available for years, and multi-monitors are quite common now, I am surprised that the "grab" feature seems to be still limited to one monitor.
🌐
GitHub
github.com › python-pillow › Pillow › issues › 6126
ImageGrab.grab colors switched · Issue #6126 · python-pillow/Pillow
March 12, 2022 - What did you do? screenshot2 = ImageGrab.grab(all_screens=True) What did you expect to happen? That the ImageGrab saves the Image with the right colors^^ What actually happened? The colors are swit...
Author   BigDvsRL
🌐
GeeksforGeeks
geeksforgeeks.org › python-pil-imagegrab-grab-method
Python PIL | ImageGrab.grab() method - GeeksforGeeks
May 3, 2022 - PIL is the Python Imaging Library ... of the screen or the clipboard to a PIL image memory. PIL.ImageGrab.grab() method takes a snapshot of the screen....
🌐
Lightrun
lightrun.com › answers › asweigart-pyautogui-use-locateonscreen-with-multiple-monitors
Use LocateOnScreen with Multiple Monitors
import win32api # used for multi-monitor fix from PIL import ImageGrab Read more comments on GitHub >
🌐
GitHub
github.com › python-pillow › Pillow › issues › 5536
Does ImageGrab on Windows release *all* DC handles/objects? · Issue #5536 · python-pillow/Pillow
June 10, 2021 - I was chasing down an issue on pyautogui and thought something was awry in their pixel() function (returns the rgb color of a pixel), however somewhat by accident I found out it's actually an interaction between pixel() and screenshot(). The latter uses PIL.ImageGrab.grab() and I'm wondering how to diagnose further.
Author   jwhendy