mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 16:07:30 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			236 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			236 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #
 | |
| # The Python Imaging Library.
 | |
| # $Id$
 | |
| #
 | |
| # a Windows DIB display interface
 | |
| #
 | |
| # History:
 | |
| # 1996-05-20 fl   Created
 | |
| # 1996-09-20 fl   Fixed subregion exposure
 | |
| # 1997-09-21 fl   Added draw primitive (for tzPrint)
 | |
| # 2003-05-21 fl   Added experimental Window/ImageWindow classes
 | |
| # 2003-09-05 fl   Added fromstring/tostring methods
 | |
| #
 | |
| # Copyright (c) Secret Labs AB 1997-2003.
 | |
| # Copyright (c) Fredrik Lundh 1996-2003.
 | |
| #
 | |
| # See the README file for information on usage and redistribution.
 | |
| #
 | |
| 
 | |
| from PIL import Image
 | |
| 
 | |
| 
 | |
| class HDC(object):
 | |
|     """
 | |
|     Wraps an HDC integer. The resulting object can be passed to the
 | |
|     :py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
 | |
|     methods.
 | |
|     """
 | |
|     def __init__(self, dc):
 | |
|         self.dc = dc
 | |
| 
 | |
|     def __int__(self):
 | |
|         return self.dc
 | |
| 
 | |
| 
 | |
| class HWND(object):
 | |
|     """
 | |
|     Wraps an HWND integer. The resulting object can be passed to the
 | |
|     :py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
 | |
|     methods, instead of a DC.
 | |
|     """
 | |
|     def __init__(self, wnd):
 | |
|         self.wnd = wnd
 | |
| 
 | |
|     def __int__(self):
 | |
|         return self.wnd
 | |
| 
 | |
| 
 | |
| class Dib(object):
 | |
|     """
 | |
|     A Windows bitmap with the given mode and size.  The mode can be one of "1",
 | |
|     "L", "P", or "RGB".
 | |
| 
 | |
|     If the display requires a palette, this constructor creates a suitable
 | |
|     palette and associates it with the image. For an "L" image, 128 greylevels
 | |
|     are allocated. For an "RGB" image, a 6x6x6 colour cube is used, together
 | |
|     with 20 greylevels.
 | |
| 
 | |
|     To make sure that palettes work properly under Windows, you must call the
 | |
|     **palette** method upon certain events from Windows.
 | |
| 
 | |
|     :param image: Either a PIL image, or a mode string. If a mode string is
 | |
|                   used, a size must also be given.  The mode can be one of "1",
 | |
|                   "L", "P", or "RGB".
 | |
|     :param size: If the first argument is a mode string, this
 | |
|                  defines the size of the image.
 | |
|     """
 | |
| 
 | |
|     def __init__(self, image, size=None):
 | |
|         if hasattr(image, "mode") and hasattr(image, "size"):
 | |
|             mode = image.mode
 | |
|             size = image.size
 | |
|         else:
 | |
|             mode = image
 | |
|             image = None
 | |
|         if mode not in ["1", "L", "P", "RGB"]:
 | |
|             mode = Image.getmodebase(mode)
 | |
|         self.image = Image.core.display(mode, size)
 | |
|         self.mode = mode
 | |
|         self.size = size
 | |
|         if image:
 | |
|             self.paste(image)
 | |
| 
 | |
|     def expose(self, handle):
 | |
|         """
 | |
|         Copy the bitmap contents to a device context.
 | |
| 
 | |
|         :param handle: Device context (HDC), cast to a Python integer, or an
 | |
|                        HDC or HWND instance.  In PythonWin, you can use the
 | |
|                        :py:meth:`CDC.GetHandleAttrib` to get a suitable handle.
 | |
|         """
 | |
|         if isinstance(handle, HWND):
 | |
|             dc = self.image.getdc(handle)
 | |
|             try:
 | |
|                 result = self.image.expose(dc)
 | |
|             finally:
 | |
|                 self.image.releasedc(handle, dc)
 | |
|         else:
 | |
|             result = self.image.expose(handle)
 | |
|         return result
 | |
| 
 | |
|     def draw(self, handle, dst, src=None):
 | |
|         """
 | |
|         Same as expose, but allows you to specify where to draw the image, and
 | |
|         what part of it to draw.
 | |
| 
 | |
|         The destination and source areas are given as 4-tuple rectangles. If
 | |
|         the source is omitted, the entire image is copied. If the source and
 | |
|         the destination have different sizes, the image is resized as
 | |
|         necessary.
 | |
|         """
 | |
|         if not src:
 | |
|             src = (0, 0) + self.size
 | |
|         if isinstance(handle, HWND):
 | |
|             dc = self.image.getdc(handle)
 | |
|             try:
 | |
|                 result = self.image.draw(dc, dst, src)
 | |
|             finally:
 | |
|                 self.image.releasedc(handle, dc)
 | |
|         else:
 | |
|             result = self.image.draw(handle, dst, src)
 | |
|         return result
 | |
| 
 | |
|     def query_palette(self, handle):
 | |
|         """
 | |
|         Installs the palette associated with the image in the given device
 | |
|         context.
 | |
| 
 | |
|         This method should be called upon **QUERYNEWPALETTE** and
 | |
|         **PALETTECHANGED** events from Windows. If this method returns a
 | |
|         non-zero value, one or more display palette entries were changed, and
 | |
|         the image should be redrawn.
 | |
| 
 | |
|         :param handle: Device context (HDC), cast to a Python integer, or an
 | |
|                        HDC or HWND instance.
 | |
|         :return: A true value if one or more entries were changed (this
 | |
|                  indicates that the image should be redrawn).
 | |
|         """
 | |
|         if isinstance(handle, HWND):
 | |
|             handle = self.image.getdc(handle)
 | |
|             try:
 | |
|                 result = self.image.query_palette(handle)
 | |
|             finally:
 | |
|                 self.image.releasedc(handle, handle)
 | |
|         else:
 | |
|             result = self.image.query_palette(handle)
 | |
|         return result
 | |
| 
 | |
|     def paste(self, im, box=None):
 | |
|         """
 | |
|         Paste a PIL image into the bitmap image.
 | |
| 
 | |
|         :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: A 4-tuple defining the left, upper, right, and
 | |
|                     lower pixel coordinate.  If None is given instead of a
 | |
|                     tuple, all of the image is assumed.
 | |
|         """
 | |
|         im.load()
 | |
|         if self.mode != im.mode:
 | |
|             im = im.convert(self.mode)
 | |
|         if box:
 | |
|             self.image.paste(im.im, box)
 | |
|         else:
 | |
|             self.image.paste(im.im)
 | |
| 
 | |
|     def frombytes(self, buffer):
 | |
|         """
 | |
|         Load display memory contents from byte data.
 | |
| 
 | |
|         :param buffer: A buffer containing display data (usually
 | |
|                        data returned from <b>tobytes</b>)
 | |
|         """
 | |
|         return self.image.frombytes(buffer)
 | |
| 
 | |
|     def tobytes(self):
 | |
|         """
 | |
|         Copy display memory contents to bytes object.
 | |
| 
 | |
|         :return: A bytes object containing display data.
 | |
|         """
 | |
|         return self.image.tobytes()
 | |
| 
 | |
|     def fromstring(self, *args, **kw):
 | |
|         raise NotImplementedError("fromstring() has been removed. " +
 | |
|                                   "Please use frombytes() instead.")
 | |
| 
 | |
|     def tostring(self, *args, **kw):
 | |
|         raise NotImplementedError("tostring() has been removed. " +
 | |
|                                   "Please use tobytes() instead.")
 | |
| 
 | |
| 
 | |
| class Window(object):
 | |
|     """Create a Window with the given title size."""
 | |
| 
 | |
|     def __init__(self, title="PIL", width=None, height=None):
 | |
|         self.hwnd = Image.core.createwindow(
 | |
|             title, self.__dispatcher, width or 0, height or 0
 | |
|             )
 | |
| 
 | |
|     def __dispatcher(self, action, *args):
 | |
|         return getattr(self, "ui_handle_" + action)(*args)
 | |
| 
 | |
|     def ui_handle_clear(self, dc, x0, y0, x1, y1):
 | |
|         pass
 | |
| 
 | |
|     def ui_handle_damage(self, x0, y0, x1, y1):
 | |
|         pass
 | |
| 
 | |
|     def ui_handle_destroy(self):
 | |
|         pass
 | |
| 
 | |
|     def ui_handle_repair(self, dc, x0, y0, x1, y1):
 | |
|         pass
 | |
| 
 | |
|     def ui_handle_resize(self, width, height):
 | |
|         pass
 | |
| 
 | |
|     def mainloop(self):
 | |
|         Image.core.eventloop()
 | |
| 
 | |
| 
 | |
| class ImageWindow(Window):
 | |
|     """Create an image window which displays the given image."""
 | |
| 
 | |
|     def __init__(self, image, title="PIL"):
 | |
|         if not isinstance(image, Dib):
 | |
|             image = Dib(image)
 | |
|         self.image = image
 | |
|         width, height = image.size
 | |
|         Window.__init__(self, title, width=width, height=height)
 | |
| 
 | |
|     def ui_handle_repair(self, dc, x0, y0, x1, y1):
 | |
|         self.image.draw(dc, (x0, y0, x1, y1))
 |