I need to create a widget that acts like Window's snipping tool and saves the cropped image on button release.
It works perfectly fine, except that the image gets cropped and saved as if it was given the wrong coordinates. I have checked a full screen snip and the coordinates are (0,0,1279,719), which is my screen resolution, so I don´t understand why ImageGrab.grab(bbox=) can't crop correctly.
Here is the code.
from PIL import *
from tkinter import *
from PIL import ImageGrab
class Widget(Frame):
def __init__(self,master):
Frame.__init__(self,master=None)
self.root = master
self.root.attributes("-alpha", 0.2)
self.root.attributes("-fullscreen", True)
self.root.title("")
self.canvas = Canvas(self, cursor="cross", background="blue", width= master.winfo_screenwidth(), height=master.winfo_screenheight() )
self.canvas.pack()
self.canvas.bind("<ButtonPress-1>", self.on_button_press)
self.canvas.bind("<B1-Motion>", self.on_move_press)
self.canvas.bind("<ButtonRelease-1>", self.on_button_release)
self.rect = None
self.start_x = None
self.start_y = None
def on_button_press(self, event):
# save mouse drag start position
self.start_x = self.canvas.canvasx(event.x)
self.start_y = self.canvas.canvasy(event.y)
self.rect = self.canvas.create_rectangle(0, 0, 1, 1, outline='red')
def on_move_press(self, event):
curX = self.canvas.canvasx(event.x)
curY = self.canvas.canvasy(event.y)
# expand rectangle as you drag the mouse
self.canvas.coords(self.rect, self.start_x, self.start_y, curX, curY)
def on_button_release(self, event):
self.endx = self.canvas.canvasx(event.x)
self.endy = self.canvas.canvasy(event.y)
x1 = min(self.start_x, self.endx)
y1 = min(self.start_y, self.endy)
x2 = max(self.start_x, self.endx)
y2 = max(self.start_y, self.endy)
self.root.destroy()
img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
img.save('capture.png')
if __name__ == "__main__":
snip_window = Tk()
width = snip_window.winfo_screenwidth()
height = snip_window.winfo_screenheight()
snip_window.geometry(f'{width}x{height}')
snip_widget = Widget(snip_window)
snip_widget.pack()
snip_window.mainloop()