How can I convert tkinter application into image? [duplicate] - python

I am trying to build a program which gets me an enlarged photo of the text I want, for this I decided to use tkinter, win32gui and pygetwindow modules after taking some tips from already asked problems on stack overflow am having the following problems:
(1)I don't know how to get the hwnd value of the tkinter window which I created.
(2)I can't get hwnd value even if I know how to get it as the window is created after the complete code has run.
So please suggest me solutions to the problem
This is my code:
from tkinter import *
import win32gui
import pygetwindow as gw
#making the tkinter window
root = Tk()
root.title('DaysLeft')
#getting all the windows with their hwnd values
hwnd=gw.getAllWindows()
print(hwnd)
win32gui.SetForegroundWindow(hwnd)
bbox = win32gui.GetWindowRect(hwnd)
img = ImageGrab.grab(bbox)
img.show()
mainloop()
The above code gives error below as expected:.
line 26, in <module>
win32gui.SetForegroundWindow(hwnd)
TypeError: The object is not a PyHANDLE object

You can use PIL for taking a screenshot and win32gui or pygetwindow to get windows location.
Install PIL by saying
pip install Pillow
then your working code would be:
from tkinter import *
from win32gui import FindWindow, GetWindowRect
import pygetwindow as gw
from PIL import ImageGrab
def ss():
win = gw.getWindowsWithTitle('DaysLeft')[0]
winleft = win.left+9
wintop = win.top+38 #change 38 to 7 to not capture the titlebar
winright = win.right-9
winbottom = win.bottom-9
final_rect = (winleft,wintop,winright,winbottom)
img = ImageGrab.grab(final_rect)
img.save('Required Image.png')
#making the tkinter window
root = Tk()
root.title('DaysLeft')
root.after(3000,ss)
root.mainloop()
Why am i subtracting some amount from the pixels? its because, windows has decorations like drop shadow effect to the windows, which are also part of the windows and will be included in the screenshot, so i used this to get rid of those extra pixels.
Or if your still reluctant on using win32gui then, change the function to:
from win32gui import FindWindow, GetWindowRect
from PIL import ImageGrab
......
def ss():
win = FindWindow(None, 'DaysLeft')
rect = GetWindowRect(win)
list_rect = list(rect)
list_frame = [-9, -38, 9, 9] #change -38 to -7 to not capture the titlebar
final_rect = tuple((map(lambda x,y:x-y,list_rect,list_frame))) #subtracting two lists
img = ImageGrab.grab(bbox=final_rect)
img.save('Image.png')
What is after method? It just calls the function after 3000 ms, i.e, 3 seconds. We are basically giving the system some time to build the GUI and capture screenshot.
Hope it helped, do let me know if any errors or doubts.
Cheers

Related

Take screenshot of python tkinter window (NOT entire computer screen)

I wish to take screenshot of python tkinter window (NOT the entire computer scrren). I applied following codes:
import pyautogui
import tkinter as tk
root= tk.Tk()
# Define tkinter window
canvas1 = tk.Canvas(root, width = 300, height = 300)
canvas1.pack()
# Define fuction to take screenshot
def takeScreenshot ():
myScreenshot = pyautogui.screenshot()
myScreenshot.save('screenshot.png')
# Define fuction to take screenshot
myButton = tk.Button(text='Take Screenshot', command=takeScreenshot, bg='green',fg='white',font= 10)
canvas1.create_window(150, 150, window=myButton)
root.mainloop()
I wish to grab screenshot of only the window defined by "tk.Canvas(root, width = 300, height = 300)"
But, I am capturing the entire screren.
Can somebody please let me know how do we go about this in python ?
You can get the region of the canvas and pass them to screenshot():
def takeScreenshot():
# get the region of the canvas
x, y = canvas1.winfo_rootx(), canvas1.winfo_rooty()
w, h = canvas1.winfo_width(), canvas1.winfo_height()
pyautogui.screenshot('screenshot.png', region=(x, y, w, h))
Since you are on windows you should be able to employ the win32 API,
Contrary to this you could use more simple solutions such as PyScreenshot
Take the following code for example:
from pyscreenshot import grab
im = grab(bbox=(100, 200, 300, 400))
im.show()
“
As you can see you can use bbox to take screenshot that is at co-ordinates (100, 200) and has a width of 300 and a height of 400.
This would require you knowing the position of the windows before hand- which you can do in Tkinter I believe.”
I found this information from previous SO questions. Here is another snippet that may help you.
Here's how you can do it using PIL on win32. Given a window handle (hwnd), you should only need the last 4 lines of code. The preceding simply search for a window with "firefox" in the title. Since PIL's source is available, you should be able to poke around the ImageGrab.grab(bbox) method and figure out the win32 code you need to make this happen.
from PIL import ImageGrab
import win32gui
toplist, winlist = [], []
def enum_cb(hwnd, results):
winlist.append((hwnd, win32gui.GetWindowText(hwnd)))
win32gui.EnumWindows(enum_cb, toplist)
firefox = [(hwnd, title) for hwnd, title in winlist if 'firefox' in title.lower()]
# just grab the hwnd for first window matching firefox
firefox = firefox[0]
hwnd = firefox[0]
win32gui.SetForegroundWindow(hwnd)
bbox = win32gui.GetWindowRect(hwnd)
img = ImageGrab.grab(bbox)
img.show()
Suggestions I found include:
How to do a screenshot of a tkinter application?
How to Get a Window or Fullscreen Screenshot in Python 3k? (without PIL)
I hope this helps, sometimes all it takes is a good google search. If this help you please select this as the correct answer
Edit
Depending upon the contents of the window you could use this- if it is a drawing.
“ You can either generate a postscript document (to feed into some other tool: ImageMagick, Ghostscript, etc)”
from Tkinter import *
root = Tk()
cv = Canvas(root)
cv.create_rectangle(10,10,50,50)
cv.pack()
root.mainloop()
cv.update()
cv.postscript(file="file_name.ps", colormode='color')
root.mainloop()
Look at this if you are trying to save a drawing https://www.daniweb.com/programming/software-development/code/216929/saving-a-tkinter-canvas-drawing-python
You would need to define the rectangle for the screenshot
instead of myScreenshot = pyautogui.screenshot()
use the following in place of it:
myScreenshot = pyautogui.screenshot(region=(0,0, 300, 400))
The 4 points describe where you want the screenshot
https://pyautogui.readthedocs.io/en/latest/screenshot.html

minsize() and maxsize() methods doesn't work in tkinter python(Toplevel)

I was recently trying to make a pdf viewer in python, so I set the minsize() and maxsize() of the window but it doesn't seem to work. Here is my code.
from pdf2image import convert_from_path
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
root4=tk.Toplevel()
root4.geometry("800x900")
root4.title("PDF Viewer")
root4.configure(bg="#202020")
root4.minsize(300, 200)
root4.maxsize(900, 800)
pdf_frame = tk.Frame(root4)
pdf_frame.pack(fill=tk.BOTH,expand=1)
scrol_y = tk.Scrollbar(pdf_frame,orient=tk.VERTICAL)
pdf = tk.Text(pdf_frame,yscrollcommand=scrol_y.set,bg="grey")
scrol_y.pack(side=tk.RIGHT,fill=tk.Y)
scrol_y.config(command=pdf.yview)
pdf.pack(fill=tk.BOTH,expand=1)
pages = convert_from_path(filedialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("pdf files","*.pdf"),("all files","*.*"))),size=(800,900))
photos = []
for i in range(len(pages)):
photos.append(ImageTk.PhotoImage(pages[i]))
for photo in photos:
pdf.image_create(tk.END,image=photo)
pdf.insert(tk.END,'\n\n')
root4.update()
root4.mainloop()
When your creating a parent window use Tk(), else using Toplevel() will create a Tk()(for which the minsize and maxsize doesnt apply) window without you asking for it and you mightve misunderstood that for your root4 window, so just say:
tk.Tk().withdraw()
root4 = tk.Tk()
This fixed the issue of two windows popping up, for me. Keep in mind the minsize() and maxsize() works, its just that you were trying it on the wrong window.

python tkinter image missing

I want to have a image of a map next to my application I am creating right now, which includes a filter system. However I wasn't sure why it wasn't showing up. Here are snippits from my code
from Tkinter import *
import Tkinter as tk
from PIL import ImageTk, Image
import os
class MainPage(tk.Frame):
def __init__(self,app):
tk.Frame.__init__(self)
frame_A = Frame(self,width=930,height=780)
frame_A.grid(row=0,column=0,columnspan=2,rowspan=3)
contentmap = Frame(frame_A)
img = ImageTk.PhotoImage(Image.open("/Users/J/Desktop/unknown.png"))
panel = Label(contentmap, image = img)
App().mainloop()
Additionally I would like to ask for some advice as to whether it was possible to make my image a interactive image like if I were to zoom in google maps.
Thanks a million!

Displaying a cv2 image onto Tkinter GUI - "TclError: image "pyimage1" doesn't exist

I am attempting to replicate the following code to output a cv2 image onto a GUI :
import numpy as np
import cv2
import Tkinter
from PIL import Image
from PIL import ImageTk
# Load an color image
img = cv2.imread('img.jpg')
#Rearrang the color channel
b,g,r = cv2.split(img)
img = cv2.merge((r,g,b))
# A root window for displaying objects
root = Tkinter.Tk()
# Convert the Image object into a TkPhoto object
im = Image.fromarray(img)
imgtk = ImageTk.PhotoImage(image=im)
# Put it in the display window
Tkinter.Label(root, image=imgtk).pack()
root.mainloop() # Start the GUI
however on trying to execute this, I end up with the following error:
TclError: image "pyimage1" doesn't exist
In my understanding it is looking for something name pyimage1, I have searched by code multiple times and there is nothing by that name, unless this is a module I am missing.
The output is essentially just a blank GUI with no image being displayed accompanied by the error in my terminal.
Any guidance on how to proceed will be very helpful.
Try changing the line:
root = Tkinter.Tk()
to
root = Toplevel
.. Just a guess let me know if it works.

Not being able to load an image in python

I am trying to load an image into a canvas in python. However I am getting the error: TclError: couldn't recognize data in image file "C:\testimage\spongesea.jpg"
import Tkinter
from Tkinter import *
import time
import inspect
import os
from PIL import Image, ImageTk
class game_one:
def __init__(self):
global root
global canvas_one
root = Tk()
root.title(" Thanks Josh Dark
canvas_one = Tkinter.Canvas(root, bg="BLACK")
canvas_one.pack(expand= YES, fill= BOTH)
canvas_one.focus_set() #allows keyboard events
p = PhotoImage(file="C:\testimage\spongesea.jpg")
canvas_one.create_image(0, 0, image = p, anchor=NW)
root.grab_set()#I forget what this does. Don't change it.
root.lift()#This makes root appear in front of the other applications
ObjectExample = game_one()# starts the animation
I can open the image manually from the file, so it is not corrupted, and it is calling the correct place. Any ideas? Thanks
PhotoImage works only with GIF and PGM/PPM.
You have to use Image, ImageTk to work with other formats
from PIL import Image, ImageTk
image = Image.open("lenna.jpg")
photo = ImageTk.PhotoImage(image)
BTW: read PhotoImage and see "Garbage Collection problem" in note.

Categories