8

I'm trying to get a full screen (1920 x 1080) capture using this code. The saved images are only 1536 x 864 though.

solution: As Mark pointed out below, Windows has scaling which can be changed via Control Panel > Display (turn it all the way down).

from PIL import ImageGrab
import os
import time

def screenGrab():
    # snapshot of screen
    im = ImageGrab.grab()
    # saves in current work directory with name based on time of pic
    im.save(os.getcwd() + '\\full_snap__' + str(int(time.time()))
            + '.png', 'PNG')

def main():
    screenGrab()

if __name__ == '__main__':
    main()
NoahLE
  • 325
  • 3
  • 15
  • 3
    I can't reproduce your problem on my 1920x1200 monitor, it grabs the whole thing. If you print `im.size` what do you get? – Mark Ransom Aug 24 '14 at 04:17
  • (1536, 864). I'm on a laptop @ 1920 x 1080 right now if that makes a difference (that's the native resolution). – NoahLE Aug 26 '14 at 04:57
  • Is it possible that you've got your desktop configured for that resolution? Go to Display Properties and verify it. – Mark Ransom Aug 26 '14 at 13:16
  • It's definitely 1920 x 1080 on both Windows 8.1 and Mint 17. I did notice that the screenshot resolution is 20% small than my native one. Any settings that could be causing this? – NoahLE Aug 26 '14 at 22:30
  • Another experiment: use the PrtScn button to copy your desktop to the clipboard, and paste it into MS Paint. See what size it says you have. – Mark Ransom Aug 26 '14 at 22:33
  • The screen shot is full resolution. Def has to do something with Pillow / PIL (or Python itself?). I don't know if it helps but [here's a screenshot](http://i.imgur.com/NrCjUCl.png) taken with a fullscreen cap, and [here's one](http://i.imgur.com/36y7k3T.png) with an explicit 1920 x 1080 resolution set. – NoahLE Aug 28 '14 at 18:52
  • 2
    It's interesting that the text in the window title bar is nice and crisp while the rest of the text looks like it was resized. I suspect Windows is lying to the software, declaring a size of 1536x864 and scaling the output through DWM. If you have any scaling option turned on in the display properties try turning it off and see if it changes anything. – Mark Ransom Aug 28 '14 at 19:18
  • @MarkRansom: Either you or the OP should have written an answer; instead, we've got a question sitting here with a positive score and no answer, but that happens to have the answer embedded in the question. Anyway, I'll write an answer, but if you or the OP writes one, ping me and I'll delete mine. – abarnert Sep 04 '14 at 23:52
  • @abarnert I didn't think it was vital that there be an official answer, but I'll add one if it makes you feel better. – Mark Ransom Sep 04 '14 at 23:54
  • @MarkRansom: Answered questions are more likely to show up, and to be noticed and looked at, by future users with the same problem (although it doesn't do nearly as much good if the OP doesn't accept it). – abarnert Sep 04 '14 at 23:55

3 Answers3

10

If you have your Display settings set to anything other than the "smaller" (100%) setting which is the default, Windows will tell your applications to render to a smaller area and then magnify the results as it puts it on the desktop. Evidently PIL has a bug caused by this setting, the capture is being cropped to the smaller size rather than the full desktop. The workaround is to be sure that your display settings are set to 100%.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
2

I manage to overcome this issue by adding registry key at

HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers

add a key with the path to your python.exe and pythonw.exe and in value set HIGHDPIAWARE

like so:

"C:\Users\Greg\Anaconda3\python.exe"="HIGHDPIAWARE"

"C:\Users\Greg\Anaconda3\pythonw.exe"="HIGHDPIAWARE"

then everythings should be ok :)

credit to that post: Marking Your Python Program as High DPI Aware Seamlessly Windows

Gregy8
  • 94
  • 8
0

I have faced the same issue.. running on 4k screen trying to capture a 1080p app. Thanks to this thread, call the following code before ImageGrab:

from ctypes import windll
user32 = windll.user32
user32.SetProcessDPIAware()

window_size = get_window_info()
last_time = time.time()
cv2.namedWindow("output", cv2.WINDOW_NORMAL)
while True:
    screen = np.array(ImageGrab.grab(bbox=window_size))
    # print('Frame took {} seconds'.format(time.time()-last_time))
    last_time = time.time()
    # new_screen = process_img(screen)
    imS = cv2.resize(screen, (960, 540))
    cv2.imshow('output', imS)
    # cv2.imshow('window',cv2.cvtColor(screen, cv2.COLOR_BGR2RGB))
    if cv2.waitKey(25) & 0xFF == ord('q'):
        cv2.destroyAllWindows()
        break

This solved my problem.

Yikang Luo
  • 186
  • 1
  • 9