ImageTk.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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 tkinter
  28. from io import BytesIO
  29. from . import Image
  30. from ._deprecate import deprecate
  31. # --------------------------------------------------------------------
  32. # Check for Tkinter interface hooks
  33. _pilbitmap_ok = None
  34. def _pilbitmap_check():
  35. global _pilbitmap_ok
  36. if _pilbitmap_ok is None:
  37. try:
  38. im = Image.new("1", (1, 1))
  39. tkinter.BitmapImage(data=f"PIL:{im.im.id}")
  40. _pilbitmap_ok = 1
  41. except tkinter.TclError:
  42. _pilbitmap_ok = 0
  43. return _pilbitmap_ok
  44. def _get_image_from_kw(kw):
  45. source = None
  46. if "file" in kw:
  47. source = kw.pop("file")
  48. elif "data" in kw:
  49. source = BytesIO(kw.pop("data"))
  50. if source:
  51. return Image.open(source)
  52. def _pyimagingtkcall(command, photo, id):
  53. tk = photo.tk
  54. try:
  55. tk.call(command, photo, id)
  56. except tkinter.TclError:
  57. # activate Tkinter hook
  58. # may raise an error if it cannot attach to Tkinter
  59. from . import _imagingtk
  60. try:
  61. if hasattr(tk, "interp"):
  62. # Required for PyPy, which always has CFFI installed
  63. from cffi import FFI
  64. ffi = FFI()
  65. # PyPy is using an FFI CDATA element
  66. # (Pdb) self.tk.interp
  67. # <cdata 'Tcl_Interp *' 0x3061b50>
  68. _imagingtk.tkinit(int(ffi.cast("uintptr_t", tk.interp)), 1)
  69. else:
  70. _imagingtk.tkinit(tk.interpaddr(), 1)
  71. except AttributeError:
  72. _imagingtk.tkinit(id(tk), 0)
  73. tk.call(command, photo, id)
  74. # --------------------------------------------------------------------
  75. # PhotoImage
  76. class PhotoImage:
  77. """
  78. A Tkinter-compatible photo image. This can be used
  79. everywhere Tkinter expects an image object. If the image is an RGBA
  80. image, pixels having alpha 0 are treated as transparent.
  81. The constructor takes either a PIL image, or a mode and a size.
  82. Alternatively, you can use the ``file`` or ``data`` options to initialize
  83. the photo image object.
  84. :param image: Either a PIL image, or a mode string. If a mode string is
  85. used, a size must also be given.
  86. :param size: If the first argument is a mode string, this defines the size
  87. of the image.
  88. :keyword file: A filename to load the image from (using
  89. ``Image.open(file)``).
  90. :keyword data: An 8-bit string containing image data (as loaded from an
  91. image file).
  92. """
  93. def __init__(self, image=None, size=None, **kw):
  94. # Tk compatibility: file or data
  95. if image is None:
  96. image = _get_image_from_kw(kw)
  97. if hasattr(image, "mode") and hasattr(image, "size"):
  98. # got an image instead of a mode
  99. mode = image.mode
  100. if mode == "P":
  101. # palette mapped data
  102. image.load()
  103. try:
  104. mode = image.palette.mode
  105. except AttributeError:
  106. mode = "RGB" # default
  107. size = image.size
  108. kw["width"], kw["height"] = size
  109. else:
  110. mode = image
  111. image = None
  112. if mode not in ["1", "L", "RGB", "RGBA"]:
  113. mode = Image.getmodebase(mode)
  114. self.__mode = mode
  115. self.__size = size
  116. self.__photo = tkinter.PhotoImage(**kw)
  117. self.tk = self.__photo.tk
  118. if image:
  119. self.paste(image)
  120. def __del__(self):
  121. name = self.__photo.name
  122. self.__photo.name = None
  123. try:
  124. self.__photo.tk.call("image", "delete", name)
  125. except Exception:
  126. pass # ignore internal errors
  127. def __str__(self):
  128. """
  129. Get the Tkinter photo image identifier. This method is automatically
  130. called by Tkinter whenever a PhotoImage object is passed to a Tkinter
  131. method.
  132. :return: A Tkinter photo image identifier (a string).
  133. """
  134. return str(self.__photo)
  135. def width(self):
  136. """
  137. Get the width of the image.
  138. :return: The width, in pixels.
  139. """
  140. return self.__size[0]
  141. def height(self):
  142. """
  143. Get the height of the image.
  144. :return: The height, in pixels.
  145. """
  146. return self.__size[1]
  147. def paste(self, im, box=None):
  148. """
  149. Paste a PIL image into the photo image. Note that this can
  150. be very slow if the photo image is displayed.
  151. :param im: A PIL image. The size must match the target region. If the
  152. mode does not match, the image is converted to the mode of
  153. the bitmap image.
  154. :param box: Deprecated. This parameter will be removed in Pillow 10
  155. (2023-07-01).
  156. """
  157. if box is not None:
  158. deprecate("The box parameter", 10, None)
  159. # convert to blittable
  160. im.load()
  161. image = im.im
  162. if image.isblock() and im.mode == self.__mode:
  163. block = image
  164. else:
  165. block = image.new_block(self.__mode, im.size)
  166. image.convert2(block, image) # convert directly between buffers
  167. _pyimagingtkcall("PyImagingPhoto", self.__photo, block.id)
  168. # --------------------------------------------------------------------
  169. # BitmapImage
  170. class BitmapImage:
  171. """
  172. A Tkinter-compatible bitmap image. This can be used everywhere Tkinter
  173. expects an image object.
  174. The given image must have mode "1". Pixels having value 0 are treated as
  175. transparent. Options, if any, are passed on to Tkinter. The most commonly
  176. used option is ``foreground``, which is used to specify the color for the
  177. non-transparent parts. See the Tkinter documentation for information on
  178. how to specify colours.
  179. :param image: A PIL image.
  180. """
  181. def __init__(self, image=None, **kw):
  182. # Tk compatibility: file or data
  183. if image is None:
  184. image = _get_image_from_kw(kw)
  185. self.__mode = image.mode
  186. self.__size = image.size
  187. if _pilbitmap_check():
  188. # fast way (requires the pilbitmap booster patch)
  189. image.load()
  190. kw["data"] = f"PIL:{image.im.id}"
  191. self.__im = image # must keep a reference
  192. else:
  193. # slow but safe way
  194. kw["data"] = image.tobitmap()
  195. self.__photo = tkinter.BitmapImage(**kw)
  196. def __del__(self):
  197. name = self.__photo.name
  198. self.__photo.name = None
  199. try:
  200. self.__photo.tk.call("image", "delete", name)
  201. except Exception:
  202. pass # ignore internal errors
  203. def width(self):
  204. """
  205. Get the width of the image.
  206. :return: The width, in pixels.
  207. """
  208. return self.__size[0]
  209. def height(self):
  210. """
  211. Get the height of the image.
  212. :return: The height, in pixels.
  213. """
  214. return self.__size[1]
  215. def __str__(self):
  216. """
  217. Get the Tkinter bitmap image identifier. This method is automatically
  218. called by Tkinter whenever a BitmapImage object is passed to a Tkinter
  219. method.
  220. :return: A Tkinter bitmap image identifier (a string).
  221. """
  222. return str(self.__photo)
  223. def getimage(photo):
  224. """Copies the contents of a PhotoImage to a PIL image memory."""
  225. im = Image.new("RGBA", (photo.width(), photo.height()))
  226. block = im.im
  227. _pyimagingtkcall("PyImagingPhotoGet", photo, block.id)
  228. return im
  229. def _show(image, title):
  230. """Helper for the Image.show method."""
  231. class UI(tkinter.Label):
  232. def __init__(self, master, im):
  233. if im.mode == "1":
  234. self.image = BitmapImage(im, foreground="white", master=master)
  235. else:
  236. self.image = PhotoImage(im, master=master)
  237. super().__init__(master, image=self.image, bg="black", bd=0)
  238. if not tkinter._default_root:
  239. raise OSError("tkinter not initialized")
  240. top = tkinter.Toplevel()
  241. if title:
  242. top.title(title)
  243. UI(top, image).pack()