I want to take a screenshot using python.
I have tried using PIL, but since I am using 64bit windows and python PIL does not work (I could only find 32bit PIL versions). I am using python 2.7.1 by the way.
I want to take a screenshot, it doesn't really matter how, as long as it can take more than 1 per second in speed. Preferably it should also be able to crop the area it takes a screenshot of, but that's not of the utmost importance.
The main problem seems to be I'm running on 64bit and a lot of things seem incompatible with that. I don't really want to move back to 32bit though if at all possible.
Are there any programs or modules that can do this?
Get PIL for win-amd64-py2.7 at http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil.
from PIL import ImageGrab
im = ImageGrab.grab()
im.save('screenshot.png')
Update: use pywin32 (http://sourceforge.net/projects/pywin32/) instead of PIL to take screenshots of multiple virtual screens:
import win32gui, win32ui, win32con, win32api
hwin = win32gui.GetDesktopWindow()
width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)
hwindc = win32gui.GetWindowDC(hwin)
srcdc = win32ui.CreateDCFromHandle(hwindc)
memdc = srcdc.CreateCompatibleDC()
bmp = win32ui.CreateBitmap()
bmp.CreateCompatibleBitmap(srcdc, width, height)
memdc.SelectObject(bmp)
memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), win32con.SRCCOPY)
bmp.SaveBitmapFile(memdc, 'screenshot.bmp')
32- or 64-bit Windows is irrelevant here; it is the 'bit-ness' of Python and its modules that matter. If you are running 32-bit-compiled Python, 32-bit-compiled PIL will work just fine on 64-bit Windows.
On the other hand, if you are running 64-bit-compiled Python, you need to find or custom-compile a 64-bit-compiled version of PIL to match.
Edit:
You can download a 64-bit-compiled version of PIL from http://www.lfd.uci.edu/~gohlke/pythonlibs/ - specifically, you want PIL-1.1.7.win-amd64-py2.7.exe
I got the same problem on PIL or pyscreenshot, here's how I solved it.
Right-click on python.exe, Properties, Compatibility tab, check 'Disable display scaling on high DPI settings'. Repeat for pythonw.exe.
Related
I have:
Pillow-3.4.0-cp34-cp34--win32.whl (md5) (which I found here)
Python-3.4.0.amd64
Pyscripter-v2.6.0-setup
I am attempting to create a program that can compare two images and have come across a problem to do with PIL. As I understand it, you have to download Pillow and import the 'Image' module from it. I have downloaded the above Pillow program and this is the various codes I have tried to use:
from Pillow import Image
OR
import pip
installed_packages = pip.get_installed_distributions()
installed_packages_list = sorted(["%s==%s" % (i.key, i.version)
for i in installed_packages])
print(installed_packages_list)
import Pillow
import Image
OR SIMPLY
import Image
None of these have worked (they come up with various different error messages including 'no module named Pillow/PIL/Image') and I have tried a couple other slight variants on these but still, none have worked. I am looking for perfection rather than simplicity and anything useful would be amazing. Thankyou. Also, if anyone can provide a way that will account for brightness differences (I am trying to compare a picture of an image on a screen with the image itself).
Try this
from PIL import Image, ImageFont, ImageDraw
im = Image.new('RGB', (100,400), (255,0,0))
dr = ImageDraw.Draw(im)
This code cpuld draw images,just try it if it works.
My PIL version
PIL.__version__
'4.0.0'
What imaging modules for python will allow you to take a specific size screenshot (not whole screen)?
I have tried PIL, but can't seem to make ImageGrab.grab() select a small rectangle
and i have tried PyGame but i can't make it take a screen shot outside of it's main display panel
You can use pyscreenshot module.
The pyscreenshot module can be used to copy the contents of the screen to a PIL image memory or file.
You can install it using pip.
$ sudo pip install pyscreenshot
Usage:
import pyscreenshot as ImageGrab
# fullscreen
im=ImageGrab.grab()
im.show()
# part of the screen
im=ImageGrab.grab(bbox=(10,10,500,500))
im.show()
# to file
ImageGrab.grab_to_file('im.png')
I have tried PIL, but can't seem to make ImageGrab.grab() select a small rectangle
What did you try?
As the documentation for ImageGrab clearly states, the function has a bbox parameter, and:
The pixels inside the bounding box are returned as an “RGB” image. If the bounding box is omitted, the entire screen is copied.
So, you only get the whole screen if you don't pass a bbox.
Note that, although I linked to the Pillow docs (and you should be using Pillow), old-school PIL's docs say the same thing:
The bounding box argument can be used to copy only a part of the screen.
So, unless you're using a really, really old version of PIL (before 1.1.3, which I believe is more than a decade out of date), it has this feature.
1) Use pyscreenshot, ImageGrab works but only on Windows
2) Grab the image and box it, then save that image
3) Don't use ImageGrab.grab_to_file, it saves the full size image
4) You don't need to show the image with im.show if you just want to save a screenshot
import pyscreenshot as ImageGrab
im=ImageGrab.grab(bbox=(10,10,500,500))
im.save('im.png')
You could use Python MSS.
From documentation to capture only a part of the screen:
import mss
import mss.tools
with mss.mss() as sct:
# The screen part to capture
monitor = {"top": 160, "left": 160, "width": 160, "height": 135}
output = "sct-{top}x{left}_{width}x{height}.png".format(**monitor)
# Grab the data
sct_img = sct.grab(monitor)
# Save to the picture file
mss.tools.to_png(sct_img.rgb, sct_img.size, output=output)
print(output)
You can use pyscreenshot at linux or windows platforms . I am using Ubuntu it works for me. You can force if subprocess is applied setting it to false together with mss gives the best performance.
import pyscreenshot as ImageGrab
import time
t1 = time.time()
imgScreen = ImageGrab.grab(backend="mss", childprocess=False)
img = imgScreen.resize((640,480))
img.save("screen.png")
t2 = time.time()
print("The passing time",(t2-t1))
I have been trying to resize images using PIL then display them using Tkinter, but the program has been crashing and I've isolated the problem to the second line below:
image = Image.open("0.gif")
photo = ImageTk.PhotoImage(image)
And this is my imports:
from Tkinter import *
from PIL import Image, ImageTk
I've read around that Tk must be initialized and I do this in the program before it reaches those lines in the program. So I don't know what it is.
I am running OSX and python 2.7 interpreter on eclipse (using PyDev).
UPDATE:
Error message on eclipse says:
STACK: Stack after current is in use
I've seen that error before using tkinter. I think it had something to do with an older version of tkinter. I updated my python version and tkinter version and it went away. Does this error happen when you run your code on a different OS/Computer/Platform/Version of Python? What version of tkinter are you using? Some google searching revealed these two pages which describe the same bug while using tkinter...
http://osdir.com/ml/python.leo.general/2008-03/msg00060.html
http://fornax.phys.unm.edu/lwa/trac/ticket/3
I can't see all your code, but I'm betting that there is not necessarily anything wrong with your code. The following code worked for me...
from Tkinter import *
from PIL import Image, ImageTk
# resize image with PIL
im = Image.open('path to gif')
resized_im = im.resize((400,400,),Image.ANTIALIAS)
# display image in tkinter window
window = Tk()
tk_im = ImageTk.PhotoImage(resized_im)
window.geometry('%dx%d' % (resized_im.size[0],resized_im.size[1]))
label_image = Label(window, image=tk_im)
label_image.place(x=0,y=0,width=resized_im.size[0],height=resized_im.size[1])
window.mainloop()
Using....
ubuntu 10.04 64 bit
python 2.6.5
python-imaging-tk 1.1.7
python-tk 2.6.5 (which uses version 8.5.0 of tkinter)
python imaging library (PIL) 1.1.7
eclipse 3.7.1
pydev 2.5.0.2012050419
Good luck!
I've been using both Tk, PIL and resizing images for a current project and the following code works fine for me.
#Imports
from Tkinter import *
from PIL import Image, ImageTk
#Create Tk instance
root = Tk()
#Open image and resize
image = Image.open("path/to/image/file").resize((400,400), Image.ANTIALIAS)
photo = ImageTk.PhotoImage(image)
After that, I find it easiest to display the images as labels in tkinter like so.
image_label = Label(root, width = 400, height = 400, image = photo bd = 0)
(I like the bd = 0 as otherwise I get a thin white border around the image.)
Hope this has helped you. Good luck!
Ed
So this is an ancient question, but in case someone stumbles upon this (like I just did), the error message is from Tcl (tclExecute.c). I have no idea what's triggering it, but one thing worth trying is to create a Tk instance before calling PhotoImage:
root = Tk()
image = Image.open("0.gif")
photo = ImageTk.PhotoImage(image)
I along with some friends are trying to do an anti cheats for a game, we chose python because it is multiplatform.
The problem is we're trying to make a screenshot of what is shown on the screen, not just the game (with OpenGL) but any windows that are open to detect programs that are superimposed on the image of the game (for example to indicate the positions of other players in online games)
We tried to use Python Imaging Library (PIL) but with the game open, taking pictures in gray, OpenGL draws the images in black and have tried other things, but nothing has worked (problems with Aero in Windows Vista / 7).
Google does not show anything about it.
Anyone know any way to make a screenshot with python in Windows 7?
from PIL import ImageGrab
ImageGrab.grab().save('test.jpg', "JPEG")
This does not work
import Tkinter
from OpenGL.GL import *
root = Tkinter.Tk()
width = int(root.winfo_screenwidth())
height = root.winfo_screenheight()
screenshot = glReadPixels( 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE)
im = Image.frombuffer("RGBA", (width, height), screenshot, "raw", "RGBA", 0, 0)
im.save('test.jpg')
And this does not work
The ImageGrab module should work on Windows 7.
http://effbot.org/imagingbook/imagegrab.htm
I'm trying to take a screen shot of an applet running inside a
browser. The applet is using JOGL (OpenGL for Java) to display 3D
models. (1) The screen shots always come out either black or white.The
current solution uses the usual GDI calls. Screen shots of applets not
running OpenGL are fine.
A few examples of JOGL apps can be found here https://jogl-demos.dev.java.net/
(2) Another thing I'm trying to achieve is to get the scrollable area
inside the screen shot as well.
I found this code on the internet which works fine except for the 2
issues mentioned above.
import win32gui as wg
import win32ui as wu
import win32con
def copyBitMap(hWnd, fname):
wg.SetForegroundWindow(hWnd)
cWnd = wu.CreateWindowFromHandle(hWnd)
rect = cWnd.GetClientRect()
(x,y) = (rect[2] - rect[0], rect[3] - rect[1])
hsrccDc = wg.GetDC(hWnd)
hdestcDc = wg.CreateCompatibleDC(hsrccDc)
hdestcBm = wg.CreateCompatibleBitmap(hsrccDc, x, y)
wg.SelectObject(hdestcDc, hdestcBm.handle)
wg.BitBlt(hdestcDc, 0, 0, x, y, hsrccDc, rect[0], rect[1], win32con.SRCCOPY)
destcDc = wu.CreateDCFromHandle(hdestcDc)
bmp = wu.CreateBitmapFromHandle(hdestcBm.handle)
bmp.SaveBitmapFile(destcDc, fname)
Unless you are trying to automate it, I would just use a Firefox extension for this. There are a number of them returned from a search for "screenshot" that can take a screenshot of the entire browser page including the scrollable area:
FireShot
Screengrab
Snapper (for older Firefox versions)
However, I apologize, I don't know enough about Python to debug your specific issue if you are indeed trying to do it programmatically.
Here is one way to do it by disabling dwm (Desktop Window Manager) composition before taking the screen shot, but this causes the whole screen to blink whenever its enabled/disabled.
from ctypes import WinDLL
from time import sleep
import win32gui as wg
import win32ui as wu
import win32con
def copyBitMap(hWnd, fname):
dwm = WinDLL("dwmapi.dll")
dwm.DwmEnableComposition(0)
wg.SetForegroundWindow(hWnd)
# Give the window sometime to redraw itself
sleep(2)
cWnd = wu.CreateWindowFromHandle(hWnd)
rect = cWnd.GetClientRect()
(x,y) = (rect[2] - rect[0], rect[3] - rect[1])
hsrccDc = wg.GetDC(hWnd)
hdestcDc = wg.CreateCompatibleDC(hsrccDc)
hdestcBm = wg.CreateCompatibleBitmap(hsrccDc, x, y)
wg.SelectObject(hdestcDc, hdestcBm.handle)
wg.BitBlt(hdestcDc, 0, 0, x, y, hsrccDc, rect[0], rect[1], win32con.SRCCOPY)
destcDc = wu.CreateDCFromHandle(hdestcDc)
bmp = wu.CreateBitmapFromHandle(hdestcBm.handle)
bmp.SaveBitmapFile(destcDc, fname)
dwm.DwmEnableComposition(1)
Grabbing an OpenGL window may be quite hard in some cases, since the OpenGL is being rendered by the GPU directly into its frame buffer. The same applies to DirectX windows and Video overlay windows.
Why not using the Screenshot class of JOGL??
com.jogamp.opengl.util.awt.Screenshot in JOGL 2.0 beta