ImageTk.py 8.3 KB

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