How to remove white background of gif when using pillow? - python

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?

Related

Python PIL - How to put text on a video

I am writing a program that puts captions on the screen and I am using PIL because it has high-quality text that is way better than the default moviepy text. I currently can put the text on a black screen, I tried using a fully transparent image as a sort of hack but that didn't work. So if anyone knows how to put PIL text on an image, or up the quality of the default moviepy text, let me know, please. Here is my basic code to put white text on a black background:
import numpy as np
from moviepy.editor import *
from PIL import Image, ImageFont, ImageDraw
SIZE = (1280, 720)
DURATION = 2
FPS = 1
TEXT = "I am having a hard time"
FONT_SIZE = 100
TEXT_COLOR_HEX = "#ffffff"
FONT = "Amiri-Bold"
def create_PIL():
img = Image.new("RGB", size=SIZE)
#draw = ImageDraw.Draw(img)
draw = ImageDraw.Draw(img)
font = ImageFont.truetype(f"../Fonts/UniNeue-Trial-Bold.ttf", size=FONT_SIZE)
draw.text((100, 100), TEXT, font=font, fill=TEXT_COLOR_HEX)
img = np.array(img)
return VideoClip(lambda t: img, duration=DURATION).set_fps(FPS)
final = concatenate_videoclips(
[create_PIL()]
)
final.write_videofile('./test.mp4')
I am trying to put this text onto a video, and I need to have custom start and duration times but all this does it put it on a black screen, which is what I expected but not what I want.

Image background black

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

PIL: Paste image with resized aspect ratio

I have 2 images (icon.png and background.png). In the background.png image, there is a blank area which will be the place for the icon.png to be pasted using PIL (Python). However, the icon.png is a little bit bigger compared to the blank frame in the background.png. How can I paste and make the icon.png smaller so it can fit with the frame?
My code so far:
icon = Image.open("./icon.png")
background = Image.open("./background.png")
mask = Image.new("L", icon.size, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0) + icon.size, fill=255)
back_im = background.copy()
back_im.paste(icon, (200, 100), mask=mask)
back_im.save("./back_im.png")
Use resize after read the icon image to fit the desired size:
from PIL import Image, ImageDraw
iconSize=(200,100)
icon = Image.open("./icon.png")
icon=icon.resize(iconSize)
background = Image.open("./background.png")
mask = Image.new("L", icon.size, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0) + icon.size, fill=255)
back_im = background.copy()
# back_im.paste(icon, iconSize, mask=mask)
back_im.paste(icon, icon.size, mask=mask)
back_im.save("./back_im.png")

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.

Categories