Skip to content

Commit 79a59bf

Browse files
committed
MSS: Speed-up grabbing o the 3 platforms
1 parent 1b99ce4 commit 79a59bf

20 files changed

+187
-94
lines changed

.github/ISSUE_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ General informations:
77
* Monitor 1: _800x600_
88
* Monitor 2: _1920x1080_
99
* Python version: _3.6.4_
10-
* MSS version: __3.1.3__
10+
* MSS version: __3.2.0__
1111

1212

1313
For GNU/Linux users:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ MANIFEST*
1010
*.png
1111
*.png.old
1212
*.pyc
13+
.pytest_cache

.travis.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
language: python
22
python:
33
- 2.7
4-
- 3.4
54
- 3.5
65
- 3.6
7-
# - nightly # currently points to 3.7-dev
6+
- nightly # currently points to 3.7-dev
87

98
addons:
109
apt:
@@ -25,12 +24,9 @@ install:
2524
script:
2625
- py.test --showlocals --display=":42.0"
2726
- flake8 .
28-
- pylint mss
27+
- if [[ $TRAVIS_PYTHON_VERSION < '3.7' ]]; then pylint mss; fi
2928
- if [[ $TRAVIS_PYTHON_VERSION > '2.8' ]]; then cd docs && make clean html; fi
3029

3130
after_script:
3231
- xpra stop :42
3332
- cat ~/.xpra/*.log
34-
35-
matrix:
36-
fast_finish: true

CHANGELOG

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ History:
44

55
dev 2018/xx/xx
66
- add PNG compression level control
7-
- MSS: add Screenshot.bgra attribute
7+
- MSS: add the Screenshot.bgra attribute
8+
- MSS: speed-up grabbing on the 3 platforms
9+
- tests: add leaks.py and benchmarks.py for manual testing
810

911
3.1.2 2018/01/05
1012
- removed support for Python 3.3
@@ -26,7 +28,7 @@ dev 2018/xx/xx
2628
- Mac: properly support all display scaling and resolutions (fix #14, #19, #21, #23)
2729
- Mac: fix memory leaks (fix #24)
2830
- Linux: handle bad display value
29-
- Windows: Take into account zoom factor for high-DPI displays (fix #20)
31+
- Windows: take into account zoom factor for high-DPI displays (fix #20)
3032

3133
3.0.1 2017/07/06
3234
- fix examples links

CHANGES.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
3.1.3 (2018-xx-xx)
1+
3.2.0 (2018-xx-xx)
22
==================
33

44
base.py
55
-------
66
- Added ``MSSBase.compression_level`` to control the PNG compression level
77

8+
linux.py
9+
--------
10+
- Added ``MSS.drawable`` to speed-up grabbing.
11+
812
screenshot.py
913
-------------
1014
- Added ``Screenshot.bgra`` to get BGRA bytes.

docs/source/api.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ Methods
124124

125125
.. versionadded:: 3.0.0
126126

127-
.. versionadded:: 3.1.3
127+
.. versionadded:: 3.2.0
128128

129129
Added the ``level`` keyword argument to control the PNG compression level.
130130

@@ -169,7 +169,7 @@ Properties
169169

170170
:rtype: bytes
171171

172-
.. versionadded:: 3.1.3
172+
.. versionadded:: 3.2.0
173173

174174
.. attribute:: height
175175

docs/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
# built documents.
3232
#
3333
# The short X.Y version.
34-
version = '3.1.3'
34+
version = '3.2.0'
3535

3636
# The full version, including alpha/beta/rc tags.
3737
release = 'latest'

docs/source/developers.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ You will need `pytest <https://pypi.python.org/pypi/pytest>`_::
2323
$ pip install pytest
2424

2525

26-
How to test?
26+
How to Test?
2727
------------
2828

2929
Enable the developer mode::
@@ -39,7 +39,7 @@ Launch the test suit::
3939
As he module is Python 2 and 3 compliant, do no forgot to test for both. If you cannot, just say it when sending the patch, someone else will validate for you.
4040

4141

42-
Validating the code
42+
Validating the Code
4343
===================
4444

4545
It is important to keep a clean base code. Use tools like `flake8 <https://pypi.python.org/pypi/flake8>`_ and `Pylint <https://pypi.python.org/pypi/pylint>`_.
@@ -53,7 +53,7 @@ Install required packages::
5353
$ pip install flake8 pylint
5454

5555

56-
How to validate?
56+
How to Validate?
5757
----------------
5858

5959
::
@@ -64,7 +64,7 @@ How to validate?
6464
If there is no output, you are good ;)
6565

6666

67-
Static type checking
67+
Static Type Checking
6868
====================
6969

7070
`mypy <http://mypy-lang.org/>`_ is a compile-time static type checker for Python, allowing optional, gradual typing of Python code.
@@ -79,7 +79,7 @@ Install required packages::
7979
$ pip install mypy-lang
8080

8181

82-
Running mypy
82+
Running Mypy
8383
------------
8484

8585
::
@@ -98,7 +98,7 @@ You will need `Sphinx <http://sphinx-doc.org/>`_::
9898
$ pip install sphinx
9999

100100

101-
How to build?
101+
How to Build?
102102
-------------
103103

104104
::

docs/source/examples.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ You can tweak the PNG compression level (see :py:func:`zlib.compress()` for deta
6363

6464
sct.compression_level = 2
6565

66-
.. versionadded:: 3.1.3
66+
.. versionadded:: 3.2.0
6767

6868
Advanced
6969
========

docs/source/installation.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
Installation
55
============
66

7-
Recommended way
7+
Recommended Way
88
===============
99

1010
Quite simple::
1111

1212
$ pip install --upgrade mss
1313

1414

15-
From sources
15+
From Sources
1616
============
1717

1818
Alternatively, you can get a copy of the module from GitHub::

docs/source/support.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Support
44

55
Feel free to try MSS on a system we had not tested, and let report us by creating an `issue <htps://github.com/BoboTiG/python-mss/issues>`_.
66

7-
GNU/Linux, macOS and Windows: **2.7**, 3.4, 3.5, **3.6** and 3.7-dev.
7+
GNU/Linux, macOS and Windows: **2.7**, 3.5, **3.6** and 3.7-dev.
88

99

1010
Future
@@ -23,8 +23,9 @@ Tested successfully on Pypy 5.1.0 on Windows, but speed is terrible.
2323
Abandoned
2424
=========
2525

26-
- 2016-10-08 Support for Python 2.6 was dropped: too old and introduced optimizations broke it.
27-
- 2016-10-08 Support for Python 3.0, 3.1, and 3.2 was dropped: there is no more tests facilities.
28-
- 2017-12-05 Support for Python 3.3 was dropped: there is no more tests facilities for the documentation.
26+
- Python 2.6 (2016-10-08)
27+
- Python 3.0, 3.1, and 3.2 (2016-10-08)
28+
- Python 3.3 (2017-12-05)
29+
- Python 3.4 (2018-03-19)
2930

3031
By the way, if you find the *force*, give it a try and tell us if you managed to make one of these versions working (a patch should be quite easy).

docs/source/usage.rst

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,25 @@ A more specific example to only target GNU/Linux:
4949
:lines: 9-
5050

5151

52-
Command line
52+
Intensive Use
53+
=============
54+
55+
If you plan to integrate MSS inside your own module or software, pay attention to using it wisely. This is a bad usage::
56+
57+
for _ in range(100):
58+
with mss() as sct:
59+
sct.shot()
60+
61+
This is a better usage, memory efficient::
62+
63+
with mss() as sct:
64+
for _ in range(100):
65+
sct.shot()
66+
67+
Also, it is a good thing to save the MSS instance inside an attribute of you class and calling it when needed.
68+
69+
70+
Command Line
5371
============
5472

5573
You can use ``mss`` via the CLI:

docs/source/where.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
============
2-
Who uses it?
2+
Who Uses it?
33
============
44

55
This is a non exhaustive list where MSS is integrated or has inspired.

mss/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from .exception import ScreenShotError
1414
from .factory import mss
1515

16-
__version__ = '3.1.3'
16+
__version__ = '3.2.0'
1717
__author__ = "Mickaël 'Tiger-222' Schoentgen"
1818
__copyright__ = """
1919
Copyright (c) 2013-2018, Mickaël 'Tiger-222' Schoentgen

mss/darwin.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -187,29 +187,30 @@ def grab(self, monitor):
187187
'height': monitor[3] - monitor[1],
188188
}
189189

190+
core = self.core
190191
rect = CGRect((monitor['left'], monitor['top']),
191192
(monitor['width'], monitor['height']))
192193

193-
image_ref = self.core.CGWindowListCreateImage(rect, 1, 0, 0)
194+
image_ref = core.CGWindowListCreateImage(rect, 1, 0, 0)
194195
if not image_ref:
195196
raise ScreenShotError(
196197
'CoreGraphics.CGWindowListCreateImage() failed.', locals())
197198

198-
width = int(self.core.CGImageGetWidth(image_ref))
199-
height = int(self.core.CGImageGetHeight(image_ref))
199+
width = int(core.CGImageGetWidth(image_ref))
200+
height = int(core.CGImageGetHeight(image_ref))
200201
prov = copy_data = None
201202
try:
202-
prov = self.core.CGImageGetDataProvider(image_ref)
203-
copy_data = self.core.CGDataProviderCopyData(prov)
204-
data_ref = self.core.CFDataGetBytePtr(copy_data)
205-
buf_len = self.core.CFDataGetLength(copy_data)
203+
prov = core.CGImageGetDataProvider(image_ref)
204+
copy_data = core.CGDataProviderCopyData(prov)
205+
data_ref = core.CFDataGetBytePtr(copy_data)
206+
buf_len = core.CFDataGetLength(copy_data)
206207
raw = ctypes.cast(
207208
data_ref, ctypes.POINTER(ctypes.c_ubyte * buf_len))
208209
data = bytearray(raw.contents)
209210

210211
# Remove padding per row
211-
bytes_per_row = int(self.core.CGImageGetBytesPerRow(image_ref))
212-
bytes_per_pixel = int(self.core.CGImageGetBitsPerPixel(image_ref))
212+
bytes_per_row = int(core.CGImageGetBytesPerRow(image_ref))
213+
bytes_per_pixel = int(core.CGImageGetBitsPerPixel(image_ref))
213214
bytes_per_pixel = (bytes_per_pixel + 7) // 8
214215

215216
if bytes_per_pixel * width != bytes_per_row:
@@ -221,8 +222,8 @@ def grab(self, monitor):
221222
data = cropped
222223
finally:
223224
if prov:
224-
self.core.CGDataProviderRelease(prov)
225+
core.CGDataProviderRelease(prov)
225226
if copy_data:
226-
self.core.CFRelease(copy_data)
227+
core.CFRelease(copy_data)
227228

228229
return self.cls_image(data, monitor, size=Size(width, height))

mss/linux.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ def __init__(self, display=None):
165165
self.root = self.xlib.XDefaultRootWindow(
166166
self.display, self.xlib.XDefaultScreen(self.display))
167167

168+
# Fix for XRRGetScreenResources and XGetImage:
169+
# expected LP_Display instance instead of LP_XWindowAttributes
170+
self.drawable = ctypes.cast(self.root, ctypes.POINTER(Display))
171+
168172
def _set_argtypes(self):
169173
# type: () -> None
170174
""" Functions arguments. """
@@ -251,10 +255,8 @@ def monitors(self):
251255
})
252256

253257
# Each monitors
254-
# Fix for XRRGetScreenResources:
255-
# expected LP_Display instance instead of LP_XWindowAttributes
256-
root = ctypes.cast(self.root, ctypes.POINTER(Display))
257-
mon = self.xrandr.XRRGetScreenResources(self.display, root)
258+
mon = self.xrandr.XRRGetScreenResources(self.display,
259+
self.drawable)
258260
for idx in range(mon.contents.ncrtc):
259261
crtc = self.xrandr.XRRGetCrtcInfo(self.display, mon,
260262
mon.contents.crtcs[idx])
@@ -286,11 +288,7 @@ def grab(self, monitor):
286288
'height': monitor[3] - monitor[1],
287289
}
288290

289-
# Fix for XGetImage:
290-
# expected LP_Display instance instead of LP_XWindowAttributes
291-
root = ctypes.cast(self.root, ctypes.POINTER(Display))
292-
293-
ximage = self.xlib.XGetImage(self.display, root,
291+
ximage = self.xlib.XGetImage(self.display, self.drawable,
294292
monitor['left'], monitor['top'],
295293
monitor['width'], monitor['height'],
296294
PLAINMASK, ZPIXMAP)
@@ -308,6 +306,5 @@ def grab(self, monitor):
308306

309307
# Free
310308
self.xlib.XDestroyImage(ximage)
311-
ximage = None
312309

313310
return self.cls_image(data, monitor)

mss/screenshot.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,10 @@ def rgb(self):
116116

117117
if not self.__rgb:
118118
rgb = bytearray(self.height * self.width * 3)
119-
rgb[0::3], rgb[1::3], rgb[2::3] = \
120-
self.raw[2::4], self.raw[1::4], self.raw[0::4]
119+
raw = self.raw
120+
rgb[0::3] = raw[2::4]
121+
rgb[1::3] = raw[1::4]
122+
rgb[2::3] = raw[0::4]
121123
self.__rgb = bytes(rgb)
122124

123125
return self.__rgb

0 commit comments

Comments
 (0)