Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/reference/ImageGrab.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ or the clipboard to a PIL image memory.
.. versionadded:: 7.1.0

:param window:
HWND, to capture a single window. Windows only.
Capture a single window. On Windows, this is a HWND. On macOS, it uses windowid.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's windowid? There's no other mention in the docs or code.

Copy link
Member

@radarhere radarhere Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pushed a commit to describe it as a CGWindowID instead.


.. versionadded:: 11.2.1
.. versionadded:: 11.2.1 (Windows), 12.0.0 (macOS)
:return: An image

.. py:function:: grabclipboard()
Expand Down
36 changes: 32 additions & 4 deletions src/PIL/ImageGrab.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,45 @@
fh, filepath = tempfile.mkstemp(".png")
os.close(fh)
args = ["screencapture"]
if bbox:
if window:
args += ["-l", str(window)]

Check warning on line 47 in src/PIL/ImageGrab.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageGrab.py#L47

Added line #L47 was not covered by tests
elif bbox:
left, top, right, bottom = bbox
args += ["-R", f"{left},{top},{right-left},{bottom-top}"]
subprocess.call(args + ["-x", filepath])
im = Image.open(filepath)
im.load()
os.unlink(filepath)
if bbox:
im_resized = im.resize((right - left, bottom - top))
im.close()
return im_resized
if window:
# Determine if the window was in retina mode or not
# by capturing it without the shadow,
# and checking how different the width is
fh, filepath = tempfile.mkstemp(".png")
os.close(fh)
subprocess.call(

Check warning on line 62 in src/PIL/ImageGrab.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageGrab.py#L60-L62

Added lines #L60 - L62 were not covered by tests
["screencapture", "-l", str(window), "-o", "-x", filepath]
)
with Image.open(filepath) as im_no_shadow:
retina = im.width - im_no_shadow.width > 100
os.unlink(filepath)

Check warning on line 67 in src/PIL/ImageGrab.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageGrab.py#L65-L67

Added lines #L65 - L67 were not covered by tests

# Since screencapture's -R does not work with -l,
# crop the image manually
if retina:
left, top, right, bottom = bbox
im_cropped = im.resize(

Check warning on line 73 in src/PIL/ImageGrab.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageGrab.py#L71-L73

Added lines #L71 - L73 were not covered by tests
(right - left, bottom - top),
box=tuple(coord * 2 for coord in bbox),
)
else:
im_cropped = im.crop(bbox)
im.close()
return im_cropped

Check warning on line 80 in src/PIL/ImageGrab.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageGrab.py#L78-L80

Added lines #L78 - L80 were not covered by tests
else:
im_resized = im.resize((right - left, bottom - top))
im.close()
return im_resized
return im
elif sys.platform == "win32":
if window is not None:
Expand Down
Loading