Pillow/PIL/ImageWin.py
2013-03-07 11:20:28 -05:00

235 lines
6.7 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.
#
import warnings
from PIL 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 byte data.
#
# @param buffer A buffer containing display data (usually
# data returned from <b>tobytes</b>)
def frombytes(self, buffer):
return self.image.frombytes(buffer)
##
# Copy display memory contents to bytes object.
#
# @return A bytes object containing display data.
def tobytes(self):
return self.image.tobytes()
##
# Deprecated aliases to frombytes & tobytes.
def fromstring(self, *args, **kw):
warnings.warn(
'fromstring() is deprecated. Please call frombytes() instead.',
DeprecationWarning,
stacklevel=2
)
return self.frombytes(*args, **kw)
def tostring(self):
warnings.warn(
'tostring() is deprecated. Please call tobytes() instead.',
DeprecationWarning,
stacklevel=2
)
return self.tobytes()
##
# 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 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))