216 lines
6.2 KiB
Python
216 lines
6.2 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 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))
|