Title: Display a grid on the image-straightening tool in Python
This is my last image-straightening example. Okay, my second-to-last. It's the last modification to this particular program, but I'll write a new program shortly that uses a different approach.
This example modifies the previous one Improve the image-straightening tool in Python to display a grid on the image so you can tell whether it's straight.
Drawing the Grid
When the program starts, the following code sets the grid's color and cell spacing.
# Grid parameters.
self.grid_color = 'yellow'
self.grid_spacing = 50 # Spacing at full scale.
The following code creates the Options menu and the Show Grid command that toggles the grid on and off.
def build_options_menu(self, menu_bar):
'''Build the Options menu.'''
options_menu = tk.Menu(menu_bar, tearoff=False)
menu_bar.add_cascade(label='Options', menu=options_menu)
self.grid_var = tk.BooleanVar(value=False)
options_menu.add_checkbutton(label='Show Grid', variable=self.grid_var,
command=self.mnu_options_grid)
That's the easy part, but the "hard" part isn't all that hard. The following code draws the image at its current rotation. The blue code shows the changes that draw the grid.
def show_image(self):
'''Display the image at the desired scale.'''
if self.pil_image is None:
# No image. Hide the canvas.
self.photo_image = None
self.menu_bar.entryconfig(2, state=tk.DISABLED) # Scale
self.file_menu.entryconfig('Save As...', state=tk.DISABLED)
self.file_menu.entryconfig('Reset', state=tk.DISABLED)
self.scrolled_frame.pack_forget()
self.start_point = self.end_point = None
self.new_line1 = self.new_line2 = None
self.angle = 0
else:
# Make a scaled version of the image.
wid = int(self.pil_image.width * self.scale_var.get())
hgt = int(self.pil_image.height * self.scale_var.get())
scaled_image = self.pil_image.resize((wid, hgt))
# Rotate to the current angle.
rotated_image = scaled_image.rotate(self.angle, expand=True,
resample=Image.Resampling.BICUBIC)
# Convert into a PhotoImage.
self.photo_image = ImageTk.PhotoImage(rotated_image)
# Display it.
self.canvas.delete(tk.ALL)
self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW,
image=self.photo_image)
wid = self.photo_image.width()
hgt = self.photo_image.height()
self.canvas.config(width=wid, height=hgt)
# Draw the grid if desired.
if self.grid_var.get():
spacing = int(self.grid_spacing * self.scale_var.get())
for y in range(spacing, hgt, spacing):
self.canvas.create_line(0, y, wid, y, fill=self.grid_color)
for x in range(spacing, wid, spacing):
self.canvas.create_line(x, 0, x, hgt, fill=self.grid_color)
# Reconfigure the frame. Do this after adding contained widgets.
self.scrolled_frame.configure_frame()
# Display the ScrolledFrame.
self.scrolled_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
# Enable the Scale menu.
self.menu_bar.entryconfig(2, state=tk.NORMAL) # Scale
# Enable the Save As and Reset menu items.
self.file_menu.entryconfig('Save As...', state=tk.NORMAL)
self.file_menu.entryconfig('Reset', state=tk.NORMAL)
This method draws the rotated image and sizes the Canvas widget to fit as before. It then checks the self.grid_var variable to see if the Show Grid command is checked. If it is checked, the program gets the grid spacing and multiplies it by the image's current scale factor to scale the grid accordingly. It then loops over the image's height, incrementing y by the scaled grid spacing at each step, to draw horizontal lines across the Canvas. It then uses similar steps to draw the grid's vertical lines.
The rest of the method is the same as in the previous example.
Conclusion
that's the end of this series. The result is pretty useful if you take pictures often and want to straighten them.
Download the example to experiment with it and to see additional details.
|