mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-26 01:46:18 +03:00
xcb screengrab fixes
This commit is contained in:
parent
3c39e6fcf6
commit
f9c74825a6
|
@ -2,67 +2,68 @@ import subprocess
|
|||
import sys
|
||||
|
||||
import pytest
|
||||
from PIL import Image, ImageGrab
|
||||
|
||||
from .helper import assert_image
|
||||
|
||||
try:
|
||||
from PIL import ImageGrab
|
||||
|
||||
class TestImageGrab:
|
||||
def test_grab(self):
|
||||
for im in [
|
||||
ImageGrab.grab(),
|
||||
ImageGrab.grab(include_layered_windows=True),
|
||||
ImageGrab.grab(all_screens=True),
|
||||
]:
|
||||
assert_image(im, im.mode, im.size)
|
||||
|
||||
im = ImageGrab.grab(bbox=(10, 20, 50, 80))
|
||||
assert_image(im, im.mode, (40, 60))
|
||||
|
||||
def test_grabclipboard(self):
|
||||
if sys.platform == "darwin":
|
||||
subprocess.call(["screencapture", "-cx"])
|
||||
else:
|
||||
p = subprocess.Popen(
|
||||
["powershell", "-command", "-"], stdin=subprocess.PIPE
|
||||
)
|
||||
p.stdin.write(
|
||||
b"""[Reflection.Assembly]::LoadWithPartialName("System.Drawing")
|
||||
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
|
||||
$bmp = New-Object Drawing.Bitmap 200, 200
|
||||
[Windows.Forms.Clipboard]::SetImage($bmp)"""
|
||||
)
|
||||
p.communicate()
|
||||
|
||||
im = ImageGrab.grabclipboard()
|
||||
class TestImageGrab:
|
||||
@pytest.mark.skipif(
|
||||
sys.platform not in ("win32", "darwin"), reason="requires Windows or macOS"
|
||||
)
|
||||
def test_grab(self):
|
||||
for im in [
|
||||
ImageGrab.grab(),
|
||||
ImageGrab.grab(include_layered_windows=True),
|
||||
ImageGrab.grab(all_screens=True),
|
||||
]:
|
||||
assert_image(im, im.mode, im.size)
|
||||
|
||||
im = ImageGrab.grab(bbox=(10, 20, 50, 80))
|
||||
assert_image(im, im.mode, (40, 60))
|
||||
|
||||
except ImportError:
|
||||
@pytest.mark.skipif(not Image.core.HAVE_XCB, reason="requires XCB")
|
||||
def test_grab_x11(self):
|
||||
try:
|
||||
if sys.platform not in ("win32", "darwin"):
|
||||
im = ImageGrab.grab()
|
||||
assert_image(im, im.mode, im.size)
|
||||
|
||||
class TestImageGrab:
|
||||
@pytest.mark.skip(reason="ImageGrab ImportError")
|
||||
def test_skip(self):
|
||||
pass
|
||||
im2 = ImageGrab.grab(xdisplay="")
|
||||
assert_image(im2, im2.mode, im2.size)
|
||||
except IOError as e:
|
||||
pytest.skip(str(e))
|
||||
|
||||
|
||||
class TestImageGrabImport:
|
||||
def test_import(self):
|
||||
# Arrange
|
||||
@pytest.mark.skipif(not Image.core.HAVE_XCB, reason="requires XCB")
|
||||
def test_grab_invalid_xdisplay(self):
|
||||
exception = None
|
||||
|
||||
# Act
|
||||
try:
|
||||
from PIL import ImageGrab
|
||||
|
||||
ImageGrab.__name__ # dummy to prevent Pyflakes warning
|
||||
ImageGrab.grab(xdisplay="error.test:0.0")
|
||||
except Exception as e:
|
||||
exception = e
|
||||
|
||||
# Assert
|
||||
if sys.platform in ["win32", "darwin"]:
|
||||
assert exception is None
|
||||
assert isinstance(exception, IOError)
|
||||
assert str(exception).startswith("X connection failed")
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.platform not in ("win32", "darwin"), reason="requires Windows or macOS"
|
||||
)
|
||||
def test_grabclipboard(self):
|
||||
if sys.platform == "darwin":
|
||||
subprocess.call(["screencapture", "-cx"])
|
||||
elif sys.platform == "win32":
|
||||
p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
|
||||
p.stdin.write(
|
||||
b"""[Reflection.Assembly]::LoadWithPartialName("System.Drawing")
|
||||
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
|
||||
$bmp = New-Object Drawing.Bitmap 200, 200
|
||||
[Windows.Forms.Clipboard]::SetImage($bmp)"""
|
||||
)
|
||||
p.communicate()
|
||||
else:
|
||||
assert isinstance(exception, ImportError)
|
||||
assert str(exception) == "ImageGrab is macOS and Windows only"
|
||||
pytest.skip("ImageGrab.grabclipboard() is macOS and Windows only")
|
||||
return
|
||||
|
||||
im = ImageGrab.grabclipboard()
|
||||
assert_image(im, im.mode, im.size)
|
||||
|
|
1
setup.py
1
setup.py
|
@ -823,6 +823,7 @@ class pil_build_ext(build_ext):
|
|||
(feature.lcms, "LITTLECMS2"),
|
||||
(feature.webp, "WEBP"),
|
||||
(feature.webpmux, "WEBPMUX"),
|
||||
(feature.xcb, "XCB (X protocol)"),
|
||||
]
|
||||
|
||||
all = 1
|
||||
|
|
|
@ -22,12 +22,12 @@ import tempfile
|
|||
|
||||
from . import Image
|
||||
|
||||
if sys.platform == "win32":
|
||||
pass
|
||||
elif sys.platform == "darwin":
|
||||
if sys.platform == "darwin":
|
||||
import os
|
||||
import tempfile
|
||||
import subprocess
|
||||
elif sys.platform == "win32":
|
||||
pass
|
||||
elif not Image.core.HAVE_XCB:
|
||||
raise ImportError("ImageGrab requires Windows, macOS, or the XCB library")
|
||||
|
||||
|
@ -65,17 +65,9 @@ def grab(bbox=None, include_layered_windows=False, all_screens=False, xdisplay=N
|
|||
return im
|
||||
# use xdisplay=None for default display on non-win32/macOS systems
|
||||
if not Image.core.HAVE_XCB:
|
||||
raise OSError("XCB support not included")
|
||||
raise AttributeError("XCB support not present")
|
||||
size, data = Image.core.grabscreen_x11(xdisplay)
|
||||
im = Image.frombytes(
|
||||
"RGB",
|
||||
size,
|
||||
data,
|
||||
"raw",
|
||||
"BGRX",
|
||||
size[0] * 4,
|
||||
1,
|
||||
)
|
||||
im = Image.frombytes("RGB", size, data, "raw", "BGRX", size[0] * 4, 1)
|
||||
if bbox:
|
||||
im = im.crop(bbox)
|
||||
return im
|
||||
|
|
|
@ -845,8 +845,8 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args)
|
|||
|
||||
connection = xcb_connect(display_name, &screen_number);
|
||||
if (xcb_connection_has_error(connection)) {
|
||||
PyErr_Format(PyExc_IOError, "X connection failed: error %i", xcb_connection_has_error(connection));
|
||||
xcb_disconnect(connection);
|
||||
PyErr_SetString(PyExc_IOError, "X connection failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -857,7 +857,8 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (screen == NULL) {
|
||||
if (screen == NULL || screen->root == 0) {
|
||||
// this case is usually caught with "X connection failed: error 6" above
|
||||
xcb_disconnect(connection);
|
||||
PyErr_SetString(PyExc_IOError, "X screen not found");
|
||||
return NULL;
|
||||
|
@ -873,16 +874,21 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args)
|
|||
0, 0, width, height, 0x00ffffff),
|
||||
&error);
|
||||
if (reply == NULL) {
|
||||
PyErr_Format(PyExc_IOError, "X get_image failed: error %i (%i, %i, %i)",
|
||||
error->error_code, error->major_code, error->minor_code, error->resource_id);
|
||||
free(error);
|
||||
xcb_disconnect(connection);
|
||||
PyErr_SetString(PyExc_IOError, "X get_image failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* store data in Python buffer */
|
||||
|
||||
buffer = PyBytes_FromStringAndSize((char*)xcb_get_image_data(reply),
|
||||
xcb_get_image_data_length(reply));
|
||||
if (reply->depth == 24) {
|
||||
buffer = PyBytes_FromStringAndSize((char*)xcb_get_image_data(reply),
|
||||
xcb_get_image_data_length(reply));
|
||||
} else {
|
||||
PyErr_Format(PyExc_IOError, "usupported bit depth: %i", reply->depth);
|
||||
}
|
||||
|
||||
free(reply);
|
||||
xcb_disconnect(connection);
|
||||
|
|
Loading…
Reference in New Issue
Block a user