ImageTk.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. from __future__ import annotations
  28. import tkinter
  29. from io import BytesIO
  30. from typing import Any
  31. from . import Image, ImageFile
  32. TYPE_CHECKING = False
  33. if TYPE_CHECKING:
  34. from ._typing import CapsuleType
  35. # --------------------------------------------------------------------
  36. # Check for Tkinter interface hooks
  37. def _get_image_from_kw(kw: dict[str, Any]) -> ImageFile.ImageFile | None:
  38. source = None
  39. if "file" in kw:
  40. source = kw.pop("file")
  41. elif "data" in kw:
  42. source = BytesIO(kw.pop("data"))
  43. if not source:
  44. return None
  45. return Image.open(source)
  46. def _pyimagingtkcall(
  47. command: str, photo: PhotoImage | tkinter.PhotoImage, ptr: CapsuleType
  48. ) -> None:
  49. tk = photo.tk
  50. try:
  51. tk.call(command, photo, repr(ptr))
  52. except tkinter.TclError:
  53. # activate Tkinter hook
  54. # may raise an error if it cannot attach to Tkinter
  55. from . import _imagingtk
  56. _imagingtk.tkinit(tk.interpaddr())
  57. tk.call(command, photo, repr(ptr))
  58. # --------------------------------------------------------------------
  59. # PhotoImage
  60. class PhotoImage:
  61. """
  62. A Tkinter-compatible photo image. This can be used
  63. everywhere Tkinter expects an image object. If the image is an RGBA
  64. image, pixels having alpha 0 are treated as transparent.
  65. The constructor takes either a PIL image, or a mode and a size.
  66. Alternatively, you can use the ``file`` or ``data`` options to initialize
  67. the photo image object.
  68. :param image: Either a PIL image, or a mode string. If a mode string is
  69. used, a size must also be given.
  70. :param size: If the first argument is a mode string, this defines the size
  71. of the image.
  72. :keyword file: A filename to load the image from (using
  73. ``Image.open(file)``).
  74. :keyword data: An 8-bit string containing image data (as loaded from an
  75. image file).
  76. """
  77. def __init__(
  78. self,
  79. image: Image.Image | str | None = None,
  80. size: tuple[int, int] | None = None,
  81. **kw: Any,
  82. ) -> None:
  83. # Tk compatibility: file or data
  84. if image is None:
  85. image = _get_image_from_kw(kw)
  86. if image is None:
  87. msg = "Image is required"
  88. raise ValueError(msg)
  89. elif isinstance(image, str):
  90. mode = image
  91. image = None
  92. if size is None:
  93. msg = "If first argument is mode, size is required"
  94. raise ValueError(msg)
  95. else:
  96. # got an image instead of a mode
  97. mode = image.mode
  98. if mode == "P":
  99. # palette mapped data
  100. image.apply_transparency()
  101. image.load()
  102. mode = image.palette.mode if image.palette else "RGB"
  103. size = image.size
  104. kw["width"], kw["height"] = size
  105. if mode not in ["1", "L", "RGB", "RGBA"]:
  106. mode = Image.getmodebase(mode)
  107. self.__mode = mode
  108. self.__size = size
  109. self.__photo = tkinter.PhotoImage(**kw)
  110. self.tk = self.__photo.tk
  111. if image:
  112. self.paste(image)
  113. def __del__(self) -> None:
  114. try:
  115. name = self.__photo.name
  116. except AttributeError:
  117. return
  118. self.__photo.name = None
  119. try:
  120. self.__photo.tk.call("image", "delete", name)
  121. except Exception:
  122. pass # ignore internal errors
  123. def __str__(self) -> str:
  124. """
  125. Get the Tkinter photo image identifier. This method is automatically
  126. called by Tkinter whenever a PhotoImage object is passed to a Tkinter
  127. method.
  128. :return: A Tkinter photo image identifier (a string).
  129. """
  130. return str(self.__photo)
  131. def width(self) -> int:
  132. """
  133. Get the width of the image.
  134. :return: The width, in pixels.
  135. """
  136. return self.__size[0]
  137. def height(self) -> int:
  138. """
  139. Get the height of the image.
  140. :return: The height, in pixels.
  141. """
  142. return self.__size[1]
  143. def paste(self, im: Image.Image) -> None:
  144. """
  145. Paste a PIL image into the photo image. Note that this can
  146. be very slow if the photo image is displayed.
  147. :param im: A PIL image. The size must match the target region. If the
  148. mode does not match, the image is converted to the mode of
  149. the bitmap image.
  150. """
  151. # convert to blittable
  152. ptr = im.getim()
  153. image = im.im
  154. if not image.isblock() or im.mode != self.__mode:
  155. block = Image.core.new_block(self.__mode, im.size)
  156. image.convert2(block, image) # convert directly between buffers
  157. ptr = block.ptr
  158. _pyimagingtkcall("PyImagingPhoto", self.__photo, ptr)
  159. # --------------------------------------------------------------------
  160. # BitmapImage
  161. class BitmapImage:
  162. """
  163. A Tkinter-compatible bitmap image. This can be used everywhere Tkinter
  164. expects an image object.
  165. The given image must have mode "1". Pixels having value 0 are treated as
  166. transparent. Options, if any, are passed on to Tkinter. The most commonly
  167. used option is ``foreground``, which is used to specify the color for the
  168. non-transparent parts. See the Tkinter documentation for information on
  169. how to specify colours.
  170. :param image: A PIL image.
  171. """
  172. def __init__(self, image: Image.Image | None = None, **kw: Any) -> None:
  173. # Tk compatibility: file or data
  174. if image is None:
  175. image = _get_image_from_kw(kw)
  176. if image is None:
  177. msg = "Image is required"
  178. raise ValueError(msg)
  179. self.__mode = image.mode
  180. self.__size = image.size
  181. self.__photo = tkinter.BitmapImage(data=image.tobitmap(), **kw)
  182. def __del__(self) -> None:
  183. try:
  184. name = self.__photo.name
  185. except AttributeError:
  186. return
  187. self.__photo.name = None
  188. try:
  189. self.__photo.tk.call("image", "delete", name)
  190. except Exception:
  191. pass # ignore internal errors
  192. def width(self) -> int:
  193. """
  194. Get the width of the image.
  195. :return: The width, in pixels.
  196. """
  197. return self.__size[0]
  198. def height(self) -> int:
  199. """
  200. Get the height of the image.
  201. :return: The height, in pixels.
  202. """
  203. return self.__size[1]
  204. def __str__(self) -> str:
  205. """
  206. Get the Tkinter bitmap image identifier. This method is automatically
  207. called by Tkinter whenever a BitmapImage object is passed to a Tkinter
  208. method.
  209. :return: A Tkinter bitmap image identifier (a string).
  210. """
  211. return str(self.__photo)
  212. def getimage(photo: PhotoImage) -> Image.Image:
  213. """Copies the contents of a PhotoImage to a PIL image memory."""
  214. im = Image.new("RGBA", (photo.width(), photo.height()))
  215. _pyimagingtkcall("PyImagingPhotoGet", photo, im.getim())
  216. return im