rantash68
rantash68

Reputation: 77

when trying to create a bitmap: _tkinter.TclError: bitmap "pyimage2" not defined

There is an image which I'd like to draw in different colors, so I converted it to a bitmap, but when trying to create it on the canvas I get an error.

This is the code:

import PIL.Image
from PIL import ImageTk
from tkinter import *


im = PIL.Image.open("lightbulb.gif")
small_im = im.resize((20,20), resample=PIL.Image.NEAREST).convert('1');

root = Tk()
canvas = Canvas(root,width=100,height=100,bg='black')
canvas.pack()
bitmap = ImageTk.BitmapImage(small_im)
bitmap_id = canvas.create_bitmap(3,3,background='', foreground='gray', bitmap=bitmap,
                                 anchor=NW)
root.mainloop()

I get the following error:

Traceback (most recent call last):
  File "/Users/ronen/Dropbox/trycanvas/bitmaps.py", line 13, in <module>
    bitmap_id = canvas.create_bitmap(3,3,background="", foreground="gray", bitmap=bitmap, anchor=NW)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tkinter/__init__.py", line 2486, in create_bitmap
    return self._create('bitmap', args, kw)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tkinter/__init__.py", line 2480, in _create
    *(args + self._options(cnf, kw))))
_tkinter.TclError: bitmap "pyimage2" not defined

What am I doing wrong?

Upvotes: 3

Views: 1496

Answers (2)

rantash68
rantash68

Reputation: 77

Okay, I now understand what's going on. ImageTk.BitmapImage actually return an image, not a bitmap, but it can be used to change the colors. So intead of:

bitmap = ImageTk.BitmapImage(small_im)
bitmap_id = canvas.create_bitmap(3,3,background='', foreground='gray', bitmap=bitmap,
                                 anchor=NW)

I should have coded:

from_bitmap = ImageTk.BitmapImage(small_im, background='', foreground='gray')
bitmap_id = canvas.create_image(3,3, image=from_bitmap, anchor=NW)

Upvotes: -1

martineau
martineau

Reputation: 123453

The tkinter canvas.create_bitmap() method expects its bitmap= option to be a string containing either the name of one of the standard bitmaps (which are 'error', 'gray75', 'gray50', 'gray25', 'gray12', 'hourglass', 'info', 'questhead', 'question', and 'warning') and which look like this:

image showing the standard bitmaps graphically

Or the pathname of a file with one of your own in it in .xbm file format prefixed with an @ character.

Below is how to modify your code so it saves the image you want to display in a temporary .xbm format file and then tells tkinter to use that:

import os
import PIL.Image
from PIL import ImageTk
from tempfile import NamedTemporaryFile
import tkinter as tk

im = PIL.Image.open("lightbulb.gif")
small_img = im.resize((20,20), resample=PIL.Image.NEAREST).convert('1');

with NamedTemporaryFile(suffix='.xbm', delete=False) as temp_img:
    small_img.save(temp_img.name)

root = tk.Tk()
canvas = tk.Canvas(root, width=100, height=100, bg='black')
canvas.pack()
bitmap_id = canvas.create_bitmap(3, 3, background='', foreground='gray',
                                 bitmap='@'+temp_img.name, anchor=tk.NW)
root.mainloop()

try:  # Cleanup
    os.remove(temp_img.name)  # Get rid of named temporary file.
except FileNotFoundError:
    pass

Upvotes: 3

Related Questions