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

gdi32.GetDIBits() failed #212

Closed FlorinPT closed 2 years ago

FlorinPT commented 2 years ago

General information:

Traceback (most recent call last): File "C:\Users\PC\AppData\Local\Programs\Python\Python39\lib\threading.py", line 980, in _bootstrap_inner self.run() File "C:\Users\PC\AppData\Local\Programs\Python\Python39\lib\threading.py", line 917, in run self._target(*self._args, **self._kwargs) File "C:\Program Files\Test\main.py", line 185, in procces procces_1 = imagesearch.imagesearch("lib/images/foto.png") File "C:\Users\PC\AppData\Local\Programs\Python\Python39\lib\site-packages\python_imagesearch\imagesearch.py", line 122, in imagesearch im = sct.grab(sct.monitors[0]) File "C:\Users\PC\AppData\Local\Programs\Python\Python39\lib\site-packages\mss\base.py", line 88, in grab return self._grab_impl(monitor) File "C:\Users\PC\AppData\Local\Programs\Python\Python39\lib\site-packages\mss\windows.py", line 285, in _grab_impl
raise ScreenShotError("gdi32.GetDIBits() failed.") mss.exception.ScreenShotError: gdi32.GetDIBits() failed.

FlorinPT commented 2 years ago

how can i solve this problem

FlorinPT commented 2 years ago

@BoboTiG

BoboTiG commented 2 years ago

Can you retry with the patch from #211 ?

FlorinPT commented 2 years ago

File "C:\Program Files\Test\main.py", line 185, in procces procces_1 = imagesearch.imagesearch("lib/images/foto.png")

File "C:\Program Files\Test\main.py", line 185, in procces procces_1 = imagesearch.imagesearch("lib/images/foto.png")

I didn't use it in test.py but because of that it gives error

CTPaHHuK-HEbA commented 2 years ago

The python_imagesearch package uses mss. so try modifying the mss/windows.py file from #211 and run your example.

CTPaHHuK-HEbA commented 2 years ago

ThreadSafety monkey patch: Download windows.txt rename to windows.py, copy to C:\Program Files\Python\Lib\site-packages\mss> and check. windows.txt

CTPaHHuK-HEbA commented 2 years ago
diff --git a/mss/windows.py b/mss/windows.py
index 05c2b45..c41adbb 100644
--- a/mss/windows.py
+++ b/mss/windows.py
@@ -99,13 +99,7 @@ CFUNCTIONS = {
 class MSS(MSSBase):
     """ Multiple ScreenShots implementation for Microsoft Windows. """

-    __slots__ = {"_bmi", "_data", "gdi32", "user32"}
-
-    # Class attributes instanced one time to prevent resource leaks.
-    bmp = None
-    memdc = None
-    height = 0
-    width = 0
+    __slots__ = {"bmp", "memdc", "height", "width", "_bmi", "_data", "gdi32", "user32"}

     # A dict to maintain *srcdc* values created by multiple threads.
     _srcdc_dict = {}  # type: Dict[threading.Thread, int]
@@ -123,9 +117,9 @@ class MSS(MSSBase):

         self._data = ctypes.create_string_buffer(0)  # type: ctypes.Array[ctypes.c_char]

+        self.bmp = None
         srcdc = self._get_srcdc()
-        if not MSS.memdc:
-            MSS.memdc = self.gdi32.CreateCompatibleDC(srcdc)
+        self.memdc = self.gdi32.CreateCompatibleDC(srcdc)

         bmi = BITMAPINFO()
         bmi.bmiHeader.biSize = ctypes.sizeof(BITMAPINFOHEADER)
@@ -136,6 +130,14 @@ class MSS(MSSBase):
         bmi.bmiHeader.biClrImportant = 0  # See grab.__doc__ [3]
         self._bmi = bmi

+        self.height = 0
+        self.width = 0
+
+    def __del__(self):
+        """ Delete resource. """
+        self.gdi32.DeleteObject(self.bmp)
+        self.gdi32.DeleteObject(self.memdc)
+
     def _set_cfunctions(self):
         """ Set all ctypes functions and attach them to attributes. """

@@ -255,22 +257,22 @@ class MSS(MSSBase):
         Thanks to http://stackoverflow.com/a/3688682
         """

-        srcdc, memdc = self._get_srcdc(), MSS.memdc
+        srcdc = self._get_srcdc()
         width, height = monitor["width"], monitor["height"]

-        if (MSS.height, MSS.width) != (height, width):
+        if (self.height, self.width) != (height, width):
             self._bmi.bmiHeader.biWidth = width
             self._bmi.bmiHeader.biHeight = -height  # Why minus? [1]
             self._data = ctypes.create_string_buffer(width * height * 4)  # [2]
-            MSS.height = height
-            MSS.width = width
-            if MSS.bmp:
-                self.gdi32.DeleteObject(MSS.bmp)
-            MSS.bmp = self.gdi32.CreateCompatibleBitmap(srcdc, width, height)
-            self.gdi32.SelectObject(memdc, MSS.bmp)
+            self.height = height
+            self.width = width
+            if self.bmp:
+                self.gdi32.DeleteObject(self.bmp)
+            self.bmp = self.gdi32.CreateCompatibleBitmap(srcdc, width, height)
+            self.gdi32.SelectObject(self.memdc, self.bmp)

         self.gdi32.BitBlt(
-            memdc,
+            self.memdc,
             0,
             0,
             width,
@@ -281,7 +283,7 @@ class MSS(MSSBase):
             SRCCOPY | CAPTUREBLT,
         )
         bits = self.gdi32.GetDIBits(
-            memdc, MSS.bmp, 0, height, self._data, self._bmi, DIB_RGB_COLORS
+            self.memdc, self.bmp, 0, height, self._data, self._bmi, DIB_RGB_COLORS
         )
         if bits != height:
             raise ScreenShotError("gdi32.GetDIBits() failed.")