ImageTk.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #
  2. # The Python Imaging Library.
  3. # $Id$
  4. #
  5. # a Tk display interface
  6. #
  7. # History:
  8. # 96-04-08 fl Created
  9. # 96-09-06 fl Added getimage method
  10. # 96-11-01 fl Rewritten, removed image attribute and crop method
  11. # 97-05-09 fl Use PyImagingPaste method instead of image type
  12. # 97-05-12 fl Minor tweaks to match the IFUNC95 interface
  13. # 97-05-17 fl Support the "pilbitmap" booster patch
  14. # 97-06-05 fl Added file= and data= argument to image constructors
  15. # 98-03-09 fl Added width and height methods to Image classes
  16. # 98-07-02 fl Use default mode for "P" images without palette attribute
  17. # 98-07-02 fl Explicitly destroy Tkinter image objects
  18. # 99-07-24 fl Support multiple Tk interpreters (from Greg Couch)
  19. # 99-07-26 fl Automatically hook into Tkinter (if possible)
  20. # 99-08-15 fl Hook uses _imagingtk instead of _imaging
  21. #
  22. # Copyright (c) 1997-1999 by Secret Labs AB
  23. # Copyright (c) 1996-1997 by Fredrik Lundh
  24. #
  25. # See the README file for information on usage and redistribution.
  26. #
  27. import sys
  28. from io import BytesIO
  29. from . import Image
  30. if sys.version_info.major > 2:
  31. import tkinter
  32. else:
  33. import Tkinter as tkinter
  34. # --------------------------------------------------------------------
  35. # Check for Tkinter interface hooks
  36. _pilbitmap_ok = None
  37. def _pilbitmap_check():
  38. global _pilbitmap_ok
  39. if _pilbitmap_ok is None:
  40. try:
  41. im = Image.new("1", (1, 1))
  42. tkinter.BitmapImage(data="PIL:%d" % im.im.id)
  43. _pilbitmap_ok = 1
  44. except tkinter.TclError:
  45. _pilbitmap_ok = 0
  46. return _pilbitmap_ok
  47. def _get_image_from_kw(kw):
  48. source = None
  49. if "file" in kw:
  50. source = kw.pop("file")
  51. elif "data" in kw:
  52. source = BytesIO(kw.pop("data"))
  53. if source:
  54. return Image.open(source)
  55. # --------------------------------------------------------------------
  56. # PhotoImage
  57. class PhotoImage(object):
  58. """
  59. A Tkinter-compatible photo image. This can be used
  60. everywhere Tkinter expects an image object. If the image is an RGBA
  61. image, pixels having alpha 0 are treated as transparent.
  62. The constructor takes either a PIL image, or a mode and a size.
  63. Alternatively, you can use the **file** or **data** options to initialize
  64. the photo image object.
  65. :param image: Either a PIL image, or a mode string. If a mode string is
  66. used, a size must also be given.
  67. :param size: If the first argument is a mode string, this defines the size
  68. of the image.
  69. :keyword file: A filename to load the image from (using
  70. ``Image.open(file)``).
  71. :keyword data: An 8-bit string containing image data (as loaded from an
  72. image file).
  73. """
  74. def __init__(self, image=None, size=None, **kw):
  75. # Tk compatibility: file or data
  76. if image is None:
  77. image = _get_image_from_kw(kw)
  78. if hasattr(image, "mode") and hasattr(image, "size"):
  79. # got an image instead of a mode
  80. mode = image.mode
  81. if mode == "P":
  82. # palette mapped data
  83. image.load()
  84. try:
  85. mode = image.palette.mode
  86. except AttributeError:
  87. mode = "RGB" # default
  88. size = image.size
  89. kw["width"], kw["height"] = size
  90. else:
  91. mode = image
  92. image = None
  93. if mode not in ["1", "L", "RGB", "RGBA"]:
  94. mode = Image.getmodebase(mode)
  95. self.__mode = mode
  96. self.__size = size
  97. self.__photo = tkinter.PhotoImage(**kw)
  98. self.tk = self.__photo.tk
  99. if image:
  100. self.paste(image)
  101. def __del__(self):
  102. name = self.__photo.name
  103. self.__photo.name = None
  104. try:
  105. self.__photo.tk.call("image", "delete", name)
  106. except Exception:
  107. pass # ignore internal errors
  108. def __str__(self):
  109. """
  110. Get the Tkinter photo image identifier. This method is automatically
  111. called by Tkinter whenever a PhotoImage object is passed to a Tkinter
  112. method.
  113. :return: A Tkinter photo image identifier (a string).
  114. """
  115. return str(self.__photo)
  116. def width(self):
  117. """
  118. Get the width of the image.
  119. :return: The width, in pixels.
  120. """
  121. return self.__size[0]
  122. def height(self):
  123. """
  124. Get the height of the image.
  125. :return: The height, in pixels.
  126. """
  127. return self.__size[1]
  128. def paste(self, im, box=None):
  129. """
  130. Paste a PIL image into the photo image. Note that this can
  131. be very slow if the photo image is displayed.
  132. :param im: A PIL image. The size must match the target region. If the
  133. mode does not match, the image is converted to the mode of
  134. the bitmap image.
  135. :param box: A 4-tuple defining the left, upper, right, and lower pixel
  136. coordinate. See :ref:`coordinate-system`. If None is given
  137. instead of a tuple, all of the image is assumed.
  138. """
  139. # convert to blittable
  140. im.load()
  141. image = im.im
  142. if image.isblock() and im.mode == self.__mode:
  143. block = image
  144. else:
  145. block = image.new_block(self.__mode, im.size)
  146. image.convert2(block, image) # convert directly between buffers
  147. tk = self.__photo.tk
  148. try:
  149. tk.call("PyImagingPhoto", self.__photo, block.id)
  150. except tkinter.TclError:
  151. # activate Tkinter hook
  152. try:
  153. from . import _imagingtk
  154. try:
  155. if hasattr(tk, "interp"):
  156. # Required for PyPy, which always has CFFI installed
  157. from cffi import FFI
  158. ffi = FFI()
  159. # PyPy is using an FFI CDATA element
  160. # (Pdb) self.tk.interp
  161. # <cdata 'Tcl_Interp *' 0x3061b50>
  162. _imagingtk.tkinit(int(ffi.cast("uintptr_t", tk.interp)), 1)
  163. else:
  164. _imagingtk.tkinit(tk.interpaddr(), 1)
  165. except AttributeError:
  166. _imagingtk.tkinit(id(tk), 0)
  167. tk.call("PyImagingPhoto", self.__photo, block.id)
  168. except (ImportError, AttributeError, tkinter.TclError):
  169. raise # configuration problem; cannot attach to Tkinter
  170. # --------------------------------------------------------------------
  171. # BitmapImage
  172. class BitmapImage(object):
  173. """
  174. A Tkinter-compatible bitmap image. This can be used everywhere Tkinter
  175. expects an image object.
  176. The given image must have mode "1". Pixels having value 0 are treated as
  177. transparent. Options, if any, are passed on to Tkinter. The most commonly
  178. used option is **foreground**, which is used to specify the color for the
  179. non-transparent parts. See the Tkinter documentation for information on
  180. how to specify colours.
  181. :param image: A PIL image.
  182. """
  183. def __init__(self, image=None, **kw):
  184. # Tk compatibility: file or data
  185. if image is None:
  186. image = _get_image_from_kw(kw)
  187. self.__mode = image.mode
  188. self.__size = image.size
  189. if _pilbitmap_check():
  190. # fast way (requires the pilbitmap booster patch)
  191. image.load()
  192. kw["data"] = "PIL:%d" % image.im.id
  193. self.__im = image # must keep a reference
  194. else:
  195. # slow but safe way
  196. kw["data"] = image.tobitmap()
  197. self.__photo = tkinter.BitmapImage(**kw)
  198. def __del__(self):
  199. name = self.__photo.name
  200. self.__photo.name = None
  201. try:
  202. self.__photo.tk.call("image", "delete", name)
  203. except Exception:
  204. pass # ignore internal errors
  205. def width(self):
  206. """
  207. Get the width of the image.
  208. :return: The width, in pixels.
  209. """
  210. return self.__size[0]
  211. def height(self):
  212. """
  213. Get the height of the image.
  214. :return: The height, in pixels.
  215. """
  216. return self.__size[1]
  217. def __str__(self):
  218. """
  219. Get the Tkinter bitmap image identifier. This method is automatically
  220. called by Tkinter whenever a BitmapImage object is passed to a Tkinter
  221. method.
  222. :return: A Tkinter bitmap image identifier (a string).
  223. """
  224. return str(self.__photo)
  225. def getimage(photo):
  226. """Copies the contents of a PhotoImage to a PIL image memory."""
  227. im = Image.new("RGBA", (photo.width(), photo.height()))
  228. block = im.im
  229. photo.tk.call("PyImagingPhotoGet", photo, block.id)
  230. return im
  231. def _show(image, title):
  232. """Helper for the Image.show method."""
  233. class UI(tkinter.Label):
  234. def __init__(self, master, im):
  235. if im.mode == "1":
  236. self.image = BitmapImage(im, foreground="white", master=master)
  237. else:
  238. self.image = PhotoImage(im, master=master)
  239. tkinter.Label.__init__(self, master, image=self.image, bg="black", bd=0)
  240. if not tkinter._default_root:
  241. raise IOError("tkinter not initialized")
  242. top = tkinter.Toplevel()
  243. if title:
  244. top.title(title)
  245. UI(top, image).pack()