PyQt4 - Image Watermark - python

I'm trying to open a PNG image and write some text to it (a watermark) via QImage and QPainter. The code works 100% on Linux but when I run it on Windows XP (haven't tested with any other versions of Windows) the text is never written to the image. I have the code in a try/except block, but no errors are returned.
image = QtGui.QImage('demo.png')
painter = QtGui.QPainter()
painter.begin(image)
painter.setOpacity(0.8)
painter.setPen(QtCore.Qt.blue)
painter.setFont(QtGui.QFont('arial', 12))
painter.drawText(image.rect(), QtCore.Qt.AlignCenter, 'Watermark')
painter.end()
image.save('demo.png')
Using Python 2.6.2, PyQt 4.5.4
Any ideas?

First thing that comes to my mind is maybe it isn't finding the specified font on Windows.

My guess would be that whatever png lib you are using on Windows doesn't do tranparency (properly)

Related

Pillow (PIL Fork): Error when using ImageFont/ImageDraw methods with custom font

After reading through much of the Pillow documentation, stack overflow, and the web, I have been unable to decipher this error message that is throwing off my application. My current setup:
Python 3.7.6
Pillow 7.0.0 [Docs]
Below is a verifiable example of what I have been working on. Essentially, my error happens when I use title_font in place of where I use default_font. Emphasized by the 2 comments stating: # TODO Aborts with error unless using default_font TODO.
from PIL import ImageFont, ImageDraw, Image
def app():
# Default Font with static size and font type
default_font = ImageFont.load_default()
# TODO Title Font that is the desired use
title_font = ImageFont.truetype(font="~/Library/Fonts/Verdana.ttf", size=36)
# Background Image to draw text on
bg_img = Image.new(mode = "RGBA",size = (3480,2160), color="Green")
# Creates an object that can be used to draw in the given image.
d = ImageDraw.Draw(bg_img)
txt = "Hello World"
# TODO: Aborts with error unless using default_font TODO
# Returns (width, height) of text in pixels with designated font
txt_width, txt_height = default_font.getsize(txt)
print(f"Text Width:{txt_width} Text Height: {txt_height}")
# TODO: Aborts with error unless using default_font TODO
# Draws "Hello World" onto background image
d.text((10,60), text=txt, font=default_font, fill=(255,255,255,255))
# Pop Up window
bg_img.show()
Below is the error message that I get back from both ImageDraw/ImageFont methods:
>>> app()
dyld: lazy symbol binding failed: Symbol not found: _hb_language_get_default
Referenced from: /usr/local/lib/libraqm.dylib
Expected in: flat namespace
dyld: Symbol not found: _hb_language_get_default
Referenced from: /usr/local/lib/libraqm.dylib
Expected in: flat namespace
I have already tried:
To change the path used for the custom font and to change to another font loading method (i.e. ImageFont.load(filename), ImageFont.load_path(filename).
To settle with ImageFont.load_default() but as you might be able to tell by running it, the default font is very small and there is no way of changing its size or style.
One last thing that I was not sure about was this line in the installation guide that recommended after brew install of the packages Pillow depends on:
Then see depends/install_raqm_cmake.sh to install libraqm.
Can be found here halfway through the Building on macOS section. I have a nagging feeling this could be the cause but I simply do not understand what action it wants me to take.
Long time lurker, first time poster. Thank you for any help now and all the help afforded to me over the years!
UPDATE: Used my example on another MacBook and it works fine. I am going to reset the one it wasn't working on and build from scratch. Thanks for all your assistance!
I assume you used (like me) a Mac with OS Catalina or similar, and might have installed the mentioned library with "$ brew install libraqm" too.
I resolved it by changing the layout_engine, and due to this, not using 'libraqm' for PIL layout work in the background.
font = ImageFont.truetype(
"/System/Library/Fonts/Keyboard.ttf", layout_engine=ImageFont.LAYOUT_BASIC, encoding=self.encoding, self.font_size,)
If you do this you might not be able to use Chinese or similar Fonts. I am not sure where, in 'brew', 'pyenv' or 'libraqm' is the issue but I try to find it out.

Which file formats can I use for tkinter icons?

I know this might be obvious, but in tkinter you can set an icon, but I have found it really hard to find one. I just wanted to know if you have to use the .ico format for the file or if there is a way to use .png or .jpeg files.
Currently I have
window = Tkinter.Tk()
window.title("Weclome!")
window.geometry("200x300")
window.wm_iconbitmap("Icon.ico")
window.configure(background = "Black")
That is the whole setup I have and I just want to know about line 4:
window.wm_iconbitmap("Icon.ico")
Thanks for responding to my question, although i am sorry for not spending more time looking into the question rather than just asking here.
Let's start by reading the documentation!
The documentation at effbot.org says the following regarding iconbitmap(bitmap=None)
Sets or gets the icon bitmap to use when this window is iconified. This method is ignored by some window managers (including Windows).
Note that this method can only be used to display monochrome icons. To display a color icon, put it in a Label widget and display it using the iconwindow method instead.
Same as wm_iconbitmap.
So here's the documentation about iconwindow(window=None):
Sets or gets the icon window to use as an icon when this window is iconified. This method is ignored by some window managers (including Windows).
Same as wm_iconwindow.
window
The new icon window. If omitted, the current window is returned.
According to this other documentation, which actually says the same things as the docstrings of the homonymous method for tkinter in (at least) Python 2.7, 3.5 and 3.6:
wm_iconbitmap(self, bitmap=None, default=None)
Set bitmap for the iconified widget to bitmap. Return the bitmap if None is given.
Under Windows, the default parameter can be used to set the icon for the widget and any descendents that don't have an icon set explicitly. default can be the relative path to a .ico file (example: root.iconbitmap(default='myicon.ico') ). See Tk documentation for more information.
So here's the original Tk documentation:
wm iconbitmap window ?bitmap?
If bitmap is specified, then it names a bitmap in the standard forms accepted by Tk (see the Tk_GetBitmap manual entry for details). This bitmap is passed to the window manager to be displayed in window's icon, and the command returns an empty string. If an empty string is specified for bitmap, then any current icon bitmap is canceled for window. If bitmap is specified then the command returns an empty string. Otherwise, it returns the name of the current icon bitmap associated with window, or an empty string if window has no icon bitmap.
From my understanding of Tcl, here window is your toplevel window (either an instance of Tk or Toplevel).
On the Windows operating system, an additional flag is supported:
wm iconbitmap window ?-default? ?image?
If the -default flag is given, the icon is applied to all toplevel windows (existing and future) to which no other specific icon has yet been applied.
In addition to bitmap image types, a full path specification to any file which contains a valid Windows icon is also accepted (usually .ico or .icr files), or any file for which the shell has assigned an icon.
Tcl will first test if the file contains an icon, then if it has an assigned icon, and finally, if that fails, test for a bitmap.
Not very concrete and thus helpful answer so far.
My conclusion
The iconbitmap function (or method, depending on the programming language) should be used to set a bitmap image to the window when the window is iconified.
On Windows you're allowed to set a full path specification to any file which contains a valid Windows icon is also accepted (usually .ico or .icr files), or any file for which the shell has assigned an icon.
So which images are bitmaps?
xbm and xpm (for X Window System)
According to the Wikipedia article to which I linked "bitmap" to above:
The X Window System uses a similar xbm format for black-and-white images, and xpm for color images.
...
BMP file format
Netpbm format
.wbmp
ILBM
...
So most of the bitmap file formats are not cross-platform! In other words, if someone tells you to use a xbm image for the icon, it may not work on your platform because xbm are bitmaps for X Window System.
Note: even after this answer you may still have problems!
Other possible useful articles
Set window icon
tkinter TclError: error reading bitmap file
I was struggling a lot to find an answer too but finally I peeked into the source code of idle3.6 where I found the following piece of code:
# set application icon
icondir = os.path.join(os.path.dirname(__file__), 'Icons')
if system() == 'Windows':
iconfile = os.path.join(icondir, 'idle.ico')
root.wm_iconbitmap(default=iconfile)
else:
ext = '.png' if TkVersion >= 8.6 else '.gif'
iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext))
for size in (16, 32, 48)]
icons = [PhotoImage(master=root, file=iconfile)
for iconfile in iconfiles]
root.wm_iconphoto(True, *icons)
I searched through all files in the idlelib folder for .ico and .png using the rummage software.
So finally I managed to get the window icon working (on GNU-linux with TkVersion>=8.6) with the following two lines:
icon = PhotoImage(master=root, file='icon.png')
root.wm_iconphoto(True, icon)
where I put the icon directly in my application folder.
From the idle code it seems to me that on Windows still only .ico files are supported.

Python 3.4 Tkinter Claims Image Doesn't Exist [duplicate]

I am trying to set an application icon (python3 / tkinter) like this:
Interface()
root.title("Quicklist Editor")
root.iconbitmap('#/home/jacob/.icons/qle_icon.ico')
root.resizable(0, 0)
root.mainloop()
no matter what I do, I keep getting an error message (Idle), saying:
return self.tk.call('wm', 'iconbitmap', self._w, bitmap)
_tkinter.TclError: error reading bitmap file "/home/jacob/.icons/qle_icon.ico"
What am I doing wrong?
The problem is not the code, but the icon. I tried creating an xbm with another program than Gimp (some KDE icon editor), and although it looks terrifyingly ugly, it does show an icon.
I guess I have to find a creator that gives an "understandable" icon for my Python program.
Edit
The iconbitmap method turned out to be black and white only, so it was useless after all.
After a long search, I found the solution to set the color of an application's icon for Python 3 (on Linux). I found it here:
root = Tk()
img = PhotoImage(file='your-icon')
root.tk.call('wm', 'iconphoto', root._w, img)
This is an old question, and there is lots of stuff written about it on the web, but all of it is either incorrect or incomplete, so having gotten it to work I thought it would be good to record my actual working code here.
First, you'll need to create an icon and save it in two formats: Windows "ico" and Unix "xbm". 64 x 64 is a good size. XBM is a 1-bit format--pixels just on or off, so no colors, no grays. Linux implementations of tkinter only accept XBM even though every Linux desktop supports real icons, so you're just out of luck there. Also, the XBM spec is ambiguous about whether "on" bits represent black or white, so you may have to invert the XBM for some desktops. Gimp is good for creating these.
Then to put the icon in your titlebar, use this code (Python 3):
import os
from tkinter import *
from tkinter.ttk import *
root = Tk()
root.title("My Application")
if "nt" == os.name:
root.wm_iconbitmap(bitmap = "myicon.ico")
else:
root.wm_iconbitmap(bitmap = "#myicon.xbm")
root.mainloop()
This will allow you to use PNG files as icons, and it does render color. I tested it on Xubuntu 14.04, 32-bit with Python 3.4 (root is your Tk object):
import sys, os
program_directory=sys.path[0]
root.iconphoto(True, PhotoImage(file=os.path.join(program_directory, "test.png")))
(Finding program directory is important if you want it to search for test.png in the same location in all contexts. os.path.join is a cross-platform way to add test.png onto the program directory.)
If you change True to False then it won't use the same icon for windows that aren't the main one.
Please let me know if this works on Windows and Mac.
I tried this, and I couldn't get it to work using Windows 7.
Found a fix.
Use Jacob's answer, but the file has to be a .gif if you're using my OS, (Windows 7) it appears.
Make a 64x64 gif using MS paint, save it, use the file path and bingo, works.
I hope this helps you for cross-platform ability
LOGO_PATH="pic/logo.ico"
LOGO_LINUX_PATH="#pic/logo_1.xbm" #do not forget "#" symbol and .xbm format for Ubuntu
root = Tk()
if detect_screen_size().detect_os()=="Linux":
root.iconbitmap(LOGO_LINUX_PATH)
else:
root.iconbitmap(LOGO_PATH)
Simply using an r string to convert the directory into raw text worked for me:
ex:
app.iconbitmap(r'enter your path here')
In my case, Ubuntu 20.04, python 3.6 (conda), the command iconbitmap(bitmap=icon_path) failed w/ this error. In the end, I put the command w/in a try-except block and it worked; I can see the colorful image.
I'm surprised to see this is such an old question with no good answers, not in eight years! I too want my own icon for my "quickie" tkinter program.
What does work for me on Linux and Python3:
#!/usr/bin/env python
import tkinter
from PIL import Image, ImageTk
root = tkinter.Tk()
im = Image.open('junk.png')
photo = ImageTk.PhotoImage(im)
root.wm_iconphoto(True, photo)
root.mainloop()
The key seems to be using Image and ImageTk. I found zero solutions that worked without these.

Setting Application icon in my python Tk base application (On Ubuntu)

I want to set an image in my GUI application built on Python Tk package.
I tried this code:
root.iconbitmap('window.xbm')
but it gives me this:
root.iconbitmap('window.xbm')
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1567, in wm_iconbitmap
return self.tk.call('wm', 'iconbitmap', self._w, bitmap)
_tkinter.TclError: bitmap "window.xbm" not defined
Can anyone help?
You want to use wm iconphoto. Being more used to Tcl/Tk than Python Tkinter I don't know how that is exposed to you (maybe root.iconphoto) but it takes a tkimage. In Tcl/Tk:
image create photo applicationIcon -file application_icon.png
wm iconphoto . -default applicationIcon
In Tk 8.6 you can provide PNG files. Before that you have to use the TkImg extension for PNG support or use a GIF. The Python PIL package can convert images into TkImage objects for you though so that should help.
EDIT
I tried this out in Python as well and the following worked for me:
import Tkinter
from Tkinter import Tk
root = Tk()
img = Tkinter.Image("photo", file="appicon.gif")
root.tk.call('wm','iconphoto',root._w,img)
Doing this interactively on Ubuntu resulted in the application icon (the image at the top left of the frame and shown in the taskbar) being changed to use my provided gif image.
This worked for me
from tkinter import *
raiz=Tk()
raiz.title("Estes es el titulo")
img = Image("photo", file="pycharm.png")
raiz.tk.call('wm','iconphoto',raiz._w, img)
raiz.mainloop()
Try this:
root.iconbitmap('#window.xbm')
And quote:
Set (get) the icon bitmap to use when this window is iconified. This method are ignored by some window managers (including Windows).
Note that this method can only be used to display monochrome icons. To display a color icon, put it in a Label widget and display it using the iconwindow method instead.

wx.ListBox.HitTest not working on Mac

The following code sample works under linux (ubuntu) and Windows XP, but not under OSX.
import wx
class frame(wx.Frame):
def __init__(self,p=None):
wx.Frame.__init__(self,p)
self.box = wx.ListBox(self)
self.box.AppendItems( ["Zero","One","Two","Three","Four","Five","Six"])
self.box.Bind(wx.EVT_MOUSE_EVENTS,self.onMouse)
def onMouse(self,evt):
pos = evt.GetPosition()
print self.box.HitTest(pos)
evt.Skip()
class guiApp(wx.App):
def __init__(self,redirect=False):
wx.App.__init__(self,redirect)
def OnInit(self):
f = frame()
f.Show()
self.SetTopWindow(f)
return True
if __name__=="__main__":
app = guiApp()
app.MainLoop()
On Linux and Windows, the correct items are identified when moused over. On OSX hittest always returns -1 (wx.NOT_FOUND)
I'm running 32-bit wxPython, 2.8.12.1 (mac-unicode) which uses the Carbon API in 32bit python 2.7.2.
I can't find this listed as a known bug in wxWidgets and I'm hesitant to submit as it seems this should work. The listbox control is deeply integrated into out GUI and I really don't want to swap it out for ListCtrl or something similar as we have all other functionality working now. Does anyone know a workaround?
There is no work around if the listbox is scrolling. The scroll is handled be the underlying Carbon library and scroll position is not accurately reported back through wx.
I found the bug in the wxWidgets source code and opened a ticket on the wxWidgets trac, http://trac.wxwidgets.org/ticket/13699, with a patch.
The root of the bug is a call to the Mac's underlying DataBrowser with an incorrect rowId argument. wxWidgets was passing row position offsets, assuming this would be the rowId's (and maybe at some point apple used these internally when true Id's weren't specified.) Adding a call to another function translates a row's position (offset) into it's real id. With a patched version of wxWidgets the above script works as expected.

Categories