I'm trying to display an image that already has a transparent background into a window. Currently I'm using OpenCV cv2.imshow which doesn't show the alpha channel and that results in the pixels being black. Are there any other library or different kinds of approach that shows an image with a transparent background in a window with the background desktop screen showing?
Original Image:
Current result:
Desired result:
You can use the python standard library Tkinter to show an image in a transparent window.
Code Snippet:
from tkinter import Tk, Canvas, PhotoImage, NW
root = Tk()
root.attributes('-transparentcolor','#f0f0f0')
# Canvas
canvas = Canvas(root, width=450, height=600)
canvas.pack()
# Image
img = PhotoImage(file="./images/panda.png")
# Positioning the Image inside the canvas
canvas.create_image(0, 0, anchor=NW, image=img)
# Starts the GUI
root.mainloop()
Related
I'm trying to display an image on the screen, without any window/application popping up/containing it. I'm pretty close with TKinter, but the method for removing the background color of the canvas is hacky and has some undesired effects.
import tkinter as tk
import ctypes
user32 = ctypes.windll.user32
screen_size = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)
root = tk.Tk()
root.overrideredirect(True)
root.config(bg="blue", bd=0, highlightthickness=0)
root.attributes("-transparentcolor", "#FEFCFD")
root.attributes("-topmost", True)
tk_img = tk.PhotoImage(file="image.png")
canvas = tk.Canvas(root, bg="#FEFCFD", bd=0, highlightthickness=0, width=screen_size[0], height=screen_size[1])
canvas.pack()
img = canvas.create_image(0, 0, image=tk_img, anchor="nw")
root.mainloop()
The -transparentcolor flag mostly removes the background, but if an image has any partially transparent pixels it will tint them. Plus, if that color exists in the image, it will be removed; that choice of color was in hopes of minimizing exact matches in an image while also being mostly white, to hopefully have the least noticeable affect on the images. Here's an image of what it looks like currently; very close to what I want, but you can see some missing pixels in the white areas of the dice, and they all seem to have a white border around them due to their edges being partially transparent. This is what the image should look like.
I've also tried to achieve this effect using wxPython, but I can't remove the background of the window, leading to transparent images always being backed by some color. I used this answer; I've modified it slightly but nothing I've done has improved it.
So, is there a way to draw an image on the screen without any background at all with Python?
Thanks to the suggestion from Kartikeya, I was able to solve my own question.
Using PyQt5, this code will display an image with transparency and no border or background at all
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel
app = QApplication(sys.argv)
window = QMainWindow()
window.setAttribute(Qt.WA_TranslucentBackground, True)
window.setAttribute(Qt.WA_NoSystemBackground, True)
window.setWindowFlags(Qt.FramelessWindowHint)
label = QLabel(window)
pixmap = QPixmap('image.png')
label.setPixmap(pixmap)
label.setGeometry(0, 0, pixmap.width(), pixmap.height())
window.label = label
window.resize(pixmap.width(),pixmap.height())
window.show()
sys.exit(app.exec_())
Once I was looking for PyQt5, I found this question and only needed to modify the code slightly. Here is what it looks like now.
So, is there a way to draw an image on the screen without any
background at all with Python?
Using Tkinter, for this image, no, you cannot achieve the desired result. (You can look for other modules like 'PyQT5', 'Kivy', 'wxPython', or 'turtle' maybe.)
See, transparentcolor Specifies the transparent color index of the toplevel.
If you want to do the best in Tkinter, here are some changes to your code:
root.attributes('-transparentcolor', '#d4d4e2')
root.attributes("-topmost", True)
tk_img = tk.PhotoImage(file="image.png")
canvas = tk.Canvas(root, bg="#d4d4e2", bd=0, highlightthickness=0, width=screen_size[0], height=screen_size[1])
So, this will display a window that contains a canvas with transparent background. Very close to what you wanted, you can see very less missing pixels in the white areas of the dice, but still, this isn't the solution.
but if an image has any partially transparent pixels it will tint them
Yes, it's true, if that color exists in the image, it will be removed, as that color is being used to mark what needs to be used as transparent color.
that choice of color was in hopes of minimizing exact matches in an
image while also being mostly white, to hopefully have the least
noticeable effect on the images.
For the edges/borders of this image to retain the partially 'white' transparent background, the choice of color needs to be some shade of 'white'. So, the color used to make it transparent is #d4d4e2 (For this image, there was only one place where this color pixel was used, so it goes unnoticable.) Still, the edges will have sharp corners and cuts.
How would I place an image inside of this code so it can scroll?
This code is from the answer here: tkinter: using scrollbars on a canvas
from tkinter import *
root=Tk()
frame=Frame(root,width=300,height=300)
frame.pack(expand=True, fill=BOTH) #.grid(row=0,column=0)
canvas=Canvas(frame,bg='#FFFFFF',width=300,height=300,scrollregion=(0,0,500,500))
hbar=Scrollbar(frame,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(frame,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(width=300,height=300)
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
canvas.pack(side=LEFT,expand=True,fill=BOTH)
root.mainloop()
I tried an image on the canvas, as well as an image inside another frame inside the canvas, and an image inside the existing frame, and I placed a label inside a nested frame and on existing canvas. The scroll bars don't function with the image that was larger than 300x300, but the scroll bars move with the label of only text, but the label doesn't move. I used L_text.place(x=20,y=90) and I used L_text.pack() with same results.
Without modification of code in the Answer, I get scrollbars to move and mousewheel moves them only when mouse pointer hovers on the vert scrollbar, but mouse on the canvas/frame area doesn't move the scrollbars.
Ubuntu 20.04 python 3.8.5
Posting code modified from above sample that is improved for my application.
I need to tweak some more, but this is at least the solution to question in title of post.
import tkinter as tk
from tkinter import *
import PIL
from PIL import Image, ImageTk
root=Tk()
root.geometry("550x850+50+50")
frame=Frame(root,width=300,height=300)
frame.pack(expand=True,fill=BOTH)
canvas=Canvas(frame,width=300,height=300,scrollregion=(0,0,500,1200))# 1200 is
# vertical scrollable area inside the window
hbar=Scrollbar(frame,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(frame,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(width=300,height=300)
canvas.config(xscrollcommand=hbar.set,yscrollcommand=vbar.set)
canvas.pack(side=LEFT,expand=True,fill=BOTH)
#frame_2=Frame(canvas,width=900,height=900)
#frame_2.pack() # place(x=1,y=1)
file='test_receipt.png'
img=ImageTk.PhotoImage(Image.open(file))
canvas.create_image(1,1,image=img,anchor=NW) #Place image directly on canvas
# 1,1 is upper left corner no padding, anchor required or image isn't alinged
# on its upper left corner.
#L_image=Label(canvas,image=img)
#L_image.pack() # place(x=1,y=1)
#L_text=Label(frame_2,text='label inside')
#L_text.pack()
#L_text.place(x=20,y=90)
root.mainloop()
I try to make a splash screen with a png.
I use Python 3.7.4 64-bit, under macOS 10.14.4 and Visual Code 1.33.1
With root.overrideredirect(True) no windows are displayed.
With root.overrideredirect(False) the png is correctly displayed but the top window border is visible.
import tkinter as tk
root = tk.Tk()
# Hide the root window drag bar and close button
root.overrideredirect(True)
# Make the root window always on top
root.wm_attributes('-topmost', True)
# Turn off the window shadow
root.wm_attributes('-transparent', True)
# Set the root window background color to a transparent color
root.config(bg='systemTransparent')
root.geometry('+300+300')
# Store the PhotoImage to prevent early garbage collection
root.image = tk.PhotoImage(file='./local/pics/splash.png')
# Display the image on a label
label = tk.Label(root, image=root.image)
# Set the label background color to a transparent color
label.config(bg='systemTransparent')
label.pack()
root.mainloop()
Thanks for your help
This will hide the title bar
and fixates your window to top always:
root.attributes('-type', 'dock')
If you don't need it at the top:
root.attributes('-type', 'splash')
This will hide the title bar
If this can be improved please comment.
I am trying to display an image on my desktop without any boarder or window, like an image floating in the desktop. I also want to be able to control its position once it has been created, with the arrow keys or with a line of code that changes its position with some coordinate system of some sorts. I haven't found any method after some reaserch (not in Python, at least).
If that's not possible, please recommend another programming language that can.
You can use Tkinter for this.
I made a little example:
Python3
from tkinter import Toplevel, Tk, Label, PhotoImage
win = Tk()
win.attributes('-alpha', 0.0)
win.iconify()
window = Toplevel(win)
window.geometry("500x500+100+100")
window.overrideredirect(1)
photo = PhotoImage(file="test.png")
label = Label(window, image=photo)
label.pack()
win.mainloop()
Python2
from Tkinter import Toplevel, Tk, Label
import ImageTk
win = Tk()
win.attributes('-alpha', 0.0)
win.iconify()
window = Toplevel(win)
window.geometry("500x500+100+100") # create an window 500x500 pixel, 100 pixels from the upper left corner
window.overrideredirect(1) # Take the border away
photo = ImageTk.PhotoImage(file="test.png")
label = Label(window, image=photo)
label.pack()
win.mainloop()
I am creating an Arduino interface on Sublime using python Tkinter..
I need to show a text over an image. Located in the middle of the screen (512, 200). I don't know how to do it using this library
import Tkinter as tk
from Tkinter import *
root = tk.Tk()
root.geometry("1024x574")
root.title("window")
photo = tk.PhotoImage(file= r"hi.gif")
cv = tk.Canvas()
cv.pack(side='top', fill='both', expand='yes')
cv.create_image(0, 0, image=photo, anchor='nw')
text=['my text']
root.mainloop()
Any suggestions?
You need to create a tk label widget and add your text to it. Then you need to use the tk label option compound=.
Taken directly from http://effbot.org/tkinterbook/label.htm:
"compound=
Controls how to combine text and image in the label. By default, if an image or bitmap is given, it is drawn instead of the text. If this option is set to CENTER, the text is drawn on top of the image. If this option is set to one of BOTTOM, LEFT, RIGHT, or TOP, the image is drawn besides the text (use BOTTOM to draw the image under the text, etc.). Default is NONE."
The following is a minimal but working example that accomplishes what you asked for:
import tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
image = Image.open('hi.gif')
tk_image = ImageTk.PhotoImage(image)
label = tk.Label(root, text='Some Plain Text', image=tk_image, compound='center')
label.pack()
root.mainloop()