| # | 
| # 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. | 
| # | 
|   | 
| import Image | 
|   | 
| ## | 
| # The <b>ImageWin</b> module contains support to create and display | 
| # images under Windows 95/98, NT, 2000 and later. | 
|   | 
| class HDC: | 
|     def __init__(self, dc): | 
|         self.dc = dc | 
|     def __int__(self): | 
|         return self.dc | 
|   | 
| class HWND: | 
|     def __init__(self, wnd): | 
|         self.wnd = wnd | 
|     def __int__(self): | 
|         return self.wnd | 
|   | 
| ## | 
| # Create 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 <b>palette</b> method upon certain events from Windows. | 
|   | 
| class Dib: | 
|   | 
|     ## | 
|     # Create Windows bitmap. | 
|     # | 
|     # @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) | 
|   | 
|     ## | 
|     # Copy the bitmap contents to a device context. | 
|     # | 
|     # @param handle Device context (HDC), cast to a Python integer, | 
|     #    or a HDC or HWND instance.  In PythonWin, you can use the | 
|     #    <b>GetHandleAttrib</b> method of the <b>CDC</b> class to get | 
|     #    a suitable handle. | 
|   | 
|     def expose(self, 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): | 
|         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 | 
|   | 
|     ## | 
|     # Installs the palette associated with the image in the | 
|     # given device context. | 
|     # <p> | 
|     # This method should be called upon <b>QUERYNEWPALETTE</b> | 
|     # and <b>PALETTECHANGED</b> 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). | 
|   | 
|     def query_palette(self, handle): | 
|         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 | 
|   | 
|     ## | 
|     # 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. | 
|   | 
|     def paste(self, im, box=None): | 
|         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) | 
|   | 
|     ## | 
|     # Load display memory contents from string buffer. | 
|     # | 
|     # @param buffer A string buffer containing display data (usually | 
|     #     data returned from <b>tostring</b>) | 
|   | 
|     def fromstring(self, buffer): | 
|         return self.image.fromstring(buffer) | 
|   | 
|     ## | 
|     # Copy display memory contents to string buffer. | 
|     # | 
|     # @return A string buffer containing display data. | 
|   | 
|     def tostring(self): | 
|         return self.image.tostring() | 
|   | 
|   | 
| ## | 
| # Create a Window with the given title size. | 
|   | 
| class Window: | 
|   | 
|     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 apply(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() | 
|   | 
| ## | 
| # Create an image window which displays the given image. | 
|   | 
| class ImageWindow(Window): | 
|   | 
|     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)) |