Tkinter Create Line with Stipple - python

I found the possibility to make a stippled line in Python tkinter. (Seen here: Canvas Line Objects)
It states that I need a bitmap file and define stipple=bitmap_file
I tried this in:
# Import the required libraries
from tkinter import *
# Create an instance of tkinter frame or window
win=Tk()
# Set the size of the tkinter window
win.geometry("700x350")
# Create a canvas widget
canvas=Canvas(win, width=500, height=300)
canvas.pack()
# Add a line in canvas widget
canvas.create_line(100,200,200,35, stipple='#CheckedLine.bmp', fill='red', width=5)
win.mainloop()
However, the console then says:
_tkinter.TclError: error reading bitmap file "CheckedLine.bmp"
Can someone help?

The page linked to in the OP, also links to a detailed description of what they meant by a "bitmap", they never mention it to be a file but rather a bitmap.
stipple
To draw a stippled line, set this option to a bitmap that specifies
the stippling pattern, such as stipple='gray25'. See Section 5.7,
“Bitmaps” for the possible values.
Section 5.7 details about the files to be used -:
The graphic above shows Button widgets bearing the standard bitmaps.
From left to right, they are 'error', 'gray75', 'gray50', 'gray25',
'gray12', 'hourglass', 'info', 'questhead', 'question', and 'warning'.
You can use your own bitmaps. Any file in .xbm (X bit map) format will
work. In place of a standard bitmap name, use the string '#' followed
by the pathname of the .xbm file.
For more information on the .xbm format this may be useful.
Some image viewers/converters, e.g., XnView, FFmpeg and IrfanView,
support XBM. A 48×48 XBM can be converted to Ikon and eventually
X-Face with Netpbm tools.
ImageMagick supports converting images both to and from XBM. GIMP
may be used to create or modify images using the XBM format, and also
supports converting images to and from the XBM format.
NOTE:
Incase, you use the standard bitmaps as listed above and in the link provided, they render to look like this -:

Related

How to save image data from clipboard to a file in Python 3 on Debian, using tkinter?

I'm trying to use the tkinter solution for obtaining clipboard image data copied from GIMP, but cannot make it work, saving the data to file:
from tkinter import Tk
r = Tk()
r.withdraw()
clip = r.clipboard_get(type="image/png")
r.update()
r.destroy()
with open("testbytes.png", mode="bw+") as f:
f.write(clip.encode())
When I try to open the testbytes.png file, the Image Viewer reports a fatal error, not a PNG file. I obtained the type parameter for the clipboard_get() call with r.selection_get(selection='CLIPBOARD', type='TARGETS'), which returned:
'TIMESTAMP TARGETS MULTIPLE SAVE_TARGETS image/png image/bmp image/x-bmp image/x-MS-bmp image/x-icon image/x-ico image/x-win-bitmap image/vnd.microsoft.icon application/ico image/ico image/icon text/ico image/tiff image/jpeg '
I think the format of the data on the clipboard is PNG. I've also tried JPEG, BMP and TIFF, but they result in similar errors.
What am I doing wrong?
Using a conversion method, obtained in a separate SO question, for the hexdump of PNG data that tkinter provides from the clipboard, the correct code is:
from tkinter import Tk
r = Tk()
r.withdraw()
clip = r.clipboard_get(type="image/png")
r.update()
r.destroy()
# Convert hexdump to bytes
clip = bytes([eval(h) for h in clip.strip().split(' ')])
with open("testbytes.png", mode="bw+") as f:
f.write(clip)
Apart from writing out a PNG file, the data may also be loaded with the pillow module (formerly known as PIL):
import io
from PIL import Image
cf = io.BytesIO(clip)
cim = Image.open(cf)
cim.show()
As far as I've been able to determine, this is the best method of reading a PNG file from the clipboard into Python 3 on Linux (Debian).
I have created a tool for this intended for windows. The code could be used for debian as well. This script monitors for change in your clipboard and pops up a tkinter window asking you the filename to be used for saving the image, if it is not present in the folder. The image is then saved into the folder as a PNG file. It is particularly helpful with the windows shortcut Windows + Shift + S used to snip the screen.
Please find it here: https://github.com/Mitzzzzz/Clipboard-Image-Saver

Creating a lightweight fallback font with fontforge and fonttools

For a webapp I need a way to prevent that a browser falls back to another font if my web font doesn't include a character. It seems the only way to do this is to add another font to the fontstack which includes "all" possible characters 1.
There are already existing fallback fonts, but those are more debug helpers as they show the codepoint as number, therefore they are much to heavy (>2MB).
The fallback font for my usecase should just show something like a box to signal a missing character.
My idea was to generate a simple font with only one glyph and apply a feature file which will replace all glyphs with this one.
My script for fontforge:
import fontforge
import fontTools.feaLib.builder as feaLibBuilder
from fontTools.ttLib import TTFont
font_name = 'maeh.ttf'
font = fontforge.font()
glyph = font.createChar(33, "theone")
pen = glyph.glyphPen()
pen.moveTo((100,100))
pen.lineTo((100,500))
pen.lineTo((500,500))
pen.lineTo((500,100))
pen.closePath()
for i in range(34, 99):
glyph = font.createChar(i)
glyph.width=10
font.cidConvertTo('Adobe', 'Identity', 0) # doesn't make a difference
font.generate(font_name)
font = TTFont(font_name)
feaLibBuilder.addOpenTypeFeatures(font, 'fallback.fea')
font.save("fea_"+font_name)
My feature file:
languagesystem DFLT dflt;
#all=[\00035-\00039];
##all=[A-Z] this works
feature liga {
sub #all by theone;
} liga;
But the above results in a
KeyError: ('cid00037', 'SingleSubst[0]', 'Lookup[0]', 'LookupList')
with changing numbers for cid00037.
If I use the out commented A-Z from the Feature file it works, so this approach doesn't seem to be completely wrong.
Why can't fonttools find the glyphs if I specify the range in CID notation?
Is there another way to crate a class for the OpenType feature file which includes all glyphs?
While working on the above problem, somebody hinted me to the Adobe NotDef font, which is pretty much what I was looking for. For some reason I wasn't able to convert the .otf of the Adobe NotDef to woff or woff2 with fontforge. Also all the online tools to create the web font files like fontsquirrel failed. To create the woff file I used sfnt2woff from the woff-tools package. For the woff2 file I used https://github.com/google/woff2.

"couldn't recognize data in image file ..." Why do I (sometimes) get this Error-message?

I wanted to implement some images in my Python-Tkinter application. I used the PhotoImage instance of Tkinter for this. It all worked perfectly whith the first picture: "RR.gif, a GIF image made with MS Paint. The second image: "Tank.gif", unfortunately caused some troubles. This picture was made (also in MS Paint) immediately after the first one and was also stored in GIF format. The images are located in the same folder so I assume the path is correct for both of them. However, the second label, (which contains the second image) gives the following error:
_tkinter.TclError: couldn't recognize data in image file "Tank.gif"
Which I think is strange since both images files are very similar. Does anyone know why I am getting this error? and how to solve it?
This is the simplest code in which the problem occurs.
from Tkinter import *
root = Tk()
icon = PhotoImage(file="RR.gif")
tank = PhotoImage(file="Tank.gif")
label_ico = Label(root, image=icon)
label_tan = Label(root, image=tank)
label_ico.pack()
label_tan.pack()
root.mainloop()

how to embed an image in a text widget

I know it is possible to embed an image in a Tkinter text widget, but I've been unable to find some simple example code.
Specifically, I need to embed a jpg, so according to the docs I think I need to use the photoimage class
I tried to use this:
img=PhotoImage ( file=imgfn )
text.image_create(image=img)
where imgfn is the image filename, and text is my text widget,
but I get "_tkinter.TclError: couldn't recognize data in image file ..."
thanks for any help!
PhotoImage only handles GIF and PGM/PPM files. In order to use JPEG with Tkinter, you can use the Python Imaging Library (PIL) to create a PhotoImage.
from PIL import Image, ImageTk
img = Image.open("yourimg.jpg")
photoImg = ImageTk.PhotoImage(img)
Alternatively you could just one of the other supported formats for PhotoImage if possible.

Python images display

How can I create a python script that runs through the images (1.jpeg-n.jpeg) in a directory on a mac and displays them in a browser OR via another python program?
Do I import a file to python and than display in browser?
Do I extract the file names 1,2,3,4,5 and add that to a list, which I give to another function that calls a browser and displays?
Any help would be great.
Thanks!
Using Tkinter and PIL for this purpose is pretty trivial. Add muskies example to the information from this thread that contains this example:
# use a Tkinter label as a panel/frame with a background image
# note that Tkinter only reads gif and ppm images
# use the Python Image Library (PIL) for other image formats
# free from [url]http://www.pythonware.com/products/pil/index.htm[/url]
# give Tkinter a namespace to avoid conflicts with PIL
# (they both have a class named Image)
import Tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
root.title('background image')
# pick an image file you have .bmp .jpg .gif. .png
# load the file and covert it to a Tkinter image object
imageFile = "Flowers.jpg"
image1 = ImageTk.PhotoImage(Image.open(imageFile))
# get the image size
w = image1.width()
h = image1.height()
# position coordinates of root 'upper left corner'
x = 0
y = 0
# make the root window the size of the image
root.geometry("%dx%d+%d+%d" % (w, h, x, y))
# root has no image argument, so use a label as a panel
panel1 = tk.Label(root, image=image1)
panel1.pack(side='top', fill='both', expand='yes')
# put a button on the image panel to test it
button2 = tk.Button(panel1, text='button2')
button2.pack(side='top')
# save the panel's image from 'garbage collection'
panel1.image = image1
# start the event loop
root.mainloop()
Of course if you're more familiar with another GUI, go ahead and adapt the example, it shouldn't take much.
You first have to find all image filenames. You can use os.listdir(...) to get all files in a certain directory, or glob.glob(...) to find all files matching a certain pattern.
Showing the images is the second and more challenging part of this. The first option is to open the images in an external program, this can be a web browser. On (most) platforms a command firefox 1.jpeg will open the image 1.jpeg in the Firefox browser. You can use the subprocess module to execute such commands. If you want to show them using a nice GUI, you have to create a GUI using some framework and use this. But if you are a beginner this might be a little bit too difficult for you.
For example:
import glob
import subprocess
files = glob.glob('dir/*.jpeg')
for file in files:
subprocess.call(['firefox', file])
muksie's answer already contains very useful advice. If don't want to write the HTML file yourself or want something a little fancier you could use a small script I wrote for the MDP library. This basically allows you to just do:
import slideshow
slideshow.show_image_slideshow(filenames, image_size=(80,60))
This will create an HTML slideshow and open it in your browser. You can grab just the needed files here (only templet.py and the two slideshow files are needed), which might be better for you than getting the full library.
It might be a lot easier to just generate a static web page with pictures than building a GUI for displaying pictures.
You can just generate a hmtl page, put the images on it and start your web browser with the newly created html file. this gives you some possibilities for layout as well.
If you just want a picture in the browser then muksie gave a working example.

Categories

Resources