BoboTiG / python-mss

An ultra fast cross-platform multiple screenshots module in pure Python using ctypes.
https://pypi.org/project/mss/
MIT License
1.04k stars 94 forks source link

Bad cached BMP: gdi32.GetDIBits() failed #211

Closed CTPaHHuK-HEbA closed 1 year ago

CTPaHHuK-HEbA commented 2 years ago

For fast grab i use 2 grab: one grab only box(const), other grab line(const). Fast - not calls: create_string_buffer + gdi32.DeleteObject + gdi32.CreateCompatibleBitmap + gdi32.SelectObject

Found Bug:

from mss import mss

grab1 = mss()
grab2 = mss()
print(id(grab1) == id(grab2))

grab1.grab({'top': 0, 'left': 0, 'width': 100, 'height': 100})
grab2.grab({'top': 0, 'left': 0, 'width': 50, 'height': 1})
grab1.grab({'top': 0, 'left': 0, 'width': 100, 'height': 100})
  File "C:\Program Files\Python310\lib\site-packages\mss\windows.py", line 285, in _grab_impl
    raise ScreenShotError("gdi32.GetDIBits() failed.")
mss.exception.ScreenShotError: gdi32.GetDIBits() failed.
sourcery-ai[bot] commented 2 years ago

Sourcery Code Quality Report

✅  Merging this PR will increase code quality in the affected files by 0.50%.

Quality metrics Before After Change
Complexity 1.36 ⭐ 1.42 ⭐ 0.06 👎
Method Length 94.25 🙂 89.33 🙂 -4.92 👍
Working memory 7.17 🙂 7.24 🙂 0.07 👎
Quality 72.17% 🙂 72.67% 🙂 0.50% 👍
Other metrics Before After Change
Lines 325 368 43
Changed files Quality Before Quality After Quality Change
mss/windows.py 67.21% 🙂 66.07% 🙂 -1.14% 👎
mss/tests/test_windows.py 83.80% ⭐ 81.29% ⭐ -2.51% 👎

Here are some functions in these files that still need a tune-up:

File Function Complexity Length Working Memory Quality Recommendation
mss/windows.py MSS._grab_impl 5 ⭐ 195 😞 12 😞 50.20% 🙂 Try splitting into smaller methods. Extract out complex expressions
mss/windows.py MSS._monitors_impl 0 ⭐ 131 😞 72.97% 🙂 Try splitting into smaller methods
mss/windows.py MSS.__init__ 1 ⭐ 137 😞 5 ⭐ 75.00% 🙂 Try splitting into smaller methods

Legend and Explanation

The emojis denote the absolute quality of the code:

The 👍 and 👎 indicate whether the quality has improved or gotten worse with this pull request.


Please see our documentation here for details on how these metrics are calculated.

We are actively working on this report - lots more documentation and extra metrics to come!

Help us improve this quality report!

CTPaHHuK-HEbA commented 2 years ago

May be fix: https://github.com/BoboTiG/python-mss/issues/198

CTPaHHuK-HEbA commented 2 years ago

This patch solves the problem when multiple grabers are used, but does not solve the problem of multithreading :( This global problem, when used cached MSS.bmp and MSS.memdc - even when the dimensions are equal !!!

If run code - all ok

from multiprocessing.pool import ThreadPool
import threading
import mss

Thread = 4

def grab_pr(bbox):
    with mss.mss() as sct:
        for i in range(50):
            # bbox = sct.monitors[0]  # FAIL 
            print(bbox, sct, threading.main_thread(), threading.current_thread())
            im = sct.grab(bbox)

if __name__ == '__main__':
    print(threading.main_thread(), threading.current_thread())
    arg = [(10, 10, 1000 + i, 1000 + i) for i in range(Thread)]
    pool = ThreadPool(Thread)
    results = pool.map(grab_pr, arg)
    pool.close()
    pool.join()

But uncoment line: # bbox = sct.monitors[0] # FAIL Return error: mss.exception.ScreenShotError: gdi32.GetDIBits() failed

CTPaHHuK-HEbA commented 2 years ago

It is necessary that each thread uses only its own cache: bmp and memdc. Well, if there is no multithreading, then one is enough for everyone.

CTPaHHuK-HEbA commented 2 years ago

If use patch windows.py from #212 - all Thred ok! - but it is monkey patch )))

CTPaHHuK-HEbA commented 2 years ago

New commit fix and thread.

Description bug: Grab1 or Thread1 region (x, y, h, w)
Set MSS.bmp = CreateCompatibleBitmap(srcdc, w, h)

Grab2 or Thread2 region (x2, y2, h2, w2) Change MSS.bmp = CreateCompatibleBitmap(srcdc, w2, h2)

Grab1 or Thread1 region (x, y, h, w)
He thinks MSS.bmp == CreateCompatibleBitmap(srcdc, w, h) and not change. But MSS.bmp == CreateCompatibleBitmap(srcdc, w2, h2) BUG

Also run test from #198 - all ok

BoboTiG commented 2 years ago

I just updated the master branch with a complete CI running on GitHub Actions. Would you mind rebasing your pull request?

BoboTiG commented 1 year ago

The CI is green again on the master branch. It will help here :)

BoboTiG commented 1 year ago

I'll review how those attributes are stored, because that's quite a mess what I did haha

BoboTiG commented 1 year ago

Thanks @CTPaHHuK-HEbA, sorry for the loooong delay. I incorporated your tests in #250, and they all pass (even if some are not really relevant, I kept all of them for safety).