ImageTk.py 9.1 KB

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