Pillow/src/PIL/ImageGrab.py

176 lines
5.4 KiB
Python
Raw Normal View History

2010-07-31 06:52:47 +04:00
#
# The Python Imaging Library
# $Id$
#
# screen grabber
2010-07-31 06:52:47 +04:00
#
# History:
# 2001-04-26 fl created
# 2001-09-17 fl use builtin driver, if present
# 2002-11-19 fl added grabclipboard support
#
# Copyright (c) 2001-2002 by Secret Labs AB
# Copyright (c) 2001-2002 by Fredrik Lundh
#
# See the README file for information on usage and redistribution.
#
import os
import shutil
import subprocess
import sys
import tempfile
2019-06-11 11:42:05 +03:00
from . import Image
2010-07-31 06:52:47 +04:00
2019-09-19 19:57:59 +03:00
def grab(bbox=None, include_layered_windows=False, all_screens=False, xdisplay=None):
if xdisplay is None:
if sys.platform == "darwin":
fh, filepath = tempfile.mkstemp(".png")
os.close(fh)
args = ["screencapture"]
if bbox:
left, top, right, bottom = bbox
args += ["-R", f"{left},{top},{right-left},{bottom-top}"]
subprocess.call(args + ["-x", filepath])
2019-09-19 19:57:59 +03:00
im = Image.open(filepath)
im.load()
os.unlink(filepath)
if bbox:
im_resized = im.resize((right - left, bottom - top))
2019-09-19 19:57:59 +03:00
im.close()
return im_resized
2019-09-19 19:57:59 +03:00
return im
elif sys.platform == "win32":
2019-12-09 17:55:15 +03:00
offset, size, data = Image.core.grabscreen_win32(
include_layered_windows, all_screens
)
2019-09-19 19:57:59 +03:00
im = Image.frombytes(
"RGB",
size,
data,
# RGB, 32-bit line padding, origin lower left corner
"raw",
"BGR",
(size[0] * 3 + 3) & -4,
-1,
)
if bbox:
x0, y0 = offset
left, top, right, bottom = bbox
im = im.crop((left - x0, top - y0, right - x0, bottom - y0))
return im
try:
if not Image.core.HAVE_XCB:
msg = "Pillow was built without XCB support"
raise OSError(msg)
size, data = Image.core.grabscreen_x11(xdisplay)
except OSError:
if (
xdisplay is None
and sys.platform not in ("darwin", "win32")
and shutil.which("gnome-screenshot")
):
fh, filepath = tempfile.mkstemp(".png")
os.close(fh)
subprocess.call(["gnome-screenshot", "-f", filepath])
im = Image.open(filepath)
im.load()
os.unlink(filepath)
if bbox:
im_cropped = im.crop(bbox)
im.close()
return im_cropped
return im
else:
raise
else:
im = Image.frombytes("RGB", size, data, "raw", "BGRX", size[0] * 4, 1)
if bbox:
im = im.crop(bbox)
return im
2010-07-31 06:52:47 +04:00
def grabclipboard():
if sys.platform == "darwin":
2019-03-21 16:28:20 +03:00
fh, filepath = tempfile.mkstemp(".jpg")
os.close(fh)
commands = [
2019-03-21 16:28:20 +03:00
'set theFile to (open for access POSIX file "'
+ filepath
+ '" with write permission)',
"try",
" write (the clipboard as JPEG picture) to theFile",
"end try",
2019-03-21 16:28:20 +03:00
"close access theFile",
]
script = ["osascript"]
for command in commands:
script += ["-e", command]
subprocess.call(script)
im = None
if os.stat(filepath).st_size != 0:
im = Image.open(filepath)
im.load()
os.unlink(filepath)
return im
2019-09-19 19:57:59 +03:00
elif sys.platform == "win32":
fmt, data = Image.core.grabclipboard_win32()
2020-05-09 11:40:10 +03:00
if fmt == "file": # CF_HDROP
import struct
o = struct.unpack_from("I", data)[0]
if data[16] != 0:
files = data[o:].decode("utf-16le").split("\0")
else:
files = data[o:].decode("mbcs").split("\0")
return files[: files.index("")]
if isinstance(data, bytes):
import io
2019-03-21 16:28:20 +03:00
data = io.BytesIO(data)
if fmt == "png":
from . import PngImagePlugin
return PngImagePlugin.PngImageFile(data)
elif fmt == "DIB":
from . import BmpImagePlugin
2019-03-21 16:28:20 +03:00
return BmpImagePlugin.DibImageFile(data)
return None
2019-12-09 17:55:15 +03:00
else:
if shutil.which("wl-paste"):
args = ["wl-paste"]
2023-04-15 13:24:19 +03:00
output = subprocess.check_output(["wl-paste", "-l"]).decode()
clipboard_mimetypes = output.splitlines()
def find_mimetype():
for mime in Image.MIME.values():
if mime in clipboard_mimetypes:
return mime
Image.preinit()
mimetype = find_mimetype()
if not mimetype:
Image.init()
mimetype = find_mimetype()
if mimetype:
args.extend(["-t", mimetype])
elif shutil.which("xclip"):
args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"]
else:
msg = "wl-paste or xclip is required for ImageGrab.grabclipboard() on Linux"
raise NotImplementedError(msg)
fh, filepath = tempfile.mkstemp()
err = subprocess.run(args, stdout=fh, stderr=subprocess.PIPE).stderr
os.close(fh)
if err:
msg = f"{args[0]} error: {err.strip().decode()}"
raise ChildProcessError(msg)
im = Image.open(filepath)
im.load()
os.unlink(filepath)
return im