So I have 2 images that I would like to display on top of each other.
The image on top should have transparency so that the one on the bottom is visible.
Here is my code so far:
from Tkinter import *
import ttk
from PIL import Image, ImageTk
root = Tk()
face = Image.open("faces/face.gif")
eyes = Image.open("faces/eyes1.png")
face = face.convert("RGBA")
eyes = eyes.convert("RGBA")
facedatas = face.getdata()
eyesdatas = eyes.getdata()
newData = []
for item in eyesdatas:
if item[0] == 255 and item[1] == 255 and item[2] == 255:
newData.append((255, 255, 255, 0))
else:
newData.append(item)
eyes.putdata(newData)
eyes.save("eyes0.png", "PNG")
facepic = ImageTk.PhotoImage(face)
eyespic = ImageTk.PhotoImage(eyes)
label1 = Label(image=facepic)
label1.image = facepic
label1.grid(row = 0, column = 0)
label2 = Label(image=eyespic)
label2.image = eyespic
label2.grid(row = 0, column = 0)
root.mainloop()
And here is what I get when I run it:
When I would like to obtain this:
With the face in the bottom and the eyes on top.
Try this
from PIL import Image, ImageTk
from Tkinter import Tk, Label
root = Tk()
def RBGAImage(path):
return Image.open(path).convert("RGBA")
face = RBGAImage("faces/face.gif")
eyes = RBGAImage("faces/eyes1.png")
face.paste(eyes, (0, 0), eyes)
facepic = ImageTk.PhotoImage(face)
label1 = Label(image=facepic)
label1.grid(row = 0, column = 0)
root.mainloop()
I do not have both your source images, so I can not be sure it will work with them. Please provide the originals of both if there is any issue.
You can use Image.alpha_composite to create a new composited image.
from PIL import Image, ImageTk
from Tkinter import Tk, Label
root = Tk()
def RBGAImage(path):
return Image.open(path).convert("RGBA")
face = RBGAImage("faces/face.gif")
eyes = RBGAImage("faces/eyes1.png")
c = Image.alpha_composite(face, eyes)
facepic = ImageTk.PhotoImage(c)
label1 = Label(image=facepic)
label1.grid(row = 0, column = 0)
root.mainloop()
Related
I'm creating a project where the Swipe transition between two images. I'm using the tkinter library and I'm stuck.
Šobrīd fragments:
import tkinter as tk
from PIL import ImageTk, Image
root = tk.Tk()
image1 = Image.open('name.jpg')
image2 = Image.open('name2.jpg')
width = min(image1.width, image2.width)
height = min(image1.height, image2.height)
image1 = image1.resize((width, height),Image.ANTIALIAS)
image2 = image2.resize((width, height),Image.ANTIALIAS)
def Swipe(image1, image2, end):
new_image = Image.new('RGB', (image1.width, image1.height), color='white')
for y in range(image1.height):
for x in range(image1.width):
if y <= end: new_image[x][y] = image1[x][y]
else: new_image[x][y] = image2[x][y]
return new_image
for i in range(image1.height):
got = Swipe(image1, image2, i)
But I get a error /'Image' object is not subscriptable/ And how do I realize this transition in the root window? Maybe someone could help?
Ok so I'm trying to reproduce a raycaster with Python. All things done, now I've got a 512x512 matrix coded as 8-bit colors, that I try rendering through Tkinter.
Problem is, after doing a bit of conversion with Pillow, the image appears roughly half-sized, but most importantly as a black square. I'm sure it's some kind of misuse of a function, but i can't find which. Here's the code :
from PIL import Image, ImageTk
import tkinter as Tk
import matplotlib.pyplot as plt, numpy as np
fen = Tk.Tk()
img = plt.imread('BG0.png')
canvas = Tk.Canvas(fen, width = 512, height = 512)
canvas.pack()
def Up(event):
global img
i = np.finfo(img.dtype)
img = img.astype(np.float64)/i.max
img = 255 * img
img = img.astype(np.uint8)
img = ImageTk.PhotoImage(Image.fromarray(img))
canvas.create_image(0, 0, image = img, anchor = Tk.NW)
fen.bind_all('<Up>', Up)
fen.mainloop()
And here's that famous image we're looking to show (but actually, any 512x512 image could do the trick i'd say), just put it in the same folder as this program:
BG0.png
You just have to press the up arrow key on your keybord to have it render in the tkinter window.
It's a PIL and Tkinter bug.
The image that ImageTk returns must to be stored in a variable, or a list.
You can try to pop one image from the list and it will disappear.
Here is what you can do.
from PIL import Image, ImageTk
import tkinter as Tk
import matplotlib.pyplot as plt, numpy as np
fen = Tk.Tk()
img = plt.imread('BG0.png')
canvas = Tk.Canvas(fen, width = 512, height = 512)
canvas.pack()
# THIS IS NEEDED
images_tk_list = []
def Up(event):
global img
i = np.finfo(img.dtype)
img = img.astype(np.float64)/i.max
img = 255 * img
img = img.astype(np.uint8)
img = ImageTk.PhotoImage(Image.fromarray(img))
# THIS IS NEEDED
images_tk_list.append( img )
canvas.create_image(0, 0, image = img, anchor = Tk.NW)
fen.bind_all('<Up>', Up)
fen.mainloop()
I'm trying to change the color of an image using RGB values in python, for example, if I want to change my image to grayscale I want to be able to manipulate the RGB values of the image. I've read that if I want my image in grayscale I would have to do something like Gray = (RedValue + GreenValue + BlueValue) / 3.
Here's my attempt code:
import tkinter as tk
from tkinter import *
from PIL import ImageTk, Image
from tkinter import filedialog
import os
import numpy as np
root = Tk()
root.geometry("550x300+300+150")
root.resizable(width=True, height=True)
#Find image
def openfn():
filename = filedialog.askopenfilename(title='Open')
return filename
#Here's where we load the image
def open_img():
x = openfn()
img = Image.open(x)
img = img.resize((350, 350), Image.ANTIALIAS)
img = ImageTk.PhotoImage(img)
panel = Label(root, image=img)
panel.image = img
panel.grid()
def gray():
imagen = openfn()
img = Image.open(imagen)
img = img.convert("RGB")
datas = img.getdata()
new_image_data = []
for item in datas:
if item[0] in list(range(0, 255)):
new_image_data.append((20, 40, 60))
else:
new_image_data.append(item)
img.putdata(new_image_data)
img.save("gray_image.png")
img = img.resize((250, 250), Image.ANTIALIAS)
img = ImageTk.PhotoImage(img)
panel = Label(root, image=img)
panel.image = img
panel.grid()
#buttons
btn = tk.Button(root, text='Select an image', command=open_img).grid(column=0,row=0)
gray = tk.Button(root, text='Gray filter', command=gray).grid(column=1,row=0)
root.mainloop()
I made a function called gray where I reloaded the image and change it's colors, but I don't want that, I want to apply changes to the image I loaded.
Hope you can help me out.
Try this:
import tkinter as tk
from tkinter import *
from PIL import ImageTk, Image
from tkinter import filedialog
import os
import numpy as np
root = Tk()
root.geometry("550x300+300+150")
root.resizable(width=True, height=True)
#Find image
def openfn():
filename = filedialog.askopenfilename(title="Open")
return filename
#Here's where we load the image
def open_img():
global filename, img, tk_img, panel
filename = openfn()
img = Image.open(filename)
img = img.resize((350, 350), Image.ANTIALIAS)
tk_img = ImageTk.PhotoImage(img)
panel = Label(root, image=tk_img)
panel.grid()
def apply_gray_filter():
global tk_img
draw = img.load()
width, height = img.size
# For each pixel
for x in range(width):
for y in range(height):
# Get the value as (r, g, b) using draw[x, y] and then average it
gray = sum(draw[x, y])/3
# turn it into an int
gray = int(gray)
# Change the pixel's value
draw[x, y] = (gray, gray, gray)
# Display the new image
tk_img = ImageTk.PhotoImage(img)
panel.config(image=tk_img)
#buttons
select_img_button = tk.Button(root, text="Select an image", command=open_img)
select_img_button.grid(column=0, row=0)
gray_filter_button = tk.Button(root, text="Gray filter",
command=apply_gray_filter)
gray_filter_button.grid(column=1, row=0)
root.mainloop()
It loops through all of the pixels and converts each one to grey scale. For some reason, if you press it multiple times it will turn the image into white. I have no idea why.
I am trying to paste several images end to end and then display on canvas. I cannot figure out why this image is showing as black. Any Ideas?
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
canvas = Canvas(root, width=1000, height=800)
canvas.pack()
grass = Image.open(r"C:\pathto\grass.gif")
water = Image.open(r"C:\pathto\ffwater.gif")
r1 = ['g','g','g','w','w','w','g','g']
row = Image.new('RGB', (1000, 800))
xx = 0
for i in r1:
if i == 'g':
img = grass
if i == 'w':
img = water
row.paste(img, (xx, 0))
xx = xx + img.size[0]
worldr1 = ImageTk.PhotoImage(row)
canvas.create_image(0,0, image=worldr1)
root.mainloop()
The image is black because it is only partially visible on the Canvas. I replaced
canvas.create_image(0,0, image=worldr1)
by
canvas.create_image(0,0, anchor="nw", image=worldr1)
and the full image was visible on the Canvas (the default value is anchor="center").
If the pics that are supossed to go on the upper layers have transparencies, but they show up with a gray square instead of the said transparency, covering the background.
I am coding a pinball game in Python, using Tkinter and PIL. I'm stuck because I need to display the elements of the game (flippers, bumpers, etc) over a background, however, when I try to overlay them, they show up with a gray square, instead of the transparency they already have.
This is the code:
import sys
from tkinter import *
from PIL import Image, ImageTk
#Secci�³n funciones
def botones():
juego_Nuevo_Boton = Button( menu_Principal, text = ("Juego nuevo"), command = juegoNuevo, font = ("Arial Black", 10), width = 20).place(x = 15, y = 125 )
continuar_Juego_Boton = Button( menu_Principal, text = "Continuar juego", font = ("Arial Black", 10), width = 20) .place(x = 15, y = 160)
cerrar_El_Juego = Button( menu_Principal, text = "Cerrar el juego", command = menu_Principal.destroy, font = ("Arial Black", 10), width = 20).place(x = 15, y = 195 )
def juegoNuevo():
ventana_Juego_Nuevo = Toplevel()
ventana_Juego_Nuevo.geometry("600x700")
ventana_Juego_Nuevo.title("Nueva partida")
imagen_Fondo_Juego_Nuevo = PhotoImage( file = "fondo_Juego.gif" )
fondo_Juego_Nuevo = Label(ventana_Juego_Nuevo, image=imagen_Fondo_Juego_Nuevo)
fondo_Juego_Nuevo.place( x = 0, y = 0, relwidth = 1, relheight = 1 )
fondo_Juego_Nuevo.image = imagen_Fondo_Juego_Nuevo
imagen_lanzador_Canal = PhotoImage( file = "LanzadorCanal.gif" )
Lanzador_Canal = Label(ventana_Juego_Nuevo, image = imagen_lanzador_Canal)
Lanzador_Canal.place( x = 0, y = 0 )
Lanzador_Canal.image = imagen_lanzador_Canal
############################################
#I ALSO TRIED THIS BUT IT SHOWS UP SOME KIND OF IMAGE EDITOR CALLED "IMAGE MAGIC",
#I don't need to edit the pictures, i just need them overlayed, so i can finish the game.
#fondo_Del_Juego = Image.open("fondo_Juego.png")
#lanzador_Canal = Image.open("LanzadorCanal.png")
#fondo_Del_Juego.paste(lanzador_Canal, (0, 0), lanzador_Canal)
#fondo_Del_Juego.show()
#############################################
ventana_Juego_Nuevo.mainloop()
#Crear pantalla y titulo
menu_Principal = Tk()
menu_Principal.title("Pinball - Proyecto : creado por Daniel Bonilla")
menu_Principal.geometry("200x400")
imagen_Fondo_Menu = PhotoImage(file = "MenuPrincipal.gif")
fondo_Menu = Label(menu_Principal, image = imagen_Fondo_Menu)
fondo_Menu.place( x = 0, y = 0, relwidth = 1, relheight = 1 )
botones()
#Llamado a la ventana
menu_Principal.mainloop()
Pay special attention to "JuegoNuevo()" function, there's where the problem is.
So, pretty much, this picture sums up my problem:
*The spring is transparent already, it just doesn't show up that way.
Have in mind that, later on, I need to put all the other elements, collisions,etc... so, that "Image Magic" thing (see the code above), I think, won't work.
*EDIT: I already tried as mentioned in the first answer with PNG files, but the problem is still there.
Use png instead of gif files will fix your problem. Also remove the unused packages:
from PIL import Image, ImageTk