Image background black - python

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

Related

How to remove white background of gif when using pillow?

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?

Tkinter - How to remove white background of pictures of buttons and in general

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:

Is there a more efficient way to create images using python PIL?

I'm trying to generate an image that contains the text of a given string. For now I'm using the Image.draw.text() from the Pyhton PIL library to generate the result and the process is working fine, but it's exceedingly slow and it takes a handful of seconds to finish drawing, which is really hampering the scalability of the program.
This is the current function to generate images:
def draw_ascii(ascii_image, new_width) :
# Source text, and wrap it.
adjusted_ascii = ascii_image.replace("\n", " ")
text = textwrap.fill(adjusted_ascii, new_width)
# Font size, color and type.
fontcolor = (0, 0, 0)
fontsize = 14
font = ImageFont.truetype("FreeMono.ttf", fontsize)
# Determine text size using a scratch image.
img = Image.new("RGBA", (1,1))
draw = ImageDraw.Draw(img)
textsize = draw.textsize(text, font)
# Creating the final image and put the text on it
background = (255, 255, 255)
img = Image.new("RGB", textsize, background)
draw = ImageDraw.Draw(img)
draw.text((0, 0), text, fontcolor, font)
return(img)

GUI button problems

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.

Draggable Tkinter Label With Transparent Image Still Covers Image from Parent Canvas

I am working on adding drag-able labels on top of a background image, where the labels are images with a transparent background. The images used for the label themselves are transparent, but the Label itself is not transparent in relation to its parent canvas. Since the labels are drag-able, I can't easily use the parent image for label, and paste the transparent image on top.
The dragon is a drag-able label, with a transparent background, but you see that the label itself is not transparent, and covers the canvas image.
The dragon image itself has a transparent background, as the normal background is blue, so I know the issue is with the label transparency.
The desired behavior would be to allow the label to be transparent, so when the image on the label is transparent, the label should show through to the image below.
Here is a minimal example:
from PIL import Image, ImageTk
import numpy as np
import tkinter as tk
#Creates a blue square with a transparent border
blue_square_transparent_border = [[[0,0,0,0]]*100]*10 + [[[0,0,0,0]]*30 + [[0,0,255,255]]*40 + [[0,0,0,0]]*30]*40 + [[[0,0,0,0]]*100]*10
blue_square_transparent_border = np.array(blue_square_transparent_border, dtype='uint8')
#convert numpy array to PIL image
pil_image = Image.fromarray(blue_square_transparent_border)
root = tk.Tk()
root.configure(background='red')
#convert PIL image to tkinter image
tk_image = ImageTk.PhotoImage(pil_image)
#create label
image_label = tk.Label(root, image=tk_image)
image_label.pack()
root.mainloop()
What I would like to see is a blue square, on a red background, with no border. In the above example though, the border of grey appears, as it is the label being seen through the transparent image; it is easy to see this when you resize the window. I suspect if the label were transparent, this would solve my issues.
Any help would be great, Thanks!
If you want to drag partially transparent images (like the dragon) over a background image, you can do it with a Canvas:
The idea is not to use labels, but the create_image method of the Canvas.
First, display your background image with canvas.create_image(0, 0, image=background_image, anchor='nw'), then display all the draggable images with the tag 'draggable': canvas.create_image(x, y, image=draggable_image, anchor='nw', tag='draggable'). Finally, bind the tag 'draggable' to mouse events.
Here is an example:
import tkinter as tk
import numpy as np
from PIL import Image, ImageTk
# drag callbacks
dragged_item = None
current_coords = 0, 0
def start_drag(event):
global current_coords
global dragged_item
result = canvas.find_withtag('current')
if result:
dragged_item = result[0]
current_coords = canvas.canvasx(event.x), canvas.canvasy(event.y)
else:
dragged_item = None
def stop_drag(event):
dragged_item = None
def drag(event):
global current_coords
xc, yc = canvas.canvasx(event.x), canvas.canvasy(event.y)
dx, dy = xc - current_coords[0], yc - current_coords[1]
current_coords = xc, yc
canvas.move(dragged_item, dx, dy)
#Create pictures
blue_square_transparent_border = [[[0,0,0,0]]*100]*10 + [[[0,0,0,0]]*30 + [[0,0,255,255]]*40 + [[0,0,0,0]]*30]*40 + [[[0,0,0,0]]*100]*10
blue_square_transparent_border = np.array(blue_square_transparent_border, dtype='uint8')
pil_image = Image.fromarray(blue_square_transparent_border)
background_data = np.zeros((200, 400, 4))
background_data[:, :, 0] = 255 * np.ones((200, 400))
background_data[:, :, 3] = 255 * np.ones((200, 400))
background_data = np.array(background_data, dtype='uint8')
pil_image_bg = Image.fromarray(background_data)
# create GUI
root = tk.Tk()
background_image = ImageTk.PhotoImage(pil_image_bg)
tk_image = ImageTk.PhotoImage(pil_image)
canvas = tk.Canvas(root, width=400, height=200)
canvas.pack()
# bind 'draggable' tag to mouse events
canvas.tag_bind('draggable', '<ButtonPress-1>', start_drag)
canvas.tag_bind('draggable', '<ButtonRelease-1>', stop_drag)
canvas.tag_bind('draggable', '<B1-Motion>', drag)
# display pictures
canvas.create_image(0, 0, image=background_image, anchor='nw')
canvas.create_image(0, 0, image=tk_image, anchor='nw', tag='draggable')
root.mainloop()

Categories