| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import tkinter |
| | from io import BytesIO |
| |
|
| | from . import Image |
| | from ._deprecate import deprecate |
| |
|
| | |
| | |
| |
|
| | _pilbitmap_ok = None |
| |
|
| |
|
| | def _pilbitmap_check(): |
| | global _pilbitmap_ok |
| | if _pilbitmap_ok is None: |
| | try: |
| | im = Image.new("1", (1, 1)) |
| | tkinter.BitmapImage(data=f"PIL:{im.im.id}") |
| | _pilbitmap_ok = 1 |
| | except tkinter.TclError: |
| | _pilbitmap_ok = 0 |
| | return _pilbitmap_ok |
| |
|
| |
|
| | def _get_image_from_kw(kw): |
| | source = None |
| | if "file" in kw: |
| | source = kw.pop("file") |
| | elif "data" in kw: |
| | source = BytesIO(kw.pop("data")) |
| | if source: |
| | return Image.open(source) |
| |
|
| |
|
| | def _pyimagingtkcall(command, photo, id): |
| | tk = photo.tk |
| | try: |
| | tk.call(command, photo, id) |
| | except tkinter.TclError: |
| | |
| | |
| | from . import _imagingtk |
| |
|
| | _imagingtk.tkinit(tk.interpaddr()) |
| | tk.call(command, photo, id) |
| |
|
| |
|
| | |
| | |
| |
|
| |
|
| | class PhotoImage: |
| | """ |
| | A Tkinter-compatible photo image. This can be used |
| | everywhere Tkinter expects an image object. If the image is an RGBA |
| | image, pixels having alpha 0 are treated as transparent. |
| | |
| | The constructor takes either a PIL image, or a mode and a size. |
| | Alternatively, you can use the ``file`` or ``data`` options to initialize |
| | the photo image object. |
| | |
| | :param image: Either a PIL image, or a mode string. If a mode string is |
| | used, a size must also be given. |
| | :param size: If the first argument is a mode string, this defines the size |
| | of the image. |
| | :keyword file: A filename to load the image from (using |
| | ``Image.open(file)``). |
| | :keyword data: An 8-bit string containing image data (as loaded from an |
| | image file). |
| | """ |
| |
|
| | def __init__(self, image=None, size=None, **kw): |
| |
|
| | |
| | if image is None: |
| | image = _get_image_from_kw(kw) |
| |
|
| | if hasattr(image, "mode") and hasattr(image, "size"): |
| | |
| | mode = image.mode |
| | if mode == "P": |
| | |
| | image.apply_transparency() |
| | image.load() |
| | try: |
| | mode = image.palette.mode |
| | except AttributeError: |
| | mode = "RGB" |
| | size = image.size |
| | kw["width"], kw["height"] = size |
| | else: |
| | mode = image |
| | image = None |
| |
|
| | if mode not in ["1", "L", "RGB", "RGBA"]: |
| | mode = Image.getmodebase(mode) |
| |
|
| | self.__mode = mode |
| | self.__size = size |
| | self.__photo = tkinter.PhotoImage(**kw) |
| | self.tk = self.__photo.tk |
| | if image: |
| | self.paste(image) |
| |
|
| | def __del__(self): |
| | name = self.__photo.name |
| | self.__photo.name = None |
| | try: |
| | self.__photo.tk.call("image", "delete", name) |
| | except Exception: |
| | pass |
| |
|
| | def __str__(self): |
| | """ |
| | Get the Tkinter photo image identifier. This method is automatically |
| | called by Tkinter whenever a PhotoImage object is passed to a Tkinter |
| | method. |
| | |
| | :return: A Tkinter photo image identifier (a string). |
| | """ |
| | return str(self.__photo) |
| |
|
| | def width(self): |
| | """ |
| | Get the width of the image. |
| | |
| | :return: The width, in pixels. |
| | """ |
| | return self.__size[0] |
| |
|
| | def height(self): |
| | """ |
| | Get the height of the image. |
| | |
| | :return: The height, in pixels. |
| | """ |
| | return self.__size[1] |
| |
|
| | def paste(self, im, box=None): |
| | """ |
| | Paste a PIL image into the photo image. Note that this can |
| | be very slow if the photo image is displayed. |
| | |
| | :param im: A PIL image. The size must match the target region. If the |
| | mode does not match, the image is converted to the mode of |
| | the bitmap image. |
| | :param box: Deprecated. This parameter will be removed in Pillow 10 |
| | (2023-07-01). |
| | """ |
| |
|
| | if box is not None: |
| | deprecate("The box parameter", 10, None) |
| |
|
| | |
| | im.load() |
| | image = im.im |
| | if image.isblock() and im.mode == self.__mode: |
| | block = image |
| | else: |
| | block = image.new_block(self.__mode, im.size) |
| | image.convert2(block, image) |
| |
|
| | _pyimagingtkcall("PyImagingPhoto", self.__photo, block.id) |
| |
|
| |
|
| | |
| | |
| |
|
| |
|
| | class BitmapImage: |
| | """ |
| | A Tkinter-compatible bitmap image. This can be used everywhere Tkinter |
| | expects an image object. |
| | |
| | The given image must have mode "1". Pixels having value 0 are treated as |
| | transparent. Options, if any, are passed on to Tkinter. The most commonly |
| | used option is ``foreground``, which is used to specify the color for the |
| | non-transparent parts. See the Tkinter documentation for information on |
| | how to specify colours. |
| | |
| | :param image: A PIL image. |
| | """ |
| |
|
| | def __init__(self, image=None, **kw): |
| |
|
| | |
| | if image is None: |
| | image = _get_image_from_kw(kw) |
| |
|
| | self.__mode = image.mode |
| | self.__size = image.size |
| |
|
| | if _pilbitmap_check(): |
| | |
| | image.load() |
| | kw["data"] = f"PIL:{image.im.id}" |
| | self.__im = image |
| | else: |
| | |
| | kw["data"] = image.tobitmap() |
| | self.__photo = tkinter.BitmapImage(**kw) |
| |
|
| | def __del__(self): |
| | name = self.__photo.name |
| | self.__photo.name = None |
| | try: |
| | self.__photo.tk.call("image", "delete", name) |
| | except Exception: |
| | pass |
| |
|
| | def width(self): |
| | """ |
| | Get the width of the image. |
| | |
| | :return: The width, in pixels. |
| | """ |
| | return self.__size[0] |
| |
|
| | def height(self): |
| | """ |
| | Get the height of the image. |
| | |
| | :return: The height, in pixels. |
| | """ |
| | return self.__size[1] |
| |
|
| | def __str__(self): |
| | """ |
| | Get the Tkinter bitmap image identifier. This method is automatically |
| | called by Tkinter whenever a BitmapImage object is passed to a Tkinter |
| | method. |
| | |
| | :return: A Tkinter bitmap image identifier (a string). |
| | """ |
| | return str(self.__photo) |
| |
|
| |
|
| | def getimage(photo): |
| | """Copies the contents of a PhotoImage to a PIL image memory.""" |
| | im = Image.new("RGBA", (photo.width(), photo.height())) |
| | block = im.im |
| |
|
| | _pyimagingtkcall("PyImagingPhotoGet", photo, block.id) |
| |
|
| | return im |
| |
|
| |
|
| | def _show(image, title): |
| | """Helper for the Image.show method.""" |
| |
|
| | class UI(tkinter.Label): |
| | def __init__(self, master, im): |
| | if im.mode == "1": |
| | self.image = BitmapImage(im, foreground="white", master=master) |
| | else: |
| | self.image = PhotoImage(im, master=master) |
| | super().__init__(master, image=self.image, bg="black", bd=0) |
| |
|
| | if not tkinter._default_root: |
| | raise OSError("tkinter not initialized") |
| | top = tkinter.Toplevel() |
| | if title: |
| | top.title(title) |
| | UI(top, image).pack() |
| |
|