I want create a GUI for my python script.
I managed to define a background and now i would like to add my buttons but problem is here. Like you can see on the following screen
Here's the portion of my code where i define the image
root = tk.Tk()
root.wm_attributes("-topmost", True)
root.wm_attributes("-transparent", True)
root.config(bg='systemTransparent')
NewAccountImg=tk.PhotoImage(file="NewAccountImg.gif")
background_image=tk.PhotoImage(file="fond.png")
background_label=tk.Label(root, image=background_image)
background_label.place(x=0, y=0, relwidth=1, relheight=1)
And
root.newaccount = tk.Button(root,text="New Account",command=partial(Set_Acc_and_Hide,root),image=NewAccountImg)
How can I make my button transparent?
You should use PIL library for image.
PIL supports transparency.
Here is an example:
from PIL import Image, ImageDraw
img = Image.new('RGBA', (100, 100), (255, 0, 0, 0))
draw = ImageDraw.Draw(img)
draw.ellipse((25, 25, 75, 75), fill=(255, 0, 0))
img.save('test1.gif', 'GIF', transparency=0)
# this generates gif of red colored circle with white background(transparent background).
img.save('test2.gif', 'GIF', transparency=1)
# this generates gif of white colored circle(transparent circle) with red background.
Related
So even though I tried to set the background to custom color the picture is automatically set with bg=black. Witch I am guessing is default.
Can someone tell me in what moment I have to set the background, and how to do it so the picture doesn't get automatically filled with black.
window = Tk()
window.title('Random Password Generator')
window.geometry('400x250')
window.config(bg=GREEN)
#openImage
pic = Image.open('lock.png')
#resized
resized = pic.resize((100,150), resample=1)
new_pic = ImageTk.PhotoImage(resized)
#enter image
image = Label(image=new_pic)
image.config(compound='bottom', anchor='e')
image.grid(column=0, row=0, padx=10)
why is the picture still bg='black' even though I set it to GREEN
According to this post, Tkinter labels do not support transparency.
As an alternative, we may create green image, and apply alpha_composite:
Create green image with RGBA color format:
green_bk = Image.new(mode="RGBA", size=(100, 150), color=(0, 128, 0, 255))
Apply alpha composition of resized image and green background:
resized_bk = Image.alpha_composite(green_bk, resized)
Code sample:
import tkinter as tk
from PIL import Image, ImageTk
window = tk.Tk()
window.title('Random Password Generator')
window.geometry('400x250')
window.config(bg='GREEN')
pic = Image.open('lock.png') # openImage
resized = pic.resize((100,150), resample=1) # resized
# Green color of Tkinter is (0, 128, 0) https://www.plus2net.com/python/tkinter-colors.php
green_bk = Image.new(mode="RGBA", size=(100, 150), color=(0, 128, 0, 255)) # Create green image with opaque background
resized_bk = Image.alpha_composite(green_bk, resized) # Apply alpha composition of resized image and green background
new_pic = ImageTk.PhotoImage(resized_bk) # Used resized_bk instead of resized
#enter image
image = tk.Label(image=new_pic)
image.config(compound='bottom', anchor='e')
image.grid(column=0, row=0, padx=10)
window.mainloop()
For testing I used the following lock.png image (the lock is transparent):
Tkinter output window:
This image is filled with black even if its not on a black background.
You should try to set a white bg or just pick an image witch is filled in white
I'm trying to dynamically create a PNG (code is working) and make it transparent (code is not working on the color white).
I can create the PNG, but making it transparent isn't working.
Code:
from PIL import Image, ImageDraw, ImageFont
import os
def text_on_img(filename='01.png', text="Hello", size=12):
"Draw a text on an Image, saves it, show it"
fnt = ImageFont.truetype('arial.ttf', 52)
# create image
image = Image.new(mode="RGB", size=(150, 75), color="white")
draw = ImageDraw.Draw(image)
# draw text
draw.text((10, 10), text, font=fnt, fill=(0, 0, 0))
newData = []
newData.append((255, 255, 255, 0))
image.save(filename)
Here's a minimal example that creates the image in RGBA mode and sets the background to be transparent.
from PIL import Image, ImageDraw, ImageFont
fnt = ImageFont.truetype("arial.ttf", 52)
img = Image.new(mode="RGBA", size=(150, 75), color=(255, 255, 255, 127))
draw = ImageDraw.Draw(img)
draw.text((10, 10), "Hello", font=fnt, fill=(0, 0, 0))
img.save("test.png", "PNG")
This creates the following image:
Changing the alpha to 127 (50%) results in the following image being created:
I'm trying to display a gif on top of an image. The gif originally has a transparent background. The code below does that, except it created a black background around the original gif that flickers white when the gif resets. If I don't resize the gif then there would still be a white background around the original gif after its merged with the image.
Is there a way to keep the original gif's background transparent when merging?
from PIL import Image
background = Image.open('GrassyField.png').convert("RGBA")
gif = Image.open("1.gif")
foreground_w, foreground_w = gif.size
background_w, background_h = background.size
frames = []
for num in range(gif.n_frames):
gif.seek(num)
layer = Image.new('RGBA', (foreground_w, foreground_w), (0, 0, 0, 0)).resize((background_w,
background_h))
layer.paste(background, (0, 0), mask=background)
layer.paste(gif.resize((100, 100)).convert('RGBA'), (220, 25))
frames.append(layer)
frames[0].save('output.gif',
save_all=True,
append_images=frames[1:],
duration=100,loop=0)
Let's say that 1.gif is:
and GrassyField.png is:
using this code:
import PIL.Image
import PIL.ImageSequence
with PIL.Image.open('1.gif') as foreground_animation, PIL.Image.open('GrassyField.png') as background_image:
image_roles = {
'foreground': foreground_animation,
'background': background_image.convert(mode='RGBA')
}
def create_frames(images_roles):
for current_frame in PIL.ImageSequence.Iterator(image_roles['foreground']):
current_background = image_roles['background'].copy()
current_foreground = current_frame.convert(mode='RGBA').resize((100, 100))
current_background.alpha_composite(current_foreground, dest=(220,25))
yield current_background
frames = tuple(create_frames(image_roles))
frames[0].save(
'output.gif',
save_all=True,
append_images=frames[1:],
duration=100,loop=0
)
You get output.gif:
Is that what you wanted?
I'm pretty new to Tkinter and I have made for a program a screen of buttons that, when pressed, do a command.
Picture of the screen:
I'm using the pictures with the buttons. The background of the photos make the screen look aesthetically unpleasing, so I have there's a way to remove the white background of the pictures.
Any advice would be appreciated! thank you very much in advance.
Also, here is how I put those image on the screen with the button (example given is keyboard image):
keyb_img = resize_img('/ServerImages/KeyBPhoto.jpg', 100)
self.keyb_img = keyb_img
keyb_share_button = Button(self.top_level, image=self.keyb_img, command=lambda: self.keyb_press('Keyboard_Change'), borderwidth=0).grid(row=2, column=5, pady=100, padx =15)
As #Matiiss pointed out: .jpg images don't have transparent backgrounds.
So we have to remove the background from the image. To do that we can use PIL like this:
import tkinter as tk
from PIL import Image, ImageTk
width = 100
height = 100
image = Image.open("/ServerImages/KeyBPhoto.jpg").convert("RGBA")
image = image.resize((width, height), Image.LANCZOS)
# Load the pizels into memory
pixels = image.load()
# For each pixel in the image
for i in range(image.size[0]):
for j in range(image.size[1]):
# If the pixel is white
if pixels[i, j] == (255, 255, 255, 255):
# Make it transparent
pixels[i, j] = (255, 255, 255, 0)
# Save the now transparent image:
image.save("new_image.png", format="png")
# Show it on the screen
root = tk.Tk()
canvas = tk.Canvas(root, bg="red")
canvas.pack()
tk_image = ImageTk.PhotoImage(image)
canvas.create_image(0, 0, image=tk_image, anchor="nw")
root.mainloop()
Please note that this will only convert the pure while pixels into transparent. If a pixel has a value of #fffffe (pure white is #ffffff), the program will ignore it. Also it will convert all while pixels.
EDIT: by #furas
If you would use numpy array then it could be shorter
import numpy as np
# convert pillow.Image to numpy.array
array = np.array(image)
mask = np.all(array == [255, 255, 255, 255], axis=-1) # png without artefacts
array[ mask ] = [255, 255, 255, 0]
# convert numpy.array to pillow.Image
image = Image.fromarray(array)
But JPG may have artefacts like #fffffe instead of pure white #ffffff and then you can use mask with >=
mask = np.all(array >= [230, 230, 230, 255], axis=-1) # jpg with artefacts
Minimal working code:
I first remove color and later resize it to reduce artefacts.
import tkinter as tk
from PIL import Image, ImageTk
import numpy as np
def convert_pillow(image):
#print('[DEBUG] convert_pillow')
# Load the pizels into memory
pixels = image.load()
# For each pixel in the image
for i in range(image.size[0]):
for j in range(image.size[1]):
# If the pixel is white
if pixels[i, j] == (255, 255, 255, 255):
# Make it transparent
pixels[i, j] = (255, 255, 255, 0)
return image
def convert_numpy(image):
#print('[DEBUG] convert_numpy')
import numpy as np
# convert pillow.Image to numpy.array
array = np.array(image)
#mask = np.all(array == [255, 255, 255, 255], axis=-1) # png without artefacts
mask = np.all(array >= [230, 230, 230, 255], axis=-1) # jpg with artefacts
array[ mask ] = [255, 255, 255, 0]
# convert numpy.array to pillow.Image
image = Image.fromarray(array)
return image
# --- main ---
width = 100
height = 100
filename = "test/rgb.png"
filename = "test/rgb.jpg"
image = Image.open(filename).convert("RGBA")
#image = convert_pillow(image)
image = convert_numpy(image)
# resize after changing color - because resize creates new artefacts
image = image.resize((width, height), Image.LANCZOS)
# Save the now transparent image:
image.save("new_image.png", format="png")
# Show it on the screen
root = tk.Tk()
canvas = tk.Canvas(root, bg="gray")
canvas.pack()
tk_image = ImageTk.PhotoImage(image)
canvas.create_image(0, 0, image=tk_image, anchor="nw")
root.mainloop()
Images for tests:
rgb.png
rgb.jpg
Result:
EDIT: added complete working example
I have the following program:
from PIL import Image, ImageDraw, ImageFont
FULL_SIZE = 50
filename = 'font_test.png'
font="/usr/share/fonts/truetype/msttcorefonts/arial.ttf"
text="5"
image = Image.new("RGBA", (FULL_SIZE, FULL_SIZE), color="grey")
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(font, 40)
font_width, font_height = font.getsize(text)
draw.rectangle(((0, 0), (font_width, font_height)), fill="black")
draw.text((0, 0), text, font=font, fill="red")
image.save(filename, "PNG")
This generates the following image:
It seems that when writing the text PIL library adds some margin at the top. This margin depends on the font I use.
How can I take this into account when trying to position the text (I want it to be in the middle of a rectangle)?
(Using Python 2.7.6 with Pillow 2.3.0 on Ubuntu 14.04)
I don't understand why, but subtracting font.getoffset(text)[1] from the y co-ordinate fixes it on my computer.
from PIL import Image, ImageDraw, ImageFont
FULL_SIZE = 100
filename = 'font_posn_test.png'
fontname = '/usr/share/fonts/truetype/msttcorefonts/arial.ttf'
textsize = 40
text = "5"
image = Image.new("RGBA", (FULL_SIZE, FULL_SIZE))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(fontname, textsize)
print font.getoffset(text)
print font.font.getsize(text)
font_width, font_height = font.getsize(text)
font_y_offset = font.getoffset(text)[1] # <<<< MAGIC!
draw.rectangle(((0, 0), (font_width, font_height)), fill="black")
draw.text((0, 0 - font_y_offset), text, font=font, fill="red")
image.save(filename, "PNG")