I am using python to get an overlay effect on an image on mouse click. How can I increase the transparency of the color so the underlying image remains visible. Currently the underlying image hides beneath. I couldn't find an option to control the opacity
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageDraw, ImageTk
class ImageEditor:
def __init__(self):
self.root = tk.Tk()
self.image = None
self.grid = None
self.colors = [(255, 0, 0), (255, 255, 0), (0, 0, 255)] # RGB colors
self.current_color_index = 0
self.display_image = None
self.canvas = tk.Canvas(self.root)
self.canvas.bind("<Button-1>", self.change_color)
self.canvas.pack(side='left')
self.load_btn = tk.Button(self.root, text='Load', command=self.load_image)
self.load_btn.pack(side='right')
self.save_btn = tk.Button(self.root, text='Save', command=self.save_image)
self.save_btn.pack(side='right')
self.root.mainloop()
def load_image(self):
img_path = filedialog.askopenfilename()
self.image = Image.open(img_path).convert("RGB") # Convert to RGB format
self.grid = Image.new("RGBA", self.image.size, (0, 0, 0, 0)) # Create a transparent overlay image
self.display_image = ImageTk.PhotoImage(self.image)
self.canvas.config(width=self.image.width, height=self.image.height)
self.canvas.create_image(0, 0, image=self.display_image, anchor='nw')
def change_color(self, event):
if self.image is None:
return
x, y = event.x, event.y
# Define the region around the mouse click (adjust as needed)
region = (x - 10, y - 10, x + 10, y + 10)
draw = ImageDraw.Draw(self.grid)
if self.current_color_index == 3:
# If it's the fourth click, remove the color (make the region transparent)
draw.rectangle(region, fill=(0, 0, 0, 0))
else:
color = self.colors[self.current_color_index]
draw.rectangle(region, fill=color)
self.display_image = ImageTk.PhotoImage(Image.alpha_composite(self.image.convert("RGBA"), self.grid))
self.canvas.create_image(0, 0, image=self.display_image, anchor='nw')
self.current_color_index = (self.current_color_index + 1) % 4 # Cycle through 4 values
def save_image(self):
if self.image is None:
return
file_path = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG File", "*.png")], initialfile="output")
if file_path:
final_image = Image.alpha_composite(self.image.convert("RGBA"), self.grid)
final_image.save(file_path, "PNG")
if __name__ == "__main__":
app = ImageEditor()
I think there are several ways of doing this. One way, just using PIL, is to draw your shapes/overlays on a blank canvas and add whatever opacity/alpha you want into a mask layer, then at the end, paste your shapes onto your background using the alpha layer as a mask.
This is the initial setup:
#!/usr/bin/env python3
from PIL import Image, ImageDraw, ImageOps
# Make a red-blue-yellow gradient as background
bg = Image.linear_gradient('L')
bg = ImageOps.colorize(bg, 'red', 'yellow', 'blue')
bg.save('DEBUG-bg.png')
Background
And here is the drawing of overlays:
# Make a canvas to draw on and an alpha mask for it
canvas = Image.new("RGB", (256,256))
mask = Image.new('L', (256,256))
canvasDraw = ImageDraw.Draw(canvas)
maskDraw = ImageDraw.Draw(mask)
# Draw a black rectangle with 64/255 alpha on left side
canvasDraw.rectangle((10,10,120,250), 'black')
maskDraw.rectangle((10,10,120,250), 64)
# Draw a white rectangle with 150/255 alpha on right side
canvasDraw.rectangle((130,10,250,250), 'white')
maskDraw.rectangle((130,10,250,250), 150)
# Paste shapes onto background with alpha mask
bg.paste(canvas, mask)
bg.save('result.png')
Overlaid shapes with transparency