Open Media Library Platform
This commit is contained in:
commit
411ad5b16f
5849 changed files with 1778641 additions and 0 deletions
504
Darwin/lib/python2.7/site-packages/PIL/ArgImagePlugin.py
Normal file
504
Darwin/lib/python2.7/site-packages/PIL/ArgImagePlugin.py
Normal file
|
|
@ -0,0 +1,504 @@
|
|||
#
|
||||
# THIS IS WORK IN PROGRESS
|
||||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# ARG animation support code
|
||||
#
|
||||
# history:
|
||||
# 1996-12-30 fl Created
|
||||
# 1996-01-06 fl Added safe scripting environment
|
||||
# 1996-01-10 fl Added JHDR, UHDR and sYNC support
|
||||
# 2005-03-02 fl Removed AAPP and ARUN support
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1996-97.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.4"
|
||||
|
||||
import Image, ImageFile, ImagePalette
|
||||
|
||||
from PngImagePlugin import i16, i32, ChunkStream, _MODES
|
||||
|
||||
MAGIC = "\212ARG\r\n\032\n"
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# ARG parser
|
||||
|
||||
class ArgStream(ChunkStream):
|
||||
"Parser callbacks for ARG data"
|
||||
|
||||
def __init__(self, fp):
|
||||
|
||||
ChunkStream.__init__(self, fp)
|
||||
|
||||
self.eof = 0
|
||||
|
||||
self.im = None
|
||||
self.palette = None
|
||||
|
||||
self.__reset()
|
||||
|
||||
def __reset(self):
|
||||
|
||||
# reset decoder state (called on init and sync)
|
||||
|
||||
self.count = 0
|
||||
self.id = None
|
||||
self.action = ("NONE",)
|
||||
|
||||
self.images = {}
|
||||
self.names = {}
|
||||
|
||||
|
||||
def chunk_AHDR(self, offset, bytes):
|
||||
"AHDR -- animation header"
|
||||
|
||||
# assertions
|
||||
if self.count != 0:
|
||||
raise SyntaxError, "misplaced AHDR chunk"
|
||||
|
||||
s = self.fp.read(bytes)
|
||||
self.size = i32(s), i32(s[4:])
|
||||
try:
|
||||
self.mode, self.rawmode = _MODES[(ord(s[8]), ord(s[9]))]
|
||||
except:
|
||||
raise SyntaxError, "unknown ARG mode"
|
||||
|
||||
if Image.DEBUG:
|
||||
print "AHDR size", self.size
|
||||
print "AHDR mode", self.mode, self.rawmode
|
||||
|
||||
return s
|
||||
|
||||
def chunk_AFRM(self, offset, bytes):
|
||||
"AFRM -- next frame follows"
|
||||
|
||||
# assertions
|
||||
if self.count != 0:
|
||||
raise SyntaxError, "misplaced AFRM chunk"
|
||||
|
||||
self.show = 1
|
||||
self.id = 0
|
||||
self.count = 1
|
||||
self.repair = None
|
||||
|
||||
s = self.fp.read(bytes)
|
||||
if len(s) >= 2:
|
||||
self.id = i16(s)
|
||||
if len(s) >= 4:
|
||||
self.count = i16(s[2:4])
|
||||
if len(s) >= 6:
|
||||
self.repair = i16(s[4:6])
|
||||
else:
|
||||
self.repair = None
|
||||
|
||||
if Image.DEBUG:
|
||||
print "AFRM", self.id, self.count
|
||||
|
||||
return s
|
||||
|
||||
def chunk_ADEF(self, offset, bytes):
|
||||
"ADEF -- store image"
|
||||
|
||||
# assertions
|
||||
if self.count != 0:
|
||||
raise SyntaxError, "misplaced ADEF chunk"
|
||||
|
||||
self.show = 0
|
||||
self.id = 0
|
||||
self.count = 1
|
||||
self.repair = None
|
||||
|
||||
s = self.fp.read(bytes)
|
||||
if len(s) >= 2:
|
||||
self.id = i16(s)
|
||||
if len(s) >= 4:
|
||||
self.count = i16(s[2:4])
|
||||
|
||||
if Image.DEBUG:
|
||||
print "ADEF", self.id, self.count
|
||||
|
||||
return s
|
||||
|
||||
def chunk_NAME(self, offset, bytes):
|
||||
"NAME -- name the current image"
|
||||
|
||||
# assertions
|
||||
if self.count == 0:
|
||||
raise SyntaxError, "misplaced NAME chunk"
|
||||
|
||||
name = self.fp.read(bytes)
|
||||
self.names[self.id] = name
|
||||
|
||||
return name
|
||||
|
||||
def chunk_AEND(self, offset, bytes):
|
||||
"AEND -- end of animation"
|
||||
|
||||
if Image.DEBUG:
|
||||
print "AEND"
|
||||
|
||||
self.eof = 1
|
||||
|
||||
raise EOFError, "end of ARG file"
|
||||
|
||||
def __getmodesize(self, s, full=1):
|
||||
|
||||
size = i32(s), i32(s[4:])
|
||||
|
||||
try:
|
||||
mode, rawmode = _MODES[(ord(s[8]), ord(s[9]))]
|
||||
except:
|
||||
raise SyntaxError, "unknown image mode"
|
||||
|
||||
if full:
|
||||
if ord(s[12]):
|
||||
pass # interlace not yet supported
|
||||
if ord(s[11]):
|
||||
raise SyntaxError, "unknown filter category"
|
||||
|
||||
return size, mode, rawmode
|
||||
|
||||
def chunk_PAST(self, offset, bytes):
|
||||
"PAST -- paste one image into another"
|
||||
|
||||
# assertions
|
||||
if self.count == 0:
|
||||
raise SyntaxError, "misplaced PAST chunk"
|
||||
|
||||
if self.repair is not None:
|
||||
# we must repair the target image before we
|
||||
# start pasting
|
||||
|
||||
# brute force; a better solution would be to
|
||||
# update only the dirty rectangles in images[id].
|
||||
# note that if images[id] doesn't exist, it must
|
||||
# be created
|
||||
|
||||
self.images[self.id] = self.images[self.repair].copy()
|
||||
self.repair = None
|
||||
|
||||
s = self.fp.read(bytes)
|
||||
im = self.images[i16(s)]
|
||||
x, y = i32(s[2:6]), i32(s[6:10])
|
||||
bbox = x, y, im.size[0]+x, im.size[1]+y
|
||||
|
||||
if im.mode in ["RGBA"]:
|
||||
# paste with transparency
|
||||
# FIXME: should handle P+transparency as well
|
||||
self.images[self.id].paste(im, bbox, im)
|
||||
else:
|
||||
# paste without transparency
|
||||
self.images[self.id].paste(im, bbox)
|
||||
|
||||
self.action = ("PAST",)
|
||||
self.__store()
|
||||
|
||||
return s
|
||||
|
||||
def chunk_BLNK(self, offset, bytes):
|
||||
"BLNK -- create blank image"
|
||||
|
||||
# assertions
|
||||
if self.count == 0:
|
||||
raise SyntaxError, "misplaced BLNK chunk"
|
||||
|
||||
s = self.fp.read(bytes)
|
||||
size, mode, rawmode = self.__getmodesize(s, 0)
|
||||
|
||||
# store image (FIXME: handle colour)
|
||||
self.action = ("BLNK",)
|
||||
self.im = Image.core.fill(mode, size, 0)
|
||||
self.__store()
|
||||
|
||||
return s
|
||||
|
||||
def chunk_IHDR(self, offset, bytes):
|
||||
"IHDR -- full image follows"
|
||||
|
||||
# assertions
|
||||
if self.count == 0:
|
||||
raise SyntaxError, "misplaced IHDR chunk"
|
||||
|
||||
# image header
|
||||
s = self.fp.read(bytes)
|
||||
size, mode, rawmode = self.__getmodesize(s)
|
||||
|
||||
# decode and store image
|
||||
self.action = ("IHDR",)
|
||||
self.im = Image.core.new(mode, size)
|
||||
self.decoder = Image.core.zip_decoder(rawmode)
|
||||
self.decoder.setimage(self.im, (0,0) + size)
|
||||
self.data = ""
|
||||
|
||||
return s
|
||||
|
||||
def chunk_DHDR(self, offset, bytes):
|
||||
"DHDR -- delta image follows"
|
||||
|
||||
# assertions
|
||||
if self.count == 0:
|
||||
raise SyntaxError, "misplaced DHDR chunk"
|
||||
|
||||
s = self.fp.read(bytes)
|
||||
|
||||
size, mode, rawmode = self.__getmodesize(s)
|
||||
|
||||
# delta header
|
||||
diff = ord(s[13])
|
||||
offs = i32(s[14:18]), i32(s[18:22])
|
||||
|
||||
bbox = offs + (offs[0]+size[0], offs[1]+size[1])
|
||||
|
||||
if Image.DEBUG:
|
||||
print "DHDR", diff, bbox
|
||||
|
||||
# FIXME: decode and apply image
|
||||
self.action = ("DHDR", diff, bbox)
|
||||
|
||||
# setup decoder
|
||||
self.im = Image.core.new(mode, size)
|
||||
|
||||
self.decoder = Image.core.zip_decoder(rawmode)
|
||||
self.decoder.setimage(self.im, (0,0) + size)
|
||||
|
||||
self.data = ""
|
||||
|
||||
return s
|
||||
|
||||
def chunk_JHDR(self, offset, bytes):
|
||||
"JHDR -- JPEG image follows"
|
||||
|
||||
# assertions
|
||||
if self.count == 0:
|
||||
raise SyntaxError, "misplaced JHDR chunk"
|
||||
|
||||
# image header
|
||||
s = self.fp.read(bytes)
|
||||
size, mode, rawmode = self.__getmodesize(s, 0)
|
||||
|
||||
# decode and store image
|
||||
self.action = ("JHDR",)
|
||||
self.im = Image.core.new(mode, size)
|
||||
self.decoder = Image.core.jpeg_decoder(rawmode)
|
||||
self.decoder.setimage(self.im, (0,0) + size)
|
||||
self.data = ""
|
||||
|
||||
return s
|
||||
|
||||
def chunk_UHDR(self, offset, bytes):
|
||||
"UHDR -- uncompressed image data follows (EXPERIMENTAL)"
|
||||
|
||||
# assertions
|
||||
if self.count == 0:
|
||||
raise SyntaxError, "misplaced UHDR chunk"
|
||||
|
||||
# image header
|
||||
s = self.fp.read(bytes)
|
||||
size, mode, rawmode = self.__getmodesize(s, 0)
|
||||
|
||||
# decode and store image
|
||||
self.action = ("UHDR",)
|
||||
self.im = Image.core.new(mode, size)
|
||||
self.decoder = Image.core.raw_decoder(rawmode)
|
||||
self.decoder.setimage(self.im, (0,0) + size)
|
||||
self.data = ""
|
||||
|
||||
return s
|
||||
|
||||
def chunk_IDAT(self, offset, bytes):
|
||||
"IDAT -- image data block"
|
||||
|
||||
# pass compressed chunks through the decoder
|
||||
s = self.fp.read(bytes)
|
||||
self.data = self.data + s
|
||||
n, e = self.decoder.decode(self.data)
|
||||
if n < 0:
|
||||
# end of image
|
||||
if e < 0:
|
||||
raise IOError, "decoder error %d" % e
|
||||
else:
|
||||
self.data = self.data[n:]
|
||||
|
||||
return s
|
||||
|
||||
def chunk_DEND(self, offset, bytes):
|
||||
return self.chunk_IEND(offset, bytes)
|
||||
|
||||
def chunk_JEND(self, offset, bytes):
|
||||
return self.chunk_IEND(offset, bytes)
|
||||
|
||||
def chunk_UEND(self, offset, bytes):
|
||||
return self.chunk_IEND(offset, bytes)
|
||||
|
||||
def chunk_IEND(self, offset, bytes):
|
||||
"IEND -- end of image"
|
||||
|
||||
# we now have a new image. carry out the operation
|
||||
# defined by the image header.
|
||||
|
||||
# won't need these anymore
|
||||
del self.decoder
|
||||
del self.data
|
||||
|
||||
self.__store()
|
||||
|
||||
return self.fp.read(bytes)
|
||||
|
||||
def __store(self):
|
||||
|
||||
# apply operation
|
||||
cid = self.action[0]
|
||||
|
||||
if cid in ["BLNK", "IHDR", "JHDR", "UHDR"]:
|
||||
# store
|
||||
self.images[self.id] = self.im
|
||||
|
||||
elif cid == "DHDR":
|
||||
# paste
|
||||
cid, mode, bbox = self.action
|
||||
im0 = self.images[self.id]
|
||||
im1 = self.im
|
||||
if mode == 0:
|
||||
im1 = im1.chop_add_modulo(im0.crop(bbox))
|
||||
im0.paste(im1, bbox)
|
||||
|
||||
self.count = self.count - 1
|
||||
|
||||
if self.count == 0 and self.show:
|
||||
self.im = self.images[self.id]
|
||||
raise EOFError # end of this frame
|
||||
|
||||
def chunk_PLTE(self, offset, bytes):
|
||||
"PLTE -- palette data"
|
||||
|
||||
s = self.fp.read(bytes)
|
||||
if self.mode == "P":
|
||||
self.palette = ImagePalette.raw("RGB", s)
|
||||
return s
|
||||
|
||||
def chunk_sYNC(self, offset, bytes):
|
||||
"SYNC -- reset decoder"
|
||||
|
||||
if self.count != 0:
|
||||
raise SyntaxError, "misplaced sYNC chunk"
|
||||
|
||||
s = self.fp.read(bytes)
|
||||
self.__reset()
|
||||
return s
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# ARG reader
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:8] == MAGIC
|
||||
|
||||
##
|
||||
# Image plugin for the experimental Animated Raster Graphics format.
|
||||
|
||||
class ArgImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "ARG"
|
||||
format_description = "Animated raster graphics"
|
||||
|
||||
def _open(self):
|
||||
|
||||
if Image.warnings:
|
||||
Image.warnings.warn(
|
||||
"The ArgImagePlugin driver is obsolete, and will be removed "
|
||||
"from a future release of PIL. If you rely on this module, "
|
||||
"please contact the PIL authors.",
|
||||
RuntimeWarning
|
||||
)
|
||||
|
||||
if self.fp.read(8) != MAGIC:
|
||||
raise SyntaxError, "not an ARG file"
|
||||
|
||||
self.arg = ArgStream(self.fp)
|
||||
|
||||
# read and process the first chunk (AHDR)
|
||||
|
||||
cid, offset, bytes = self.arg.read()
|
||||
|
||||
if cid != "AHDR":
|
||||
raise SyntaxError, "expected an AHDR chunk"
|
||||
|
||||
s = self.arg.call(cid, offset, bytes)
|
||||
|
||||
self.arg.crc(cid, s)
|
||||
|
||||
# image characteristics
|
||||
self.mode = self.arg.mode
|
||||
self.size = self.arg.size
|
||||
|
||||
def load(self):
|
||||
|
||||
if self.arg.im is None:
|
||||
self.seek(0)
|
||||
|
||||
# image data
|
||||
self.im = self.arg.im
|
||||
self.palette = self.arg.palette
|
||||
|
||||
# set things up for further processing
|
||||
Image.Image.load(self)
|
||||
|
||||
def seek(self, frame):
|
||||
|
||||
if self.arg.eof:
|
||||
raise EOFError, "end of animation"
|
||||
|
||||
self.fp = self.arg.fp
|
||||
|
||||
while 1:
|
||||
|
||||
#
|
||||
# process chunks
|
||||
|
||||
cid, offset, bytes = self.arg.read()
|
||||
|
||||
if self.arg.eof:
|
||||
raise EOFError, "end of animation"
|
||||
|
||||
try:
|
||||
s = self.arg.call(cid, offset, bytes)
|
||||
except EOFError:
|
||||
break
|
||||
|
||||
except "glurk": # AttributeError
|
||||
if Image.DEBUG:
|
||||
print cid, bytes, "(unknown)"
|
||||
s = self.fp.read(bytes)
|
||||
|
||||
self.arg.crc(cid, s)
|
||||
|
||||
self.fp.read(4) # ship extra CRC
|
||||
|
||||
def tell(self):
|
||||
return 0
|
||||
|
||||
def verify(self):
|
||||
"Verify ARG file"
|
||||
|
||||
# back up to first chunk
|
||||
self.fp.seek(8)
|
||||
|
||||
self.arg.verify(self)
|
||||
self.arg.close()
|
||||
|
||||
self.fp = None
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("ARG", ArgImageFile, _accept)
|
||||
|
||||
Image.register_extension("ARG", ".arg")
|
||||
|
||||
Image.register_mime("ARG", "video/x-arg")
|
||||
133
Darwin/lib/python2.7/site-packages/PIL/BdfFontFile.py
Normal file
133
Darwin/lib/python2.7/site-packages/PIL/BdfFontFile.py
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# bitmap distribution font (bdf) file parser
|
||||
#
|
||||
# history:
|
||||
# 1996-05-16 fl created (as bdf2pil)
|
||||
# 1997-08-25 fl converted to FontFile driver
|
||||
# 2001-05-25 fl removed bogus __init__ call
|
||||
# 2002-11-20 fl robustification (from Kevin Cazabon, Dmitry Vasiliev)
|
||||
# 2003-04-22 fl more robustification (from Graham Dumpleton)
|
||||
#
|
||||
# Copyright (c) 1997-2003 by Secret Labs AB.
|
||||
# Copyright (c) 1997-2003 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
import FontFile
|
||||
|
||||
import string
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# parse X Bitmap Distribution Format (BDF)
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
bdf_slant = {
|
||||
"R": "Roman",
|
||||
"I": "Italic",
|
||||
"O": "Oblique",
|
||||
"RI": "Reverse Italic",
|
||||
"RO": "Reverse Oblique",
|
||||
"OT": "Other"
|
||||
}
|
||||
|
||||
bdf_spacing = {
|
||||
"P": "Proportional",
|
||||
"M": "Monospaced",
|
||||
"C": "Cell"
|
||||
}
|
||||
|
||||
def bdf_char(f):
|
||||
|
||||
# skip to STARTCHAR
|
||||
while 1:
|
||||
s = f.readline()
|
||||
if not s:
|
||||
return None
|
||||
if s[:9] == "STARTCHAR":
|
||||
break
|
||||
id = string.strip(s[9:])
|
||||
|
||||
# load symbol properties
|
||||
props = {}
|
||||
while 1:
|
||||
s = f.readline()
|
||||
if not s or s[:6] == "BITMAP":
|
||||
break
|
||||
i = string.find(s, " ")
|
||||
props[s[:i]] = s[i+1:-1]
|
||||
|
||||
# load bitmap
|
||||
bitmap = []
|
||||
while 1:
|
||||
s = f.readline()
|
||||
if not s or s[:7] == "ENDCHAR":
|
||||
break
|
||||
bitmap.append(s[:-1])
|
||||
bitmap = string.join(bitmap, "")
|
||||
|
||||
[x, y, l, d] = map(int, string.split(props["BBX"]))
|
||||
[dx, dy] = map(int, string.split(props["DWIDTH"]))
|
||||
|
||||
bbox = (dx, dy), (l, -d-y, x+l, -d), (0, 0, x, y)
|
||||
|
||||
try:
|
||||
im = Image.fromstring("1", (x, y), bitmap, "hex", "1")
|
||||
except ValueError:
|
||||
# deal with zero-width characters
|
||||
im = Image.new("1", (x, y))
|
||||
|
||||
return id, int(props["ENCODING"]), bbox, im
|
||||
|
||||
##
|
||||
# Font file plugin for the X11 BDF format.
|
||||
|
||||
class BdfFontFile(FontFile.FontFile):
|
||||
|
||||
def __init__(self, fp):
|
||||
|
||||
FontFile.FontFile.__init__(self)
|
||||
|
||||
s = fp.readline()
|
||||
if s[:13] != "STARTFONT 2.1":
|
||||
raise SyntaxError, "not a valid BDF file"
|
||||
|
||||
props = {}
|
||||
comments = []
|
||||
|
||||
while 1:
|
||||
s = fp.readline()
|
||||
if not s or s[:13] == "ENDPROPERTIES":
|
||||
break
|
||||
i = string.find(s, " ")
|
||||
props[s[:i]] = s[i+1:-1]
|
||||
if s[:i] in ["COMMENT", "COPYRIGHT"]:
|
||||
if string.find(s, "LogicalFontDescription") < 0:
|
||||
comments.append(s[i+1:-1])
|
||||
|
||||
font = string.split(props["FONT"], "-")
|
||||
|
||||
font[4] = bdf_slant[string.upper(font[4])]
|
||||
font[11] = bdf_spacing[string.upper(font[11])]
|
||||
|
||||
ascent = int(props["FONT_ASCENT"])
|
||||
descent = int(props["FONT_DESCENT"])
|
||||
|
||||
fontname = string.join(font[1:], ";")
|
||||
|
||||
# print "#", fontname
|
||||
# for i in comments:
|
||||
# print "#", i
|
||||
|
||||
font = []
|
||||
while 1:
|
||||
c = bdf_char(fp)
|
||||
if not c:
|
||||
break
|
||||
id, ch, (xy, dst, src), im = c
|
||||
if ch >= 0 and ch < len(self.glyph):
|
||||
self.glyph[ch] = xy, dst, src, im
|
||||
251
Darwin/lib/python2.7/site-packages/PIL/BmpImagePlugin.py
Normal file
251
Darwin/lib/python2.7/site-packages/PIL/BmpImagePlugin.py
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# BMP file handler
|
||||
#
|
||||
# Windows (and OS/2) native bitmap storage format.
|
||||
#
|
||||
# history:
|
||||
# 1995-09-01 fl Created
|
||||
# 1996-04-30 fl Added save
|
||||
# 1997-08-27 fl Fixed save of 1-bit images
|
||||
# 1998-03-06 fl Load P images as L where possible
|
||||
# 1998-07-03 fl Load P images as 1 where possible
|
||||
# 1998-12-29 fl Handle small palettes
|
||||
# 2002-12-30 fl Fixed load of 1-bit palette images
|
||||
# 2003-04-21 fl Fixed load of 1-bit monochrome images
|
||||
# 2003-04-23 fl Added limited support for BI_BITFIELDS compression
|
||||
#
|
||||
# Copyright (c) 1997-2003 by Secret Labs AB
|
||||
# Copyright (c) 1995-2003 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.7"
|
||||
|
||||
|
||||
import string
|
||||
import Image, ImageFile, ImagePalette
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Read BMP file
|
||||
|
||||
def i16(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8)
|
||||
|
||||
def i32(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
|
||||
|
||||
|
||||
BIT2MODE = {
|
||||
# bits => mode, rawmode
|
||||
1: ("P", "P;1"),
|
||||
4: ("P", "P;4"),
|
||||
8: ("P", "P"),
|
||||
16: ("RGB", "BGR;15"),
|
||||
24: ("RGB", "BGR"),
|
||||
32: ("RGB", "BGRX")
|
||||
}
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:2] == "BM"
|
||||
|
||||
##
|
||||
# Image plugin for the Windows BMP format.
|
||||
|
||||
class BmpImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "BMP"
|
||||
format_description = "Windows Bitmap"
|
||||
|
||||
def _bitmap(self, header = 0, offset = 0):
|
||||
|
||||
if header:
|
||||
self.fp.seek(header)
|
||||
|
||||
read = self.fp.read
|
||||
|
||||
# CORE/INFO
|
||||
s = read(4)
|
||||
s = s + ImageFile._safe_read(self.fp, i32(s)-4)
|
||||
|
||||
if len(s) == 12:
|
||||
|
||||
# OS/2 1.0 CORE
|
||||
bits = i16(s[10:])
|
||||
self.size = i16(s[4:]), i16(s[6:])
|
||||
compression = 0
|
||||
lutsize = 3
|
||||
colors = 0
|
||||
direction = -1
|
||||
|
||||
elif len(s) in [40, 64]:
|
||||
|
||||
# WIN 3.1 or OS/2 2.0 INFO
|
||||
bits = i16(s[14:])
|
||||
self.size = i32(s[4:]), i32(s[8:])
|
||||
compression = i32(s[16:])
|
||||
lutsize = 4
|
||||
colors = i32(s[32:])
|
||||
direction = -1
|
||||
if s[11] == '\xff':
|
||||
# upside-down storage
|
||||
self.size = self.size[0], 2**32 - self.size[1]
|
||||
direction = 0
|
||||
|
||||
else:
|
||||
raise IOError("Unsupported BMP header type (%d)" % len(s))
|
||||
|
||||
if not colors:
|
||||
colors = 1 << bits
|
||||
|
||||
# MODE
|
||||
try:
|
||||
self.mode, rawmode = BIT2MODE[bits]
|
||||
except KeyError:
|
||||
raise IOError("Unsupported BMP pixel depth (%d)" % bits)
|
||||
|
||||
if compression == 3:
|
||||
# BI_BITFIELDS compression
|
||||
mask = i32(read(4)), i32(read(4)), i32(read(4))
|
||||
if bits == 32 and mask == (0xff0000, 0x00ff00, 0x0000ff):
|
||||
rawmode = "BGRX"
|
||||
elif bits == 16 and mask == (0x00f800, 0x0007e0, 0x00001f):
|
||||
rawmode = "BGR;16"
|
||||
elif bits == 16 and mask == (0x007c00, 0x0003e0, 0x00001f):
|
||||
rawmode = "BGR;15"
|
||||
else:
|
||||
# print bits, map(hex, mask)
|
||||
raise IOError("Unsupported BMP bitfields layout")
|
||||
elif compression != 0:
|
||||
raise IOError("Unsupported BMP compression (%d)" % compression)
|
||||
|
||||
# LUT
|
||||
if self.mode == "P":
|
||||
palette = []
|
||||
greyscale = 1
|
||||
if colors == 2:
|
||||
indices = (0, 255)
|
||||
else:
|
||||
indices = range(colors)
|
||||
for i in indices:
|
||||
rgb = read(lutsize)[:3]
|
||||
if rgb != chr(i)*3:
|
||||
greyscale = 0
|
||||
palette.append(rgb)
|
||||
if greyscale:
|
||||
if colors == 2:
|
||||
self.mode = rawmode = "1"
|
||||
else:
|
||||
self.mode = rawmode = "L"
|
||||
else:
|
||||
self.mode = "P"
|
||||
self.palette = ImagePalette.raw(
|
||||
"BGR", string.join(palette, "")
|
||||
)
|
||||
|
||||
if not offset:
|
||||
offset = self.fp.tell()
|
||||
|
||||
self.tile = [("raw",
|
||||
(0, 0) + self.size,
|
||||
offset,
|
||||
(rawmode, ((self.size[0]*bits+31)>>3)&(~3), direction))]
|
||||
|
||||
self.info["compression"] = compression
|
||||
|
||||
def _open(self):
|
||||
|
||||
# HEAD
|
||||
s = self.fp.read(14)
|
||||
if s[:2] != "BM":
|
||||
raise SyntaxError("Not a BMP file")
|
||||
offset = i32(s[10:])
|
||||
|
||||
self._bitmap(offset=offset)
|
||||
|
||||
|
||||
class DibImageFile(BmpImageFile):
|
||||
|
||||
format = "DIB"
|
||||
format_description = "Windows Bitmap"
|
||||
|
||||
def _open(self):
|
||||
self._bitmap()
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Write BMP file
|
||||
|
||||
def o16(i):
|
||||
return chr(i&255) + chr(i>>8&255)
|
||||
|
||||
def o32(i):
|
||||
return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
|
||||
|
||||
SAVE = {
|
||||
"1": ("1", 1, 2),
|
||||
"L": ("L", 8, 256),
|
||||
"P": ("P", 8, 256),
|
||||
"RGB": ("BGR", 24, 0),
|
||||
}
|
||||
|
||||
def _save(im, fp, filename, check=0):
|
||||
|
||||
try:
|
||||
rawmode, bits, colors = SAVE[im.mode]
|
||||
except KeyError:
|
||||
raise IOError("cannot write mode %s as BMP" % im.mode)
|
||||
|
||||
if check:
|
||||
return check
|
||||
|
||||
stride = ((im.size[0]*bits+7)/8+3)&(~3)
|
||||
header = 40 # or 64 for OS/2 version 2
|
||||
offset = 14 + header + colors * 4
|
||||
image = stride * im.size[1]
|
||||
|
||||
# bitmap header
|
||||
fp.write("BM" + # file type (magic)
|
||||
o32(offset+image) + # file size
|
||||
o32(0) + # reserved
|
||||
o32(offset)) # image data offset
|
||||
|
||||
# bitmap info header
|
||||
fp.write(o32(header) + # info header size
|
||||
o32(im.size[0]) + # width
|
||||
o32(im.size[1]) + # height
|
||||
o16(1) + # planes
|
||||
o16(bits) + # depth
|
||||
o32(0) + # compression (0=uncompressed)
|
||||
o32(image) + # size of bitmap
|
||||
o32(1) + o32(1) + # resolution
|
||||
o32(colors) + # colors used
|
||||
o32(colors)) # colors important
|
||||
|
||||
fp.write("\000" * (header - 40)) # padding (for OS/2 format)
|
||||
|
||||
if im.mode == "1":
|
||||
for i in (0, 255):
|
||||
fp.write(chr(i) * 4)
|
||||
elif im.mode == "L":
|
||||
for i in range(256):
|
||||
fp.write(chr(i) * 4)
|
||||
elif im.mode == "P":
|
||||
fp.write(im.im.getpalette("RGB", "BGRX"))
|
||||
|
||||
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))])
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Registry
|
||||
|
||||
Image.register_open(BmpImageFile.format, BmpImageFile, _accept)
|
||||
Image.register_save(BmpImageFile.format, _save)
|
||||
|
||||
Image.register_extension(BmpImageFile.format, ".bmp")
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# BUFR stub adapter
|
||||
#
|
||||
# Copyright (c) 1996-2003 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
_handler = None
|
||||
|
||||
##
|
||||
# Install application-specific BUFR image handler.
|
||||
#
|
||||
# @param handler Handler object.
|
||||
|
||||
def register_handler(handler):
|
||||
global _handler
|
||||
_handler = handler
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Image adapter
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] == "BUFR" or prefix[:4] == "ZCZC"
|
||||
|
||||
class BufrStubImageFile(ImageFile.StubImageFile):
|
||||
|
||||
format = "BUFR"
|
||||
format_description = "BUFR"
|
||||
|
||||
def _open(self):
|
||||
|
||||
offset = self.fp.tell()
|
||||
|
||||
if not _accept(self.fp.read(8)):
|
||||
raise SyntaxError("Not a BUFR file")
|
||||
|
||||
self.fp.seek(offset)
|
||||
|
||||
# make something up
|
||||
self.mode = "F"
|
||||
self.size = 1, 1
|
||||
|
||||
loader = self._load()
|
||||
if loader:
|
||||
loader.open(self)
|
||||
|
||||
def _load(self):
|
||||
return _handler
|
||||
|
||||
def _save(im, fp, filename):
|
||||
if _handler is None or not hasattr("_handler", "save"):
|
||||
raise IOError("BUFR save handler not installed")
|
||||
_handler.save(im, fp, filename)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Registry
|
||||
|
||||
Image.register_open(BufrStubImageFile.format, BufrStubImageFile, _accept)
|
||||
Image.register_save(BufrStubImageFile.format, _save)
|
||||
|
||||
Image.register_extension(BufrStubImageFile.format, ".bufr")
|
||||
116
Darwin/lib/python2.7/site-packages/PIL/ContainerIO.py
Normal file
116
Darwin/lib/python2.7/site-packages/PIL/ContainerIO.py
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# a class to read from a container file
|
||||
#
|
||||
# History:
|
||||
# 1995-06-18 fl Created
|
||||
# 1995-09-07 fl Added readline(), readlines()
|
||||
#
|
||||
# Copyright (c) 1997-2001 by Secret Labs AB
|
||||
# Copyright (c) 1995 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
##
|
||||
# A file object that provides read access to a part of an existing
|
||||
# file (for example a TAR file).
|
||||
|
||||
class ContainerIO:
|
||||
|
||||
##
|
||||
# Create file object.
|
||||
#
|
||||
# @param file Existing file.
|
||||
# @param offset Start of region, in bytes.
|
||||
# @param length Size of region, in bytes.
|
||||
|
||||
def __init__(self, file, offset, length):
|
||||
self.fh = file
|
||||
self.pos = 0
|
||||
self.offset = offset
|
||||
self.length = length
|
||||
self.fh.seek(offset)
|
||||
|
||||
##
|
||||
# Always false.
|
||||
|
||||
def isatty(self):
|
||||
return 0
|
||||
|
||||
##
|
||||
# Move file pointer.
|
||||
#
|
||||
# @param offset Offset in bytes.
|
||||
# @param mode Starting position. Use 0 for beginning of region, 1
|
||||
# for current offset, and 2 for end of region. You cannot move
|
||||
# the pointer outside the defined region.
|
||||
|
||||
def seek(self, offset, mode = 0):
|
||||
if mode == 1:
|
||||
self.pos = self.pos + offset
|
||||
elif mode == 2:
|
||||
self.pos = self.length + offset
|
||||
else:
|
||||
self.pos = offset
|
||||
# clamp
|
||||
self.pos = max(0, min(self.pos, self.length))
|
||||
self.fh.seek(self.offset + self.pos)
|
||||
|
||||
##
|
||||
# Get current file pointer.
|
||||
#
|
||||
# @return Offset from start of region, in bytes.
|
||||
|
||||
def tell(self):
|
||||
return self.pos
|
||||
|
||||
##
|
||||
# Read data.
|
||||
#
|
||||
# @def read(bytes=0)
|
||||
# @param bytes Number of bytes to read. If omitted or zero,
|
||||
# read until end of region.
|
||||
# @return An 8-bit string.
|
||||
|
||||
def read(self, n = 0):
|
||||
if n:
|
||||
n = min(n, self.length - self.pos)
|
||||
else:
|
||||
n = self.length - self.pos
|
||||
if not n: # EOF
|
||||
return ""
|
||||
self.pos = self.pos + n
|
||||
return self.fh.read(n)
|
||||
|
||||
##
|
||||
# Read a line of text.
|
||||
#
|
||||
# @return An 8-bit string.
|
||||
|
||||
def readline(self):
|
||||
s = ""
|
||||
while 1:
|
||||
c = self.read(1)
|
||||
if not c:
|
||||
break
|
||||
s = s + c
|
||||
if c == "\n":
|
||||
break
|
||||
return s
|
||||
|
||||
##
|
||||
# Read multiple lines of text.
|
||||
#
|
||||
# @return A list of 8-bit strings.
|
||||
|
||||
def readlines(self):
|
||||
l = []
|
||||
while 1:
|
||||
s = self.readline()
|
||||
if not s:
|
||||
break
|
||||
l.append(s)
|
||||
return l
|
||||
88
Darwin/lib/python2.7/site-packages/PIL/CurImagePlugin.py
Normal file
88
Darwin/lib/python2.7/site-packages/PIL/CurImagePlugin.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# Windows Cursor support for PIL
|
||||
#
|
||||
# notes:
|
||||
# uses BmpImagePlugin.py to read the bitmap data.
|
||||
#
|
||||
# history:
|
||||
# 96-05-27 fl Created
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1996.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.1"
|
||||
|
||||
import Image, BmpImagePlugin
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
def i16(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8)
|
||||
|
||||
def i32(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] == "\0\0\2\0"
|
||||
|
||||
##
|
||||
# Image plugin for Windows Cursor files.
|
||||
|
||||
class CurImageFile(BmpImagePlugin.BmpImageFile):
|
||||
|
||||
format = "CUR"
|
||||
format_description = "Windows Cursor"
|
||||
|
||||
def _open(self):
|
||||
|
||||
offset = self.fp.tell()
|
||||
|
||||
# check magic
|
||||
s = self.fp.read(6)
|
||||
if not _accept(s):
|
||||
raise SyntaxError, "not an CUR file"
|
||||
|
||||
# pick the largest cursor in the file
|
||||
m = ""
|
||||
for i in range(i16(s[4:])):
|
||||
s = self.fp.read(16)
|
||||
if not m:
|
||||
m = s
|
||||
elif ord(s[0]) > ord(m[0]) and ord(s[1]) > ord(m[1]):
|
||||
m = s
|
||||
#print "width", ord(s[0])
|
||||
#print "height", ord(s[1])
|
||||
#print "colors", ord(s[2])
|
||||
#print "reserved", ord(s[3])
|
||||
#print "hotspot x", i16(s[4:])
|
||||
#print "hotspot y", i16(s[6:])
|
||||
#print "bytes", i32(s[8:])
|
||||
#print "offset", i32(s[12:])
|
||||
|
||||
# load as bitmap
|
||||
self._bitmap(i32(m[12:]) + offset)
|
||||
|
||||
# patch up the bitmap height
|
||||
self.size = self.size[0], self.size[1]/2
|
||||
d, e, o, a = self.tile[0]
|
||||
self.tile[0] = d, (0,0)+self.size, o, a
|
||||
|
||||
return
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("CUR", CurImageFile, _accept)
|
||||
|
||||
Image.register_extension("CUR", ".cur")
|
||||
78
Darwin/lib/python2.7/site-packages/PIL/DcxImagePlugin.py
Normal file
78
Darwin/lib/python2.7/site-packages/PIL/DcxImagePlugin.py
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# DCX file handling
|
||||
#
|
||||
# DCX is a container file format defined by Intel, commonly used
|
||||
# for fax applications. Each DCX file consists of a directory
|
||||
# (a list of file offsets) followed by a set of (usually 1-bit)
|
||||
# PCX files.
|
||||
#
|
||||
# History:
|
||||
# 1995-09-09 fl Created
|
||||
# 1996-03-20 fl Properly derived from PcxImageFile.
|
||||
# 1998-07-15 fl Renamed offset attribute to avoid name clash
|
||||
# 2002-07-30 fl Fixed file handling
|
||||
#
|
||||
# Copyright (c) 1997-98 by Secret Labs AB.
|
||||
# Copyright (c) 1995-96 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.2"
|
||||
|
||||
import Image
|
||||
|
||||
from PcxImagePlugin import PcxImageFile
|
||||
|
||||
MAGIC = 0x3ADE68B1 # QUIZ: what's this value, then?
|
||||
|
||||
def i32(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
|
||||
|
||||
def _accept(prefix):
|
||||
return i32(prefix) == MAGIC
|
||||
|
||||
##
|
||||
# Image plugin for the Intel DCX format.
|
||||
|
||||
class DcxImageFile(PcxImageFile):
|
||||
|
||||
format = "DCX"
|
||||
format_description = "Intel DCX"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# Header
|
||||
s = self.fp.read(4)
|
||||
if i32(s) != MAGIC:
|
||||
raise SyntaxError, "not a DCX file"
|
||||
|
||||
# Component directory
|
||||
self._offset = []
|
||||
for i in range(1024):
|
||||
offset = i32(self.fp.read(4))
|
||||
if not offset:
|
||||
break
|
||||
self._offset.append(offset)
|
||||
|
||||
self.__fp = self.fp
|
||||
self.seek(0)
|
||||
|
||||
def seek(self, frame):
|
||||
if frame >= len(self._offset):
|
||||
raise EOFError("attempt to seek outside DCX directory")
|
||||
self.frame = frame
|
||||
self.fp = self.__fp
|
||||
self.fp.seek(self._offset[frame])
|
||||
PcxImageFile._open(self)
|
||||
|
||||
def tell(self):
|
||||
return self.frame
|
||||
|
||||
|
||||
Image.register_open("DCX", DcxImageFile, _accept)
|
||||
|
||||
Image.register_extension("DCX", ".dcx")
|
||||
349
Darwin/lib/python2.7/site-packages/PIL/EpsImagePlugin.py
Normal file
349
Darwin/lib/python2.7/site-packages/PIL/EpsImagePlugin.py
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# EPS file handling
|
||||
#
|
||||
# History:
|
||||
# 1995-09-01 fl Created (0.1)
|
||||
# 1996-05-18 fl Don't choke on "atend" fields, Ghostscript interface (0.2)
|
||||
# 1996-08-22 fl Don't choke on floating point BoundingBox values
|
||||
# 1996-08-23 fl Handle files from Macintosh (0.3)
|
||||
# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.4)
|
||||
# 2003-09-07 fl Check gs.close status (from Federico Di Gregorio) (0.5)
|
||||
#
|
||||
# Copyright (c) 1997-2003 by Secret Labs AB.
|
||||
# Copyright (c) 1995-2003 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.5"
|
||||
|
||||
import re, string
|
||||
import Image, ImageFile
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
def i32(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
|
||||
|
||||
def o32(i):
|
||||
return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
|
||||
|
||||
split = re.compile(r"^%%([^:]*):[ \t]*(.*)[ \t]*$")
|
||||
field = re.compile(r"^%[%!\w]([^:]*)[ \t]*$")
|
||||
|
||||
def Ghostscript(tile, size, fp):
|
||||
"""Render an image using Ghostscript (Unix only)"""
|
||||
|
||||
# Unpack decoder tile
|
||||
decoder, tile, offset, data = tile[0]
|
||||
length, bbox = data
|
||||
|
||||
import tempfile, os
|
||||
|
||||
file = tempfile.mktemp()
|
||||
|
||||
# Build ghostscript command
|
||||
command = ["gs",
|
||||
"-q", # quite mode
|
||||
"-g%dx%d" % size, # set output geometry (pixels)
|
||||
"-dNOPAUSE -dSAFER", # don't pause between pages, safe mode
|
||||
"-sDEVICE=ppmraw", # ppm driver
|
||||
"-sOutputFile=%s" % file,# output file
|
||||
"- >/dev/null 2>/dev/null"]
|
||||
|
||||
command = string.join(command)
|
||||
|
||||
# push data through ghostscript
|
||||
try:
|
||||
gs = os.popen(command, "w")
|
||||
# adjust for image origin
|
||||
if bbox[0] != 0 or bbox[1] != 0:
|
||||
gs.write("%d %d translate\n" % (-bbox[0], -bbox[1]))
|
||||
fp.seek(offset)
|
||||
while length > 0:
|
||||
s = fp.read(8192)
|
||||
if not s:
|
||||
break
|
||||
length = length - len(s)
|
||||
gs.write(s)
|
||||
status = gs.close()
|
||||
if status:
|
||||
raise IOError("gs failed (status %d)" % status)
|
||||
im = Image.core.open_ppm(file)
|
||||
finally:
|
||||
try: os.unlink(file)
|
||||
except: pass
|
||||
|
||||
return im
|
||||
|
||||
|
||||
class PSFile:
|
||||
"""Wrapper that treats either CR or LF as end of line."""
|
||||
def __init__(self, fp):
|
||||
self.fp = fp
|
||||
self.char = None
|
||||
def __getattr__(self, id):
|
||||
v = getattr(self.fp, id)
|
||||
setattr(self, id, v)
|
||||
return v
|
||||
def seek(self, offset, whence=0):
|
||||
self.char = None
|
||||
self.fp.seek(offset, whence)
|
||||
def tell(self):
|
||||
pos = self.fp.tell()
|
||||
if self.char:
|
||||
pos = pos - 1
|
||||
return pos
|
||||
def readline(self):
|
||||
s = ""
|
||||
if self.char:
|
||||
c = self.char
|
||||
self.char = None
|
||||
else:
|
||||
c = self.fp.read(1)
|
||||
while c not in "\r\n":
|
||||
s = s + c
|
||||
c = self.fp.read(1)
|
||||
if c == "\r":
|
||||
self.char = self.fp.read(1)
|
||||
if self.char == "\n":
|
||||
self.char = None
|
||||
return s + "\n"
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] == "%!PS" or i32(prefix) == 0xC6D3D0C5L
|
||||
|
||||
##
|
||||
# Image plugin for Encapsulated Postscript. This plugin supports only
|
||||
# a few variants of this format.
|
||||
|
||||
class EpsImageFile(ImageFile.ImageFile):
|
||||
"""EPS File Parser for the Python Imaging Library"""
|
||||
|
||||
format = "EPS"
|
||||
format_description = "Encapsulated Postscript"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# FIXME: should check the first 512 bytes to see if this
|
||||
# really is necessary (platform-dependent, though...)
|
||||
|
||||
fp = PSFile(self.fp)
|
||||
|
||||
# HEAD
|
||||
s = fp.read(512)
|
||||
if s[:4] == "%!PS":
|
||||
offset = 0
|
||||
fp.seek(0, 2)
|
||||
length = fp.tell()
|
||||
elif i32(s) == 0xC6D3D0C5L:
|
||||
offset = i32(s[4:])
|
||||
length = i32(s[8:])
|
||||
fp.seek(offset)
|
||||
else:
|
||||
raise SyntaxError, "not an EPS file"
|
||||
|
||||
fp.seek(offset)
|
||||
|
||||
box = None
|
||||
|
||||
self.mode = "RGB"
|
||||
self.size = 1, 1 # FIXME: huh?
|
||||
|
||||
#
|
||||
# Load EPS header
|
||||
|
||||
s = fp.readline()
|
||||
|
||||
while s:
|
||||
|
||||
if len(s) > 255:
|
||||
raise SyntaxError, "not an EPS file"
|
||||
|
||||
if s[-2:] == '\r\n':
|
||||
s = s[:-2]
|
||||
elif s[-1:] == '\n':
|
||||
s = s[:-1]
|
||||
|
||||
try:
|
||||
m = split.match(s)
|
||||
except re.error, v:
|
||||
raise SyntaxError, "not an EPS file"
|
||||
|
||||
if m:
|
||||
k, v = m.group(1, 2)
|
||||
self.info[k] = v
|
||||
if k == "BoundingBox":
|
||||
try:
|
||||
# Note: The DSC spec says that BoundingBox
|
||||
# fields should be integers, but some drivers
|
||||
# put floating point values there anyway.
|
||||
box = map(int, map(float, string.split(v)))
|
||||
self.size = box[2] - box[0], box[3] - box[1]
|
||||
self.tile = [("eps", (0,0) + self.size, offset,
|
||||
(length, box))]
|
||||
except:
|
||||
pass
|
||||
|
||||
else:
|
||||
|
||||
m = field.match(s)
|
||||
|
||||
if m:
|
||||
k = m.group(1)
|
||||
if k == "EndComments":
|
||||
break
|
||||
if k[:8] == "PS-Adobe":
|
||||
self.info[k[:8]] = k[9:]
|
||||
else:
|
||||
self.info[k] = ""
|
||||
else:
|
||||
raise IOError, "bad EPS header"
|
||||
|
||||
s = fp.readline()
|
||||
|
||||
if s[:1] != "%":
|
||||
break
|
||||
|
||||
|
||||
#
|
||||
# Scan for an "ImageData" descriptor
|
||||
|
||||
while s[0] == "%":
|
||||
|
||||
if len(s) > 255:
|
||||
raise SyntaxError, "not an EPS file"
|
||||
|
||||
if s[-2:] == '\r\n':
|
||||
s = s[:-2]
|
||||
elif s[-1:] == '\n':
|
||||
s = s[:-1]
|
||||
|
||||
if s[:11] == "%ImageData:":
|
||||
|
||||
[x, y, bi, mo, z3, z4, en, id] =\
|
||||
string.split(s[11:], maxsplit=7)
|
||||
|
||||
x = int(x); y = int(y)
|
||||
|
||||
bi = int(bi)
|
||||
mo = int(mo)
|
||||
|
||||
en = int(en)
|
||||
|
||||
if en == 1:
|
||||
decoder = "eps_binary"
|
||||
elif en == 2:
|
||||
decoder = "eps_hex"
|
||||
else:
|
||||
break
|
||||
if bi != 8:
|
||||
break
|
||||
if mo == 1:
|
||||
self.mode = "L"
|
||||
elif mo == 2:
|
||||
self.mode = "LAB"
|
||||
elif mo == 3:
|
||||
self.mode = "RGB"
|
||||
else:
|
||||
break
|
||||
|
||||
if id[:1] == id[-1:] == '"':
|
||||
id = id[1:-1]
|
||||
|
||||
# Scan forward to the actual image data
|
||||
while 1:
|
||||
s = fp.readline()
|
||||
if not s:
|
||||
break
|
||||
if s[:len(id)] == id:
|
||||
self.size = x, y
|
||||
self.tile2 = [(decoder,
|
||||
(0, 0, x, y),
|
||||
fp.tell(),
|
||||
0)]
|
||||
return
|
||||
|
||||
s = fp.readline()
|
||||
if not s:
|
||||
break
|
||||
|
||||
if not box:
|
||||
raise IOError, "cannot determine EPS bounding box"
|
||||
|
||||
def load(self):
|
||||
# Load EPS via Ghostscript
|
||||
if not self.tile:
|
||||
return
|
||||
self.im = Ghostscript(self.tile, self.size, self.fp)
|
||||
self.mode = self.im.mode
|
||||
self.size = self.im.size
|
||||
self.tile = []
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
def _save(im, fp, filename, eps=1):
|
||||
"""EPS Writer for the Python Imaging Library."""
|
||||
|
||||
#
|
||||
# make sure image data is available
|
||||
im.load()
|
||||
|
||||
#
|
||||
# determine postscript image mode
|
||||
if im.mode == "L":
|
||||
operator = (8, 1, "image")
|
||||
elif im.mode == "RGB":
|
||||
operator = (8, 3, "false 3 colorimage")
|
||||
elif im.mode == "CMYK":
|
||||
operator = (8, 4, "false 4 colorimage")
|
||||
else:
|
||||
raise ValueError, "image mode is not supported"
|
||||
|
||||
if eps:
|
||||
#
|
||||
# write EPS header
|
||||
fp.write("%!PS-Adobe-3.0 EPSF-3.0\n")
|
||||
fp.write("%%Creator: PIL 0.1 EpsEncode\n")
|
||||
#fp.write("%%CreationDate: %s"...)
|
||||
fp.write("%%%%BoundingBox: 0 0 %d %d\n" % im.size)
|
||||
fp.write("%%Pages: 1\n")
|
||||
fp.write("%%EndComments\n")
|
||||
fp.write("%%Page: 1 1\n")
|
||||
fp.write("%%ImageData: %d %d " % im.size)
|
||||
fp.write("%d %d 0 1 1 \"%s\"\n" % operator)
|
||||
|
||||
#
|
||||
# image header
|
||||
fp.write("gsave\n")
|
||||
fp.write("10 dict begin\n")
|
||||
fp.write("/buf %d string def\n" % (im.size[0] * operator[1]))
|
||||
fp.write("%d %d scale\n" % im.size)
|
||||
fp.write("%d %d 8\n" % im.size) # <= bits
|
||||
fp.write("[%d 0 0 -%d 0 %d]\n" % (im.size[0], im.size[1], im.size[1]))
|
||||
fp.write("{ currentfile buf readhexstring pop } bind\n")
|
||||
fp.write("%s\n" % operator[2])
|
||||
|
||||
ImageFile._save(im, fp, [("eps", (0,0)+im.size, 0, None)])
|
||||
|
||||
fp.write("\n%%%%EndBinary\n")
|
||||
fp.write("grestore end\n")
|
||||
fp.flush()
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open(EpsImageFile.format, EpsImageFile, _accept)
|
||||
|
||||
Image.register_save(EpsImageFile.format, _save)
|
||||
|
||||
Image.register_extension(EpsImageFile.format, ".ps")
|
||||
Image.register_extension(EpsImageFile.format, ".eps")
|
||||
|
||||
Image.register_mime(EpsImageFile.format, "application/postscript")
|
||||
157
Darwin/lib/python2.7/site-packages/PIL/ExifTags.py
Normal file
157
Darwin/lib/python2.7/site-packages/PIL/ExifTags.py
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# EXIF tags
|
||||
#
|
||||
# Copyright (c) 2003 by Secret Labs AB
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
##
|
||||
# This module provides constants and clear-text names for various
|
||||
# well-known EXIF tags.
|
||||
##
|
||||
|
||||
##
|
||||
# Maps EXIF tags to tag names.
|
||||
|
||||
TAGS = {
|
||||
|
||||
# possibly incomplete
|
||||
0x0100: "ImageWidth",
|
||||
0x0101: "ImageLength",
|
||||
0x0102: "BitsPerSample",
|
||||
0x0103: "Compression",
|
||||
0x0106: "PhotometricInterpretation",
|
||||
0x010e: "ImageDescription",
|
||||
0x010f: "Make",
|
||||
0x0110: "Model",
|
||||
0x0111: "StripOffsets",
|
||||
0x0112: "Orientation",
|
||||
0x0115: "SamplesPerPixel",
|
||||
0x0116: "RowsPerStrip",
|
||||
0x0117: "StripByteConunts",
|
||||
0x011a: "XResolution",
|
||||
0x011a: "XResolution",
|
||||
0x011b: "YResolution",
|
||||
0x011b: "YResolution",
|
||||
0x011c: "PlanarConfiguration",
|
||||
0x0128: "ResolutionUnit",
|
||||
0x0128: "ResolutionUnit",
|
||||
0x012d: "TransferFunction",
|
||||
0x0131: "Software",
|
||||
0x0132: "DateTime",
|
||||
0x013b: "Artist",
|
||||
0x013e: "WhitePoint",
|
||||
0x013f: "PrimaryChromaticities",
|
||||
0x0201: "JpegIFOffset",
|
||||
0x0202: "JpegIFByteCount",
|
||||
0x0211: "YCbCrCoefficients",
|
||||
0x0211: "YCbCrCoefficients",
|
||||
0x0212: "YCbCrSubSampling",
|
||||
0x0213: "YCbCrPositioning",
|
||||
0x0213: "YCbCrPositioning",
|
||||
0x0214: "ReferenceBlackWhite",
|
||||
0x0214: "ReferenceBlackWhite",
|
||||
0x1000: "RelatedImageFileFormat",
|
||||
0x1001: "RelatedImageLength",
|
||||
0x1001: "RelatedImageWidth",
|
||||
0x828d: "CFARepeatPatternDim",
|
||||
0x828e: "CFAPattern",
|
||||
0x828f: "BatteryLevel",
|
||||
0x8298: "Copyright",
|
||||
0x829a: "ExposureTime",
|
||||
0x829d: "FNumber",
|
||||
0x8769: "ExifOffset",
|
||||
0x8773: "InterColorProfile",
|
||||
0x8822: "ExposureProgram",
|
||||
0x8824: "SpectralSensitivity",
|
||||
0x8825: "GPSInfo",
|
||||
0x8827: "ISOSpeedRatings",
|
||||
0x8828: "OECF",
|
||||
0x8829: "Interlace",
|
||||
0x882a: "TimeZoneOffset",
|
||||
0x882b: "SelfTimerMode",
|
||||
0x9000: "ExifVersion",
|
||||
0x9003: "DateTimeOriginal",
|
||||
0x9004: "DateTimeDigitized",
|
||||
0x9101: "ComponentsConfiguration",
|
||||
0x9102: "CompressedBitsPerPixel",
|
||||
0x9201: "ShutterSpeedValue",
|
||||
0x9202: "ApertureValue",
|
||||
0x9203: "BrightnessValue",
|
||||
0x9204: "ExposureBiasValue",
|
||||
0x9205: "MaxApertureValue",
|
||||
0x9206: "SubjectDistance",
|
||||
0x9207: "MeteringMode",
|
||||
0x9208: "LightSource",
|
||||
0x9209: "Flash",
|
||||
0x920a: "FocalLength",
|
||||
0x920b: "FlashEnergy",
|
||||
0x920c: "SpatialFrequencyResponse",
|
||||
0x920d: "Noise",
|
||||
0x9211: "ImageNumber",
|
||||
0x9212: "SecurityClassification",
|
||||
0x9213: "ImageHistory",
|
||||
0x9214: "SubjectLocation",
|
||||
0x9215: "ExposureIndex",
|
||||
0x9216: "TIFF/EPStandardID",
|
||||
0x927c: "MakerNote",
|
||||
0x9286: "UserComment",
|
||||
0x9290: "SubsecTime",
|
||||
0x9291: "SubsecTimeOriginal",
|
||||
0x9292: "SubsecTimeDigitized",
|
||||
0xa000: "FlashPixVersion",
|
||||
0xa001: "ColorSpace",
|
||||
0xa002: "ExifImageWidth",
|
||||
0xa003: "ExifImageHeight",
|
||||
0xa004: "RelatedSoundFile",
|
||||
0xa005: "ExifInteroperabilityOffset",
|
||||
0xa20b: "FlashEnergy",
|
||||
0xa20c: "SpatialFrequencyResponse",
|
||||
0xa20e: "FocalPlaneXResolution",
|
||||
0xa20f: "FocalPlaneYResolution",
|
||||
0xa210: "FocalPlaneResolutionUnit",
|
||||
0xa214: "SubjectLocation",
|
||||
0xa215: "ExposureIndex",
|
||||
0xa217: "SensingMethod",
|
||||
0xa300: "FileSource",
|
||||
0xa301: "SceneType",
|
||||
0xa302: "CFAPattern",
|
||||
|
||||
}
|
||||
|
||||
##
|
||||
# Maps EXIF GSP tags to tag names.
|
||||
|
||||
GPSTAGS = {
|
||||
0: "GPSVersionID",
|
||||
1: "GPSLatitudeRef",
|
||||
2: "GPSLatitude",
|
||||
3: "GPSLongitudeRef",
|
||||
4: "GPSLongitude",
|
||||
5: "GPSAltitudeRef",
|
||||
6: "GPSAltitude",
|
||||
7: "GPSTimeStamp",
|
||||
8: "GPSSatellites",
|
||||
9: "GPSStatus",
|
||||
10: "GPSMeasureMode",
|
||||
11: "GPSDOP",
|
||||
12: "GPSSpeedRef",
|
||||
13: "GPSSpeed",
|
||||
14: "GPSTrackRef",
|
||||
15: "GPSTrack",
|
||||
16: "GPSImgDirectionRef",
|
||||
17: "GPSImgDirection",
|
||||
18: "GPSMapDatum",
|
||||
19: "GPSDestLatitudeRef",
|
||||
20: "GPSDestLatitude",
|
||||
21: "GPSDestLongitudeRef",
|
||||
22: "GPSDestLongitude",
|
||||
23: "GPSDestBearingRef",
|
||||
24: "GPSDestBearing",
|
||||
25: "GPSDestDistanceRef",
|
||||
26: "GPSDestDistance"
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# FITS stub adapter
|
||||
#
|
||||
# Copyright (c) 1998-2003 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
_handler = None
|
||||
|
||||
##
|
||||
# Install application-specific FITS image handler.
|
||||
#
|
||||
# @param handler Handler object.
|
||||
|
||||
def register_handler(handler):
|
||||
global _handler
|
||||
_handler = handler
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Image adapter
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:6] == "SIMPLE"
|
||||
|
||||
class FITSStubImageFile(ImageFile.StubImageFile):
|
||||
|
||||
format = "FITS"
|
||||
format_description = "FITS"
|
||||
|
||||
def _open(self):
|
||||
|
||||
offset = self.fp.tell()
|
||||
|
||||
if not _accept(self.fp.read(6)):
|
||||
raise SyntaxError("Not a FITS file")
|
||||
|
||||
# FIXME: add more sanity checks here; mandatory header items
|
||||
# include SIMPLE, BITPIX, NAXIS, etc.
|
||||
|
||||
self.fp.seek(offset)
|
||||
|
||||
# make something up
|
||||
self.mode = "F"
|
||||
self.size = 1, 1
|
||||
|
||||
loader = self._load()
|
||||
if loader:
|
||||
loader.open(self)
|
||||
|
||||
def _load(self):
|
||||
return _handler
|
||||
|
||||
|
||||
def _save(im, fp, filename):
|
||||
if _handler is None or not hasattr("_handler", "save"):
|
||||
raise IOError("FITS save handler not installed")
|
||||
_handler.save(im, fp, filename)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Registry
|
||||
|
||||
Image.register_open(FITSStubImageFile.format, FITSStubImageFile, _accept)
|
||||
Image.register_save(FITSStubImageFile.format, _save)
|
||||
|
||||
Image.register_extension(FITSStubImageFile.format, ".fit")
|
||||
Image.register_extension(FITSStubImageFile.format, ".fits")
|
||||
142
Darwin/lib/python2.7/site-packages/PIL/FliImagePlugin.py
Normal file
142
Darwin/lib/python2.7/site-packages/PIL/FliImagePlugin.py
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# FLI/FLC file handling.
|
||||
#
|
||||
# History:
|
||||
# 95-09-01 fl Created
|
||||
# 97-01-03 fl Fixed parser, setup decoder tile
|
||||
# 98-07-15 fl Renamed offset attribute to avoid name clash
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997-98.
|
||||
# Copyright (c) Fredrik Lundh 1995-97.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.2"
|
||||
|
||||
import Image, ImageFile, ImagePalette
|
||||
import string
|
||||
|
||||
|
||||
def i16(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8)
|
||||
|
||||
def i32(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
|
||||
|
||||
#
|
||||
# decoder
|
||||
|
||||
def _accept(prefix):
|
||||
return i16(prefix[4:6]) in [0xAF11, 0xAF12]
|
||||
|
||||
##
|
||||
# Image plugin for the FLI/FLC animation format. Use the <b>seek</b>
|
||||
# method to load individual frames.
|
||||
|
||||
class FliImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "FLI"
|
||||
format_description = "Autodesk FLI/FLC Animation"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# HEAD
|
||||
s = self.fp.read(128)
|
||||
magic = i16(s[4:6])
|
||||
if magic not in [0xAF11, 0xAF12]:
|
||||
raise SyntaxError, "not an FLI/FLC file"
|
||||
|
||||
# image characteristics
|
||||
self.mode = "P"
|
||||
self.size = i16(s[8:10]), i16(s[10:12])
|
||||
|
||||
# animation speed
|
||||
duration = i32(s[16:20])
|
||||
if magic == 0xAF11:
|
||||
duration = (duration * 1000) / 70
|
||||
self.info["duration"] = duration
|
||||
|
||||
# look for palette
|
||||
palette = map(lambda a: (a,a,a), range(256))
|
||||
|
||||
s = self.fp.read(16)
|
||||
|
||||
self.__offset = 128
|
||||
|
||||
if i16(s[4:6]) == 0xF100:
|
||||
# prefix chunk; ignore it
|
||||
self.__offset = self.__offset + i32(s)
|
||||
s = self.fp.read(16)
|
||||
|
||||
if i16(s[4:6]) == 0xF1FA:
|
||||
# look for palette chunk
|
||||
s = self.fp.read(6)
|
||||
if i16(s[4:6]) == 11:
|
||||
self._palette(palette, 2)
|
||||
elif i16(s[4:6]) == 4:
|
||||
self._palette(palette, 0)
|
||||
|
||||
palette = map(lambda (r,g,b): chr(r)+chr(g)+chr(b), palette)
|
||||
self.palette = ImagePalette.raw("RGB", string.join(palette, ""))
|
||||
|
||||
# set things up to decode first frame
|
||||
self.frame = -1
|
||||
self.__fp = self.fp
|
||||
|
||||
self.seek(0)
|
||||
|
||||
def _palette(self, palette, shift):
|
||||
# load palette
|
||||
|
||||
i = 0
|
||||
for e in range(i16(self.fp.read(2))):
|
||||
s = self.fp.read(2)
|
||||
i = i + ord(s[0])
|
||||
n = ord(s[1])
|
||||
if n == 0:
|
||||
n = 256
|
||||
s = self.fp.read(n * 3)
|
||||
for n in range(0, len(s), 3):
|
||||
r = ord(s[n]) << shift
|
||||
g = ord(s[n+1]) << shift
|
||||
b = ord(s[n+2]) << shift
|
||||
palette[i] = (r, g, b)
|
||||
i = i + 1
|
||||
|
||||
def seek(self, frame):
|
||||
|
||||
if frame != self.frame + 1:
|
||||
raise ValueError, "cannot seek to frame %d" % frame
|
||||
self.frame = frame
|
||||
|
||||
# move to next frame
|
||||
self.fp = self.__fp
|
||||
self.fp.seek(self.__offset)
|
||||
|
||||
s = self.fp.read(4)
|
||||
if not s:
|
||||
raise EOFError
|
||||
|
||||
framesize = i32(s)
|
||||
|
||||
self.decodermaxblock = framesize
|
||||
self.tile = [("fli", (0,0)+self.size, self.__offset, None)]
|
||||
|
||||
self.__offset = self.__offset + framesize
|
||||
|
||||
def tell(self):
|
||||
|
||||
return self.frame
|
||||
|
||||
#
|
||||
# registry
|
||||
|
||||
Image.register_open("FLI", FliImageFile, _accept)
|
||||
|
||||
Image.register_extension("FLI", ".fli")
|
||||
Image.register_extension("FLI", ".flc")
|
||||
146
Darwin/lib/python2.7/site-packages/PIL/FontFile.py
Normal file
146
Darwin/lib/python2.7/site-packages/PIL/FontFile.py
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# base class for raster font file parsers
|
||||
#
|
||||
# history:
|
||||
# 1997-06-05 fl created
|
||||
# 1997-08-19 fl restrict image width
|
||||
#
|
||||
# Copyright (c) 1997-1998 by Secret Labs AB
|
||||
# Copyright (c) 1997-1998 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import os
|
||||
import Image
|
||||
|
||||
import marshal
|
||||
|
||||
try:
|
||||
import zlib
|
||||
except ImportError:
|
||||
zlib = None
|
||||
|
||||
WIDTH = 800
|
||||
|
||||
def puti16(fp, values):
|
||||
# write network order (big-endian) 16-bit sequence
|
||||
for v in values:
|
||||
if v < 0:
|
||||
v = v + 65536
|
||||
fp.write(chr(v>>8&255) + chr(v&255))
|
||||
|
||||
##
|
||||
# Base class for raster font file handlers.
|
||||
|
||||
class FontFile:
|
||||
|
||||
bitmap = None
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.info = {}
|
||||
self.glyph = [None] * 256
|
||||
|
||||
def __getitem__(self, ix):
|
||||
return self.glyph[ix]
|
||||
|
||||
def compile(self):
|
||||
"Create metrics and bitmap"
|
||||
|
||||
if self.bitmap:
|
||||
return
|
||||
|
||||
# create bitmap large enough to hold all data
|
||||
h = w = maxwidth = 0
|
||||
lines = 1
|
||||
for glyph in self:
|
||||
if glyph:
|
||||
d, dst, src, im = glyph
|
||||
h = max(h, src[3] - src[1])
|
||||
w = w + (src[2] - src[0])
|
||||
if w > WIDTH:
|
||||
lines = lines + 1
|
||||
w = (src[2] - src[0])
|
||||
maxwidth = max(maxwidth, w)
|
||||
|
||||
xsize = maxwidth
|
||||
ysize = lines * h
|
||||
|
||||
if xsize == 0 and ysize == 0:
|
||||
return ""
|
||||
|
||||
self.ysize = h
|
||||
|
||||
# paste glyphs into bitmap
|
||||
self.bitmap = Image.new("1", (xsize, ysize))
|
||||
self.metrics = [None] * 256
|
||||
x = y = 0
|
||||
for i in range(256):
|
||||
glyph = self[i]
|
||||
if glyph:
|
||||
d, dst, src, im = glyph
|
||||
xx, yy = src[2] - src[0], src[3] - src[1]
|
||||
x0, y0 = x, y
|
||||
x = x + xx
|
||||
if x > WIDTH:
|
||||
x, y = 0, y + h
|
||||
x0, y0 = x, y
|
||||
x = xx
|
||||
s = src[0] + x0, src[1] + y0, src[2] + x0, src[3] + y0
|
||||
self.bitmap.paste(im.crop(src), s)
|
||||
# print chr(i), dst, s
|
||||
self.metrics[i] = d, dst, s
|
||||
|
||||
|
||||
def save1(self, filename):
|
||||
"Save font in version 1 format"
|
||||
|
||||
self.compile()
|
||||
|
||||
# font data
|
||||
self.bitmap.save(os.path.splitext(filename)[0] + ".pbm", "PNG")
|
||||
|
||||
# font metrics
|
||||
fp = open(os.path.splitext(filename)[0] + ".pil", "wb")
|
||||
fp.write("PILfont\n")
|
||||
fp.write(";;;;;;%d;\n" % self.ysize) # HACK!!!
|
||||
fp.write("DATA\n")
|
||||
for id in range(256):
|
||||
m = self.metrics[id]
|
||||
if not m:
|
||||
puti16(fp, [0] * 10)
|
||||
else:
|
||||
puti16(fp, m[0] + m[1] + m[2])
|
||||
fp.close()
|
||||
|
||||
|
||||
def save2(self, filename):
|
||||
"Save font in version 2 format"
|
||||
|
||||
# THIS IS WORK IN PROGRESS
|
||||
|
||||
self.compile()
|
||||
|
||||
data = marshal.dumps((self.metrics, self.info))
|
||||
|
||||
if zlib:
|
||||
data = "z" + zlib.compress(data, 9)
|
||||
else:
|
||||
data = "u" + data
|
||||
|
||||
fp = open(os.path.splitext(filename)[0] + ".pil", "wb")
|
||||
|
||||
fp.write("PILfont2\n" + self.name + "\n" + "DATA\n")
|
||||
|
||||
fp.write(data)
|
||||
|
||||
self.bitmap.save(fp, "PNG")
|
||||
|
||||
fp.close()
|
||||
|
||||
|
||||
save = save1 # for now
|
||||
224
Darwin/lib/python2.7/site-packages/PIL/FpxImagePlugin.py
Normal file
224
Darwin/lib/python2.7/site-packages/PIL/FpxImagePlugin.py
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
#
|
||||
# THIS IS WORK IN PROGRESS
|
||||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# FlashPix support for PIL
|
||||
#
|
||||
# History:
|
||||
# 97-01-25 fl Created (reads uncompressed RGB images only)
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1997.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.1"
|
||||
|
||||
|
||||
import Image, ImageFile
|
||||
from OleFileIO import *
|
||||
|
||||
|
||||
# we map from colour field tuples to (mode, rawmode) descriptors
|
||||
MODES = {
|
||||
# opacity
|
||||
(0x00007ffe): ("A", "L"),
|
||||
# monochrome
|
||||
(0x00010000,): ("L", "L"),
|
||||
(0x00018000, 0x00017ffe): ("RGBA", "LA"),
|
||||
# photo YCC
|
||||
(0x00020000, 0x00020001, 0x00020002): ("RGB", "YCC;P"),
|
||||
(0x00028000, 0x00028001, 0x00028002, 0x00027ffe): ("RGBA", "YCCA;P"),
|
||||
# standard RGB (NIFRGB)
|
||||
(0x00030000, 0x00030001, 0x00030002): ("RGB","RGB"),
|
||||
(0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA","RGBA"),
|
||||
}
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:8] == MAGIC
|
||||
|
||||
##
|
||||
# Image plugin for the FlashPix images.
|
||||
|
||||
class FpxImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "FPX"
|
||||
format_description = "FlashPix"
|
||||
|
||||
def _open(self):
|
||||
#
|
||||
# read the OLE directory and see if this is a likely
|
||||
# to be a FlashPix file
|
||||
|
||||
try:
|
||||
self.ole = OleFileIO(self.fp)
|
||||
except IOError:
|
||||
raise SyntaxError, "not an FPX file; invalid OLE file"
|
||||
|
||||
if self.ole.root.clsid != "56616700-C154-11CE-8553-00AA00A1F95B":
|
||||
raise SyntaxError, "not an FPX file; bad root CLSID"
|
||||
|
||||
self._open_index(1)
|
||||
|
||||
def _open_index(self, index = 1):
|
||||
#
|
||||
# get the Image Contents Property Set
|
||||
|
||||
prop = self.ole.getproperties([
|
||||
"Data Object Store %06d" % index,
|
||||
"\005Image Contents"
|
||||
])
|
||||
|
||||
# size (highest resolution)
|
||||
|
||||
self.size = prop[0x1000002], prop[0x1000003]
|
||||
|
||||
size = max(self.size)
|
||||
i = 1
|
||||
while size > 64:
|
||||
size = size / 2
|
||||
i = i + 1
|
||||
self.maxid = i - 1
|
||||
|
||||
# mode. instead of using a single field for this, flashpix
|
||||
# requires you to specify the mode for each channel in each
|
||||
# resolution subimage, and leaves it to the decoder to make
|
||||
# sure that they all match. for now, we'll cheat and assume
|
||||
# that this is always the case.
|
||||
|
||||
id = self.maxid << 16
|
||||
|
||||
s = prop[0x2000002|id]
|
||||
|
||||
colors = []
|
||||
for i in range(i32(s, 4)):
|
||||
# note: for now, we ignore the "uncalibrated" flag
|
||||
colors.append(i32(s, 8+i*4) & 0x7fffffff)
|
||||
|
||||
self.mode, self.rawmode = MODES[tuple(colors)]
|
||||
|
||||
# load JPEG tables, if any
|
||||
self.jpeg = {}
|
||||
for i in range(256):
|
||||
id = 0x3000001|(i << 16)
|
||||
if prop.has_key(id):
|
||||
self.jpeg[i] = prop[id]
|
||||
|
||||
# print len(self.jpeg), "tables loaded"
|
||||
|
||||
self._open_subimage(1, self.maxid)
|
||||
|
||||
def _open_subimage(self, index = 1, subimage = 0):
|
||||
#
|
||||
# setup tile descriptors for a given subimage
|
||||
|
||||
stream = [
|
||||
"Data Object Store %06d" % index,
|
||||
"Resolution %04d" % subimage,
|
||||
"Subimage 0000 Header"
|
||||
]
|
||||
|
||||
fp = self.ole.openstream(stream)
|
||||
|
||||
# skip prefix
|
||||
p = fp.read(28)
|
||||
|
||||
# header stream
|
||||
s = fp.read(36)
|
||||
|
||||
size = i32(s, 4), i32(s, 8)
|
||||
tilecount = i32(s, 12)
|
||||
tilesize = i32(s, 16), i32(s, 20)
|
||||
channels = i32(s, 24)
|
||||
offset = i32(s, 28)
|
||||
length = i32(s, 32)
|
||||
|
||||
# print size, self.mode, self.rawmode
|
||||
|
||||
if size != self.size:
|
||||
raise IOError, "subimage mismatch"
|
||||
|
||||
# get tile descriptors
|
||||
fp.seek(28 + offset)
|
||||
s = fp.read(i32(s, 12) * length)
|
||||
|
||||
x = y = 0
|
||||
xsize, ysize = size
|
||||
xtile, ytile = tilesize
|
||||
self.tile = []
|
||||
|
||||
for i in range(0, len(s), length):
|
||||
|
||||
compression = i32(s, i+8)
|
||||
|
||||
if compression == 0:
|
||||
self.tile.append(("raw", (x,y,x+xtile,y+ytile),
|
||||
i32(s, i) + 28, (self.rawmode)))
|
||||
|
||||
elif compression == 1:
|
||||
|
||||
# FIXME: the fill decoder is not implemented
|
||||
self.tile.append(("fill", (x,y,x+xtile,y+ytile),
|
||||
i32(s, i) + 28, (self.rawmode, s[12:16])))
|
||||
|
||||
elif compression == 2:
|
||||
|
||||
internal_color_conversion = ord(s[14])
|
||||
jpeg_tables = ord(s[15])
|
||||
rawmode = self.rawmode
|
||||
|
||||
if internal_color_conversion:
|
||||
# The image is stored as usual (usually YCbCr).
|
||||
if rawmode == "RGBA":
|
||||
# For "RGBA", data is stored as YCbCrA based on
|
||||
# negative RGB. The following trick works around
|
||||
# this problem :
|
||||
jpegmode, rawmode = "YCbCrK", "CMYK"
|
||||
else:
|
||||
jpegmode = None # let the decoder decide
|
||||
|
||||
else:
|
||||
# The image is stored as defined by rawmode
|
||||
jpegmode = rawmode
|
||||
|
||||
self.tile.append(("jpeg", (x,y,x+xtile,y+ytile),
|
||||
i32(s, i) + 28, (rawmode, jpegmode)))
|
||||
|
||||
# FIXME: jpeg tables are tile dependent; the prefix
|
||||
# data must be placed in the tile descriptor itself!
|
||||
|
||||
if jpeg_tables:
|
||||
self.tile_prefix = self.jpeg[jpeg_tables]
|
||||
|
||||
else:
|
||||
raise IOError, "unknown/invalid compression"
|
||||
|
||||
x = x + xtile
|
||||
if x >= xsize:
|
||||
x, y = 0, y + ytile
|
||||
if y >= ysize:
|
||||
break # isn't really required
|
||||
|
||||
self.stream = stream
|
||||
self.fp = None
|
||||
|
||||
def load(self):
|
||||
|
||||
if not self.fp:
|
||||
self.fp = self.ole.openstream(self.stream[:2] + ["Subimage 0000 Data"])
|
||||
|
||||
ImageFile.ImageFile.load(self)
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("FPX", FpxImageFile, _accept)
|
||||
|
||||
Image.register_extension("FPX", ".fpx")
|
||||
70
Darwin/lib/python2.7/site-packages/PIL/GbrImagePlugin.py
Normal file
70
Darwin/lib/python2.7/site-packages/PIL/GbrImagePlugin.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# load a GIMP brush file
|
||||
#
|
||||
# History:
|
||||
# 96-03-14 fl Created
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1996.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
def i32(c):
|
||||
return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24L)
|
||||
|
||||
def _accept(prefix):
|
||||
return i32(prefix) >= 20 and i32(prefix[4:8]) == 1
|
||||
|
||||
##
|
||||
# Image plugin for the GIMP brush format.
|
||||
|
||||
class GbrImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "GBR"
|
||||
format_description = "GIMP brush file"
|
||||
|
||||
def _open(self):
|
||||
|
||||
header_size = i32(self.fp.read(4))
|
||||
version = i32(self.fp.read(4))
|
||||
if header_size < 20 or version != 1:
|
||||
raise SyntaxError, "not a GIMP brush"
|
||||
|
||||
width = i32(self.fp.read(4))
|
||||
height = i32(self.fp.read(4))
|
||||
bytes = i32(self.fp.read(4))
|
||||
if width <= 0 or height <= 0 or bytes != 1:
|
||||
raise SyntaxError, "not a GIMP brush"
|
||||
|
||||
comment = self.fp.read(header_size - 20)[:-1]
|
||||
|
||||
self.mode = "L"
|
||||
self.size = width, height
|
||||
|
||||
self.info["comment"] = comment
|
||||
|
||||
# Since the brush is so small, we read the data immediately
|
||||
self.data = self.fp.read(width * height)
|
||||
|
||||
def load(self):
|
||||
|
||||
if not self.data:
|
||||
return
|
||||
|
||||
# create an image out of the brush data block
|
||||
self.im = Image.core.new(self.mode, self.size)
|
||||
self.im.fromstring(self.data)
|
||||
self.data = ""
|
||||
|
||||
#
|
||||
# registry
|
||||
|
||||
Image.register_open("GBR", GbrImageFile, _accept)
|
||||
|
||||
Image.register_extension("GBR", ".gbr")
|
||||
85
Darwin/lib/python2.7/site-packages/PIL/GdImageFile.py
Normal file
85
Darwin/lib/python2.7/site-packages/PIL/GdImageFile.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# GD file handling
|
||||
#
|
||||
# History:
|
||||
# 1996-04-12 fl Created
|
||||
#
|
||||
# Copyright (c) 1997 by Secret Labs AB.
|
||||
# Copyright (c) 1996 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
# NOTE: This format cannot be automatically recognized, so the
|
||||
# class is not registered for use with Image.open(). To open a
|
||||
# gd file, use the GdImageFile.open() function instead.
|
||||
|
||||
# THE GD FORMAT IS NOT DESIGNED FOR DATA INTERCHANGE. This
|
||||
# implementation is provided for convenience and demonstrational
|
||||
# purposes only.
|
||||
|
||||
|
||||
__version__ = "0.1"
|
||||
|
||||
import ImageFile, ImagePalette
|
||||
|
||||
def i16(c):
|
||||
return ord(c[1]) + (ord(c[0])<<8)
|
||||
|
||||
##
|
||||
# Image plugin for the GD uncompressed format. Note that this format
|
||||
# is not supported by the standard <b>Image.open</b> function. To use
|
||||
# this plugin, you have to import the <b>GdImageFile</b> module and
|
||||
# use the <b>GdImageFile.open</b> function.
|
||||
|
||||
class GdImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "GD"
|
||||
format_description = "GD uncompressed images"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# Header
|
||||
s = self.fp.read(775)
|
||||
|
||||
self.mode = "L" # FIXME: "P"
|
||||
self.size = i16(s[0:2]), i16(s[2:4])
|
||||
|
||||
# transparency index
|
||||
tindex = i16(s[5:7])
|
||||
if tindex < 256:
|
||||
self.info["transparent"] = tindex
|
||||
|
||||
self.palette = ImagePalette.raw("RGB", s[7:])
|
||||
|
||||
self.tile = [("raw", (0,0)+self.size, 775, ("L", 0, -1))]
|
||||
|
||||
##
|
||||
# Load texture from a GD image file.
|
||||
#
|
||||
# @param filename GD file name, or an opened file handle.
|
||||
# @param mode Optional mode. In this version, if the mode argument
|
||||
# is given, it must be "r".
|
||||
# @return An image instance.
|
||||
# @exception IOError If the image could not be read.
|
||||
|
||||
def open(fp, mode = "r"):
|
||||
|
||||
if mode != "r":
|
||||
raise ValueError("bad mode")
|
||||
|
||||
if type(fp) == type(""):
|
||||
import __builtin__
|
||||
filename = fp
|
||||
fp = __builtin__.open(fp, "rb")
|
||||
else:
|
||||
filename = ""
|
||||
|
||||
try:
|
||||
return GdImageFile(fp, filename)
|
||||
except SyntaxError:
|
||||
raise IOError("cannot identify this image file")
|
||||
407
Darwin/lib/python2.7/site-packages/PIL/GifImagePlugin.py
Normal file
407
Darwin/lib/python2.7/site-packages/PIL/GifImagePlugin.py
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# GIF file handling
|
||||
#
|
||||
# History:
|
||||
# 1995-09-01 fl Created
|
||||
# 1996-12-14 fl Added interlace support
|
||||
# 1996-12-30 fl Added animation support
|
||||
# 1997-01-05 fl Added write support, fixed local colour map bug
|
||||
# 1997-02-23 fl Make sure to load raster data in getdata()
|
||||
# 1997-07-05 fl Support external decoder (0.4)
|
||||
# 1998-07-09 fl Handle all modes when saving (0.5)
|
||||
# 1998-07-15 fl Renamed offset attribute to avoid name clash
|
||||
# 2001-04-16 fl Added rewind support (seek to frame 0) (0.6)
|
||||
# 2001-04-17 fl Added palette optimization (0.7)
|
||||
# 2002-06-06 fl Added transparency support for save (0.8)
|
||||
# 2004-02-24 fl Disable interlacing for small images
|
||||
#
|
||||
# Copyright (c) 1997-2004 by Secret Labs AB
|
||||
# Copyright (c) 1995-2004 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.9"
|
||||
|
||||
|
||||
import Image, ImageFile, ImagePalette
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Helpers
|
||||
|
||||
def i16(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8)
|
||||
|
||||
def o16(i):
|
||||
return chr(i&255) + chr(i>>8&255)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Identify/read GIF files
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:6] in ["GIF87a", "GIF89a"]
|
||||
|
||||
##
|
||||
# Image plugin for GIF images. This plugin supports both GIF87 and
|
||||
# GIF89 images.
|
||||
|
||||
class GifImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "GIF"
|
||||
format_description = "Compuserve GIF"
|
||||
|
||||
global_palette = None
|
||||
|
||||
def data(self):
|
||||
s = self.fp.read(1)
|
||||
if s and ord(s):
|
||||
return self.fp.read(ord(s))
|
||||
return None
|
||||
|
||||
def _open(self):
|
||||
|
||||
# Screen
|
||||
s = self.fp.read(13)
|
||||
if s[:6] not in ["GIF87a", "GIF89a"]:
|
||||
raise SyntaxError, "not a GIF file"
|
||||
|
||||
self.info["version"] = s[:6]
|
||||
|
||||
self.size = i16(s[6:]), i16(s[8:])
|
||||
|
||||
self.tile = []
|
||||
|
||||
flags = ord(s[10])
|
||||
|
||||
bits = (flags & 7) + 1
|
||||
|
||||
if flags & 128:
|
||||
# get global palette
|
||||
self.info["background"] = ord(s[11])
|
||||
# check if palette contains colour indices
|
||||
p = self.fp.read(3<<bits)
|
||||
for i in range(0, len(p), 3):
|
||||
if not (chr(i/3) == p[i] == p[i+1] == p[i+2]):
|
||||
p = ImagePalette.raw("RGB", p)
|
||||
self.global_palette = self.palette = p
|
||||
break
|
||||
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self.__rewind = self.fp.tell()
|
||||
self.seek(0) # get ready to read first frame
|
||||
|
||||
def seek(self, frame):
|
||||
|
||||
if frame == 0:
|
||||
# rewind
|
||||
self.__offset = 0
|
||||
self.dispose = None
|
||||
self.__frame = -1
|
||||
self.__fp.seek(self.__rewind)
|
||||
|
||||
if frame != self.__frame + 1:
|
||||
raise ValueError, "cannot seek to frame %d" % frame
|
||||
self.__frame = frame
|
||||
|
||||
self.tile = []
|
||||
|
||||
self.fp = self.__fp
|
||||
if self.__offset:
|
||||
# backup to last frame
|
||||
self.fp.seek(self.__offset)
|
||||
while self.data():
|
||||
pass
|
||||
self.__offset = 0
|
||||
|
||||
if self.dispose:
|
||||
self.im = self.dispose
|
||||
self.dispose = None
|
||||
|
||||
self.palette = self.global_palette
|
||||
|
||||
while 1:
|
||||
|
||||
s = self.fp.read(1)
|
||||
if not s or s == ";":
|
||||
break
|
||||
|
||||
elif s == "!":
|
||||
#
|
||||
# extensions
|
||||
#
|
||||
s = self.fp.read(1)
|
||||
block = self.data()
|
||||
if ord(s) == 249:
|
||||
#
|
||||
# graphic control extension
|
||||
#
|
||||
flags = ord(block[0])
|
||||
if flags & 1:
|
||||
self.info["transparency"] = ord(block[3])
|
||||
self.info["duration"] = i16(block[1:3]) * 10
|
||||
try:
|
||||
# disposal methods
|
||||
if flags & 8:
|
||||
# replace with background colour
|
||||
self.dispose = Image.core.fill("P", self.size,
|
||||
self.info["background"])
|
||||
elif flags & 16:
|
||||
# replace with previous contents
|
||||
self.dispose = self.im.copy()
|
||||
except (AttributeError, KeyError):
|
||||
pass
|
||||
elif ord(s) == 255:
|
||||
#
|
||||
# application extension
|
||||
#
|
||||
self.info["extension"] = block, self.fp.tell()
|
||||
if block[:11] == "NETSCAPE2.0":
|
||||
block = self.data()
|
||||
if len(block) >= 3 and ord(block[0]) == 1:
|
||||
self.info["loop"] = i16(block[1:3])
|
||||
while self.data():
|
||||
pass
|
||||
|
||||
elif s == ",":
|
||||
#
|
||||
# local image
|
||||
#
|
||||
s = self.fp.read(9)
|
||||
|
||||
# extent
|
||||
x0, y0 = i16(s[0:]), i16(s[2:])
|
||||
x1, y1 = x0 + i16(s[4:]), y0 + i16(s[6:])
|
||||
flags = ord(s[8])
|
||||
|
||||
interlace = (flags & 64) != 0
|
||||
|
||||
if flags & 128:
|
||||
bits = (flags & 7) + 1
|
||||
self.palette =\
|
||||
ImagePalette.raw("RGB", self.fp.read(3<<bits))
|
||||
|
||||
# image data
|
||||
bits = ord(self.fp.read(1))
|
||||
self.__offset = self.fp.tell()
|
||||
self.tile = [("gif",
|
||||
(x0, y0, x1, y1),
|
||||
self.__offset,
|
||||
(bits, interlace))]
|
||||
break
|
||||
|
||||
else:
|
||||
pass
|
||||
# raise IOError, "illegal GIF tag `%x`" % ord(s)
|
||||
|
||||
if not self.tile:
|
||||
# self.__fp = None
|
||||
raise EOFError, "no more images in GIF file"
|
||||
|
||||
self.mode = "L"
|
||||
if self.palette:
|
||||
self.mode = "P"
|
||||
|
||||
def tell(self):
|
||||
return self.__frame
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Write GIF files
|
||||
|
||||
try:
|
||||
import _imaging_gif
|
||||
except ImportError:
|
||||
_imaging_gif = None
|
||||
|
||||
RAWMODE = {
|
||||
"1": "L",
|
||||
"L": "L",
|
||||
"P": "P",
|
||||
}
|
||||
|
||||
def _save(im, fp, filename):
|
||||
|
||||
if _imaging_gif:
|
||||
# call external driver
|
||||
try:
|
||||
_imaging_gif.save(im, fp, filename)
|
||||
return
|
||||
except IOError:
|
||||
pass # write uncompressed file
|
||||
|
||||
try:
|
||||
rawmode = RAWMODE[im.mode]
|
||||
imOut = im
|
||||
except KeyError:
|
||||
# convert on the fly (EXPERIMENTAL -- I'm not sure PIL
|
||||
# should automatically convert images on save...)
|
||||
if Image.getmodebase(im.mode) == "RGB":
|
||||
imOut = im.convert("P")
|
||||
rawmode = "P"
|
||||
else:
|
||||
imOut = im.convert("L")
|
||||
rawmode = "L"
|
||||
|
||||
# header
|
||||
for s in getheader(imOut, im.encoderinfo):
|
||||
fp.write(s)
|
||||
|
||||
flags = 0
|
||||
|
||||
try:
|
||||
interlace = im.encoderinfo["interlace"]
|
||||
except KeyError:
|
||||
interlace = 1
|
||||
|
||||
# workaround for @PIL153
|
||||
if min(im.size) < 16:
|
||||
interlace = 0
|
||||
|
||||
if interlace:
|
||||
flags = flags | 64
|
||||
|
||||
try:
|
||||
transparency = im.encoderinfo["transparency"]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
# transparency extension block
|
||||
fp.write("!" +
|
||||
chr(249) + # extension intro
|
||||
chr(4) + # length
|
||||
chr(1) + # transparency info present
|
||||
o16(0) + # duration
|
||||
chr(int(transparency)) # transparency index
|
||||
+ chr(0))
|
||||
|
||||
# local image header
|
||||
fp.write("," +
|
||||
o16(0) + o16(0) + # bounding box
|
||||
o16(im.size[0]) + # size
|
||||
o16(im.size[1]) +
|
||||
chr(flags) + # flags
|
||||
chr(8)) # bits
|
||||
|
||||
imOut.encoderconfig = (8, interlace)
|
||||
|
||||
ImageFile._save(imOut, fp, [("gif", (0,0)+im.size, 0, rawmode)])
|
||||
|
||||
fp.write("\0") # end of image data
|
||||
|
||||
fp.write(";") # end of file
|
||||
|
||||
try:
|
||||
fp.flush()
|
||||
except: pass
|
||||
|
||||
def _save_netpbm(im, fp, filename):
|
||||
|
||||
#
|
||||
# If you need real GIF compression and/or RGB quantization, you
|
||||
# can use the external NETPBM/PBMPLUS utilities. See comments
|
||||
# below for information on how to enable this.
|
||||
|
||||
import os
|
||||
file = im._dump()
|
||||
if im.mode != "RGB":
|
||||
os.system("ppmtogif %s >%s" % (file, filename))
|
||||
else:
|
||||
os.system("ppmquant 256 %s | ppmtogif >%s" % (file, filename))
|
||||
try: os.unlink(file)
|
||||
except: pass
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# GIF utilities
|
||||
|
||||
def getheader(im, info=None):
|
||||
"""Return a list of strings representing a GIF header"""
|
||||
|
||||
optimize = info and info.get("optimize", 0)
|
||||
|
||||
s = [
|
||||
"GIF87a" + # magic
|
||||
o16(im.size[0]) + # size
|
||||
o16(im.size[1]) +
|
||||
chr(7 + 128) + # flags: bits + palette
|
||||
chr(0) + # background
|
||||
chr(0) # reserved/aspect
|
||||
]
|
||||
|
||||
if optimize:
|
||||
# minimize color palette
|
||||
i = 0
|
||||
maxcolor = 0
|
||||
for count in im.histogram():
|
||||
if count:
|
||||
maxcolor = i
|
||||
i = i + 1
|
||||
else:
|
||||
maxcolor = 256
|
||||
|
||||
# global palette
|
||||
if im.mode == "P":
|
||||
# colour palette
|
||||
s.append(im.im.getpalette("RGB")[:maxcolor*3])
|
||||
else:
|
||||
# greyscale
|
||||
for i in range(maxcolor):
|
||||
s.append(chr(i) * 3)
|
||||
|
||||
return s
|
||||
|
||||
def getdata(im, offset = (0, 0), **params):
|
||||
"""Return a list of strings representing this image.
|
||||
The first string is a local image header, the rest contains
|
||||
encoded image data."""
|
||||
|
||||
class collector:
|
||||
data = []
|
||||
def write(self, data):
|
||||
self.data.append(data)
|
||||
|
||||
im.load() # make sure raster data is available
|
||||
|
||||
fp = collector()
|
||||
|
||||
try:
|
||||
im.encoderinfo = params
|
||||
|
||||
# local image header
|
||||
fp.write("," +
|
||||
o16(offset[0]) + # offset
|
||||
o16(offset[1]) +
|
||||
o16(im.size[0]) + # size
|
||||
o16(im.size[1]) +
|
||||
chr(0) + # flags
|
||||
chr(8)) # bits
|
||||
|
||||
ImageFile._save(im, fp, [("gif", (0,0)+im.size, 0, RAWMODE[im.mode])])
|
||||
|
||||
fp.write("\0") # end of image data
|
||||
|
||||
finally:
|
||||
del im.encoderinfo
|
||||
|
||||
return fp.data
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Registry
|
||||
|
||||
Image.register_open(GifImageFile.format, GifImageFile, _accept)
|
||||
Image.register_save(GifImageFile.format, _save)
|
||||
Image.register_extension(GifImageFile.format, ".gif")
|
||||
Image.register_mime(GifImageFile.format, "image/gif")
|
||||
|
||||
#
|
||||
# Uncomment the following line if you wish to use NETPBM/PBMPLUS
|
||||
# instead of the built-in "uncompressed" GIF encoder
|
||||
|
||||
# Image.register_save(GifImageFile.format, _save_netpbm)
|
||||
124
Darwin/lib/python2.7/site-packages/PIL/GimpGradientFile.py
Normal file
124
Darwin/lib/python2.7/site-packages/PIL/GimpGradientFile.py
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
#
|
||||
# Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# stuff to read (and render) GIMP gradient files
|
||||
#
|
||||
# History:
|
||||
# 97-08-23 fl Created
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1997.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
from math import pi, log, sin, sqrt
|
||||
import string
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Stuff to translate curve segments to palette values (derived from
|
||||
# the corresponding code in GIMP, written by Federico Mena Quintero.
|
||||
# See the GIMP distribution for more information.)
|
||||
#
|
||||
|
||||
EPSILON = 1e-10
|
||||
|
||||
def linear(middle, pos):
|
||||
if pos <= middle:
|
||||
if middle < EPSILON:
|
||||
return 0.0
|
||||
else:
|
||||
return 0.5 * pos / middle
|
||||
else:
|
||||
pos = pos - middle
|
||||
middle = 1.0 - middle
|
||||
if middle < EPSILON:
|
||||
return 1.0
|
||||
else:
|
||||
return 0.5 + 0.5 * pos / middle
|
||||
|
||||
def curved(middle, pos):
|
||||
return pos ** (log(0.5) / log(max(middle, EPSILON)))
|
||||
|
||||
def sine(middle, pos):
|
||||
return (sin((-pi / 2.0) + pi * linear(middle, pos)) + 1.0) / 2.0
|
||||
|
||||
def sphere_increasing(middle, pos):
|
||||
return sqrt(1.0 - (linear(middle, pos) - 1.0) ** 2)
|
||||
|
||||
def sphere_decreasing(middle, pos):
|
||||
return 1.0 - sqrt(1.0 - linear(middle, pos) ** 2)
|
||||
|
||||
SEGMENTS = [ linear, curved, sine, sphere_increasing, sphere_decreasing ]
|
||||
|
||||
class GradientFile:
|
||||
|
||||
gradient = None
|
||||
|
||||
def getpalette(self, entries = 256):
|
||||
|
||||
palette = []
|
||||
|
||||
ix = 0
|
||||
x0, x1, xm, rgb0, rgb1, segment = self.gradient[ix]
|
||||
|
||||
for i in range(entries):
|
||||
|
||||
x = i / float(entries-1)
|
||||
|
||||
while x1 < x:
|
||||
ix = ix + 1
|
||||
x0, x1, xm, rgb0, rgb1, segment = self.gradient[ix]
|
||||
|
||||
w = x1 - x0
|
||||
|
||||
if w < EPSILON:
|
||||
scale = segment(0.5, 0.5)
|
||||
else:
|
||||
scale = segment((xm - x0) / w, (x - x0) / w)
|
||||
|
||||
# expand to RGBA
|
||||
r = chr(int(255 * ((rgb1[0] - rgb0[0]) * scale + rgb0[0]) + 0.5))
|
||||
g = chr(int(255 * ((rgb1[1] - rgb0[1]) * scale + rgb0[1]) + 0.5))
|
||||
b = chr(int(255 * ((rgb1[2] - rgb0[2]) * scale + rgb0[2]) + 0.5))
|
||||
a = chr(int(255 * ((rgb1[3] - rgb0[3]) * scale + rgb0[3]) + 0.5))
|
||||
|
||||
# add to palette
|
||||
palette.append(r + g + b + a)
|
||||
|
||||
return string.join(palette, ""), "RGBA"
|
||||
|
||||
##
|
||||
# File handler for GIMP's gradient format.
|
||||
|
||||
class GimpGradientFile(GradientFile):
|
||||
|
||||
def __init__(self, fp):
|
||||
|
||||
if fp.readline()[:13] != "GIMP Gradient":
|
||||
raise SyntaxError, "not a GIMP gradient file"
|
||||
|
||||
count = int(fp.readline())
|
||||
|
||||
gradient = []
|
||||
|
||||
for i in range(count):
|
||||
|
||||
s = string.split(fp.readline())
|
||||
w = map(float, s[:11])
|
||||
|
||||
x0, x1 = w[0], w[2]
|
||||
xm = w[1]
|
||||
rgb0 = w[3:7]
|
||||
rgb1 = w[7:11]
|
||||
|
||||
segment = SEGMENTS[int(s[11])]
|
||||
cspace = int(s[12])
|
||||
|
||||
if cspace != 0:
|
||||
raise IOError, "cannot handle HSV colour space"
|
||||
|
||||
gradient.append((x0, x1, xm, rgb0, rgb1, segment))
|
||||
|
||||
self.gradient = gradient
|
||||
61
Darwin/lib/python2.7/site-packages/PIL/GimpPaletteFile.py
Normal file
61
Darwin/lib/python2.7/site-packages/PIL/GimpPaletteFile.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#
|
||||
# Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# stuff to read GIMP palette files
|
||||
#
|
||||
# History:
|
||||
# 1997-08-23 fl Created
|
||||
# 2004-09-07 fl Support GIMP 2.0 palette files.
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997-2004. All rights reserved.
|
||||
# Copyright (c) Fredrik Lundh 1997-2004.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import re, string
|
||||
|
||||
##
|
||||
# File handler for GIMP's palette format.
|
||||
|
||||
class GimpPaletteFile:
|
||||
|
||||
rawmode = "RGB"
|
||||
|
||||
def __init__(self, fp):
|
||||
|
||||
self.palette = map(lambda i: chr(i)*3, range(256))
|
||||
|
||||
if fp.readline()[:12] != "GIMP Palette":
|
||||
raise SyntaxError, "not a GIMP palette file"
|
||||
|
||||
i = 0
|
||||
|
||||
while i <= 255:
|
||||
|
||||
s = fp.readline()
|
||||
|
||||
if not s:
|
||||
break
|
||||
# skip fields and comment lines
|
||||
if re.match("\w+:|#", s):
|
||||
continue
|
||||
if len(s) > 100:
|
||||
raise SyntaxError, "bad palette file"
|
||||
|
||||
v = tuple(map(int, string.split(s)[:3]))
|
||||
if len(v) != 3:
|
||||
raise ValueError, "bad palette entry"
|
||||
|
||||
if 0 <= i <= 255:
|
||||
self.palette[i] = chr(v[0]) + chr(v[1]) + chr(v[2])
|
||||
|
||||
i = i + 1
|
||||
|
||||
self.palette = string.join(self.palette, "")
|
||||
|
||||
|
||||
def getpalette(self):
|
||||
|
||||
return self.palette, self.rawmode
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# GRIB stub adapter
|
||||
#
|
||||
# Copyright (c) 1996-2003 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
_handler = None
|
||||
|
||||
##
|
||||
# Install application-specific GRIB image handler.
|
||||
#
|
||||
# @param handler Handler object.
|
||||
|
||||
def register_handler(handler):
|
||||
global _handler
|
||||
_handler = handler
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Image adapter
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[0:4] == "GRIB" and prefix[7] == chr(1)
|
||||
|
||||
class GribStubImageFile(ImageFile.StubImageFile):
|
||||
|
||||
format = "GRIB"
|
||||
format_description = "GRIB"
|
||||
|
||||
def _open(self):
|
||||
|
||||
offset = self.fp.tell()
|
||||
|
||||
if not _accept(self.fp.read(8)):
|
||||
raise SyntaxError("Not a GRIB file")
|
||||
|
||||
self.fp.seek(offset)
|
||||
|
||||
# make something up
|
||||
self.mode = "F"
|
||||
self.size = 1, 1
|
||||
|
||||
loader = self._load()
|
||||
if loader:
|
||||
loader.open(self)
|
||||
|
||||
def _load(self):
|
||||
return _handler
|
||||
|
||||
def _save(im, fp, filename):
|
||||
if _handler is None or not hasattr("_handler", "save"):
|
||||
raise IOError("GRIB save handler not installed")
|
||||
_handler.save(im, fp, filename)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Registry
|
||||
|
||||
Image.register_open(GribStubImageFile.format, GribStubImageFile, _accept)
|
||||
Image.register_save(GribStubImageFile.format, _save)
|
||||
|
||||
Image.register_extension(GribStubImageFile.format, ".grib")
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# HDF5 stub adapter
|
||||
#
|
||||
# Copyright (c) 2000-2003 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
_handler = None
|
||||
|
||||
##
|
||||
# Install application-specific HDF5 image handler.
|
||||
#
|
||||
# @param handler Handler object.
|
||||
|
||||
def register_handler(handler):
|
||||
global _handler
|
||||
_handler = handler
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Image adapter
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:8] == "\x89HDF\r\n\x1a\n"
|
||||
|
||||
class HDF5StubImageFile(ImageFile.StubImageFile):
|
||||
|
||||
format = "HDF5"
|
||||
format_description = "HDF5"
|
||||
|
||||
def _open(self):
|
||||
|
||||
offset = self.fp.tell()
|
||||
|
||||
if not _accept(self.fp.read(8)):
|
||||
raise SyntaxError("Not an HDF file")
|
||||
|
||||
self.fp.seek(offset)
|
||||
|
||||
# make something up
|
||||
self.mode = "F"
|
||||
self.size = 1, 1
|
||||
|
||||
loader = self._load()
|
||||
if loader:
|
||||
loader.open(self)
|
||||
|
||||
def _load(self):
|
||||
return _handler
|
||||
|
||||
|
||||
def _save(im, fp, filename):
|
||||
if _handler is None or not hasattr("_handler", "save"):
|
||||
raise IOError("HDF5 save handler not installed")
|
||||
_handler.save(im, fp, filename)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Registry
|
||||
|
||||
Image.register_open(HDF5StubImageFile.format, HDF5StubImageFile, _accept)
|
||||
Image.register_save(HDF5StubImageFile.format, _save)
|
||||
|
||||
Image.register_extension(HDF5StubImageFile.format, ".h5")
|
||||
Image.register_extension(HDF5StubImageFile.format, ".hdf")
|
||||
211
Darwin/lib/python2.7/site-packages/PIL/IcnsImagePlugin.py
Normal file
211
Darwin/lib/python2.7/site-packages/PIL/IcnsImagePlugin.py
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# Mac OS X icns file decoder, based on icns.py by Bob Ippolito.
|
||||
#
|
||||
# history:
|
||||
# 2004-10-09 fl Turned into a PIL plugin; removed 2.3 dependencies.
|
||||
#
|
||||
# Copyright (c) 2004 by Bob Ippolito.
|
||||
# Copyright (c) 2004 by Secret Labs.
|
||||
# Copyright (c) 2004 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image, ImageFile
|
||||
import string, struct
|
||||
|
||||
HEADERSIZE = 8
|
||||
|
||||
def nextheader(fobj):
|
||||
return struct.unpack('>4sI', fobj.read(HEADERSIZE))
|
||||
|
||||
def read_32t(fobj, (start, length), (width, height)):
|
||||
# The 128x128 icon seems to have an extra header for some reason.
|
||||
fobj.seek(start)
|
||||
sig = fobj.read(4)
|
||||
if sig != '\x00\x00\x00\x00':
|
||||
raise SyntaxError, 'Unknown signature, expecting 0x00000000'
|
||||
return read_32(fobj, (start + 4, length - 4), (width, height))
|
||||
|
||||
def read_32(fobj, (start, length), size):
|
||||
"""
|
||||
Read a 32bit RGB icon resource. Seems to be either uncompressed or
|
||||
an RLE packbits-like scheme.
|
||||
"""
|
||||
fobj.seek(start)
|
||||
sizesq = size[0] * size[1]
|
||||
if length == sizesq * 3:
|
||||
# uncompressed ("RGBRGBGB")
|
||||
indata = fobj.read(length)
|
||||
im = Image.frombuffer("RGB", size, indata, "raw", "RGB", 0, 1)
|
||||
else:
|
||||
# decode image
|
||||
im = Image.new("RGB", size, None)
|
||||
for band_ix in range(3):
|
||||
data = []
|
||||
bytesleft = sizesq
|
||||
while bytesleft > 0:
|
||||
byte = fobj.read(1)
|
||||
if not byte:
|
||||
break
|
||||
byte = ord(byte)
|
||||
if byte & 0x80:
|
||||
blocksize = byte - 125
|
||||
byte = fobj.read(1)
|
||||
for i in range(blocksize):
|
||||
data.append(byte)
|
||||
else:
|
||||
blocksize = byte + 1
|
||||
data.append(fobj.read(blocksize))
|
||||
bytesleft = bytesleft - blocksize
|
||||
if bytesleft <= 0:
|
||||
break
|
||||
if bytesleft != 0:
|
||||
raise SyntaxError(
|
||||
"Error reading channel [%r left]" % bytesleft
|
||||
)
|
||||
band = Image.frombuffer(
|
||||
"L", size, string.join(data, ""), "raw", "L", 0, 1
|
||||
)
|
||||
im.im.putband(band.im, band_ix)
|
||||
return {"RGB": im}
|
||||
|
||||
def read_mk(fobj, (start, length), size):
|
||||
# Alpha masks seem to be uncompressed
|
||||
fobj.seek(start)
|
||||
band = Image.frombuffer(
|
||||
"L", size, fobj.read(size[0]*size[1]), "raw", "L", 0, 1
|
||||
)
|
||||
return {"A": band}
|
||||
|
||||
class IcnsFile:
|
||||
|
||||
SIZES = {
|
||||
(128, 128): [
|
||||
('it32', read_32t),
|
||||
('t8mk', read_mk),
|
||||
],
|
||||
(48, 48): [
|
||||
('ih32', read_32),
|
||||
('h8mk', read_mk),
|
||||
],
|
||||
(32, 32): [
|
||||
('il32', read_32),
|
||||
('l8mk', read_mk),
|
||||
],
|
||||
(16, 16): [
|
||||
('is32', read_32),
|
||||
('s8mk', read_mk),
|
||||
],
|
||||
}
|
||||
|
||||
def __init__(self, fobj):
|
||||
"""
|
||||
fobj is a file-like object as an icns resource
|
||||
"""
|
||||
# signature : (start, length)
|
||||
self.dct = dct = {}
|
||||
self.fobj = fobj
|
||||
sig, filesize = nextheader(fobj)
|
||||
if sig != 'icns':
|
||||
raise SyntaxError, 'not an icns file'
|
||||
i = HEADERSIZE
|
||||
while i < filesize:
|
||||
sig, blocksize = nextheader(fobj)
|
||||
i = i + HEADERSIZE
|
||||
blocksize = blocksize - HEADERSIZE
|
||||
dct[sig] = (i, blocksize)
|
||||
fobj.seek(blocksize, 1)
|
||||
i = i + blocksize
|
||||
|
||||
def itersizes(self):
|
||||
sizes = []
|
||||
for size, fmts in self.SIZES.items():
|
||||
for (fmt, reader) in fmts:
|
||||
if self.dct.has_key(fmt):
|
||||
sizes.append(size)
|
||||
break
|
||||
return sizes
|
||||
|
||||
def bestsize(self):
|
||||
sizes = self.itersizes()
|
||||
if not sizes:
|
||||
raise SyntaxError, "No 32bit icon resources found"
|
||||
return max(sizes)
|
||||
|
||||
def dataforsize(self, size):
|
||||
"""
|
||||
Get an icon resource as {channel: array}. Note that
|
||||
the arrays are bottom-up like windows bitmaps and will likely
|
||||
need to be flipped or transposed in some way.
|
||||
"""
|
||||
dct = {}
|
||||
for code, reader in self.SIZES[size]:
|
||||
desc = self.dct.get(code)
|
||||
if desc is not None:
|
||||
dct.update(reader(self.fobj, desc, size))
|
||||
return dct
|
||||
|
||||
def getimage(self, size=None):
|
||||
if size is None:
|
||||
size = self.bestsize()
|
||||
channels = self.dataforsize(size)
|
||||
im = channels.get("RGB").copy()
|
||||
try:
|
||||
im.putalpha(channels["A"])
|
||||
except KeyError:
|
||||
pass
|
||||
return im
|
||||
|
||||
##
|
||||
# Image plugin for Mac OS icons.
|
||||
|
||||
class IcnsImageFile(ImageFile.ImageFile):
|
||||
"""
|
||||
PIL read-only image support for Mac OS .icns files.
|
||||
Chooses the best resolution, but will possibly load
|
||||
a different size image if you mutate the size attribute
|
||||
before calling 'load'.
|
||||
|
||||
The info dictionary has a key 'sizes' that is a list
|
||||
of sizes that the icns file has.
|
||||
"""
|
||||
|
||||
format = "ICNS"
|
||||
format_description = "Mac OS icns resource"
|
||||
|
||||
def _open(self):
|
||||
self.icns = IcnsFile(self.fp)
|
||||
self.mode = 'RGBA'
|
||||
self.size = self.icns.bestsize()
|
||||
self.info['sizes'] = self.icns.itersizes()
|
||||
# Just use this to see if it's loaded or not yet.
|
||||
self.tile = ('',)
|
||||
|
||||
def load(self):
|
||||
Image.Image.load(self)
|
||||
if not self.tile:
|
||||
return
|
||||
self.load_prepare()
|
||||
# This is likely NOT the best way to do it, but whatever.
|
||||
im = self.icns.getimage(self.size)
|
||||
self.im = im.im
|
||||
self.mode = im.mode
|
||||
self.size = im.size
|
||||
self.fp = None
|
||||
self.icns = None
|
||||
self.tile = ()
|
||||
self.load_end()
|
||||
|
||||
|
||||
Image.register_open("ICNS", IcnsImageFile, lambda x: x[:4] == 'icns')
|
||||
Image.register_extension("ICNS", '.icns')
|
||||
|
||||
if __name__ == '__main__':
|
||||
import os, sys
|
||||
im = Image.open(open(sys.argv[1], "rb"))
|
||||
im.save("out.png")
|
||||
os.startfile("out.png")
|
||||
86
Darwin/lib/python2.7/site-packages/PIL/IcoImagePlugin.py
Normal file
86
Darwin/lib/python2.7/site-packages/PIL/IcoImagePlugin.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# Windows Icon support for PIL
|
||||
#
|
||||
# Notes:
|
||||
# uses BmpImagePlugin.py to read the bitmap data.
|
||||
#
|
||||
# History:
|
||||
# 96-05-27 fl Created
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1996.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.1"
|
||||
|
||||
import Image, BmpImagePlugin
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
def i16(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8)
|
||||
|
||||
def i32(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] == "\0\0\1\0"
|
||||
|
||||
##
|
||||
# Image plugin for Windows Icon files.
|
||||
|
||||
class IcoImageFile(BmpImagePlugin.BmpImageFile):
|
||||
|
||||
format = "ICO"
|
||||
format_description = "Windows Icon"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# check magic
|
||||
s = self.fp.read(6)
|
||||
if not _accept(s):
|
||||
raise SyntaxError, "not an ICO file"
|
||||
|
||||
# pick the largest icon in the file
|
||||
m = ""
|
||||
for i in range(i16(s[4:])):
|
||||
s = self.fp.read(16)
|
||||
if not m:
|
||||
m = s
|
||||
elif ord(s[0]) > ord(m[0]) and ord(s[1]) > ord(m[1]):
|
||||
m = s
|
||||
#print "width", ord(s[0])
|
||||
#print "height", ord(s[1])
|
||||
#print "colors", ord(s[2])
|
||||
#print "reserved", ord(s[3])
|
||||
#print "planes", i16(s[4:])
|
||||
#print "bitcount", i16(s[6:])
|
||||
#print "bytes", i32(s[8:])
|
||||
#print "offset", i32(s[12:])
|
||||
|
||||
# load as bitmap
|
||||
self._bitmap(i32(m[12:]))
|
||||
|
||||
# patch up the bitmap height
|
||||
self.size = self.size[0], self.size[1]/2
|
||||
d, e, o, a = self.tile[0]
|
||||
self.tile[0] = d, (0,0)+self.size, o, a
|
||||
|
||||
return
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("ICO", IcoImageFile, _accept)
|
||||
|
||||
Image.register_extension("ICO", ".ico")
|
||||
336
Darwin/lib/python2.7/site-packages/PIL/ImImagePlugin.py
Normal file
336
Darwin/lib/python2.7/site-packages/PIL/ImImagePlugin.py
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# IFUNC IM file handling for PIL
|
||||
#
|
||||
# history:
|
||||
# 1995-09-01 fl Created.
|
||||
# 1997-01-03 fl Save palette images
|
||||
# 1997-01-08 fl Added sequence support
|
||||
# 1997-01-23 fl Added P and RGB save support
|
||||
# 1997-05-31 fl Read floating point images
|
||||
# 1997-06-22 fl Save floating point images
|
||||
# 1997-08-27 fl Read and save 1-bit images
|
||||
# 1998-06-25 fl Added support for RGB+LUT images
|
||||
# 1998-07-02 fl Added support for YCC images
|
||||
# 1998-07-15 fl Renamed offset attribute to avoid name clash
|
||||
# 1998-12-29 fl Added I;16 support
|
||||
# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.7)
|
||||
# 2003-09-26 fl Added LA/PA support
|
||||
#
|
||||
# Copyright (c) 1997-2003 by Secret Labs AB.
|
||||
# Copyright (c) 1995-2001 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.7"
|
||||
|
||||
import re, string
|
||||
import Image, ImageFile, ImagePalette
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Standard tags
|
||||
|
||||
COMMENT = "Comment"
|
||||
DATE = "Date"
|
||||
EQUIPMENT = "Digitalization equipment"
|
||||
FRAMES = "File size (no of images)"
|
||||
LUT = "Lut"
|
||||
NAME = "Name"
|
||||
SCALE = "Scale (x,y)"
|
||||
SIZE = "Image size (x*y)"
|
||||
MODE = "Image type"
|
||||
|
||||
TAGS = { COMMENT:0, DATE:0, EQUIPMENT:0, FRAMES:0, LUT:0, NAME:0,
|
||||
SCALE:0, SIZE:0, MODE:0 }
|
||||
|
||||
OPEN = {
|
||||
# ifunc93/p3cfunc formats
|
||||
"0 1 image": ("1", "1"),
|
||||
"L 1 image": ("1", "1"),
|
||||
"Greyscale image": ("L", "L"),
|
||||
"Grayscale image": ("L", "L"),
|
||||
"RGB image": ("RGB", "RGB;L"),
|
||||
"RLB image": ("RGB", "RLB"),
|
||||
"RYB image": ("RGB", "RLB"),
|
||||
"B1 image": ("1", "1"),
|
||||
"B2 image": ("P", "P;2"),
|
||||
"B4 image": ("P", "P;4"),
|
||||
"X 24 image": ("RGB", "RGB"),
|
||||
"L 32 S image": ("I", "I;32"),
|
||||
"L 32 F image": ("F", "F;32"),
|
||||
# old p3cfunc formats
|
||||
"RGB3 image": ("RGB", "RGB;T"),
|
||||
"RYB3 image": ("RGB", "RYB;T"),
|
||||
# extensions
|
||||
"LA image": ("LA", "LA;L"),
|
||||
"RGBA image": ("RGBA", "RGBA;L"),
|
||||
"RGBX image": ("RGBX", "RGBX;L"),
|
||||
"CMYK image": ("CMYK", "CMYK;L"),
|
||||
"YCC image": ("YCbCr", "YCbCr;L"),
|
||||
}
|
||||
|
||||
# ifunc95 extensions
|
||||
for i in ["8", "8S", "16", "16S", "32", "32F"]:
|
||||
OPEN["L %s image" % i] = ("F", "F;%s" % i)
|
||||
OPEN["L*%s image" % i] = ("F", "F;%s" % i)
|
||||
for i in ["16", "16L", "16B"]:
|
||||
OPEN["L %s image" % i] = ("I;%s" % i, "I;%s" % i)
|
||||
OPEN["L*%s image" % i] = ("I;%s" % i, "I;%s" % i)
|
||||
for i in ["32S"]:
|
||||
OPEN["L %s image" % i] = ("I", "I;%s" % i)
|
||||
OPEN["L*%s image" % i] = ("I", "I;%s" % i)
|
||||
for i in range(2, 33):
|
||||
OPEN["L*%s image" % i] = ("F", "F;%s" % i)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Read IM directory
|
||||
|
||||
split = re.compile(r"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
|
||||
|
||||
def number(s):
|
||||
try:
|
||||
return int(s)
|
||||
except ValueError:
|
||||
return float(s)
|
||||
|
||||
##
|
||||
# Image plugin for the IFUNC IM file format.
|
||||
|
||||
class ImImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "IM"
|
||||
format_description = "IFUNC Image Memory"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# Quick rejection: if there's not an LF among the first
|
||||
# 100 bytes, this is (probably) not a text header.
|
||||
|
||||
if not "\n" in self.fp.read(100):
|
||||
raise SyntaxError, "not an IM file"
|
||||
self.fp.seek(0)
|
||||
|
||||
n = 0
|
||||
|
||||
# Default values
|
||||
self.info[MODE] = "L"
|
||||
self.info[SIZE] = (512, 512)
|
||||
self.info[FRAMES] = 1
|
||||
|
||||
self.rawmode = "L"
|
||||
|
||||
while 1:
|
||||
|
||||
s = self.fp.read(1)
|
||||
|
||||
# Some versions of IFUNC uses \n\r instead of \r\n...
|
||||
if s == "\r":
|
||||
continue
|
||||
|
||||
if not s or s[0] == chr(0) or s[0] == chr(26):
|
||||
break
|
||||
|
||||
# FIXME: this may read whole file if not a text file
|
||||
s = s + self.fp.readline()
|
||||
|
||||
if len(s) > 100:
|
||||
raise SyntaxError, "not an IM file"
|
||||
|
||||
if s[-2:] == '\r\n':
|
||||
s = s[:-2]
|
||||
elif s[-1:] == '\n':
|
||||
s = s[:-1]
|
||||
|
||||
try:
|
||||
m = split.match(s)
|
||||
except re.error, v:
|
||||
raise SyntaxError, "not an IM file"
|
||||
|
||||
if m:
|
||||
|
||||
k, v = m.group(1,2)
|
||||
|
||||
# Convert value as appropriate
|
||||
if k in [FRAMES, SCALE, SIZE]:
|
||||
v = string.replace(v, "*", ",")
|
||||
v = tuple(map(number, string.split(v, ",")))
|
||||
if len(v) == 1:
|
||||
v = v[0]
|
||||
elif k == MODE and OPEN.has_key(v):
|
||||
v, self.rawmode = OPEN[v]
|
||||
|
||||
# Add to dictionary. Note that COMMENT tags are
|
||||
# combined into a list of strings.
|
||||
if k == COMMENT:
|
||||
if self.info.has_key(k):
|
||||
self.info[k].append(v)
|
||||
else:
|
||||
self.info[k] = [v]
|
||||
else:
|
||||
self.info[k] = v
|
||||
|
||||
if TAGS.has_key(k):
|
||||
n = n + 1
|
||||
|
||||
else:
|
||||
|
||||
raise SyntaxError, "Syntax error in IM header: " + s
|
||||
|
||||
if not n:
|
||||
raise SyntaxError, "Not an IM file"
|
||||
|
||||
# Basic attributes
|
||||
self.size = self.info[SIZE]
|
||||
self.mode = self.info[MODE]
|
||||
|
||||
# Skip forward to start of image data
|
||||
while s and s[0] != chr(26):
|
||||
s = self.fp.read(1)
|
||||
if not s:
|
||||
raise SyntaxError, "File truncated"
|
||||
|
||||
if self.info.has_key(LUT):
|
||||
# convert lookup table to palette or lut attribute
|
||||
palette = self.fp.read(768)
|
||||
greyscale = 1 # greyscale palette
|
||||
linear = 1 # linear greyscale palette
|
||||
for i in range(256):
|
||||
if palette[i] == palette[i+256] == palette[i+512]:
|
||||
if palette[i] != chr(i):
|
||||
linear = 0
|
||||
else:
|
||||
greyscale = 0
|
||||
if self.mode == "L" or self.mode == "LA":
|
||||
if greyscale:
|
||||
if not linear:
|
||||
self.lut = map(ord, palette[:256])
|
||||
else:
|
||||
if self.mode == "L":
|
||||
self.mode = self.rawmode = "P"
|
||||
elif self.mode == "LA":
|
||||
self.mode = self.rawmode = "PA"
|
||||
self.palette = ImagePalette.raw("RGB;L", palette)
|
||||
elif self.mode == "RGB":
|
||||
if not greyscale or not linear:
|
||||
self.lut = map(ord, palette)
|
||||
|
||||
self.frame = 0
|
||||
|
||||
self.__offset = offs = self.fp.tell()
|
||||
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
|
||||
if self.rawmode[:2] == "F;":
|
||||
|
||||
# ifunc95 formats
|
||||
try:
|
||||
# use bit decoder (if necessary)
|
||||
bits = int(self.rawmode[2:])
|
||||
if bits not in [8, 16, 32]:
|
||||
self.tile = [("bit", (0,0)+self.size, offs,
|
||||
(bits, 8, 3, 0, -1))]
|
||||
return
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if self.rawmode in ["RGB;T", "RYB;T"]:
|
||||
# Old LabEye/3PC files. Would be very surprised if anyone
|
||||
# ever stumbled upon such a file ;-)
|
||||
size = self.size[0] * self.size[1]
|
||||
self.tile = [("raw", (0,0)+self.size, offs, ("G", 0, -1)),
|
||||
("raw", (0,0)+self.size, offs+size, ("R", 0, -1)),
|
||||
("raw", (0,0)+self.size, offs+2*size, ("B", 0, -1))]
|
||||
else:
|
||||
# LabEye/IFUNC files
|
||||
self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
|
||||
|
||||
def seek(self, frame):
|
||||
|
||||
if frame < 0 or frame >= self.info[FRAMES]:
|
||||
raise EOFError, "seek outside sequence"
|
||||
|
||||
if self.frame == frame:
|
||||
return
|
||||
|
||||
self.frame = frame
|
||||
|
||||
if self.mode == "1":
|
||||
bits = 1
|
||||
else:
|
||||
bits = 8 * len(self.mode)
|
||||
|
||||
size = ((self.size[0] * bits + 7) / 8) * self.size[1]
|
||||
offs = self.__offset + frame * size
|
||||
|
||||
self.fp = self.__fp
|
||||
|
||||
self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
|
||||
|
||||
def tell(self):
|
||||
|
||||
return self.frame
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Save IM files
|
||||
|
||||
SAVE = {
|
||||
# mode: (im type, raw mode)
|
||||
"1": ("0 1", "1"),
|
||||
"L": ("Greyscale", "L"),
|
||||
"LA": ("LA", "LA;L"),
|
||||
"P": ("Greyscale", "P"),
|
||||
"PA": ("LA", "PA;L"),
|
||||
"I": ("L 32S", "I;32S"),
|
||||
"I;16": ("L 16", "I;16"),
|
||||
"I;16L": ("L 16L", "I;16L"),
|
||||
"I;16B": ("L 16B", "I;16B"),
|
||||
"F": ("L 32F", "F;32F"),
|
||||
"RGB": ("RGB", "RGB;L"),
|
||||
"RGBA": ("RGBA", "RGBA;L"),
|
||||
"RGBX": ("RGBX", "RGBX;L"),
|
||||
"CMYK": ("CMYK", "CMYK;L"),
|
||||
"YCbCr": ("YCC", "YCbCr;L")
|
||||
}
|
||||
|
||||
def _save(im, fp, filename, check=0):
|
||||
|
||||
try:
|
||||
type, rawmode = SAVE[im.mode]
|
||||
except KeyError:
|
||||
raise ValueError, "Cannot save %s images as IM" % im.mode
|
||||
|
||||
try:
|
||||
frames = im.encoderinfo["frames"]
|
||||
except KeyError:
|
||||
frames = 1
|
||||
|
||||
if check:
|
||||
return check
|
||||
|
||||
fp.write("Image type: %s image\r\n" % type)
|
||||
if filename:
|
||||
fp.write("Name: %s\r\n" % filename)
|
||||
fp.write("Image size (x*y): %d*%d\r\n" % im.size)
|
||||
fp.write("File size (no of images): %d\r\n" % frames)
|
||||
if im.mode == "P":
|
||||
fp.write("Lut: 1\r\n")
|
||||
fp.write("\000" * (511-fp.tell()) + "\032")
|
||||
if im.mode == "P":
|
||||
fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes
|
||||
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, -1))])
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Registry
|
||||
|
||||
Image.register_open("IM", ImImageFile)
|
||||
Image.register_save("IM", _save)
|
||||
|
||||
Image.register_extension("IM", ".im")
|
||||
2127
Darwin/lib/python2.7/site-packages/PIL/Image.py
Normal file
2127
Darwin/lib/python2.7/site-packages/PIL/Image.py
Normal file
File diff suppressed because it is too large
Load diff
302
Darwin/lib/python2.7/site-packages/PIL/ImageChops.py
Normal file
302
Darwin/lib/python2.7/site-packages/PIL/ImageChops.py
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# standard channel operations
|
||||
#
|
||||
# History:
|
||||
# 1996-03-24 fl Created
|
||||
# 1996-08-13 fl Added logical operations (for "1" images)
|
||||
# 2000-10-12 fl Added offset method (from Image.py)
|
||||
#
|
||||
# Copyright (c) 1997-2000 by Secret Labs AB
|
||||
# Copyright (c) 1996-2000 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
|
||||
##
|
||||
# The <b>ImageChops</b> module contains a number of arithmetical image
|
||||
# operations, called <i>channel operations</i> ("chops"). These can be
|
||||
# used for various purposes, including special effects, image
|
||||
# compositions, algorithmic painting, and more.
|
||||
# <p>
|
||||
# At this time, channel operations are only implemented for 8-bit
|
||||
# images (e.g. "L" and "RGB").
|
||||
# <p>
|
||||
# Most channel operations take one or two image arguments and returns
|
||||
# a new image. Unless otherwise noted, the result of a channel
|
||||
# operation is always clipped to the range 0 to MAX (which is 255 for
|
||||
# all modes supported by the operations in this module).
|
||||
##
|
||||
|
||||
##
|
||||
# Return an image with the same size as the given image, but filled
|
||||
# with the given pixel value.
|
||||
#
|
||||
# @param image Reference image.
|
||||
# @param value Pixel value.
|
||||
# @return An image object.
|
||||
|
||||
def constant(image, value):
|
||||
"Fill a channel with a given grey level"
|
||||
|
||||
return Image.new("L", image.size, value)
|
||||
|
||||
##
|
||||
# Copy image.
|
||||
#
|
||||
# @param image Source image.
|
||||
# @return A copy of the source image.
|
||||
|
||||
def duplicate(image):
|
||||
"Create a copy of a channel"
|
||||
|
||||
return image.copy()
|
||||
|
||||
##
|
||||
# Inverts an image
|
||||
# (MAX - image).
|
||||
#
|
||||
# @param image Source image.
|
||||
# @return An image object.
|
||||
|
||||
def invert(image):
|
||||
"Invert a channel"
|
||||
|
||||
image.load()
|
||||
return image._new(image.im.chop_invert())
|
||||
|
||||
##
|
||||
# Compare images, and return lighter pixel value
|
||||
# (max(image1, image2)).
|
||||
# <p>
|
||||
# Compares the two images, pixel by pixel, and returns a new image
|
||||
# containing the lighter values.
|
||||
#
|
||||
# @param image1 First image.
|
||||
# @param image1 Second image.
|
||||
# @return An image object.
|
||||
|
||||
def lighter(image1, image2):
|
||||
"Select the lighter pixels from each image"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_lighter(image2.im))
|
||||
|
||||
##
|
||||
# Compare images, and return darker pixel value
|
||||
# (min(image1, image2)).
|
||||
# <p>
|
||||
# Compares the two images, pixel by pixel, and returns a new image
|
||||
# containing the darker values.
|
||||
#
|
||||
# @param image1 First image.
|
||||
# @param image1 Second image.
|
||||
# @return An image object.
|
||||
|
||||
def darker(image1, image2):
|
||||
"Select the darker pixels from each image"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_darker(image2.im))
|
||||
|
||||
##
|
||||
# Calculate absolute difference
|
||||
# (abs(image1 - image2)).
|
||||
# <p>
|
||||
# Returns the absolute value of the difference between the two images.
|
||||
#
|
||||
# @param image1 First image.
|
||||
# @param image1 Second image.
|
||||
# @return An image object.
|
||||
|
||||
def difference(image1, image2):
|
||||
"Subtract one image from another"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_difference(image2.im))
|
||||
|
||||
##
|
||||
# Superimpose positive images
|
||||
# (image1 * image2 / MAX).
|
||||
# <p>
|
||||
# Superimposes two images on top of each other. If you multiply an
|
||||
# image with a solid black image, the result is black. If you multiply
|
||||
# with a solid white image, the image is unaffected.
|
||||
#
|
||||
# @param image1 First image.
|
||||
# @param image1 Second image.
|
||||
# @return An image object.
|
||||
|
||||
def multiply(image1, image2):
|
||||
"Superimpose two positive images"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_multiply(image2.im))
|
||||
|
||||
##
|
||||
# Superimpose negative images
|
||||
# (MAX - ((MAX - image1) * (MAX - image2) / MAX)).
|
||||
# <p>
|
||||
# Superimposes two inverted images on top of each other.
|
||||
#
|
||||
# @param image1 First image.
|
||||
# @param image1 Second image.
|
||||
# @return An image object.
|
||||
|
||||
def screen(image1, image2):
|
||||
"Superimpose two negative images"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_screen(image2.im))
|
||||
|
||||
##
|
||||
# Add images
|
||||
# ((image1 + image2) / scale + offset).
|
||||
# <p>
|
||||
# Adds two images, dividing the result by scale and adding the
|
||||
# offset. If omitted, scale defaults to 1.0, and offset to 0.0.
|
||||
#
|
||||
# @param image1 First image.
|
||||
# @param image1 Second image.
|
||||
# @return An image object.
|
||||
|
||||
def add(image1, image2, scale=1.0, offset=0):
|
||||
"Add two images"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_add(image2.im, scale, offset))
|
||||
|
||||
##
|
||||
# Subtract images
|
||||
# ((image1 - image2) / scale + offset).
|
||||
# <p>
|
||||
# Subtracts two images, dividing the result by scale and adding the
|
||||
# offset. If omitted, scale defaults to 1.0, and offset to 0.0.
|
||||
#
|
||||
# @param image1 First image.
|
||||
# @param image1 Second image.
|
||||
# @return An image object.
|
||||
|
||||
def subtract(image1, image2, scale=1.0, offset=0):
|
||||
"Subtract two images"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_subtract(image2.im, scale, offset))
|
||||
|
||||
##
|
||||
# Add images without clipping
|
||||
# ((image1 + image2) % MAX).
|
||||
# <p>
|
||||
# Adds two images, without clipping the result.
|
||||
#
|
||||
# @param image1 First image.
|
||||
# @param image1 Second image.
|
||||
# @return An image object.
|
||||
|
||||
def add_modulo(image1, image2):
|
||||
"Add two images without clipping"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_add_modulo(image2.im))
|
||||
|
||||
##
|
||||
# Subtract images without clipping
|
||||
# ((image1 - image2) % MAX).
|
||||
# <p>
|
||||
# Subtracts two images, without clipping the result.
|
||||
#
|
||||
# @param image1 First image.
|
||||
# @param image1 Second image.
|
||||
# @return An image object.
|
||||
|
||||
def subtract_modulo(image1, image2):
|
||||
"Subtract two images without clipping"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_subtract_modulo(image2.im))
|
||||
|
||||
##
|
||||
# Logical AND
|
||||
# (image1 and image2).
|
||||
|
||||
def logical_and(image1, image2):
|
||||
"Logical and between two images"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_and(image2.im))
|
||||
|
||||
##
|
||||
# Logical OR
|
||||
# (image1 or image2).
|
||||
|
||||
def logical_or(image1, image2):
|
||||
"Logical or between two images"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_or(image2.im))
|
||||
|
||||
##
|
||||
# Logical XOR
|
||||
# (image1 xor image2).
|
||||
|
||||
def logical_xor(image1, image2):
|
||||
"Logical xor between two images"
|
||||
|
||||
image1.load()
|
||||
image2.load()
|
||||
return image1._new(image1.im.chop_xor(image2.im))
|
||||
|
||||
##
|
||||
# Blend images using constant transparency weight.
|
||||
# <p>
|
||||
# Same as the <b>blend</b> function in the <b>Image</b> module.
|
||||
|
||||
def blend(image1, image2, alpha):
|
||||
"Blend two images using a constant transparency weight"
|
||||
|
||||
return Image.blend(image1, image2, alpha)
|
||||
|
||||
##
|
||||
# Create composite using transparency mask.
|
||||
# <p>
|
||||
# Same as the <b>composite</b> function in the <b>Image</b> module.
|
||||
|
||||
def composite(image1, image2, mask):
|
||||
"Create composite image by blending images using a transparency mask"
|
||||
|
||||
return Image.composite(image1, image2, mask)
|
||||
|
||||
##
|
||||
# Offset image data.
|
||||
# <p>
|
||||
# Returns a copy of the image where data has been offset by the given
|
||||
# distances. Data wraps around the edges. If yoffset is omitted, it
|
||||
# is assumed to be equal to xoffset.
|
||||
#
|
||||
# @param image Source image.
|
||||
# @param xoffset The horizontal distance.
|
||||
# @param yoffset The vertical distance. If omitted, both
|
||||
# distances are set to the same value.
|
||||
# @return An Image object.
|
||||
|
||||
def offset(image, xoffset, yoffset=None):
|
||||
"Offset image in horizontal and/or vertical direction"
|
||||
if yoffset is None:
|
||||
yoffset = xoffset
|
||||
image.load()
|
||||
return image._new(image.im.offset(xoffset, yoffset))
|
||||
786
Darwin/lib/python2.7/site-packages/PIL/ImageCms.py
Normal file
786
Darwin/lib/python2.7/site-packages/PIL/ImageCms.py
Normal file
|
|
@ -0,0 +1,786 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# optional color managment support, based on Kevin Cazabon's PyCMS
|
||||
# library.
|
||||
#
|
||||
# History:
|
||||
# 2009-03-08 fl Added to PIL.
|
||||
#
|
||||
# Copyright (C) 2002-2003 Kevin Cazabon
|
||||
# Copyright (c) 2009 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution. See
|
||||
# below for the original description.
|
||||
#
|
||||
|
||||
DESCRIPTION = """
|
||||
pyCMS
|
||||
|
||||
a Python / PIL interface to the littleCMS ICC Color Management System
|
||||
Copyright (C) 2002-2003 Kevin Cazabon
|
||||
kevin@cazabon.com
|
||||
http://www.cazabon.com
|
||||
|
||||
pyCMS home page: http://www.cazabon.com/pyCMS
|
||||
littleCMS home page: http://www.littlecms.com
|
||||
(littleCMS is Copyright (C) 1998-2001 Marti Maria)
|
||||
|
||||
Originally released under LGPL. Graciously donated to PIL in
|
||||
March 2009, for distribution under the standard PIL license
|
||||
|
||||
The pyCMS.py module provides a "clean" interface between Python/PIL and
|
||||
pyCMSdll, taking care of some of the more complex handling of the direct
|
||||
pyCMSdll functions, as well as error-checking and making sure that all
|
||||
relevant data is kept together.
|
||||
|
||||
While it is possible to call pyCMSdll functions directly, it's not highly
|
||||
recommended.
|
||||
|
||||
Version History:
|
||||
|
||||
0.1.0 pil mod March 10, 2009
|
||||
|
||||
Renamed display profile to proof profile. The proof
|
||||
profile is the profile of the device that is being
|
||||
simulated, not the profile of the device which is
|
||||
actually used to display/print the final simulation
|
||||
(that'd be the output profile) - also see LCMSAPI.txt
|
||||
input colorspace -> using 'renderingIntent' -> proof
|
||||
colorspace -> using 'proofRenderingIntent' -> output
|
||||
colorspace
|
||||
|
||||
Added LCMS FLAGS support.
|
||||
Added FLAGS["SOFTPROOFING"] as default flag for
|
||||
buildProofTransform (otherwise the proof profile/intent
|
||||
would be ignored).
|
||||
|
||||
0.1.0 pil March 2009 - added to PIL, as PIL.ImageCms
|
||||
|
||||
0.0.2 alpha Jan 6, 2002
|
||||
|
||||
Added try/except statements arount type() checks of
|
||||
potential CObjects... Python won't let you use type()
|
||||
on them, and raises a TypeError (stupid, if you ask me!)
|
||||
|
||||
Added buildProofTransformFromOpenProfiles() function.
|
||||
Additional fixes in DLL, see DLL code for details.
|
||||
|
||||
0.0.1 alpha first public release, Dec. 26, 2002
|
||||
|
||||
Known to-do list with current version (of Python interface, not pyCMSdll):
|
||||
|
||||
none
|
||||
|
||||
"""
|
||||
|
||||
VERSION = "0.1.0 pil"
|
||||
|
||||
# --------------------------------------------------------------------.
|
||||
|
||||
import Image
|
||||
import _imagingcms
|
||||
|
||||
core = _imagingcms
|
||||
|
||||
#
|
||||
# intent/direction values
|
||||
|
||||
INTENT_PERCEPTUAL = 0
|
||||
INTENT_RELATIVE_COLORIMETRIC = 1
|
||||
INTENT_SATURATION = 2
|
||||
INTENT_ABSOLUTE_COLORIMETRIC = 3
|
||||
|
||||
DIRECTION_INPUT = 0
|
||||
DIRECTION_OUTPUT = 1
|
||||
DIRECTION_PROOF = 2
|
||||
|
||||
#
|
||||
# flags
|
||||
|
||||
FLAGS = {
|
||||
"MATRIXINPUT": 1,
|
||||
"MATRIXOUTPUT": 2,
|
||||
"MATRIXONLY": (1|2),
|
||||
"NOWHITEONWHITEFIXUP": 4, # Don't hot fix scum dot
|
||||
"NOPRELINEARIZATION": 16, # Don't create prelinearization tables on precalculated transforms (internal use)
|
||||
"GUESSDEVICECLASS": 32, # Guess device class (for transform2devicelink)
|
||||
"NOTCACHE": 64, # Inhibit 1-pixel cache
|
||||
"NOTPRECALC": 256,
|
||||
"NULLTRANSFORM": 512, # Don't transform anyway
|
||||
"HIGHRESPRECALC": 1024, # Use more memory to give better accurancy
|
||||
"LOWRESPRECALC": 2048, # Use less memory to minimize resouces
|
||||
"WHITEBLACKCOMPENSATION": 8192,
|
||||
"BLACKPOINTCOMPENSATION": 8192,
|
||||
"GAMUTCHECK": 4096, # Out of Gamut alarm
|
||||
"SOFTPROOFING": 16384, # Do softproofing
|
||||
"PRESERVEBLACK": 32768, # Black preservation
|
||||
"NODEFAULTRESOURCEDEF": 16777216, # CRD special
|
||||
"GRIDPOINTS": lambda n: ((n) & 0xFF) << 16 # Gridpoints
|
||||
}
|
||||
|
||||
_MAX_FLAG = 0
|
||||
for flag in FLAGS.values():
|
||||
if isinstance(flag, type(0)):
|
||||
_MAX_FLAG = _MAX_FLAG | flag
|
||||
|
||||
# --------------------------------------------------------------------.
|
||||
# Experimental PIL-level API
|
||||
# --------------------------------------------------------------------.
|
||||
|
||||
##
|
||||
# Profile.
|
||||
|
||||
class ImageCmsProfile:
|
||||
|
||||
def __init__(self, profile):
|
||||
# accepts a string (filename), a file-like object, or a low-level
|
||||
# profile object
|
||||
if Image.isStringType(profile):
|
||||
self._set(core.profile_open(profile), profile)
|
||||
elif hasattr(profile, "read"):
|
||||
self._set(core.profile_fromstring(profile.read()))
|
||||
else:
|
||||
self._set(profile) # assume it's already a profile
|
||||
|
||||
def _set(self, profile, filename=None):
|
||||
self.profile = profile
|
||||
self.filename = filename
|
||||
if profile:
|
||||
self.product_name = profile.product_name
|
||||
self.product_info = profile.product_info
|
||||
else:
|
||||
self.product_name = None
|
||||
self.product_info = None
|
||||
|
||||
##
|
||||
# Transform. This can be used with the procedural API, or with the
|
||||
# standard {@link Image.point} method.
|
||||
|
||||
class ImageCmsTransform(Image.ImagePointHandler):
|
||||
|
||||
def __init__(self, input, output, input_mode, output_mode,
|
||||
intent=INTENT_PERCEPTUAL,
|
||||
proof=None, proof_intent=INTENT_ABSOLUTE_COLORIMETRIC, flags=0):
|
||||
if proof is None:
|
||||
self.transform = core.buildTransform(
|
||||
input.profile, output.profile,
|
||||
input_mode, output_mode,
|
||||
intent,
|
||||
flags
|
||||
)
|
||||
else:
|
||||
self.transform = core.buildProofTransform(
|
||||
input.profile, output.profile, proof.profile,
|
||||
input_mode, output_mode,
|
||||
intent, proof_intent,
|
||||
flags
|
||||
)
|
||||
# Note: inputMode and outputMode are for pyCMS compatibility only
|
||||
self.input_mode = self.inputMode = input_mode
|
||||
self.output_mode = self.outputMode = output_mode
|
||||
|
||||
def point(self, im):
|
||||
return self.apply(im)
|
||||
|
||||
def apply(self, im, imOut=None):
|
||||
im.load()
|
||||
if imOut is None:
|
||||
imOut = Image.new(self.output_mode, im.size, None)
|
||||
result = self.transform.apply(im.im.id, imOut.im.id)
|
||||
return imOut
|
||||
|
||||
def apply_in_place(self, im):
|
||||
im.load()
|
||||
if im.mode != self.output_mode:
|
||||
raise ValueError("mode mismatch") # wrong output mode
|
||||
result = self.transform.apply(im.im.id, im.im.id)
|
||||
return im
|
||||
|
||||
##
|
||||
# (experimental) Fetches the profile for the current display device.
|
||||
# Returns None if the profile is not known.
|
||||
|
||||
def get_display_profile(handle=None):
|
||||
import sys
|
||||
if sys.platform == "win32":
|
||||
import ImageWin
|
||||
if isinstance(handle, ImageWin.HDC):
|
||||
profile = core.get_display_profile_win32(handle, 1)
|
||||
else:
|
||||
profile = core.get_display_profile_win32(handle or 0)
|
||||
else:
|
||||
try:
|
||||
get = _imagingcms.get_display_profile
|
||||
except AttributeError:
|
||||
return None
|
||||
else:
|
||||
profile = get()
|
||||
return ImageCmsProfile(profile)
|
||||
|
||||
# --------------------------------------------------------------------.
|
||||
# pyCMS compatible layer
|
||||
# --------------------------------------------------------------------.
|
||||
|
||||
##
|
||||
# (pyCMS) Exception class. This is used for all errors in the pyCMS API.
|
||||
|
||||
class PyCMSError(Exception):
|
||||
pass
|
||||
|
||||
##
|
||||
# (pyCMS) Applies an ICC transformation to a given image, mapping from
|
||||
# inputProfile to outputProfile.
|
||||
|
||||
def profileToProfile(im, inputProfile, outputProfile, renderingIntent=INTENT_PERCEPTUAL, outputMode=None, inPlace=0, flags=0):
|
||||
"""
|
||||
ImageCms.profileToProfile(im, inputProfile, outputProfile,
|
||||
[renderingIntent], [outputMode], [inPlace])
|
||||
|
||||
Returns either None or a new PIL image object, depending on value of
|
||||
inPlace (see below).
|
||||
|
||||
im = an open PIL image object (i.e. Image.new(...) or
|
||||
Image.open(...), etc.)
|
||||
inputProfile = string, as a valid filename path to the ICC input
|
||||
profile you wish to use for this image, or a profile object
|
||||
outputProfile = string, as a valid filename path to the ICC output
|
||||
profile you wish to use for this image, or a profile object
|
||||
renderingIntent = integer (0-3) specifying the rendering intent you
|
||||
wish to use for the transform
|
||||
INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL)
|
||||
INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC)
|
||||
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
|
||||
INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
|
||||
|
||||
see the pyCMS documentation for details on rendering intents and
|
||||
what they do.
|
||||
outputMode = a valid PIL mode for the output image (i.e. "RGB", "CMYK",
|
||||
etc.). Note: if rendering the image "inPlace", outputMode MUST be
|
||||
the same mode as the input, or omitted completely. If omitted, the
|
||||
outputMode will be the same as the mode of the input image (im.mode)
|
||||
inPlace = BOOL (1 = TRUE, None or 0 = FALSE). If TRUE, the original
|
||||
image is modified in-place, and None is returned. If FALSE
|
||||
(default), a new Image object is returned with the transform
|
||||
applied.
|
||||
flags = integer (0-...) specifying additional flags
|
||||
|
||||
If the input or output profiles specified are not valid filenames, a
|
||||
PyCMSError will be raised. If inPlace == TRUE and outputMode != im.mode,
|
||||
a PyCMSError will be raised. If an error occurs during application of
|
||||
the profiles, a PyCMSError will be raised. If outputMode is not a mode
|
||||
supported by the outputProfile (or by pyCMS), a PyCMSError will be
|
||||
raised.
|
||||
|
||||
This function applies an ICC transformation to im from inputProfile's
|
||||
color space to outputProfile's color space using the specified rendering
|
||||
intent to decide how to handle out-of-gamut colors.
|
||||
|
||||
OutputMode can be used to specify that a color mode conversion is to
|
||||
be done using these profiles, but the specified profiles must be able
|
||||
to handle that mode. I.e., if converting im from RGB to CMYK using
|
||||
profiles, the input profile must handle RGB data, and the output
|
||||
profile must handle CMYK data.
|
||||
|
||||
"""
|
||||
|
||||
if outputMode is None:
|
||||
outputMode = im.mode
|
||||
|
||||
if type(renderingIntent) != type(1) or not (0 <= renderingIntent <=3):
|
||||
raise PyCMSError("renderingIntent must be an integer between 0 and 3")
|
||||
|
||||
if type(flags) != type(1) or not (0 <= flags <= _MAX_FLAG):
|
||||
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
|
||||
|
||||
try:
|
||||
if not isinstance(inputProfile, ImageCmsProfile):
|
||||
inputProfile = ImageCmsProfile(inputProfile)
|
||||
if not isinstance(outputProfile, ImageCmsProfile):
|
||||
outputProfile = ImageCmsProfile(outputProfile)
|
||||
transform = ImageCmsTransform(
|
||||
inputProfile, outputProfile, im.mode, outputMode, renderingIntent, flags=flags
|
||||
)
|
||||
if inPlace:
|
||||
transform.apply_in_place(im)
|
||||
imOut = None
|
||||
else:
|
||||
imOut = transform.apply(im)
|
||||
except (IOError, TypeError, ValueError), v:
|
||||
raise PyCMSError(v)
|
||||
|
||||
return imOut
|
||||
|
||||
##
|
||||
# (pyCMS) Opens an ICC profile file.
|
||||
|
||||
def getOpenProfile(profileFilename):
|
||||
"""
|
||||
ImageCms.getOpenProfile(profileFilename)
|
||||
|
||||
Returns a CmsProfile class object.
|
||||
|
||||
profileFilename = string, as a valid filename path to the ICC profile
|
||||
you wish to open, or a file-like object.
|
||||
|
||||
The PyCMSProfile object can be passed back into pyCMS for use in creating
|
||||
transforms and such (as in ImageCms.buildTransformFromOpenProfiles()).
|
||||
|
||||
If profileFilename is not a vaild filename for an ICC profile, a
|
||||
PyCMSError will be raised.
|
||||
|
||||
"""
|
||||
|
||||
try:
|
||||
return ImageCmsProfile(profileFilename)
|
||||
except (IOError, TypeError, ValueError), v:
|
||||
raise PyCMSError(v)
|
||||
|
||||
##
|
||||
# (pyCMS) Builds an ICC transform mapping from the inputProfile to the
|
||||
# outputProfile. Use applyTransform to apply the transform to a given
|
||||
# image.
|
||||
|
||||
def buildTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent=INTENT_PERCEPTUAL, flags=0):
|
||||
"""
|
||||
ImageCms.buildTransform(inputProfile, outputProfile, inMode, outMode,
|
||||
[renderingIntent])
|
||||
|
||||
Returns a CmsTransform class object.
|
||||
|
||||
inputProfile = string, as a valid filename path to the ICC input
|
||||
profile you wish to use for this transform, or a profile object
|
||||
outputProfile = string, as a valid filename path to the ICC output
|
||||
profile you wish to use for this transform, or a profile object
|
||||
inMode = string, as a valid PIL mode that the appropriate profile also
|
||||
supports (i.e. "RGB", "RGBA", "CMYK", etc.)
|
||||
outMode = string, as a valid PIL mode that the appropriate profile also
|
||||
supports (i.e. "RGB", "RGBA", "CMYK", etc.)
|
||||
renderingIntent = integer (0-3) specifying the rendering intent you
|
||||
wish to use for the transform
|
||||
INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL)
|
||||
INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC)
|
||||
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
|
||||
INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
|
||||
see the pyCMS documentation for details on rendering intents and
|
||||
what they do.
|
||||
flags = integer (0-...) specifying additional flags
|
||||
|
||||
If the input or output profiles specified are not valid filenames, a
|
||||
PyCMSError will be raised. If an error occurs during creation of the
|
||||
transform, a PyCMSError will be raised.
|
||||
|
||||
If inMode or outMode are not a mode supported by the outputProfile (or
|
||||
by pyCMS), a PyCMSError will be raised.
|
||||
|
||||
This function builds and returns an ICC transform from the inputProfile
|
||||
to the outputProfile using the renderingIntent to determine what to do
|
||||
with out-of-gamut colors. It will ONLY work for converting images that
|
||||
are in inMode to images that are in outMode color format (PIL mode,
|
||||
i.e. "RGB", "RGBA", "CMYK", etc.).
|
||||
|
||||
Building the transform is a fair part of the overhead in
|
||||
ImageCms.profileToProfile(), so if you're planning on converting multiple
|
||||
images using the same input/output settings, this can save you time.
|
||||
Once you have a transform object, it can be used with
|
||||
ImageCms.applyProfile() to convert images without the need to re-compute
|
||||
the lookup table for the transform.
|
||||
|
||||
The reason pyCMS returns a class object rather than a handle directly
|
||||
to the transform is that it needs to keep track of the PIL input/output
|
||||
modes that the transform is meant for. These attributes are stored in
|
||||
the "inMode" and "outMode" attributes of the object (which can be
|
||||
manually overridden if you really want to, but I don't know of any
|
||||
time that would be of use, or would even work).
|
||||
|
||||
"""
|
||||
|
||||
if type(renderingIntent) != type(1) or not (0 <= renderingIntent <=3):
|
||||
raise PyCMSError("renderingIntent must be an integer between 0 and 3")
|
||||
|
||||
if type(flags) != type(1) or not (0 <= flags <= _MAX_FLAG):
|
||||
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
|
||||
|
||||
try:
|
||||
if not isinstance(inputProfile, ImageCmsProfile):
|
||||
inputProfile = ImageCmsProfile(inputProfile)
|
||||
if not isinstance(outputProfile, ImageCmsProfile):
|
||||
outputProfile = ImageCmsProfile(outputProfile)
|
||||
return ImageCmsTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent, flags=flags)
|
||||
except (IOError, TypeError, ValueError), v:
|
||||
raise PyCMSError(v)
|
||||
|
||||
##
|
||||
# (pyCMS) Builds an ICC transform mapping from the inputProfile to the
|
||||
# outputProfile, but tries to simulate the result that would be
|
||||
# obtained on the proofProfile device.
|
||||
|
||||
def buildProofTransform(inputProfile, outputProfile, proofProfile, inMode, outMode, renderingIntent=INTENT_PERCEPTUAL, proofRenderingIntent=INTENT_ABSOLUTE_COLORIMETRIC, flags=FLAGS["SOFTPROOFING"]):
|
||||
"""
|
||||
ImageCms.buildProofTransform(inputProfile, outputProfile, proofProfile,
|
||||
inMode, outMode, [renderingIntent], [proofRenderingIntent])
|
||||
|
||||
Returns a CmsTransform class object.
|
||||
|
||||
inputProfile = string, as a valid filename path to the ICC input
|
||||
profile you wish to use for this transform, or a profile object
|
||||
outputProfile = string, as a valid filename path to the ICC output
|
||||
(monitor, usually) profile you wish to use for this transform,
|
||||
or a profile object
|
||||
proofProfile = string, as a valid filename path to the ICC proof
|
||||
profile you wish to use for this transform, or a profile object
|
||||
inMode = string, as a valid PIL mode that the appropriate profile also
|
||||
supports (i.e. "RGB", "RGBA", "CMYK", etc.)
|
||||
outMode = string, as a valid PIL mode that the appropriate profile also
|
||||
supports (i.e. "RGB", "RGBA", "CMYK", etc.)
|
||||
renderingIntent = integer (0-3) specifying the rendering intent you
|
||||
wish to use for the input->proof (simulated) transform
|
||||
INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL)
|
||||
INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC)
|
||||
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
|
||||
INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
|
||||
see the pyCMS documentation for details on rendering intents and
|
||||
what they do.
|
||||
proofRenderingIntent = integer (0-3) specifying the rendering intent
|
||||
you wish to use for proof->output transform
|
||||
INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL)
|
||||
INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC)
|
||||
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
|
||||
INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
|
||||
see the pyCMS documentation for details on rendering intents and
|
||||
what they do.
|
||||
flags = integer (0-...) specifying additional flags
|
||||
|
||||
If the input, output, or proof profiles specified are not valid
|
||||
filenames, a PyCMSError will be raised.
|
||||
|
||||
If an error occurs during creation of the transform, a PyCMSError will
|
||||
be raised.
|
||||
|
||||
If inMode or outMode are not a mode supported by the outputProfile
|
||||
(or by pyCMS), a PyCMSError will be raised.
|
||||
|
||||
This function builds and returns an ICC transform from the inputProfile
|
||||
to the outputProfile, but tries to simulate the result that would be
|
||||
obtained on the proofProfile device using renderingIntent and
|
||||
proofRenderingIntent to determine what to do with out-of-gamut
|
||||
colors. This is known as "soft-proofing". It will ONLY work for
|
||||
converting images that are in inMode to images that are in outMode
|
||||
color format (PIL mode, i.e. "RGB", "RGBA", "CMYK", etc.).
|
||||
|
||||
Usage of the resulting transform object is exactly the same as with
|
||||
ImageCms.buildTransform().
|
||||
|
||||
Proof profiling is generally used when using an output device to get a
|
||||
good idea of what the final printed/displayed image would look like on
|
||||
the proofProfile device when it's quicker and easier to use the
|
||||
output device for judging color. Generally, this means that the
|
||||
output device is a monitor, or a dye-sub printer (etc.), and the simulated
|
||||
device is something more expensive, complicated, or time consuming
|
||||
(making it difficult to make a real print for color judgement purposes).
|
||||
|
||||
Soft-proofing basically functions by adjusting the colors on the
|
||||
output device to match the colors of the device being simulated. However,
|
||||
when the simulated device has a much wider gamut than the output
|
||||
device, you may obtain marginal results.
|
||||
|
||||
"""
|
||||
|
||||
if type(renderingIntent) != type(1) or not (0 <= renderingIntent <=3):
|
||||
raise PyCMSError("renderingIntent must be an integer between 0 and 3")
|
||||
|
||||
if type(flags) != type(1) or not (0 <= flags <= _MAX_FLAG):
|
||||
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
|
||||
|
||||
try:
|
||||
if not isinstance(inputProfile, ImageCmsProfile):
|
||||
inputProfile = ImageCmsProfile(inputProfile)
|
||||
if not isinstance(outputProfile, ImageCmsProfile):
|
||||
outputProfile = ImageCmsProfile(outputProfile)
|
||||
if not isinstance(proofProfile, ImageCmsProfile):
|
||||
proofProfile = ImageCmsProfile(proofProfile)
|
||||
return ImageCmsTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent, proofProfile, proofRenderingIntent, flags)
|
||||
except (IOError, TypeError, ValueError), v:
|
||||
raise PyCMSError(v)
|
||||
|
||||
buildTransformFromOpenProfiles = buildTransform
|
||||
buildProofTransformFromOpenProfiles = buildProofTransform
|
||||
|
||||
##
|
||||
# (pyCMS) Applies a transform to a given image.
|
||||
|
||||
def applyTransform(im, transform, inPlace=0):
|
||||
"""
|
||||
ImageCms.applyTransform(im, transform, [inPlace])
|
||||
|
||||
Returns either None, or a new PIL Image object, depending on the value
|
||||
of inPlace (see below)
|
||||
|
||||
im = a PIL Image object, and im.mode must be the same as the inMode
|
||||
supported by the transform.
|
||||
transform = a valid CmsTransform class object
|
||||
inPlace = BOOL (1 == TRUE, 0 or None == FALSE). If TRUE, im is
|
||||
modified in place and None is returned, if FALSE, a new Image
|
||||
object with the transform applied is returned (and im is not
|
||||
changed). The default is FALSE.
|
||||
|
||||
If im.mode != transform.inMode, a PyCMSError is raised.
|
||||
|
||||
If inPlace == TRUE and transform.inMode != transform.outMode, a
|
||||
PyCMSError is raised.
|
||||
|
||||
If im.mode, transfer.inMode, or transfer.outMode is not supported by
|
||||
pyCMSdll or the profiles you used for the transform, a PyCMSError is
|
||||
raised.
|
||||
|
||||
If an error occurs while the transform is being applied, a PyCMSError
|
||||
is raised.
|
||||
|
||||
This function applies a pre-calculated transform (from
|
||||
ImageCms.buildTransform() or ImageCms.buildTransformFromOpenProfiles()) to an
|
||||
image. The transform can be used for multiple images, saving
|
||||
considerable calcuation time if doing the same conversion multiple times.
|
||||
|
||||
If you want to modify im in-place instead of receiving a new image as
|
||||
the return value, set inPlace to TRUE. This can only be done if
|
||||
transform.inMode and transform.outMode are the same, because we can't
|
||||
change the mode in-place (the buffer sizes for some modes are
|
||||
different). The default behavior is to return a new Image object of
|
||||
the same dimensions in mode transform.outMode.
|
||||
|
||||
"""
|
||||
|
||||
try:
|
||||
if inPlace:
|
||||
transform.apply_in_place(im)
|
||||
imOut = None
|
||||
else:
|
||||
imOut = transform.apply(im)
|
||||
except (TypeError, ValueError), v:
|
||||
raise PyCMSError(v)
|
||||
|
||||
return imOut
|
||||
|
||||
##
|
||||
# (pyCMS) Creates a profile.
|
||||
|
||||
def createProfile(colorSpace, colorTemp=-1):
|
||||
"""
|
||||
ImageCms.createProfile(colorSpace, [colorTemp])
|
||||
|
||||
Returns a CmsProfile class object
|
||||
|
||||
colorSpace = string, the color space of the profile you wish to create.
|
||||
Currently only "LAB", "XYZ", and "sRGB" are supported.
|
||||
colorTemp = positive integer for the white point for the profile, in
|
||||
degrees Kelvin (i.e. 5000, 6500, 9600, etc.). The default is for
|
||||
D50 illuminant if omitted (5000k). colorTemp is ONLY applied to
|
||||
LAB profiles, and is ignored for XYZ and sRGB.
|
||||
|
||||
If colorSpace not in ["LAB", "XYZ", "sRGB"], a PyCMSError is raised
|
||||
|
||||
If using LAB and colorTemp != a positive integer, a PyCMSError is raised.
|
||||
|
||||
If an error occurs while creating the profile, a PyCMSError is raised.
|
||||
|
||||
Use this function to create common profiles on-the-fly instead of
|
||||
having to supply a profile on disk and knowing the path to it. It
|
||||
returns a normal CmsProfile object that can be passed to
|
||||
ImageCms.buildTransformFromOpenProfiles() to create a transform to apply
|
||||
to images.
|
||||
|
||||
"""
|
||||
if colorSpace not in ["LAB", "XYZ", "sRGB"]:
|
||||
raise PyCMSError("Color space not supported for on-the-fly profile creation (%s)" % colorSpace)
|
||||
|
||||
if colorSpace == "LAB":
|
||||
if type(colorTemp) == type(5000.0):
|
||||
colorTemp = int(colorTemp + 0.5)
|
||||
if type (colorTemp) != type (5000):
|
||||
raise PyCMSError("Color temperature must be a positive integer, \"%s\" not valid" % colorTemp)
|
||||
|
||||
try:
|
||||
return core.createProfile(colorSpace, colorTemp)
|
||||
except (TypeError, ValueError), v:
|
||||
raise PyCMSError(v)
|
||||
|
||||
##
|
||||
# (pyCMS) Gets the internal product name for the given profile.
|
||||
|
||||
def getProfileName(profile):
|
||||
"""
|
||||
ImageCms.getProfileName(profile)
|
||||
|
||||
Returns a string containing the internal name of the profile as stored
|
||||
in an ICC tag.
|
||||
|
||||
profile = EITHER a valid CmsProfile object, OR a string of the
|
||||
filename of an ICC profile.
|
||||
|
||||
If profile isn't a valid CmsProfile object or filename to a profile,
|
||||
a PyCMSError is raised If an error occurs while trying to obtain the
|
||||
name tag, a PyCMSError is raised.
|
||||
|
||||
Use this function to obtain the INTERNAL name of the profile (stored
|
||||
in an ICC tag in the profile itself), usually the one used when the
|
||||
profile was originally created. Sometimes this tag also contains
|
||||
additional information supplied by the creator.
|
||||
|
||||
"""
|
||||
try:
|
||||
# add an extra newline to preserve pyCMS compatibility
|
||||
if not isinstance(profile, ImageCmsProfile):
|
||||
profile = ImageCmsProfile(profile)
|
||||
return profile.profile.product_name + "\n"
|
||||
except (AttributeError, IOError, TypeError, ValueError), v:
|
||||
raise PyCMSError(v)
|
||||
|
||||
##
|
||||
# (pyCMS) Gets the internal product information for the given profile.
|
||||
|
||||
def getProfileInfo(profile):
|
||||
"""
|
||||
ImageCms.getProfileInfo(profile)
|
||||
|
||||
Returns a string containing the internal profile information stored in
|
||||
an ICC tag.
|
||||
|
||||
profile = EITHER a valid CmsProfile object, OR a string of the
|
||||
filename of an ICC profile.
|
||||
|
||||
If profile isn't a valid CmsProfile object or filename to a profile,
|
||||
a PyCMSError is raised.
|
||||
|
||||
If an error occurs while trying to obtain the info tag, a PyCMSError
|
||||
is raised
|
||||
|
||||
Use this function to obtain the information stored in the profile's
|
||||
info tag. This often contains details about the profile, and how it
|
||||
was created, as supplied by the creator.
|
||||
|
||||
"""
|
||||
try:
|
||||
if not isinstance(profile, ImageCmsProfile):
|
||||
profile = ImageCmsProfile(profile)
|
||||
# add an extra newline to preserve pyCMS compatibility
|
||||
return profile.product_info + "\n"
|
||||
except (AttributeError, IOError, TypeError, ValueError), v:
|
||||
raise PyCMSError(v)
|
||||
|
||||
##
|
||||
# (pyCMS) Gets the default intent name for the given profile.
|
||||
|
||||
def getDefaultIntent(profile):
|
||||
"""
|
||||
ImageCms.getDefaultIntent(profile)
|
||||
|
||||
Returns integer 0-3 specifying the default rendering intent for this
|
||||
profile.
|
||||
INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL)
|
||||
INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC)
|
||||
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
|
||||
INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
|
||||
see the pyCMS documentation for details on rendering intents and
|
||||
what they do.
|
||||
|
||||
profile = EITHER a valid CmsProfile object, OR a string of the
|
||||
filename of an ICC profile.
|
||||
|
||||
If profile isn't a valid CmsProfile object or filename to a profile,
|
||||
a PyCMSError is raised.
|
||||
|
||||
If an error occurs while trying to obtain the default intent, a
|
||||
PyCMSError is raised.
|
||||
|
||||
Use this function to determine the default (and usually best optomized)
|
||||
rendering intent for this profile. Most profiles support multiple
|
||||
rendering intents, but are intended mostly for one type of conversion.
|
||||
If you wish to use a different intent than returned, use
|
||||
ImageCms.isIntentSupported() to verify it will work first.
|
||||
"""
|
||||
try:
|
||||
if not isinstance(profile, ImageCmsProfile):
|
||||
profile = ImageCmsProfile(profile)
|
||||
return profile.profile.rendering_intent
|
||||
except (AttributeError, IOError, TypeError, ValueError), v:
|
||||
raise PyCMSError(v)
|
||||
|
||||
##
|
||||
# (pyCMS) Checks if a given intent is supported.
|
||||
|
||||
def isIntentSupported(profile, intent, direction):
|
||||
"""
|
||||
ImageCms.isIntentSupported(profile, intent, direction)
|
||||
|
||||
Returns 1 if the intent/direction are supported, -1 if they are not.
|
||||
|
||||
profile = EITHER a valid CmsProfile object, OR a string of the
|
||||
filename of an ICC profile.
|
||||
intent = integer (0-3) specifying the rendering intent you wish to use
|
||||
with this profile
|
||||
INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL)
|
||||
INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC)
|
||||
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
|
||||
INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
|
||||
see the pyCMS documentation for details on rendering intents and
|
||||
what they do.
|
||||
direction = integer specifing if the profile is to be used for input,
|
||||
output, or proof
|
||||
INPUT = 0 (or use ImageCms.DIRECTION_INPUT)
|
||||
OUTPUT = 1 (or use ImageCms.DIRECTION_OUTPUT)
|
||||
PROOF = 2 (or use ImageCms.DIRECTION_PROOF)
|
||||
|
||||
Use this function to verify that you can use your desired
|
||||
renderingIntent with profile, and that profile can be used for the
|
||||
input/output/proof profile as you desire.
|
||||
|
||||
Some profiles are created specifically for one "direction", can cannot
|
||||
be used for others. Some profiles can only be used for certain
|
||||
rendering intents... so it's best to either verify this before trying
|
||||
to create a transform with them (using this function), or catch the
|
||||
potential PyCMSError that will occur if they don't support the modes
|
||||
you select.
|
||||
|
||||
"""
|
||||
try:
|
||||
if not isinstance(profile, ImageCmsProfile):
|
||||
profile = ImageCmsProfile(profile)
|
||||
# FIXME: I get different results for the same data w. different
|
||||
# compilers. Bug in LittleCMS or in the binding?
|
||||
if profile.profile.is_intent_supported(intent, direction):
|
||||
return 1
|
||||
else:
|
||||
return -1
|
||||
except (AttributeError, IOError, TypeError, ValueError), v:
|
||||
raise PyCMSError(v)
|
||||
|
||||
##
|
||||
# (pyCMS) Fetches versions.
|
||||
|
||||
def versions():
|
||||
import sys
|
||||
return (
|
||||
VERSION, core.littlecms_version, sys.version.split()[0], Image.VERSION
|
||||
)
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
# create a cheap manual from the __doc__ strings for the functions above
|
||||
|
||||
import ImageCms
|
||||
import string
|
||||
print __doc__
|
||||
|
||||
for f in dir(pyCMS):
|
||||
print "="*80
|
||||
print "%s" %f
|
||||
|
||||
try:
|
||||
exec ("doc = ImageCms.%s.__doc__" %(f))
|
||||
if string.find(doc, "pyCMS") >= 0:
|
||||
# so we don't get the __doc__ string for imported modules
|
||||
print doc
|
||||
except AttributeError:
|
||||
pass
|
||||
263
Darwin/lib/python2.7/site-packages/PIL/ImageColor.py
Normal file
263
Darwin/lib/python2.7/site-packages/PIL/ImageColor.py
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# map CSS3-style colour description strings to RGB
|
||||
#
|
||||
# History:
|
||||
# 2002-10-24 fl Added support for CSS-style color strings
|
||||
# 2002-12-15 fl Added RGBA support
|
||||
# 2004-03-27 fl Fixed remaining int() problems for Python 1.5.2
|
||||
# 2004-07-19 fl Fixed gray/grey spelling issues
|
||||
# 2009-03-05 fl Fixed rounding error in grayscale calculation
|
||||
#
|
||||
# Copyright (c) 2002-2004 by Secret Labs AB
|
||||
# Copyright (c) 2002-2004 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
import re, string
|
||||
|
||||
try:
|
||||
x = int("a", 16)
|
||||
except TypeError:
|
||||
# python 1.5.2 doesn't support int(x,b)
|
||||
str2int = string.atoi
|
||||
else:
|
||||
str2int = int
|
||||
|
||||
##
|
||||
# Convert color string to RGB tuple.
|
||||
#
|
||||
# @param color A CSS3-style colour string.
|
||||
# @return An RGB-tuple.
|
||||
# @exception ValueError If the color string could not be interpreted
|
||||
# as an RGB value.
|
||||
|
||||
def getrgb(color):
|
||||
# FIXME: add RGBA support
|
||||
try:
|
||||
rgb = colormap[color]
|
||||
except KeyError:
|
||||
try:
|
||||
# fall back on case-insensitive lookup
|
||||
rgb = colormap[string.lower(color)]
|
||||
except KeyError:
|
||||
rgb = None
|
||||
# found color in cache
|
||||
if rgb:
|
||||
if isinstance(rgb, type(())):
|
||||
return rgb
|
||||
colormap[color] = rgb = getrgb(rgb)
|
||||
return rgb
|
||||
# check for known string formats
|
||||
m = re.match("#\w\w\w$", color)
|
||||
if m:
|
||||
return (
|
||||
str2int(color[1]*2, 16),
|
||||
str2int(color[2]*2, 16),
|
||||
str2int(color[3]*2, 16)
|
||||
)
|
||||
m = re.match("#\w\w\w\w\w\w$", color)
|
||||
if m:
|
||||
return (
|
||||
str2int(color[1:3], 16),
|
||||
str2int(color[3:5], 16),
|
||||
str2int(color[5:7], 16)
|
||||
)
|
||||
m = re.match("rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color)
|
||||
if m:
|
||||
return (
|
||||
str2int(m.group(1)),
|
||||
str2int(m.group(2)),
|
||||
str2int(m.group(3))
|
||||
)
|
||||
m = re.match("rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$", color)
|
||||
if m:
|
||||
return (
|
||||
int((str2int(m.group(1)) * 255) / 100.0 + 0.5),
|
||||
int((str2int(m.group(2)) * 255) / 100.0 + 0.5),
|
||||
int((str2int(m.group(3)) * 255) / 100.0 + 0.5)
|
||||
)
|
||||
m = re.match("hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$", color)
|
||||
if m:
|
||||
from colorsys import hls_to_rgb
|
||||
rgb = hls_to_rgb(
|
||||
float(m.group(1)) / 360.0,
|
||||
float(m.group(3)) / 100.0,
|
||||
float(m.group(2)) / 100.0,
|
||||
)
|
||||
return (
|
||||
int(rgb[0] * 255 + 0.5),
|
||||
int(rgb[1] * 255 + 0.5),
|
||||
int(rgb[2] * 255 + 0.5)
|
||||
)
|
||||
raise ValueError("unknown color specifier: %r" % color)
|
||||
|
||||
def getcolor(color, mode):
|
||||
# same as getrgb, but converts the result to the given mode
|
||||
color = getrgb(color)
|
||||
if mode == "RGB":
|
||||
return color
|
||||
if mode == "RGBA":
|
||||
r, g, b = color
|
||||
return r, g, b, 255
|
||||
if Image.getmodebase(mode) == "L":
|
||||
r, g, b = color
|
||||
return (r*299 + g*587 + b*114)/1000
|
||||
return color
|
||||
|
||||
colormap = {
|
||||
# X11 colour table (from "CSS3 module: Color working draft"), with
|
||||
# gray/grey spelling issues fixed. This is a superset of HTML 4.0
|
||||
# colour names used in CSS 1.
|
||||
"aliceblue": "#f0f8ff",
|
||||
"antiquewhite": "#faebd7",
|
||||
"aqua": "#00ffff",
|
||||
"aquamarine": "#7fffd4",
|
||||
"azure": "#f0ffff",
|
||||
"beige": "#f5f5dc",
|
||||
"bisque": "#ffe4c4",
|
||||
"black": "#000000",
|
||||
"blanchedalmond": "#ffebcd",
|
||||
"blue": "#0000ff",
|
||||
"blueviolet": "#8a2be2",
|
||||
"brown": "#a52a2a",
|
||||
"burlywood": "#deb887",
|
||||
"cadetblue": "#5f9ea0",
|
||||
"chartreuse": "#7fff00",
|
||||
"chocolate": "#d2691e",
|
||||
"coral": "#ff7f50",
|
||||
"cornflowerblue": "#6495ed",
|
||||
"cornsilk": "#fff8dc",
|
||||
"crimson": "#dc143c",
|
||||
"cyan": "#00ffff",
|
||||
"darkblue": "#00008b",
|
||||
"darkcyan": "#008b8b",
|
||||
"darkgoldenrod": "#b8860b",
|
||||
"darkgray": "#a9a9a9",
|
||||
"darkgrey": "#a9a9a9",
|
||||
"darkgreen": "#006400",
|
||||
"darkkhaki": "#bdb76b",
|
||||
"darkmagenta": "#8b008b",
|
||||
"darkolivegreen": "#556b2f",
|
||||
"darkorange": "#ff8c00",
|
||||
"darkorchid": "#9932cc",
|
||||
"darkred": "#8b0000",
|
||||
"darksalmon": "#e9967a",
|
||||
"darkseagreen": "#8fbc8f",
|
||||
"darkslateblue": "#483d8b",
|
||||
"darkslategray": "#2f4f4f",
|
||||
"darkslategrey": "#2f4f4f",
|
||||
"darkturquoise": "#00ced1",
|
||||
"darkviolet": "#9400d3",
|
||||
"deeppink": "#ff1493",
|
||||
"deepskyblue": "#00bfff",
|
||||
"dimgray": "#696969",
|
||||
"dimgrey": "#696969",
|
||||
"dodgerblue": "#1e90ff",
|
||||
"firebrick": "#b22222",
|
||||
"floralwhite": "#fffaf0",
|
||||
"forestgreen": "#228b22",
|
||||
"fuchsia": "#ff00ff",
|
||||
"gainsboro": "#dcdcdc",
|
||||
"ghostwhite": "#f8f8ff",
|
||||
"gold": "#ffd700",
|
||||
"goldenrod": "#daa520",
|
||||
"gray": "#808080",
|
||||
"grey": "#808080",
|
||||
"green": "#008000",
|
||||
"greenyellow": "#adff2f",
|
||||
"honeydew": "#f0fff0",
|
||||
"hotpink": "#ff69b4",
|
||||
"indianred": "#cd5c5c",
|
||||
"indigo": "#4b0082",
|
||||
"ivory": "#fffff0",
|
||||
"khaki": "#f0e68c",
|
||||
"lavender": "#e6e6fa",
|
||||
"lavenderblush": "#fff0f5",
|
||||
"lawngreen": "#7cfc00",
|
||||
"lemonchiffon": "#fffacd",
|
||||
"lightblue": "#add8e6",
|
||||
"lightcoral": "#f08080",
|
||||
"lightcyan": "#e0ffff",
|
||||
"lightgoldenrodyellow": "#fafad2",
|
||||
"lightgreen": "#90ee90",
|
||||
"lightgray": "#d3d3d3",
|
||||
"lightgrey": "#d3d3d3",
|
||||
"lightpink": "#ffb6c1",
|
||||
"lightsalmon": "#ffa07a",
|
||||
"lightseagreen": "#20b2aa",
|
||||
"lightskyblue": "#87cefa",
|
||||
"lightslategray": "#778899",
|
||||
"lightslategrey": "#778899",
|
||||
"lightsteelblue": "#b0c4de",
|
||||
"lightyellow": "#ffffe0",
|
||||
"lime": "#00ff00",
|
||||
"limegreen": "#32cd32",
|
||||
"linen": "#faf0e6",
|
||||
"magenta": "#ff00ff",
|
||||
"maroon": "#800000",
|
||||
"mediumaquamarine": "#66cdaa",
|
||||
"mediumblue": "#0000cd",
|
||||
"mediumorchid": "#ba55d3",
|
||||
"mediumpurple": "#9370db",
|
||||
"mediumseagreen": "#3cb371",
|
||||
"mediumslateblue": "#7b68ee",
|
||||
"mediumspringgreen": "#00fa9a",
|
||||
"mediumturquoise": "#48d1cc",
|
||||
"mediumvioletred": "#c71585",
|
||||
"midnightblue": "#191970",
|
||||
"mintcream": "#f5fffa",
|
||||
"mistyrose": "#ffe4e1",
|
||||
"moccasin": "#ffe4b5",
|
||||
"navajowhite": "#ffdead",
|
||||
"navy": "#000080",
|
||||
"oldlace": "#fdf5e6",
|
||||
"olive": "#808000",
|
||||
"olivedrab": "#6b8e23",
|
||||
"orange": "#ffa500",
|
||||
"orangered": "#ff4500",
|
||||
"orchid": "#da70d6",
|
||||
"palegoldenrod": "#eee8aa",
|
||||
"palegreen": "#98fb98",
|
||||
"paleturquoise": "#afeeee",
|
||||
"palevioletred": "#db7093",
|
||||
"papayawhip": "#ffefd5",
|
||||
"peachpuff": "#ffdab9",
|
||||
"peru": "#cd853f",
|
||||
"pink": "#ffc0cb",
|
||||
"plum": "#dda0dd",
|
||||
"powderblue": "#b0e0e6",
|
||||
"purple": "#800080",
|
||||
"red": "#ff0000",
|
||||
"rosybrown": "#bc8f8f",
|
||||
"royalblue": "#4169e1",
|
||||
"saddlebrown": "#8b4513",
|
||||
"salmon": "#fa8072",
|
||||
"sandybrown": "#f4a460",
|
||||
"seagreen": "#2e8b57",
|
||||
"seashell": "#fff5ee",
|
||||
"sienna": "#a0522d",
|
||||
"silver": "#c0c0c0",
|
||||
"skyblue": "#87ceeb",
|
||||
"slateblue": "#6a5acd",
|
||||
"slategray": "#708090",
|
||||
"slategrey": "#708090",
|
||||
"snow": "#fffafa",
|
||||
"springgreen": "#00ff7f",
|
||||
"steelblue": "#4682b4",
|
||||
"tan": "#d2b48c",
|
||||
"teal": "#008080",
|
||||
"thistle": "#d8bfd8",
|
||||
"tomato": "#ff6347",
|
||||
"turquoise": "#40e0d0",
|
||||
"violet": "#ee82ee",
|
||||
"wheat": "#f5deb3",
|
||||
"white": "#ffffff",
|
||||
"whitesmoke": "#f5f5f5",
|
||||
"yellow": "#ffff00",
|
||||
"yellowgreen": "#9acd32",
|
||||
}
|
||||
378
Darwin/lib/python2.7/site-packages/PIL/ImageDraw.py
Normal file
378
Darwin/lib/python2.7/site-packages/PIL/ImageDraw.py
Normal file
|
|
@ -0,0 +1,378 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# drawing interface operations
|
||||
#
|
||||
# History:
|
||||
# 1996-04-13 fl Created (experimental)
|
||||
# 1996-08-07 fl Filled polygons, ellipses.
|
||||
# 1996-08-13 fl Added text support
|
||||
# 1998-06-28 fl Handle I and F images
|
||||
# 1998-12-29 fl Added arc; use arc primitive to draw ellipses
|
||||
# 1999-01-10 fl Added shape stuff (experimental)
|
||||
# 1999-02-06 fl Added bitmap support
|
||||
# 1999-02-11 fl Changed all primitives to take options
|
||||
# 1999-02-20 fl Fixed backwards compatibility
|
||||
# 2000-10-12 fl Copy on write, when necessary
|
||||
# 2001-02-18 fl Use default ink for bitmap/text also in fill mode
|
||||
# 2002-10-24 fl Added support for CSS-style color strings
|
||||
# 2002-12-10 fl Added experimental support for RGBA-on-RGB drawing
|
||||
# 2002-12-11 fl Refactored low-level drawing API (work in progress)
|
||||
# 2004-08-26 fl Made Draw() a factory function, added getdraw() support
|
||||
# 2004-09-04 fl Added width support to line primitive
|
||||
# 2004-09-10 fl Added font mode handling
|
||||
# 2006-06-19 fl Added font bearing support (getmask2)
|
||||
#
|
||||
# Copyright (c) 1997-2006 by Secret Labs AB
|
||||
# Copyright (c) 1996-2006 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image, ImageColor
|
||||
|
||||
try:
|
||||
import warnings
|
||||
except ImportError:
|
||||
warnings = None
|
||||
|
||||
##
|
||||
# A simple 2D drawing interface for PIL images.
|
||||
# <p>
|
||||
# Application code should use the <b>Draw</b> factory, instead of
|
||||
# directly.
|
||||
|
||||
class ImageDraw:
|
||||
|
||||
##
|
||||
# Create a drawing instance.
|
||||
#
|
||||
# @param im The image to draw in.
|
||||
# @param mode Optional mode to use for color values. For RGB
|
||||
# images, this argument can be RGB or RGBA (to blend the
|
||||
# drawing into the image). For all other modes, this argument
|
||||
# must be the same as the image mode. If omitted, the mode
|
||||
# defaults to the mode of the image.
|
||||
|
||||
def __init__(self, im, mode=None):
|
||||
im.load()
|
||||
if im.readonly:
|
||||
im._copy() # make it writable
|
||||
blend = 0
|
||||
if mode is None:
|
||||
mode = im.mode
|
||||
if mode != im.mode:
|
||||
if mode == "RGBA" and im.mode == "RGB":
|
||||
blend = 1
|
||||
else:
|
||||
raise ValueError("mode mismatch")
|
||||
if mode == "P":
|
||||
self.palette = im.palette
|
||||
else:
|
||||
self.palette = None
|
||||
self.im = im.im
|
||||
self.draw = Image.core.draw(self.im, blend)
|
||||
self.mode = mode
|
||||
if mode in ("I", "F"):
|
||||
self.ink = self.draw.draw_ink(1, mode)
|
||||
else:
|
||||
self.ink = self.draw.draw_ink(-1, mode)
|
||||
if mode in ("1", "P", "I", "F"):
|
||||
# FIXME: fix Fill2 to properly support matte for I+F images
|
||||
self.fontmode = "1"
|
||||
else:
|
||||
self.fontmode = "L" # aliasing is okay for other modes
|
||||
self.fill = 0
|
||||
self.font = None
|
||||
|
||||
##
|
||||
# Set the default pen color.
|
||||
|
||||
def setink(self, ink):
|
||||
# compatibility
|
||||
if warnings:
|
||||
warnings.warn(
|
||||
"'setink' is deprecated; use keyword arguments instead",
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
if Image.isStringType(ink):
|
||||
ink = ImageColor.getcolor(ink, self.mode)
|
||||
if self.palette and not Image.isNumberType(ink):
|
||||
ink = self.palette.getcolor(ink)
|
||||
self.ink = self.draw.draw_ink(ink, self.mode)
|
||||
|
||||
##
|
||||
# Set the default background color.
|
||||
|
||||
def setfill(self, onoff):
|
||||
# compatibility
|
||||
if warnings:
|
||||
warnings.warn(
|
||||
"'setfill' is deprecated; use keyword arguments instead",
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
self.fill = onoff
|
||||
|
||||
##
|
||||
# Set the default font.
|
||||
|
||||
def setfont(self, font):
|
||||
# compatibility
|
||||
self.font = font
|
||||
|
||||
##
|
||||
# Get the current default font.
|
||||
|
||||
def getfont(self):
|
||||
if not self.font:
|
||||
# FIXME: should add a font repository
|
||||
import ImageFont
|
||||
self.font = ImageFont.load_default()
|
||||
return self.font
|
||||
|
||||
def _getink(self, ink, fill=None):
|
||||
if ink is None and fill is None:
|
||||
if self.fill:
|
||||
fill = self.ink
|
||||
else:
|
||||
ink = self.ink
|
||||
else:
|
||||
if ink is not None:
|
||||
if Image.isStringType(ink):
|
||||
ink = ImageColor.getcolor(ink, self.mode)
|
||||
if self.palette and not Image.isNumberType(ink):
|
||||
ink = self.palette.getcolor(ink)
|
||||
ink = self.draw.draw_ink(ink, self.mode)
|
||||
if fill is not None:
|
||||
if Image.isStringType(fill):
|
||||
fill = ImageColor.getcolor(fill, self.mode)
|
||||
if self.palette and not Image.isNumberType(fill):
|
||||
fill = self.palette.getcolor(fill)
|
||||
fill = self.draw.draw_ink(fill, self.mode)
|
||||
return ink, fill
|
||||
|
||||
##
|
||||
# Draw an arc.
|
||||
|
||||
def arc(self, xy, start, end, fill=None):
|
||||
ink, fill = self._getink(fill)
|
||||
if ink is not None:
|
||||
self.draw.draw_arc(xy, start, end, ink)
|
||||
|
||||
##
|
||||
# Draw a bitmap.
|
||||
|
||||
def bitmap(self, xy, bitmap, fill=None):
|
||||
bitmap.load()
|
||||
ink, fill = self._getink(fill)
|
||||
if ink is None:
|
||||
ink = fill
|
||||
if ink is not None:
|
||||
self.draw.draw_bitmap(xy, bitmap.im, ink)
|
||||
|
||||
##
|
||||
# Draw a chord.
|
||||
|
||||
def chord(self, xy, start, end, fill=None, outline=None):
|
||||
ink, fill = self._getink(outline, fill)
|
||||
if fill is not None:
|
||||
self.draw.draw_chord(xy, start, end, fill, 1)
|
||||
if ink is not None:
|
||||
self.draw.draw_chord(xy, start, end, ink, 0)
|
||||
|
||||
##
|
||||
# Draw an ellipse.
|
||||
|
||||
def ellipse(self, xy, fill=None, outline=None):
|
||||
ink, fill = self._getink(outline, fill)
|
||||
if fill is not None:
|
||||
self.draw.draw_ellipse(xy, fill, 1)
|
||||
if ink is not None:
|
||||
self.draw.draw_ellipse(xy, ink, 0)
|
||||
|
||||
##
|
||||
# Draw a line, or a connected sequence of line segments.
|
||||
|
||||
def line(self, xy, fill=None, width=0):
|
||||
ink, fill = self._getink(fill)
|
||||
if ink is not None:
|
||||
self.draw.draw_lines(xy, ink, width)
|
||||
|
||||
##
|
||||
# (Experimental) Draw a shape.
|
||||
|
||||
def shape(self, shape, fill=None, outline=None):
|
||||
# experimental
|
||||
shape.close()
|
||||
ink, fill = self._getink(outline, fill)
|
||||
if fill is not None:
|
||||
self.draw.draw_outline(shape, fill, 1)
|
||||
if ink is not None:
|
||||
self.draw.draw_outline(shape, ink, 0)
|
||||
|
||||
##
|
||||
# Draw a pieslice.
|
||||
|
||||
def pieslice(self, xy, start, end, fill=None, outline=None):
|
||||
ink, fill = self._getink(outline, fill)
|
||||
if fill is not None:
|
||||
self.draw.draw_pieslice(xy, start, end, fill, 1)
|
||||
if ink is not None:
|
||||
self.draw.draw_pieslice(xy, start, end, ink, 0)
|
||||
|
||||
##
|
||||
# Draw one or more individual pixels.
|
||||
|
||||
def point(self, xy, fill=None):
|
||||
ink, fill = self._getink(fill)
|
||||
if ink is not None:
|
||||
self.draw.draw_points(xy, ink)
|
||||
|
||||
##
|
||||
# Draw a polygon.
|
||||
|
||||
def polygon(self, xy, fill=None, outline=None):
|
||||
ink, fill = self._getink(outline, fill)
|
||||
if fill is not None:
|
||||
self.draw.draw_polygon(xy, fill, 1)
|
||||
if ink is not None:
|
||||
self.draw.draw_polygon(xy, ink, 0)
|
||||
|
||||
##
|
||||
# Draw a rectangle.
|
||||
|
||||
def rectangle(self, xy, fill=None, outline=None):
|
||||
ink, fill = self._getink(outline, fill)
|
||||
if fill is not None:
|
||||
self.draw.draw_rectangle(xy, fill, 1)
|
||||
if ink is not None:
|
||||
self.draw.draw_rectangle(xy, ink, 0)
|
||||
|
||||
##
|
||||
# Draw text.
|
||||
|
||||
def text(self, xy, text, fill=None, font=None, anchor=None):
|
||||
ink, fill = self._getink(fill)
|
||||
if font is None:
|
||||
font = self.getfont()
|
||||
if ink is None:
|
||||
ink = fill
|
||||
if ink is not None:
|
||||
try:
|
||||
mask, offset = font.getmask2(text, self.fontmode)
|
||||
xy = xy[0] + offset[0], xy[1] + offset[1]
|
||||
except AttributeError:
|
||||
try:
|
||||
mask = font.getmask(text, self.fontmode)
|
||||
except TypeError:
|
||||
mask = font.getmask(text)
|
||||
self.draw.draw_bitmap(xy, mask, ink)
|
||||
|
||||
##
|
||||
# Get the size of a given string, in pixels.
|
||||
|
||||
def textsize(self, text, font=None):
|
||||
if font is None:
|
||||
font = self.getfont()
|
||||
return font.getsize(text)
|
||||
|
||||
##
|
||||
# A simple 2D drawing interface for PIL images.
|
||||
#
|
||||
# @param im The image to draw in.
|
||||
# @param mode Optional mode to use for color values. For RGB
|
||||
# images, this argument can be RGB or RGBA (to blend the
|
||||
# drawing into the image). For all other modes, this argument
|
||||
# must be the same as the image mode. If omitted, the mode
|
||||
# defaults to the mode of the image.
|
||||
|
||||
def Draw(im, mode=None):
|
||||
try:
|
||||
return im.getdraw(mode)
|
||||
except AttributeError:
|
||||
return ImageDraw(im, mode)
|
||||
|
||||
# experimental access to the outline API
|
||||
try:
|
||||
Outline = Image.core.outline
|
||||
except:
|
||||
Outline = None
|
||||
|
||||
##
|
||||
# (Experimental) A more advanced 2D drawing interface for PIL images,
|
||||
# based on the WCK interface.
|
||||
#
|
||||
# @param im The image to draw in.
|
||||
# @param hints An optional list of hints.
|
||||
# @return A (drawing context, drawing resource factory) tuple.
|
||||
|
||||
def getdraw(im=None, hints=None):
|
||||
# FIXME: this needs more work!
|
||||
# FIXME: come up with a better 'hints' scheme.
|
||||
handler = None
|
||||
if not hints or "nicest" in hints:
|
||||
try:
|
||||
import _imagingagg
|
||||
handler = _imagingagg
|
||||
except ImportError:
|
||||
pass
|
||||
if handler is None:
|
||||
import ImageDraw2
|
||||
handler = ImageDraw2
|
||||
if im:
|
||||
im = handler.Draw(im)
|
||||
return im, handler
|
||||
|
||||
##
|
||||
# (experimental) Fills a bounded region with a given color.
|
||||
#
|
||||
# @param image Target image.
|
||||
# @param xy Seed position (a 2-item coordinate tuple).
|
||||
# @param value Fill color.
|
||||
# @param border Optional border value. If given, the region consists of
|
||||
# pixels with a color different from the border color. If not given,
|
||||
# the region consists of pixels having the same color as the seed
|
||||
# pixel.
|
||||
|
||||
def floodfill(image, xy, value, border=None):
|
||||
"Fill bounded region."
|
||||
# based on an implementation by Eric S. Raymond
|
||||
pixel = image.load()
|
||||
x, y = xy
|
||||
try:
|
||||
background = pixel[x, y]
|
||||
if background == value:
|
||||
return # seed point already has fill color
|
||||
pixel[x, y] = value
|
||||
except IndexError:
|
||||
return # seed point outside image
|
||||
edge = [(x, y)]
|
||||
if border is None:
|
||||
while edge:
|
||||
newedge = []
|
||||
for (x, y) in edge:
|
||||
for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
|
||||
try:
|
||||
p = pixel[s, t]
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
if p == background:
|
||||
pixel[s, t] = value
|
||||
newedge.append((s, t))
|
||||
edge = newedge
|
||||
else:
|
||||
while edge:
|
||||
newedge = []
|
||||
for (x, y) in edge:
|
||||
for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
|
||||
try:
|
||||
p = pixel[s, t]
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
if p != value and p != border:
|
||||
pixel[s, t] = value
|
||||
newedge.append((s, t))
|
||||
edge = newedge
|
||||
105
Darwin/lib/python2.7/site-packages/PIL/ImageDraw2.py
Normal file
105
Darwin/lib/python2.7/site-packages/PIL/ImageDraw2.py
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# WCK-style drawing interface operations
|
||||
#
|
||||
# History:
|
||||
# 2003-12-07 fl created
|
||||
# 2005-05-15 fl updated; added to PIL as ImageDraw2
|
||||
# 2005-05-15 fl added text support
|
||||
# 2005-05-20 fl added arc/chord/pieslice support
|
||||
#
|
||||
# Copyright (c) 2003-2005 by Secret Labs AB
|
||||
# Copyright (c) 2003-2005 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image, ImageColor, ImageDraw, ImageFont, ImagePath
|
||||
|
||||
class Pen:
|
||||
def __init__(self, color, width=1, opacity=255):
|
||||
self.color = ImageColor.getrgb(color)
|
||||
self.width = width
|
||||
|
||||
class Brush:
|
||||
def __init__(self, color, opacity=255):
|
||||
self.color = ImageColor.getrgb(color)
|
||||
|
||||
class Font:
|
||||
def __init__(self, color, file, size=12):
|
||||
# FIXME: add support for bitmap fonts
|
||||
self.color = ImageColor.getrgb(color)
|
||||
self.font = ImageFont.truetype(file, size)
|
||||
|
||||
class Draw:
|
||||
|
||||
def __init__(self, image, size=None, color=None):
|
||||
if not hasattr(image, "im"):
|
||||
image = Image.new(image, size, color)
|
||||
self.draw = ImageDraw.Draw(image)
|
||||
self.image = image
|
||||
self.transform = None
|
||||
|
||||
def flush(self):
|
||||
return self.image
|
||||
|
||||
def render(self, op, xy, pen, brush=None):
|
||||
# handle color arguments
|
||||
outline = fill = None; width = 1
|
||||
if isinstance(pen, Pen):
|
||||
outline = pen.color
|
||||
width = pen.width
|
||||
elif isinstance(brush, Pen):
|
||||
outline = brush.color
|
||||
width = brush.width
|
||||
if isinstance(brush, Brush):
|
||||
fill = brush.color
|
||||
elif isinstance(pen, Brush):
|
||||
fill = pen.color
|
||||
# handle transformation
|
||||
if self.transform:
|
||||
xy = ImagePath.Path(xy)
|
||||
xy.transform(self.transform)
|
||||
# render the item
|
||||
if op == "line":
|
||||
self.draw.line(xy, fill=outline, width=width)
|
||||
else:
|
||||
getattr(self.draw, op)(xy, fill=fill, outline=outline)
|
||||
|
||||
def settransform(self, (xoffset, yoffset)):
|
||||
self.transform = (1, 0, xoffset, 0, 1, yoffset)
|
||||
|
||||
def arc(self, xy, start, end, *options):
|
||||
self.render("arc", xy, start, end, *options)
|
||||
|
||||
def chord(self, xy, start, end, *options):
|
||||
self.render("chord", xy, start, end, *options)
|
||||
|
||||
def ellipse(self, xy, *options):
|
||||
self.render("ellipse", xy, *options)
|
||||
|
||||
def line(self, xy, *options):
|
||||
self.render("line", xy, *options)
|
||||
|
||||
def pieslice(self, xy, start, end, *options):
|
||||
self.render("pieslice", xy, start, end, *options)
|
||||
|
||||
def polygon(self, xy, *options):
|
||||
self.render("polygon", xy, *options)
|
||||
|
||||
def rectangle(self, xy, *options):
|
||||
self.render("rectangle", xy, *options)
|
||||
|
||||
def symbol(self, xy, symbol, *options):
|
||||
raise NotImplementedError("not in this version")
|
||||
|
||||
def text(self, xy, text, font):
|
||||
if self.transform:
|
||||
xy = ImagePath.Path(xy)
|
||||
xy.transform(self.transform)
|
||||
self.draw.text(xy, text, font=font.font, fill=font.color)
|
||||
|
||||
def textsize(self, text, font):
|
||||
return self.draw.textsize(text, font=font.font)
|
||||
90
Darwin/lib/python2.7/site-packages/PIL/ImageEnhance.py
Normal file
90
Darwin/lib/python2.7/site-packages/PIL/ImageEnhance.py
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# image enhancement classes
|
||||
#
|
||||
# For a background, see "Image Processing By Interpolation and
|
||||
# Extrapolation", Paul Haeberli and Douglas Voorhies. Available
|
||||
# at http://www.sgi.com/grafica/interp/index.html
|
||||
#
|
||||
# History:
|
||||
# 1996-03-23 fl Created
|
||||
# 2009-06-16 fl Fixed mean calculation
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1996.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image, ImageFilter, ImageStat
|
||||
|
||||
class _Enhance:
|
||||
|
||||
##
|
||||
# Returns an enhanced image. The enhancement factor is a floating
|
||||
# point value controlling the enhancement. Factor 1.0 always
|
||||
# returns a copy of the original image, lower factors mean less
|
||||
# colour (brightness, contrast, etc), and higher values more.
|
||||
# There are no restrictions on this value.
|
||||
#
|
||||
# @param factor Enhancement factor.
|
||||
# @return An enhanced image.
|
||||
|
||||
def enhance(self, factor):
|
||||
return Image.blend(self.degenerate, self.image, factor)
|
||||
|
||||
##
|
||||
# Color enhancement object.
|
||||
# <p>
|
||||
# This class can be used to adjust the colour balance of an image, in
|
||||
# a manner similar to the controls on a colour TV set. An enhancement
|
||||
# factor of 0.0 gives a black and white image, a factor of 1.0 gives
|
||||
# the original image.
|
||||
|
||||
class Color(_Enhance):
|
||||
"Adjust image colour balance"
|
||||
def __init__(self, image):
|
||||
self.image = image
|
||||
self.degenerate = image.convert("L").convert(image.mode)
|
||||
|
||||
##
|
||||
# Contrast enhancement object.
|
||||
# <p>
|
||||
# This class can be used to control the contrast of an image, similar
|
||||
# to the contrast control on a TV set. An enhancement factor of 0.0
|
||||
# gives a solid grey image, factor 1.0 gives the original image.
|
||||
|
||||
class Contrast(_Enhance):
|
||||
"Adjust image contrast"
|
||||
def __init__(self, image):
|
||||
self.image = image
|
||||
mean = int(ImageStat.Stat(image.convert("L")).mean[0] + 0.5)
|
||||
self.degenerate = Image.new("L", image.size, mean).convert(image.mode)
|
||||
|
||||
##
|
||||
# Brightness enhancement object.
|
||||
# <p>
|
||||
# This class can be used to control the brighntess of an image. An
|
||||
# enhancement factor of 0.0 gives a black image, factor 1.0 gives the
|
||||
# original image.
|
||||
|
||||
class Brightness(_Enhance):
|
||||
"Adjust image brightness"
|
||||
def __init__(self, image):
|
||||
self.image = image
|
||||
self.degenerate = Image.new(image.mode, image.size, 0)
|
||||
|
||||
##
|
||||
# Sharpness enhancement object.
|
||||
# <p>
|
||||
# This class can be used to adjust the sharpness of an image. The
|
||||
# enhancement factor 0.0 gives a blurred image, 1.0 gives the original
|
||||
# image, and a factor of 2.0 gives a sharpened image.
|
||||
|
||||
class Sharpness(_Enhance):
|
||||
"Adjust image sharpness"
|
||||
def __init__(self, image):
|
||||
self.image = image
|
||||
self.degenerate = image.filter(ImageFilter.SMOOTH)
|
||||
528
Darwin/lib/python2.7/site-packages/PIL/ImageFile.py
Normal file
528
Darwin/lib/python2.7/site-packages/PIL/ImageFile.py
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# base class for image file handlers
|
||||
#
|
||||
# history:
|
||||
# 1995-09-09 fl Created
|
||||
# 1996-03-11 fl Fixed load mechanism.
|
||||
# 1996-04-15 fl Added pcx/xbm decoders.
|
||||
# 1996-04-30 fl Added encoders.
|
||||
# 1996-12-14 fl Added load helpers
|
||||
# 1997-01-11 fl Use encode_to_file where possible
|
||||
# 1997-08-27 fl Flush output in _save
|
||||
# 1998-03-05 fl Use memory mapping for some modes
|
||||
# 1999-02-04 fl Use memory mapping also for "I;16" and "I;16B"
|
||||
# 1999-05-31 fl Added image parser
|
||||
# 2000-10-12 fl Set readonly flag on memory-mapped images
|
||||
# 2002-03-20 fl Use better messages for common decoder errors
|
||||
# 2003-04-21 fl Fall back on mmap/map_buffer if map is not available
|
||||
# 2003-10-30 fl Added StubImageFile class
|
||||
# 2004-02-25 fl Made incremental parser more robust
|
||||
#
|
||||
# Copyright (c) 1997-2004 by Secret Labs AB
|
||||
# Copyright (c) 1995-2004 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
import traceback, string, os
|
||||
|
||||
MAXBLOCK = 65536
|
||||
|
||||
SAFEBLOCK = 1024*1024
|
||||
|
||||
ERRORS = {
|
||||
-1: "image buffer overrun error",
|
||||
-2: "decoding error",
|
||||
-3: "unknown error",
|
||||
-8: "bad configuration",
|
||||
-9: "out of memory error"
|
||||
}
|
||||
|
||||
def raise_ioerror(error):
|
||||
try:
|
||||
message = Image.core.getcodecstatus(error)
|
||||
except AttributeError:
|
||||
message = ERRORS.get(error)
|
||||
if not message:
|
||||
message = "decoder error %d" % error
|
||||
raise IOError(message + " when reading image file")
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Helpers
|
||||
|
||||
def _tilesort(t1, t2):
|
||||
# sort on offset
|
||||
return cmp(t1[2], t2[2])
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# ImageFile base class
|
||||
|
||||
##
|
||||
# Base class for image file handlers.
|
||||
|
||||
class ImageFile(Image.Image):
|
||||
"Base class for image file format handlers."
|
||||
|
||||
def __init__(self, fp=None, filename=None):
|
||||
Image.Image.__init__(self)
|
||||
|
||||
self.tile = None
|
||||
self.readonly = 1 # until we know better
|
||||
|
||||
self.decoderconfig = ()
|
||||
self.decodermaxblock = MAXBLOCK
|
||||
|
||||
if Image.isStringType(fp):
|
||||
# filename
|
||||
self.fp = open(fp, "rb")
|
||||
self.filename = fp
|
||||
else:
|
||||
# stream
|
||||
self.fp = fp
|
||||
self.filename = filename
|
||||
|
||||
try:
|
||||
self._open()
|
||||
except IndexError, v: # end of data
|
||||
if Image.DEBUG > 1:
|
||||
traceback.print_exc()
|
||||
raise SyntaxError, v
|
||||
except TypeError, v: # end of data (ord)
|
||||
if Image.DEBUG > 1:
|
||||
traceback.print_exc()
|
||||
raise SyntaxError, v
|
||||
except KeyError, v: # unsupported mode
|
||||
if Image.DEBUG > 1:
|
||||
traceback.print_exc()
|
||||
raise SyntaxError, v
|
||||
except EOFError, v: # got header but not the first frame
|
||||
if Image.DEBUG > 1:
|
||||
traceback.print_exc()
|
||||
raise SyntaxError, v
|
||||
|
||||
if not self.mode or self.size[0] <= 0:
|
||||
raise SyntaxError, "not identified by this driver"
|
||||
|
||||
def draft(self, mode, size):
|
||||
"Set draft mode"
|
||||
|
||||
pass
|
||||
|
||||
def verify(self):
|
||||
"Check file integrity"
|
||||
|
||||
# raise exception if something's wrong. must be called
|
||||
# directly after open, and closes file when finished.
|
||||
self.fp = None
|
||||
|
||||
def load(self):
|
||||
"Load image data based on tile list"
|
||||
|
||||
pixel = Image.Image.load(self)
|
||||
|
||||
if self.tile is None:
|
||||
raise IOError("cannot load this image")
|
||||
if not self.tile:
|
||||
return pixel
|
||||
|
||||
self.map = None
|
||||
|
||||
readonly = 0
|
||||
|
||||
if self.filename and len(self.tile) == 1:
|
||||
# try memory mapping
|
||||
d, e, o, a = self.tile[0]
|
||||
if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES:
|
||||
try:
|
||||
if hasattr(Image.core, "map"):
|
||||
# use built-in mapper
|
||||
self.map = Image.core.map(self.filename)
|
||||
self.map.seek(o)
|
||||
self.im = self.map.readimage(
|
||||
self.mode, self.size, a[1], a[2]
|
||||
)
|
||||
else:
|
||||
# use mmap, if possible
|
||||
import mmap
|
||||
file = open(self.filename, "r+")
|
||||
size = os.path.getsize(self.filename)
|
||||
# FIXME: on Unix, use PROT_READ etc
|
||||
self.map = mmap.mmap(file.fileno(), size)
|
||||
self.im = Image.core.map_buffer(
|
||||
self.map, self.size, d, e, o, a
|
||||
)
|
||||
readonly = 1
|
||||
except (AttributeError, EnvironmentError, ImportError):
|
||||
self.map = None
|
||||
|
||||
self.load_prepare()
|
||||
|
||||
# look for read/seek overrides
|
||||
try:
|
||||
read = self.load_read
|
||||
except AttributeError:
|
||||
read = self.fp.read
|
||||
|
||||
try:
|
||||
seek = self.load_seek
|
||||
except AttributeError:
|
||||
seek = self.fp.seek
|
||||
|
||||
if not self.map:
|
||||
|
||||
# sort tiles in file order
|
||||
self.tile.sort(_tilesort)
|
||||
|
||||
try:
|
||||
# FIXME: This is a hack to handle TIFF's JpegTables tag.
|
||||
prefix = self.tile_prefix
|
||||
except AttributeError:
|
||||
prefix = ""
|
||||
|
||||
for d, e, o, a in self.tile:
|
||||
d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
|
||||
seek(o)
|
||||
try:
|
||||
d.setimage(self.im, e)
|
||||
except ValueError:
|
||||
continue
|
||||
b = prefix
|
||||
t = len(b)
|
||||
while 1:
|
||||
s = read(self.decodermaxblock)
|
||||
if not s:
|
||||
self.tile = []
|
||||
raise IOError("image file is truncated (%d bytes not processed)" % len(b))
|
||||
b = b + s
|
||||
n, e = d.decode(b)
|
||||
if n < 0:
|
||||
break
|
||||
b = b[n:]
|
||||
t = t + n
|
||||
|
||||
self.tile = []
|
||||
self.readonly = readonly
|
||||
|
||||
self.fp = None # might be shared
|
||||
|
||||
if not self.map and e < 0:
|
||||
raise_ioerror(e)
|
||||
|
||||
# post processing
|
||||
if hasattr(self, "tile_post_rotate"):
|
||||
# FIXME: This is a hack to handle rotated PCD's
|
||||
self.im = self.im.rotate(self.tile_post_rotate)
|
||||
self.size = self.im.size
|
||||
|
||||
self.load_end()
|
||||
|
||||
return Image.Image.load(self)
|
||||
|
||||
def load_prepare(self):
|
||||
# create image memory if necessary
|
||||
if not self.im or\
|
||||
self.im.mode != self.mode or self.im.size != self.size:
|
||||
self.im = Image.core.new(self.mode, self.size)
|
||||
# create palette (optional)
|
||||
if self.mode == "P":
|
||||
Image.Image.load(self)
|
||||
|
||||
def load_end(self):
|
||||
# may be overridden
|
||||
pass
|
||||
|
||||
# may be defined for contained formats
|
||||
# def load_seek(self, pos):
|
||||
# pass
|
||||
|
||||
# may be defined for blocked formats (e.g. PNG)
|
||||
# def load_read(self, bytes):
|
||||
# pass
|
||||
|
||||
##
|
||||
# Base class for stub image loaders.
|
||||
# <p>
|
||||
# A stub loader is an image loader that can identify files of a
|
||||
# certain format, but relies on external code to load the file.
|
||||
|
||||
class StubImageFile(ImageFile):
|
||||
"Base class for stub image loaders."
|
||||
|
||||
def _open(self):
|
||||
raise NotImplementedError(
|
||||
"StubImageFile subclass must implement _open"
|
||||
)
|
||||
|
||||
def load(self):
|
||||
loader = self._load()
|
||||
if loader is None:
|
||||
raise IOError("cannot find loader for this %s file" % self.format)
|
||||
image = loader.load(self)
|
||||
assert image is not None
|
||||
# become the other object (!)
|
||||
self.__class__ = image.__class__
|
||||
self.__dict__ = image.__dict__
|
||||
|
||||
##
|
||||
# (Hook) Find actual image loader.
|
||||
|
||||
def _load(self):
|
||||
raise NotImplementedError(
|
||||
"StubImageFile subclass must implement _load"
|
||||
)
|
||||
|
||||
##
|
||||
# (Internal) Support class for the <b>Parser</b> file.
|
||||
|
||||
class _ParserFile:
|
||||
# parser support class.
|
||||
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.offset = 0
|
||||
|
||||
def close(self):
|
||||
self.data = self.offset = None
|
||||
|
||||
def tell(self):
|
||||
return self.offset
|
||||
|
||||
def seek(self, offset, whence=0):
|
||||
if whence == 0:
|
||||
self.offset = offset
|
||||
elif whence == 1:
|
||||
self.offset = self.offset + offset
|
||||
else:
|
||||
# force error in Image.open
|
||||
raise IOError("illegal argument to seek")
|
||||
|
||||
def read(self, bytes=0):
|
||||
pos = self.offset
|
||||
if bytes:
|
||||
data = self.data[pos:pos+bytes]
|
||||
else:
|
||||
data = self.data[pos:]
|
||||
self.offset = pos + len(data)
|
||||
return data
|
||||
|
||||
def readline(self):
|
||||
# FIXME: this is slow!
|
||||
s = ""
|
||||
while 1:
|
||||
c = self.read(1)
|
||||
if not c:
|
||||
break
|
||||
s = s + c
|
||||
if c == "\n":
|
||||
break
|
||||
return s
|
||||
|
||||
##
|
||||
# Incremental image parser. This class implements the standard
|
||||
# feed/close consumer interface.
|
||||
|
||||
class Parser:
|
||||
|
||||
incremental = None
|
||||
image = None
|
||||
data = None
|
||||
decoder = None
|
||||
finished = 0
|
||||
|
||||
##
|
||||
# (Consumer) Reset the parser. Note that you can only call this
|
||||
# method immediately after you've created a parser; parser
|
||||
# instances cannot be reused.
|
||||
|
||||
def reset(self):
|
||||
assert self.data is None, "cannot reuse parsers"
|
||||
|
||||
##
|
||||
# (Consumer) Feed data to the parser.
|
||||
#
|
||||
# @param data A string buffer.
|
||||
# @exception IOError If the parser failed to parse the image file.
|
||||
|
||||
def feed(self, data):
|
||||
# collect data
|
||||
|
||||
if self.finished:
|
||||
return
|
||||
|
||||
if self.data is None:
|
||||
self.data = data
|
||||
else:
|
||||
self.data = self.data + data
|
||||
|
||||
# parse what we have
|
||||
if self.decoder:
|
||||
|
||||
if self.offset > 0:
|
||||
# skip header
|
||||
skip = min(len(self.data), self.offset)
|
||||
self.data = self.data[skip:]
|
||||
self.offset = self.offset - skip
|
||||
if self.offset > 0 or not self.data:
|
||||
return
|
||||
|
||||
n, e = self.decoder.decode(self.data)
|
||||
|
||||
if n < 0:
|
||||
# end of stream
|
||||
self.data = None
|
||||
self.finished = 1
|
||||
if e < 0:
|
||||
# decoding error
|
||||
self.image = None
|
||||
raise_ioerror(e)
|
||||
else:
|
||||
# end of image
|
||||
return
|
||||
self.data = self.data[n:]
|
||||
|
||||
elif self.image:
|
||||
|
||||
# if we end up here with no decoder, this file cannot
|
||||
# be incrementally parsed. wait until we've gotten all
|
||||
# available data
|
||||
pass
|
||||
|
||||
else:
|
||||
|
||||
# attempt to open this file
|
||||
try:
|
||||
try:
|
||||
fp = _ParserFile(self.data)
|
||||
im = Image.open(fp)
|
||||
finally:
|
||||
fp.close() # explicitly close the virtual file
|
||||
except IOError:
|
||||
pass # not enough data
|
||||
else:
|
||||
flag = hasattr(im, "load_seek") or hasattr(im, "load_read")
|
||||
if flag or len(im.tile) != 1:
|
||||
# custom load code, or multiple tiles
|
||||
self.decode = None
|
||||
else:
|
||||
# initialize decoder
|
||||
im.load_prepare()
|
||||
d, e, o, a = im.tile[0]
|
||||
im.tile = []
|
||||
self.decoder = Image._getdecoder(
|
||||
im.mode, d, a, im.decoderconfig
|
||||
)
|
||||
self.decoder.setimage(im.im, e)
|
||||
|
||||
# calculate decoder offset
|
||||
self.offset = o
|
||||
if self.offset <= len(self.data):
|
||||
self.data = self.data[self.offset:]
|
||||
self.offset = 0
|
||||
|
||||
self.image = im
|
||||
|
||||
##
|
||||
# (Consumer) Close the stream.
|
||||
#
|
||||
# @return An image object.
|
||||
# @exception IOError If the parser failed to parse the image file.
|
||||
|
||||
def close(self):
|
||||
# finish decoding
|
||||
if self.decoder:
|
||||
# get rid of what's left in the buffers
|
||||
self.feed("")
|
||||
self.data = self.decoder = None
|
||||
if not self.finished:
|
||||
raise IOError("image was incomplete")
|
||||
if not self.image:
|
||||
raise IOError("cannot parse this image")
|
||||
if self.data:
|
||||
# incremental parsing not possible; reopen the file
|
||||
# not that we have all data
|
||||
try:
|
||||
fp = _ParserFile(self.data)
|
||||
self.image = Image.open(fp)
|
||||
finally:
|
||||
self.image.load()
|
||||
fp.close() # explicitly close the virtual file
|
||||
return self.image
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
##
|
||||
# (Helper) Save image body to file.
|
||||
#
|
||||
# @param im Image object.
|
||||
# @param fp File object.
|
||||
# @param tile Tile list.
|
||||
|
||||
def _save(im, fp, tile):
|
||||
"Helper to save image based on tile list"
|
||||
|
||||
im.load()
|
||||
if not hasattr(im, "encoderconfig"):
|
||||
im.encoderconfig = ()
|
||||
tile.sort(_tilesort)
|
||||
# FIXME: make MAXBLOCK a configuration parameter
|
||||
bufsize = max(MAXBLOCK, im.size[0] * 4) # see RawEncode.c
|
||||
try:
|
||||
fh = fp.fileno()
|
||||
fp.flush()
|
||||
except AttributeError:
|
||||
# compress to Python file-compatible object
|
||||
for e, b, o, a in tile:
|
||||
e = Image._getencoder(im.mode, e, a, im.encoderconfig)
|
||||
if o > 0:
|
||||
fp.seek(o, 0)
|
||||
e.setimage(im.im, b)
|
||||
while 1:
|
||||
l, s, d = e.encode(bufsize)
|
||||
fp.write(d)
|
||||
if s:
|
||||
break
|
||||
if s < 0:
|
||||
raise IOError("encoder error %d when writing image file" % s)
|
||||
else:
|
||||
# slight speedup: compress to real file object
|
||||
for e, b, o, a in tile:
|
||||
e = Image._getencoder(im.mode, e, a, im.encoderconfig)
|
||||
if o > 0:
|
||||
fp.seek(o, 0)
|
||||
e.setimage(im.im, b)
|
||||
s = e.encode_to_file(fh, bufsize)
|
||||
if s < 0:
|
||||
raise IOError("encoder error %d when writing image file" % s)
|
||||
try:
|
||||
fp.flush()
|
||||
except: pass
|
||||
|
||||
|
||||
##
|
||||
# Reads large blocks in a safe way. Unlike fp.read(n), this function
|
||||
# doesn't trust the user. If the requested size is larger than
|
||||
# SAFEBLOCK, the file is read block by block.
|
||||
#
|
||||
# @param fp File handle. Must implement a <b>read</b> method.
|
||||
# @param size Number of bytes to read.
|
||||
# @return A string containing up to <i>size</i> bytes of data.
|
||||
|
||||
def _safe_read(fp, size):
|
||||
if size <= 0:
|
||||
return ""
|
||||
if size <= SAFEBLOCK:
|
||||
return fp.read(size)
|
||||
data = []
|
||||
while size > 0:
|
||||
block = fp.read(min(size, SAFEBLOCK))
|
||||
if not block:
|
||||
break
|
||||
data.append(block)
|
||||
size = size - len(block)
|
||||
return string.join(data, "")
|
||||
39
Darwin/lib/python2.7/site-packages/PIL/ImageFileIO.py
Normal file
39
Darwin/lib/python2.7/site-packages/PIL/ImageFileIO.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# kludge to get basic ImageFileIO functionality
|
||||
#
|
||||
# History:
|
||||
# 1998-08-06 fl Recreated
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1998-2002.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
from StringIO import StringIO
|
||||
|
||||
##
|
||||
# The <b>ImageFileIO</b> module can be used to read an image from a
|
||||
# socket, or any other stream device.
|
||||
# <p>
|
||||
# This module is deprecated. New code should use the <b>Parser</b>
|
||||
# class in the <a href="imagefile">ImageFile</a> module instead.
|
||||
#
|
||||
# @see ImageFile#Parser
|
||||
|
||||
class ImageFileIO(StringIO):
|
||||
|
||||
##
|
||||
# Adds buffering to a stream file object, in order to
|
||||
# provide <b>seek</b> and <b>tell</b> methods required
|
||||
# by the <b>Image.open</b> method. The stream object must
|
||||
# implement <b>read</b> and <b>close</b> methods.
|
||||
#
|
||||
# @param fp Stream file handle.
|
||||
# @see Image#open
|
||||
|
||||
def __init__(self, fp):
|
||||
data = fp.read()
|
||||
StringIO.__init__(self, data)
|
||||
289
Darwin/lib/python2.7/site-packages/PIL/ImageFilter.py
Normal file
289
Darwin/lib/python2.7/site-packages/PIL/ImageFilter.py
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# standard filters
|
||||
#
|
||||
# History:
|
||||
# 1995-11-27 fl Created
|
||||
# 2002-06-08 fl Added rank and mode filters
|
||||
# 2003-09-15 fl Fixed rank calculation in rank filter; added expand call
|
||||
#
|
||||
# Copyright (c) 1997-2003 by Secret Labs AB.
|
||||
# Copyright (c) 1995-2002 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
class Filter:
|
||||
pass
|
||||
|
||||
##
|
||||
# Convolution filter kernel.
|
||||
|
||||
class Kernel(Filter):
|
||||
|
||||
##
|
||||
# Create a convolution kernel. The current version only
|
||||
# supports 3x3 and 5x5 integer and floating point kernels.
|
||||
# <p>
|
||||
# In the current version, kernels can only be applied to
|
||||
# "L" and "RGB" images.
|
||||
#
|
||||
# @def __init__(size, kernel, **options)
|
||||
# @param size Kernel size, given as (width, height). In
|
||||
# the current version, this must be (3,3) or (5,5).
|
||||
# @param kernel A sequence containing kernel weights.
|
||||
# @param **options Optional keyword arguments.
|
||||
# @keyparam scale Scale factor. If given, the result for each
|
||||
# pixel is divided by this value. The default is the sum
|
||||
# of the kernel weights.
|
||||
# @keyparam offset Offset. If given, this value is added to the
|
||||
# result, after it has been divided by the scale factor.
|
||||
|
||||
def __init__(self, size, kernel, scale=None, offset=0):
|
||||
if scale is None:
|
||||
# default scale is sum of kernel
|
||||
scale = reduce(lambda a,b: a+b, kernel)
|
||||
if size[0] * size[1] != len(kernel):
|
||||
raise ValueError("not enough coefficients in kernel")
|
||||
self.filterargs = size, scale, offset, kernel
|
||||
|
||||
def filter(self, image):
|
||||
if image.mode == "P":
|
||||
raise ValueError("cannot filter palette images")
|
||||
return apply(image.filter, self.filterargs)
|
||||
|
||||
class BuiltinFilter(Kernel):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
##
|
||||
# Rank filter.
|
||||
|
||||
class RankFilter(Filter):
|
||||
name = "Rank"
|
||||
|
||||
##
|
||||
# Create a rank filter. The rank filter sorts all pixels in
|
||||
# a window of the given size, and returns the rank'th value.
|
||||
#
|
||||
# @param size The kernel size, in pixels.
|
||||
# @param rank What pixel value to pick. Use 0 for a min filter,
|
||||
# size*size/2 for a median filter, size*size-1 for a max filter,
|
||||
# etc.
|
||||
|
||||
def __init__(self, size, rank):
|
||||
self.size = size
|
||||
self.rank = rank
|
||||
|
||||
def filter(self, image):
|
||||
if image.mode == "P":
|
||||
raise ValueError("cannot filter palette images")
|
||||
image = image.expand(self.size/2, self.size/2)
|
||||
return image.rankfilter(self.size, self.rank)
|
||||
|
||||
##
|
||||
# Median filter. Picks the median pixel value in a window with the
|
||||
# given size.
|
||||
|
||||
class MedianFilter(RankFilter):
|
||||
name = "Median"
|
||||
|
||||
##
|
||||
# Create a median filter.
|
||||
#
|
||||
# @param size The kernel size, in pixels.
|
||||
|
||||
def __init__(self, size=3):
|
||||
self.size = size
|
||||
self.rank = size*size/2
|
||||
|
||||
##
|
||||
# Min filter. Picks the lowest pixel value in a window with the given
|
||||
# size.
|
||||
|
||||
class MinFilter(RankFilter):
|
||||
name = "Min"
|
||||
|
||||
##
|
||||
# Create a min filter.
|
||||
#
|
||||
# @param size The kernel size, in pixels.
|
||||
|
||||
def __init__(self, size=3):
|
||||
self.size = size
|
||||
self.rank = 0
|
||||
|
||||
##
|
||||
# Max filter. Picks the largest pixel value in a window with the
|
||||
# given size.
|
||||
|
||||
class MaxFilter(RankFilter):
|
||||
name = "Max"
|
||||
|
||||
##
|
||||
# Create a max filter.
|
||||
#
|
||||
# @param size The kernel size, in pixels.
|
||||
|
||||
def __init__(self, size=3):
|
||||
self.size = size
|
||||
self.rank = size*size-1
|
||||
|
||||
##
|
||||
# Mode filter. Picks the most frequent pixel value in a box with the
|
||||
# given size. Pixel values that occur only once or twice are ignored;
|
||||
# if no pixel value occurs more than twice, the original pixel value
|
||||
# is preserved.
|
||||
|
||||
class ModeFilter(Filter):
|
||||
name = "Mode"
|
||||
|
||||
##
|
||||
# Create a mode filter.
|
||||
#
|
||||
# @param size The kernel size, in pixels.
|
||||
|
||||
def __init__(self, size=3):
|
||||
self.size = size
|
||||
def filter(self, image):
|
||||
return image.modefilter(self.size)
|
||||
|
||||
##
|
||||
# Gaussian blur filter.
|
||||
|
||||
class GaussianBlur(Filter):
|
||||
name = "GaussianBlur"
|
||||
|
||||
def __init__(self, radius=2):
|
||||
self.radius = 2
|
||||
def filter(self, image):
|
||||
return image.gaussian_blur(self.radius)
|
||||
|
||||
##
|
||||
# Unsharp mask filter.
|
||||
|
||||
class UnsharpMask(Filter):
|
||||
name = "UnsharpMask"
|
||||
|
||||
def __init__(self, radius=2, percent=150, threshold=3):
|
||||
self.radius = 2
|
||||
self.percent = percent
|
||||
self.threshold = threshold
|
||||
def filter(self, image):
|
||||
return image.unsharp_mask(self.radius, self.percent, self.threshold)
|
||||
|
||||
##
|
||||
# Simple blur filter.
|
||||
|
||||
class BLUR(BuiltinFilter):
|
||||
name = "Blur"
|
||||
filterargs = (5, 5), 16, 0, (
|
||||
1, 1, 1, 1, 1,
|
||||
1, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 1,
|
||||
1, 1, 1, 1, 1
|
||||
)
|
||||
|
||||
##
|
||||
# Simple contour filter.
|
||||
|
||||
class CONTOUR(BuiltinFilter):
|
||||
name = "Contour"
|
||||
filterargs = (3, 3), 1, 255, (
|
||||
-1, -1, -1,
|
||||
-1, 8, -1,
|
||||
-1, -1, -1
|
||||
)
|
||||
|
||||
##
|
||||
# Simple detail filter.
|
||||
|
||||
class DETAIL(BuiltinFilter):
|
||||
name = "Detail"
|
||||
filterargs = (3, 3), 6, 0, (
|
||||
0, -1, 0,
|
||||
-1, 10, -1,
|
||||
0, -1, 0
|
||||
)
|
||||
|
||||
##
|
||||
# Simple edge enhancement filter.
|
||||
|
||||
class EDGE_ENHANCE(BuiltinFilter):
|
||||
name = "Edge-enhance"
|
||||
filterargs = (3, 3), 2, 0, (
|
||||
-1, -1, -1,
|
||||
-1, 10, -1,
|
||||
-1, -1, -1
|
||||
)
|
||||
|
||||
##
|
||||
# Simple stronger edge enhancement filter.
|
||||
|
||||
class EDGE_ENHANCE_MORE(BuiltinFilter):
|
||||
name = "Edge-enhance More"
|
||||
filterargs = (3, 3), 1, 0, (
|
||||
-1, -1, -1,
|
||||
-1, 9, -1,
|
||||
-1, -1, -1
|
||||
)
|
||||
|
||||
##
|
||||
# Simple embossing filter.
|
||||
|
||||
class EMBOSS(BuiltinFilter):
|
||||
name = "Emboss"
|
||||
filterargs = (3, 3), 1, 128, (
|
||||
-1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 0
|
||||
)
|
||||
|
||||
##
|
||||
# Simple edge-finding filter.
|
||||
|
||||
class FIND_EDGES(BuiltinFilter):
|
||||
name = "Find Edges"
|
||||
filterargs = (3, 3), 1, 0, (
|
||||
-1, -1, -1,
|
||||
-1, 8, -1,
|
||||
-1, -1, -1
|
||||
)
|
||||
|
||||
##
|
||||
# Simple smoothing filter.
|
||||
|
||||
class SMOOTH(BuiltinFilter):
|
||||
name = "Smooth"
|
||||
filterargs = (3, 3), 13, 0, (
|
||||
1, 1, 1,
|
||||
1, 5, 1,
|
||||
1, 1, 1
|
||||
)
|
||||
|
||||
##
|
||||
# Simple stronger smoothing filter.
|
||||
|
||||
class SMOOTH_MORE(BuiltinFilter):
|
||||
name = "Smooth More"
|
||||
filterargs = (5, 5), 100, 0, (
|
||||
1, 1, 1, 1, 1,
|
||||
1, 5, 5, 5, 1,
|
||||
1, 5, 44, 5, 1,
|
||||
1, 5, 5, 5, 1,
|
||||
1, 1, 1, 1, 1
|
||||
)
|
||||
|
||||
##
|
||||
# Simple sharpening filter.
|
||||
|
||||
class SHARPEN(BuiltinFilter):
|
||||
name = "Sharpen"
|
||||
filterargs = (3, 3), 16, 0, (
|
||||
-2, -2, -2,
|
||||
-2, 32, -2,
|
||||
-2, -2, -2
|
||||
)
|
||||
390
Darwin/lib/python2.7/site-packages/PIL/ImageFont.py
Normal file
390
Darwin/lib/python2.7/site-packages/PIL/ImageFont.py
Normal file
|
|
@ -0,0 +1,390 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# PIL raster font management
|
||||
#
|
||||
# History:
|
||||
# 1996-08-07 fl created (experimental)
|
||||
# 1997-08-25 fl minor adjustments to handle fonts from pilfont 0.3
|
||||
# 1999-02-06 fl rewrote most font management stuff in C
|
||||
# 1999-03-17 fl take pth files into account in load_path (from Richard Jones)
|
||||
# 2001-02-17 fl added freetype support
|
||||
# 2001-05-09 fl added TransposedFont wrapper class
|
||||
# 2002-03-04 fl make sure we have a "L" or "1" font
|
||||
# 2002-12-04 fl skip non-directory entries in the system path
|
||||
# 2003-04-29 fl add embedded default font
|
||||
# 2003-09-27 fl added support for truetype charmap encodings
|
||||
#
|
||||
# Todo:
|
||||
# Adapt to PILFONT2 format (16-bit fonts, compressed, single file)
|
||||
#
|
||||
# Copyright (c) 1997-2003 by Secret Labs AB
|
||||
# Copyright (c) 1996-2003 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
import os, string, sys
|
||||
|
||||
class _imagingft_not_installed:
|
||||
# module placeholder
|
||||
def __getattr__(self, id):
|
||||
raise ImportError("The _imagingft C module is not installed")
|
||||
|
||||
try:
|
||||
import _imagingft
|
||||
core = _imagingft
|
||||
del _imagingft
|
||||
except ImportError:
|
||||
core = _imagingft_not_installed()
|
||||
|
||||
# FIXME: add support for pilfont2 format (see FontFile.py)
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Font metrics format:
|
||||
# "PILfont" LF
|
||||
# fontdescriptor LF
|
||||
# (optional) key=value... LF
|
||||
# "DATA" LF
|
||||
# binary data: 256*10*2 bytes (dx, dy, dstbox, srcbox)
|
||||
#
|
||||
# To place a character, cut out srcbox and paste at dstbox,
|
||||
# relative to the character position. Then move the character
|
||||
# position according to dx, dy.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
##
|
||||
# The <b>ImageFont</b> module defines a class with the same name.
|
||||
# Instances of this class store bitmap fonts, and are used with the
|
||||
# <b>text</b> method of the <b>ImageDraw</b> class.
|
||||
# <p>
|
||||
# PIL uses it's own font file format to store bitmap fonts. You can
|
||||
# use the <b>pilfont</b> utility to convert BDF and PCF font
|
||||
# descriptors (X window font formats) to this format.
|
||||
# <p>
|
||||
# Starting with version 1.1.4, PIL can be configured to support
|
||||
# TrueType and OpenType fonts. For earlier version, TrueType
|
||||
# support is only available as part of the imToolkit package
|
||||
#
|
||||
# @see ImageDraw#ImageDraw.text
|
||||
# @see pilfont
|
||||
|
||||
class ImageFont:
|
||||
"PIL font wrapper"
|
||||
|
||||
def _load_pilfont(self, filename):
|
||||
|
||||
file = open(filename, "rb")
|
||||
|
||||
for ext in (".png", ".gif", ".pbm"):
|
||||
try:
|
||||
fullname = os.path.splitext(filename)[0] + ext
|
||||
image = Image.open(fullname)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
if image and image.mode in ("1", "L"):
|
||||
break
|
||||
else:
|
||||
raise IOError("cannot find glyph data file")
|
||||
|
||||
self.file = fullname
|
||||
|
||||
return self._load_pilfont_data(file, image)
|
||||
|
||||
def _load_pilfont_data(self, file, image):
|
||||
|
||||
# read PILfont header
|
||||
if file.readline() != "PILfont\n":
|
||||
raise SyntaxError("Not a PILfont file")
|
||||
d = string.split(file.readline(), ";")
|
||||
self.info = [] # FIXME: should be a dictionary
|
||||
while True:
|
||||
s = file.readline()
|
||||
if not s or s == "DATA\n":
|
||||
break
|
||||
self.info.append(s)
|
||||
|
||||
# read PILfont metrics
|
||||
data = file.read(256*20)
|
||||
|
||||
# check image
|
||||
if image.mode not in ("1", "L"):
|
||||
raise TypeError("invalid font image mode")
|
||||
|
||||
image.load()
|
||||
|
||||
self.font = Image.core.font(image.im, data)
|
||||
|
||||
# delegate critical operations to internal type
|
||||
self.getsize = self.font.getsize
|
||||
self.getmask = self.font.getmask
|
||||
|
||||
##
|
||||
# Wrapper for FreeType fonts. Application code should use the
|
||||
# <b>truetype</b> factory function to create font objects.
|
||||
|
||||
class FreeTypeFont:
|
||||
"FreeType font wrapper (requires _imagingft service)"
|
||||
|
||||
def __init__(self, file, size, index=0, encoding=""):
|
||||
# FIXME: use service provider instead
|
||||
self.font = core.getfont(file, size, index, encoding)
|
||||
|
||||
def getname(self):
|
||||
return self.font.family, self.font.style
|
||||
|
||||
def getmetrics(self):
|
||||
return self.font.ascent, self.font.descent
|
||||
|
||||
def getsize(self, text):
|
||||
return self.font.getsize(text)[0]
|
||||
|
||||
def getmask(self, text, mode=""):
|
||||
return self.getmask2(text, mode)[0]
|
||||
|
||||
def getmask2(self, text, mode="", fill=Image.core.fill):
|
||||
size, offset = self.font.getsize(text)
|
||||
im = fill("L", size, 0)
|
||||
self.font.render(text, im.id, mode=="1")
|
||||
return im, offset
|
||||
|
||||
##
|
||||
# Wrapper that creates a transposed font from any existing font
|
||||
# object.
|
||||
#
|
||||
# @param font A font object.
|
||||
# @param orientation An optional orientation. If given, this should
|
||||
# be one of Image.FLIP_LEFT_RIGHT, Image.FLIP_TOP_BOTTOM,
|
||||
# Image.ROTATE_90, Image.ROTATE_180, or Image.ROTATE_270.
|
||||
|
||||
class TransposedFont:
|
||||
"Wrapper for writing rotated or mirrored text"
|
||||
|
||||
def __init__(self, font, orientation=None):
|
||||
self.font = font
|
||||
self.orientation = orientation # any 'transpose' argument, or None
|
||||
|
||||
def getsize(self, text):
|
||||
w, h = self.font.getsize(text)
|
||||
if self.orientation in (Image.ROTATE_90, Image.ROTATE_270):
|
||||
return h, w
|
||||
return w, h
|
||||
|
||||
def getmask(self, text, mode=""):
|
||||
im = self.font.getmask(text, mode)
|
||||
if self.orientation is not None:
|
||||
return im.transpose(self.orientation)
|
||||
return im
|
||||
|
||||
##
|
||||
# Load font file. This function loads a font object from the given
|
||||
# bitmap font file, and returns the corresponding font object.
|
||||
#
|
||||
# @param filename Name of font file.
|
||||
# @return A font object.
|
||||
# @exception IOError If the file could not be read.
|
||||
|
||||
def load(filename):
|
||||
"Load a font file."
|
||||
f = ImageFont()
|
||||
f._load_pilfont(filename)
|
||||
return f
|
||||
|
||||
##
|
||||
# Load a TrueType or OpenType font file, and create a font object.
|
||||
# This function loads a font object from the given file, and creates
|
||||
# a font object for a font of the given size.
|
||||
# <p>
|
||||
# This function requires the _imagingft service.
|
||||
#
|
||||
# @param filename A truetype font file. Under Windows, if the file
|
||||
# is not found in this filename, the loader also looks in Windows
|
||||
# <b>fonts</b> directory
|
||||
# @param size The requested size, in points.
|
||||
# @param index Which font face to load (default is first available face).
|
||||
# @param encoding Which font encoding to use (default is Unicode). Common
|
||||
# encodings are "unic" (Unicode), "symb" (Microsoft Symbol), "ADOB"
|
||||
# (Adobe Standard), "ADBE" (Adobe Expert), and "armn" (Apple Roman).
|
||||
# See the FreeType documentation for more information.
|
||||
# @return A font object.
|
||||
# @exception IOError If the file could not be read.
|
||||
|
||||
def truetype(filename, size, index=0, encoding=""):
|
||||
"Load a truetype font file."
|
||||
try:
|
||||
return FreeTypeFont(filename, size, index, encoding)
|
||||
except IOError:
|
||||
if sys.platform == "win32":
|
||||
# check the windows font repository
|
||||
# NOTE: must use uppercase WINDIR, to work around bugs in
|
||||
# 1.5.2's os.environ.get()
|
||||
windir = os.environ.get("WINDIR")
|
||||
if windir:
|
||||
filename = os.path.join(windir, "fonts", filename)
|
||||
return FreeTypeFont(filename, size, index, encoding)
|
||||
raise
|
||||
|
||||
##
|
||||
# Load font file. Same as load, but searches for a bitmap font along
|
||||
# the Python path.
|
||||
#
|
||||
# @param filename Name of font file.
|
||||
# @return A font object.
|
||||
# @exception IOError If the file could not be read.
|
||||
# @see #load
|
||||
|
||||
def load_path(filename):
|
||||
"Load a font file, searching along the Python path."
|
||||
for dir in sys.path:
|
||||
if Image.isDirectory(dir):
|
||||
try:
|
||||
return load(os.path.join(dir, filename))
|
||||
except IOError:
|
||||
pass
|
||||
raise IOError("cannot find font file")
|
||||
|
||||
##
|
||||
# Load a (probably rather ugly) default font.
|
||||
#
|
||||
# @return A font object.
|
||||
|
||||
def load_default():
|
||||
"Load a default font."
|
||||
from StringIO import StringIO
|
||||
import base64
|
||||
f = ImageFont()
|
||||
f._load_pilfont_data(
|
||||
# courB08
|
||||
StringIO(base64.decodestring('''
|
||||
UElMZm9udAo7Ozs7OzsxMDsKREFUQQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA//8AAQAAAAAAAAABAAEA
|
||||
BgAAAAH/+gADAAAAAQAAAAMABgAGAAAAAf/6AAT//QADAAAABgADAAYAAAAA//kABQABAAYAAAAL
|
||||
AAgABgAAAAD/+AAFAAEACwAAABAACQAGAAAAAP/5AAUAAAAQAAAAFQAHAAYAAP////oABQAAABUA
|
||||
AAAbAAYABgAAAAH/+QAE//wAGwAAAB4AAwAGAAAAAf/5AAQAAQAeAAAAIQAIAAYAAAAB//kABAAB
|
||||
ACEAAAAkAAgABgAAAAD/+QAE//0AJAAAACgABAAGAAAAAP/6AAX//wAoAAAALQAFAAYAAAAB//8A
|
||||
BAACAC0AAAAwAAMABgAAAAD//AAF//0AMAAAADUAAQAGAAAAAf//AAMAAAA1AAAANwABAAYAAAAB
|
||||
//kABQABADcAAAA7AAgABgAAAAD/+QAFAAAAOwAAAEAABwAGAAAAAP/5AAYAAABAAAAARgAHAAYA
|
||||
AAAA//kABQAAAEYAAABLAAcABgAAAAD/+QAFAAAASwAAAFAABwAGAAAAAP/5AAYAAABQAAAAVgAH
|
||||
AAYAAAAA//kABQAAAFYAAABbAAcABgAAAAD/+QAFAAAAWwAAAGAABwAGAAAAAP/5AAUAAABgAAAA
|
||||
ZQAHAAYAAAAA//kABQAAAGUAAABqAAcABgAAAAD/+QAFAAAAagAAAG8ABwAGAAAAAf/8AAMAAABv
|
||||
AAAAcQAEAAYAAAAA//wAAwACAHEAAAB0AAYABgAAAAD/+gAE//8AdAAAAHgABQAGAAAAAP/7AAT/
|
||||
/gB4AAAAfAADAAYAAAAB//oABf//AHwAAACAAAUABgAAAAD/+gAFAAAAgAAAAIUABgAGAAAAAP/5
|
||||
AAYAAQCFAAAAiwAIAAYAAP////oABgAAAIsAAACSAAYABgAA////+gAFAAAAkgAAAJgABgAGAAAA
|
||||
AP/6AAUAAACYAAAAnQAGAAYAAP////oABQAAAJ0AAACjAAYABgAA////+gAFAAAAowAAAKkABgAG
|
||||
AAD////6AAUAAACpAAAArwAGAAYAAAAA//oABQAAAK8AAAC0AAYABgAA////+gAGAAAAtAAAALsA
|
||||
BgAGAAAAAP/6AAQAAAC7AAAAvwAGAAYAAP////oABQAAAL8AAADFAAYABgAA////+gAGAAAAxQAA
|
||||
AMwABgAGAAD////6AAUAAADMAAAA0gAGAAYAAP////oABQAAANIAAADYAAYABgAA////+gAGAAAA
|
||||
2AAAAN8ABgAGAAAAAP/6AAUAAADfAAAA5AAGAAYAAP////oABQAAAOQAAADqAAYABgAAAAD/+gAF
|
||||
AAEA6gAAAO8ABwAGAAD////6AAYAAADvAAAA9gAGAAYAAAAA//oABQAAAPYAAAD7AAYABgAA////
|
||||
+gAFAAAA+wAAAQEABgAGAAD////6AAYAAAEBAAABCAAGAAYAAP////oABgAAAQgAAAEPAAYABgAA
|
||||
////+gAGAAABDwAAARYABgAGAAAAAP/6AAYAAAEWAAABHAAGAAYAAP////oABgAAARwAAAEjAAYA
|
||||
BgAAAAD/+gAFAAABIwAAASgABgAGAAAAAf/5AAQAAQEoAAABKwAIAAYAAAAA//kABAABASsAAAEv
|
||||
AAgABgAAAAH/+QAEAAEBLwAAATIACAAGAAAAAP/5AAX//AEyAAABNwADAAYAAAAAAAEABgACATcA
|
||||
AAE9AAEABgAAAAH/+QAE//wBPQAAAUAAAwAGAAAAAP/7AAYAAAFAAAABRgAFAAYAAP////kABQAA
|
||||
AUYAAAFMAAcABgAAAAD/+wAFAAABTAAAAVEABQAGAAAAAP/5AAYAAAFRAAABVwAHAAYAAAAA//sA
|
||||
BQAAAVcAAAFcAAUABgAAAAD/+QAFAAABXAAAAWEABwAGAAAAAP/7AAYAAgFhAAABZwAHAAYAAP//
|
||||
//kABQAAAWcAAAFtAAcABgAAAAD/+QAGAAABbQAAAXMABwAGAAAAAP/5AAQAAgFzAAABdwAJAAYA
|
||||
AP////kABgAAAXcAAAF+AAcABgAAAAD/+QAGAAABfgAAAYQABwAGAAD////7AAUAAAGEAAABigAF
|
||||
AAYAAP////sABQAAAYoAAAGQAAUABgAAAAD/+wAFAAABkAAAAZUABQAGAAD////7AAUAAgGVAAAB
|
||||
mwAHAAYAAAAA//sABgACAZsAAAGhAAcABgAAAAD/+wAGAAABoQAAAacABQAGAAAAAP/7AAYAAAGn
|
||||
AAABrQAFAAYAAAAA//kABgAAAa0AAAGzAAcABgAA////+wAGAAABswAAAboABQAGAAD////7AAUA
|
||||
AAG6AAABwAAFAAYAAP////sABgAAAcAAAAHHAAUABgAAAAD/+wAGAAABxwAAAc0ABQAGAAD////7
|
||||
AAYAAgHNAAAB1AAHAAYAAAAA//sABQAAAdQAAAHZAAUABgAAAAH/+QAFAAEB2QAAAd0ACAAGAAAA
|
||||
Av/6AAMAAQHdAAAB3gAHAAYAAAAA//kABAABAd4AAAHiAAgABgAAAAD/+wAF//0B4gAAAecAAgAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAB
|
||||
//sAAwACAecAAAHpAAcABgAAAAD/+QAFAAEB6QAAAe4ACAAGAAAAAP/5AAYAAAHuAAAB9AAHAAYA
|
||||
AAAA//oABf//AfQAAAH5AAUABgAAAAD/+QAGAAAB+QAAAf8ABwAGAAAAAv/5AAMAAgH/AAACAAAJ
|
||||
AAYAAAAA//kABQABAgAAAAIFAAgABgAAAAH/+gAE//sCBQAAAggAAQAGAAAAAP/5AAYAAAIIAAAC
|
||||
DgAHAAYAAAAB//kABf/+Ag4AAAISAAUABgAA////+wAGAAACEgAAAhkABQAGAAAAAP/7AAX//gIZ
|
||||
AAACHgADAAYAAAAA//wABf/9Ah4AAAIjAAEABgAAAAD/+QAHAAACIwAAAioABwAGAAAAAP/6AAT/
|
||||
+wIqAAACLgABAAYAAAAA//kABP/8Ai4AAAIyAAMABgAAAAD/+gAFAAACMgAAAjcABgAGAAAAAf/5
|
||||
AAT//QI3AAACOgAEAAYAAAAB//kABP/9AjoAAAI9AAQABgAAAAL/+QAE//sCPQAAAj8AAgAGAAD/
|
||||
///7AAYAAgI/AAACRgAHAAYAAAAA//kABgABAkYAAAJMAAgABgAAAAH//AAD//0CTAAAAk4AAQAG
|
||||
AAAAAf//AAQAAgJOAAACUQADAAYAAAAB//kABP/9AlEAAAJUAAQABgAAAAH/+QAF//4CVAAAAlgA
|
||||
BQAGAAD////7AAYAAAJYAAACXwAFAAYAAP////kABgAAAl8AAAJmAAcABgAA////+QAGAAACZgAA
|
||||
Am0ABwAGAAD////5AAYAAAJtAAACdAAHAAYAAAAA//sABQACAnQAAAJ5AAcABgAA////9wAGAAAC
|
||||
eQAAAoAACQAGAAD////3AAYAAAKAAAAChwAJAAYAAP////cABgAAAocAAAKOAAkABgAA////9wAG
|
||||
AAACjgAAApUACQAGAAD////4AAYAAAKVAAACnAAIAAYAAP////cABgAAApwAAAKjAAkABgAA////
|
||||
+gAGAAACowAAAqoABgAGAAAAAP/6AAUAAgKqAAACrwAIAAYAAP////cABQAAAq8AAAK1AAkABgAA
|
||||
////9wAFAAACtQAAArsACQAGAAD////3AAUAAAK7AAACwQAJAAYAAP////gABQAAAsEAAALHAAgA
|
||||
BgAAAAD/9wAEAAACxwAAAssACQAGAAAAAP/3AAQAAALLAAACzwAJAAYAAAAA//cABAAAAs8AAALT
|
||||
AAkABgAAAAD/+AAEAAAC0wAAAtcACAAGAAD////6AAUAAALXAAAC3QAGAAYAAP////cABgAAAt0A
|
||||
AALkAAkABgAAAAD/9wAFAAAC5AAAAukACQAGAAAAAP/3AAUAAALpAAAC7gAJAAYAAAAA//cABQAA
|
||||
Au4AAALzAAkABgAAAAD/9wAFAAAC8wAAAvgACQAGAAAAAP/4AAUAAAL4AAAC/QAIAAYAAAAA//oA
|
||||
Bf//Av0AAAMCAAUABgAA////+gAGAAADAgAAAwkABgAGAAD////3AAYAAAMJAAADEAAJAAYAAP//
|
||||
//cABgAAAxAAAAMXAAkABgAA////9wAGAAADFwAAAx4ACQAGAAD////4AAYAAAAAAAoABwASAAYA
|
||||
AP////cABgAAAAcACgAOABMABgAA////+gAFAAAADgAKABQAEAAGAAD////6AAYAAAAUAAoAGwAQ
|
||||
AAYAAAAA//gABgAAABsACgAhABIABgAAAAD/+AAGAAAAIQAKACcAEgAGAAAAAP/4AAYAAAAnAAoA
|
||||
LQASAAYAAAAA//gABgAAAC0ACgAzABIABgAAAAD/+QAGAAAAMwAKADkAEQAGAAAAAP/3AAYAAAA5
|
||||
AAoAPwATAAYAAP////sABQAAAD8ACgBFAA8ABgAAAAD/+wAFAAIARQAKAEoAEQAGAAAAAP/4AAUA
|
||||
AABKAAoATwASAAYAAAAA//gABQAAAE8ACgBUABIABgAAAAD/+AAFAAAAVAAKAFkAEgAGAAAAAP/5
|
||||
AAUAAABZAAoAXgARAAYAAAAA//gABgAAAF4ACgBkABIABgAAAAD/+AAGAAAAZAAKAGoAEgAGAAAA
|
||||
AP/4AAYAAABqAAoAcAASAAYAAAAA//kABgAAAHAACgB2ABEABgAAAAD/+AAFAAAAdgAKAHsAEgAG
|
||||
AAD////4AAYAAAB7AAoAggASAAYAAAAA//gABQAAAIIACgCHABIABgAAAAD/+AAFAAAAhwAKAIwA
|
||||
EgAGAAAAAP/4AAUAAACMAAoAkQASAAYAAAAA//gABQAAAJEACgCWABIABgAAAAD/+QAFAAAAlgAK
|
||||
AJsAEQAGAAAAAP/6AAX//wCbAAoAoAAPAAYAAAAA//oABQABAKAACgClABEABgAA////+AAGAAAA
|
||||
pQAKAKwAEgAGAAD////4AAYAAACsAAoAswASAAYAAP////gABgAAALMACgC6ABIABgAA////+QAG
|
||||
AAAAugAKAMEAEQAGAAD////4AAYAAgDBAAoAyAAUAAYAAP////kABQACAMgACgDOABMABgAA////
|
||||
+QAGAAIAzgAKANUAEw==
|
||||
''')), Image.open(StringIO(base64.decodestring('''
|
||||
iVBORw0KGgoAAAANSUhEUgAAAx4AAAAUAQAAAAArMtZoAAAEwElEQVR4nABlAJr/AHVE4czCI/4u
|
||||
Mc4b7vuds/xzjz5/3/7u/n9vMe7vnfH/9++vPn/xyf5zhxzjt8GHw8+2d83u8x27199/nxuQ6Od9
|
||||
M43/5z2I+9n9ZtmDBwMQECDRQw/eQIQohJXxpBCNVE6QCCAAAAD//wBlAJr/AgALyj1t/wINwq0g
|
||||
LeNZUworuN1cjTPIzrTX6ofHWeo3v336qPzfEwRmBnHTtf95/fglZK5N0PDgfRTslpGBvz7LFc4F
|
||||
IUXBWQGjQ5MGCx34EDFPwXiY4YbYxavpnhHFrk14CDAAAAD//wBlAJr/AgKqRooH2gAgPeggvUAA
|
||||
Bu2WfgPoAwzRAABAAAAAAACQgLz/3Uv4Gv+gX7BJgDeeGP6AAAD1NMDzKHD7ANWr3loYbxsAD791
|
||||
NAADfcoIDyP44K/jv4Y63/Z+t98Ovt+ub4T48LAAAAD//wBlAJr/AuplMlADJAAAAGuAphWpqhMx
|
||||
in0A/fRvAYBABPgBwBUgABBQ/sYAyv9g0bCHgOLoGAAAAAAAREAAwI7nr0ArYpow7aX8//9LaP/9
|
||||
SjdavWA8ePHeBIKB//81/83ndznOaXx379wAAAD//wBlAJr/AqDxW+D3AABAAbUh/QMnbQag/gAY
|
||||
AYDAAACgtgD/gOqAAAB5IA/8AAAk+n9w0AAA8AAAmFRJuPo27ciC0cD5oeW4E7KA/wD3ECMAn2tt
|
||||
y8PgwH8AfAxFzC0JzeAMtratAsC/ffwAAAD//wBlAJr/BGKAyCAA4AAAAvgeYTAwHd1kmQF5chkG
|
||||
ABoMIHcL5xVpTfQbUqzlAAAErwAQBgAAEOClA5D9il08AEh/tUzdCBsXkbgACED+woQg8Si9VeqY
|
||||
lODCn7lmF6NhnAEYgAAA/NMIAAAAAAD//2JgjLZgVGBg5Pv/Tvpc8hwGBjYGJADjHDrAwPzAjv/H
|
||||
/Wf3PzCwtzcwHmBgYGcwbZz8wHaCAQMDOwMDQ8MCBgYOC3W7mp+f0w+wHOYxO3OG+e376hsMZjk3
|
||||
AAAAAP//YmCMY2A4wMAIN5e5gQETPD6AZisDAwMDgzSDAAPjByiHcQMDAwMDg1nOze1lByRu5/47
|
||||
c4859311AYNZzg0AAAAA//9iYGDBYihOIIMuwIjGL39/fwffA8b//xv/P2BPtzzHwCBjUQAAAAD/
|
||||
/yLFBrIBAAAA//9i1HhcwdhizX7u8NZNzyLbvT97bfrMf/QHI8evOwcSqGUJAAAA//9iYBB81iSw
|
||||
pEE170Qrg5MIYydHqwdDQRMrAwcVrQAAAAD//2J4x7j9AAMDn8Q/BgYLBoaiAwwMjPdvMDBYM1Tv
|
||||
oJodAAAAAP//Yqo/83+dxePWlxl3npsel9lvLfPcqlE9725C+acfVLMEAAAA//9i+s9gwCoaaGMR
|
||||
evta/58PTEWzr21hufPjA8N+qlnBwAAAAAD//2JiWLci5v1+HmFXDqcnULE/MxgYGBj+f6CaJQAA
|
||||
AAD//2Ji2FrkY3iYpYC5qDeGgeEMAwPDvwQBBoYvcTwOVLMEAAAA//9isDBgkP///0EOg9z35v//
|
||||
Gc/eeW7BwPj5+QGZhANUswMAAAD//2JgqGBgYGBgqEMXlvhMPUsAAAAA//8iYDd1AAAAAP//AwDR
|
||||
w7IkEbzhVQAAAABJRU5ErkJggg==
|
||||
'''))))
|
||||
return f
|
||||
|
||||
if __name__ == "__main__":
|
||||
# create font data chunk for embedding
|
||||
import base64, os, sys
|
||||
font = "../Images/courB08"
|
||||
print " f._load_pilfont_data("
|
||||
print " # %s" % os.path.basename(font)
|
||||
print " StringIO(base64.decodestring('''"
|
||||
base64.encode(open(font + ".pil", "rb"), sys.stdout)
|
||||
print "''')), Image.open(StringIO(base64.decodestring('''"
|
||||
base64.encode(open(font + ".pbm", "rb"), sys.stdout)
|
||||
print "'''))))"
|
||||
28
Darwin/lib/python2.7/site-packages/PIL/ImageGL.py
Normal file
28
Darwin/lib/python2.7/site-packages/PIL/ImageGL.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# OpenGL pixmap/texture interface (requires imToolkit OpenGL extensions)
|
||||
#
|
||||
# History:
|
||||
# 2003-09-13 fl Added
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 2003.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
##
|
||||
# OpenGL pixmap/texture interface (requires imToolkit OpenGL
|
||||
# extensions.)
|
||||
##
|
||||
|
||||
import _imaginggl
|
||||
|
||||
##
|
||||
# Texture factory.
|
||||
|
||||
class TextureFactory:
|
||||
pass # overwritten by the _imaginggl module
|
||||
|
||||
from _imaginggl import *
|
||||
71
Darwin/lib/python2.7/site-packages/PIL/ImageGrab.py
Normal file
71
Darwin/lib/python2.7/site-packages/PIL/ImageGrab.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# screen grabber (windows only)
|
||||
#
|
||||
# History:
|
||||
# 2001-04-26 fl created
|
||||
# 2001-09-17 fl use builtin driver, if present
|
||||
# 2002-11-19 fl added grabclipboard support
|
||||
#
|
||||
# Copyright (c) 2001-2002 by Secret Labs AB
|
||||
# Copyright (c) 2001-2002 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
|
||||
##
|
||||
# (New in 1.1.3) The <b>ImageGrab</b> module can be used to copy
|
||||
# the contents of the screen to a PIL image memory.
|
||||
# <p>
|
||||
# The current version works on Windows only.</p>
|
||||
#
|
||||
# @since 1.1.3
|
||||
##
|
||||
|
||||
try:
|
||||
# built-in driver (1.1.3 and later)
|
||||
grabber = Image.core.grabscreen
|
||||
except AttributeError:
|
||||
# stand-alone driver (pil plus)
|
||||
import _grabscreen
|
||||
grabber = _grabscreen.grab
|
||||
|
||||
##
|
||||
# (New in 1.1.3) Take a snapshot of the screen. The pixels inside the
|
||||
# bounding box are returned as an "RGB" image. If the bounding box is
|
||||
# omitted, the entire screen is copied.
|
||||
#
|
||||
# @param bbox What region to copy. Default is the entire screen.
|
||||
# @return An image
|
||||
# @since 1.1.3
|
||||
|
||||
def grab(bbox=None):
|
||||
size, data = grabber()
|
||||
im = Image.fromstring(
|
||||
"RGB", size, data,
|
||||
# RGB, 32-bit line padding, origo in lower left corner
|
||||
"raw", "BGR", (size[0]*3 + 3) & -4, -1
|
||||
)
|
||||
if bbox:
|
||||
im = im.crop(bbox)
|
||||
return im
|
||||
|
||||
##
|
||||
# (New in 1.1.4) Take a snapshot of the clipboard image, if any.
|
||||
#
|
||||
# @return An image, a list of filenames, or None if the clipboard does
|
||||
# not contain image data or filenames. Note that if a list is
|
||||
# returned, the filenames may not represent image files.
|
||||
# @since 1.1.4
|
||||
|
||||
def grabclipboard():
|
||||
debug = 0 # temporary interface
|
||||
data = Image.core.grabclipboard(debug)
|
||||
if Image.isStringType(data):
|
||||
import BmpImagePlugin, StringIO
|
||||
return BmpImagePlugin.DibImageFile(StringIO.StringIO(data))
|
||||
return data
|
||||
207
Darwin/lib/python2.7/site-packages/PIL/ImageMath.py
Normal file
207
Darwin/lib/python2.7/site-packages/PIL/ImageMath.py
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# a simple math add-on for the Python Imaging Library
|
||||
#
|
||||
# History:
|
||||
# 1999-02-15 fl Original PIL Plus release
|
||||
# 2005-05-05 fl Simplified and cleaned up for PIL 1.1.6
|
||||
# 2005-09-12 fl Fixed int() and float() for Python 2.4.1
|
||||
#
|
||||
# Copyright (c) 1999-2005 by Secret Labs AB
|
||||
# Copyright (c) 2005 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
import _imagingmath
|
||||
|
||||
VERBOSE = 0
|
||||
|
||||
def _isconstant(v):
|
||||
return isinstance(v, type(0)) or isinstance(v, type(0.0))
|
||||
|
||||
class _Operand:
|
||||
# wraps an image operand, providing standard operators
|
||||
|
||||
def __init__(self, im):
|
||||
self.im = im
|
||||
|
||||
def __fixup(self, im1):
|
||||
# convert image to suitable mode
|
||||
if isinstance(im1, _Operand):
|
||||
# argument was an image.
|
||||
if im1.im.mode in ("1", "L"):
|
||||
return im1.im.convert("I")
|
||||
elif im1.im.mode in ("I", "F"):
|
||||
return im1.im
|
||||
else:
|
||||
raise ValueError, "unsupported mode: %s" % im1.im.mode
|
||||
else:
|
||||
# argument was a constant
|
||||
if _isconstant(im1) and self.im.mode in ("1", "L", "I"):
|
||||
return Image.new("I", self.im.size, im1)
|
||||
else:
|
||||
return Image.new("F", self.im.size, im1)
|
||||
|
||||
def apply(self, op, im1, im2=None, mode=None):
|
||||
im1 = self.__fixup(im1)
|
||||
if im2 is None:
|
||||
# unary operation
|
||||
out = Image.new(mode or im1.mode, im1.size, None)
|
||||
im1.load()
|
||||
try:
|
||||
op = getattr(_imagingmath, op+"_"+im1.mode)
|
||||
except AttributeError:
|
||||
raise TypeError, "bad operand type for '%s'" % op
|
||||
_imagingmath.unop(op, out.im.id, im1.im.id)
|
||||
else:
|
||||
# binary operation
|
||||
im2 = self.__fixup(im2)
|
||||
if im1.mode != im2.mode:
|
||||
# convert both arguments to floating point
|
||||
if im1.mode != "F": im1 = im1.convert("F")
|
||||
if im2.mode != "F": im2 = im2.convert("F")
|
||||
if im1.mode != im2.mode:
|
||||
raise ValueError, "mode mismatch"
|
||||
if im1.size != im2.size:
|
||||
# crop both arguments to a common size
|
||||
size = (min(im1.size[0], im2.size[0]),
|
||||
min(im1.size[1], im2.size[1]))
|
||||
if im1.size != size: im1 = im1.crop((0, 0) + size)
|
||||
if im2.size != size: im2 = im2.crop((0, 0) + size)
|
||||
out = Image.new(mode or im1.mode, size, None)
|
||||
else:
|
||||
out = Image.new(mode or im1.mode, im1.size, None)
|
||||
im1.load(); im2.load()
|
||||
try:
|
||||
op = getattr(_imagingmath, op+"_"+im1.mode)
|
||||
except AttributeError:
|
||||
raise TypeError, "bad operand type for '%s'" % op
|
||||
_imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id)
|
||||
return _Operand(out)
|
||||
|
||||
# unary operators
|
||||
def __nonzero__(self):
|
||||
# an image is "true" if it contains at least one non-zero pixel
|
||||
return self.im.getbbox() is not None
|
||||
def __abs__(self):
|
||||
return self.apply("abs", self)
|
||||
def __pos__(self):
|
||||
return self
|
||||
def __neg__(self):
|
||||
return self.apply("neg", self)
|
||||
|
||||
# binary operators
|
||||
def __add__(self, other):
|
||||
return self.apply("add", self, other)
|
||||
def __radd__(self, other):
|
||||
return self.apply("add", other, self)
|
||||
def __sub__(self, other):
|
||||
return self.apply("sub", self, other)
|
||||
def __rsub__(self, other):
|
||||
return self.apply("sub", other, self)
|
||||
def __mul__(self, other):
|
||||
return self.apply("mul", self, other)
|
||||
def __rmul__(self, other):
|
||||
return self.apply("mul", other, self)
|
||||
def __div__(self, other):
|
||||
return self.apply("div", self, other)
|
||||
def __rdiv__(self, other):
|
||||
return self.apply("div", other, self)
|
||||
def __mod__(self, other):
|
||||
return self.apply("mod", self, other)
|
||||
def __rmod__(self, other):
|
||||
return self.apply("mod", other, self)
|
||||
def __pow__(self, other):
|
||||
return self.apply("pow", self, other)
|
||||
def __rpow__(self, other):
|
||||
return self.apply("pow", other, self)
|
||||
|
||||
# bitwise
|
||||
def __invert__(self):
|
||||
return self.apply("invert", self)
|
||||
def __and__(self, other):
|
||||
return self.apply("and", self, other)
|
||||
def __rand__(self, other):
|
||||
return self.apply("and", other, self)
|
||||
def __or__(self, other):
|
||||
return self.apply("or", self, other)
|
||||
def __ror__(self, other):
|
||||
return self.apply("or", other, self)
|
||||
def __xor__(self, other):
|
||||
return self.apply("xor", self, other)
|
||||
def __rxor__(self, other):
|
||||
return self.apply("xor", other, self)
|
||||
def __lshift__(self, other):
|
||||
return self.apply("lshift", self, other)
|
||||
def __rshift__(self, other):
|
||||
return self.apply("rshift", self, other)
|
||||
|
||||
# logical
|
||||
def __eq__(self, other):
|
||||
return self.apply("eq", self, other)
|
||||
def __ne__(self, other):
|
||||
return self.apply("ne", self, other)
|
||||
def __lt__(self, other):
|
||||
return self.apply("lt", self, other)
|
||||
def __le__(self, other):
|
||||
return self.apply("le", self, other)
|
||||
def __gt__(self, other):
|
||||
return self.apply("gt", self, other)
|
||||
def __ge__(self, other):
|
||||
return self.apply("ge", self, other)
|
||||
|
||||
# conversions
|
||||
def imagemath_int(self):
|
||||
return _Operand(self.im.convert("I"))
|
||||
def imagemath_float(self):
|
||||
return _Operand(self.im.convert("F"))
|
||||
|
||||
# logical
|
||||
def imagemath_equal(self, other):
|
||||
return self.apply("eq", self, other, mode="I")
|
||||
def imagemath_notequal(self, other):
|
||||
return self.apply("ne", self, other, mode="I")
|
||||
|
||||
def imagemath_min(self, other):
|
||||
return self.apply("min", self, other)
|
||||
def imagemath_max(self, other):
|
||||
return self.apply("max", self, other)
|
||||
|
||||
def imagemath_convert(self, mode):
|
||||
return _Operand(self.im.convert(mode))
|
||||
|
||||
ops = {}
|
||||
for k, v in globals().items():
|
||||
if k[:10] == "imagemath_":
|
||||
ops[k[10:]] = v
|
||||
|
||||
##
|
||||
# Evaluates an image expression.
|
||||
#
|
||||
# @param expression A string containing a Python-style expression.
|
||||
# @keyparam options Values to add to the evaluation context. You
|
||||
# can either use a dictionary, or one or more keyword arguments.
|
||||
# @return The evaluated expression. This is usually an image object,
|
||||
# but can also be an integer, a floating point value, or a pixel
|
||||
# tuple, depending on the expression.
|
||||
|
||||
def eval(expression, _dict={}, **kw):
|
||||
|
||||
# build execution namespace
|
||||
args = ops.copy()
|
||||
args.update(_dict)
|
||||
args.update(kw)
|
||||
for k, v in args.items():
|
||||
if hasattr(v, "im"):
|
||||
args[k] = _Operand(v)
|
||||
|
||||
import __builtin__
|
||||
out =__builtin__.eval(expression, args)
|
||||
try:
|
||||
return out.im
|
||||
except AttributeError:
|
||||
return out
|
||||
50
Darwin/lib/python2.7/site-packages/PIL/ImageMode.py
Normal file
50
Darwin/lib/python2.7/site-packages/PIL/ImageMode.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# standard mode descriptors
|
||||
#
|
||||
# History:
|
||||
# 2006-03-20 fl Added
|
||||
#
|
||||
# Copyright (c) 2006 by Secret Labs AB.
|
||||
# Copyright (c) 2006 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
# mode descriptor cache
|
||||
_modes = {}
|
||||
|
||||
##
|
||||
# Wrapper for mode strings.
|
||||
|
||||
class ModeDescriptor:
|
||||
|
||||
def __init__(self, mode, bands, basemode, basetype):
|
||||
self.mode = mode
|
||||
self.bands = bands
|
||||
self.basemode = basemode
|
||||
self.basetype = basetype
|
||||
|
||||
def __str__(self):
|
||||
return self.mode
|
||||
|
||||
##
|
||||
# Gets a mode descriptor for the given mode.
|
||||
|
||||
def getmode(mode):
|
||||
if not _modes:
|
||||
# initialize mode cache
|
||||
import Image
|
||||
# core modes
|
||||
for m, (basemode, basetype, bands) in Image._MODEINFO.items():
|
||||
_modes[m] = ModeDescriptor(m, bands, basemode, basetype)
|
||||
# extra experimental modes
|
||||
_modes["LA"] = ModeDescriptor("LA", ("L", "A"), "L", "L")
|
||||
_modes["PA"] = ModeDescriptor("PA", ("P", "A"), "RGB", "L")
|
||||
# mapping modes
|
||||
_modes["I;16"] = ModeDescriptor("I;16", "I", "L", "L")
|
||||
_modes["I;16L"] = ModeDescriptor("I;16L", "I", "L", "L")
|
||||
_modes["I;16B"] = ModeDescriptor("I;16B", "I", "L", "L")
|
||||
return _modes[mode]
|
||||
439
Darwin/lib/python2.7/site-packages/PIL/ImageOps.py
Normal file
439
Darwin/lib/python2.7/site-packages/PIL/ImageOps.py
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# standard image operations
|
||||
#
|
||||
# History:
|
||||
# 2001-10-20 fl Created
|
||||
# 2001-10-23 fl Added autocontrast operator
|
||||
# 2001-12-18 fl Added Kevin's fit operator
|
||||
# 2004-03-14 fl Fixed potential division by zero in equalize
|
||||
# 2005-05-05 fl Fixed equalize for low number of values
|
||||
#
|
||||
# Copyright (c) 2001-2004 by Secret Labs AB
|
||||
# Copyright (c) 2001-2004 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
import operator
|
||||
|
||||
##
|
||||
# (New in 1.1.3) The <b>ImageOps</b> module contains a number of
|
||||
# 'ready-made' image processing operations. This module is somewhat
|
||||
# experimental, and most operators only work on L and RGB images.
|
||||
#
|
||||
# @since 1.1.3
|
||||
##
|
||||
|
||||
#
|
||||
# helpers
|
||||
|
||||
def _border(border):
|
||||
if type(border) is type(()):
|
||||
if len(border) == 2:
|
||||
left, top = right, bottom = border
|
||||
elif len(border) == 4:
|
||||
left, top, right, bottom = border
|
||||
else:
|
||||
left = top = right = bottom = border
|
||||
return left, top, right, bottom
|
||||
|
||||
def _color(color, mode):
|
||||
if Image.isStringType(color):
|
||||
import ImageColor
|
||||
color = ImageColor.getcolor(color, mode)
|
||||
return color
|
||||
|
||||
def _lut(image, lut):
|
||||
if image.mode == "P":
|
||||
# FIXME: apply to lookup table, not image data
|
||||
raise NotImplementedError("mode P support coming soon")
|
||||
elif image.mode in ("L", "RGB"):
|
||||
if image.mode == "RGB" and len(lut) == 256:
|
||||
lut = lut + lut + lut
|
||||
return image.point(lut)
|
||||
else:
|
||||
raise IOError, "not supported for this image mode"
|
||||
|
||||
#
|
||||
# actions
|
||||
|
||||
##
|
||||
# Maximize (normalize) image contrast. This function calculates a
|
||||
# histogram of the input image, removes <i>cutoff</i> percent of the
|
||||
# lightest and darkest pixels from the histogram, and remaps the image
|
||||
# so that the darkest pixel becomes black (0), and the lightest
|
||||
# becomes white (255).
|
||||
#
|
||||
# @param image The image to process.
|
||||
# @param cutoff How many percent to cut off from the histogram.
|
||||
# @param ignore The background pixel value (use None for no background).
|
||||
# @return An image.
|
||||
|
||||
def autocontrast(image, cutoff=0, ignore=None):
|
||||
"Maximize image contrast, based on histogram"
|
||||
histogram = image.histogram()
|
||||
lut = []
|
||||
for layer in range(0, len(histogram), 256):
|
||||
h = histogram[layer:layer+256]
|
||||
if ignore is not None:
|
||||
# get rid of outliers
|
||||
try:
|
||||
h[ignore] = 0
|
||||
except TypeError:
|
||||
# assume sequence
|
||||
for ix in ignore:
|
||||
h[ix] = 0
|
||||
if cutoff:
|
||||
# cut off pixels from both ends of the histogram
|
||||
# get number of pixels
|
||||
n = 0
|
||||
for ix in range(256):
|
||||
n = n + h[ix]
|
||||
# remove cutoff% pixels from the low end
|
||||
cut = n * cutoff / 100
|
||||
for lo in range(256):
|
||||
if cut > h[lo]:
|
||||
cut = cut - h[lo]
|
||||
h[lo] = 0
|
||||
else:
|
||||
h[lo] = h[lo] - cut
|
||||
cut = 0
|
||||
if cut <= 0:
|
||||
break
|
||||
# remove cutoff% samples from the hi end
|
||||
cut = n * cutoff / 100
|
||||
for hi in range(255, -1, -1):
|
||||
if cut > h[hi]:
|
||||
cut = cut - h[hi]
|
||||
h[hi] = 0
|
||||
else:
|
||||
h[hi] = h[hi] - cut
|
||||
cut = 0
|
||||
if cut <= 0:
|
||||
break
|
||||
# find lowest/highest samples after preprocessing
|
||||
for lo in range(256):
|
||||
if h[lo]:
|
||||
break
|
||||
for hi in range(255, -1, -1):
|
||||
if h[hi]:
|
||||
break
|
||||
if hi <= lo:
|
||||
# don't bother
|
||||
lut.extend(range(256))
|
||||
else:
|
||||
scale = 255.0 / (hi - lo)
|
||||
offset = -lo * scale
|
||||
for ix in range(256):
|
||||
ix = int(ix * scale + offset)
|
||||
if ix < 0:
|
||||
ix = 0
|
||||
elif ix > 255:
|
||||
ix = 255
|
||||
lut.append(ix)
|
||||
return _lut(image, lut)
|
||||
|
||||
##
|
||||
# Colorize grayscale image. The <i>black</i> and <i>white</i>
|
||||
# arguments should be RGB tuples; this function calculates a colour
|
||||
# wedge mapping all black pixels in the source image to the first
|
||||
# colour, and all white pixels to the second colour.
|
||||
#
|
||||
# @param image The image to colourize.
|
||||
# @param black The colour to use for black input pixels.
|
||||
# @param white The colour to use for white input pixels.
|
||||
# @return An image.
|
||||
|
||||
def colorize(image, black, white):
|
||||
"Colorize a grayscale image"
|
||||
assert image.mode == "L"
|
||||
black = _color(black, "RGB")
|
||||
white = _color(white, "RGB")
|
||||
red = []; green = []; blue = []
|
||||
for i in range(256):
|
||||
red.append(black[0]+i*(white[0]-black[0])/255)
|
||||
green.append(black[1]+i*(white[1]-black[1])/255)
|
||||
blue.append(black[2]+i*(white[2]-black[2])/255)
|
||||
image = image.convert("RGB")
|
||||
return _lut(image, red + green + blue)
|
||||
|
||||
##
|
||||
# Remove border from image. The same amount of pixels are removed
|
||||
# from all four sides. This function works on all image modes.
|
||||
#
|
||||
# @param image The image to crop.
|
||||
# @param border The number of pixels to remove.
|
||||
# @return An image.
|
||||
# @see Image#Image.crop
|
||||
|
||||
def crop(image, border=0):
|
||||
"Crop border off image"
|
||||
left, top, right, bottom = _border(border)
|
||||
return image.crop(
|
||||
(left, top, image.size[0]-right, image.size[1]-bottom)
|
||||
)
|
||||
|
||||
##
|
||||
# Deform the image.
|
||||
#
|
||||
# @param image The image to deform.
|
||||
# @param deformer A deformer object. Any object that implements a
|
||||
# <b>getmesh</b> method can be used.
|
||||
# @param resample What resampling filter to use.
|
||||
# @return An image.
|
||||
|
||||
def deform(image, deformer, resample=Image.BILINEAR):
|
||||
"Deform image using the given deformer"
|
||||
return image.transform(
|
||||
image.size, Image.MESH, deformer.getmesh(image), resample
|
||||
)
|
||||
|
||||
##
|
||||
# Equalize the image histogram. This function applies a non-linear
|
||||
# mapping to the input image, in order to create a uniform
|
||||
# distribution of grayscale values in the output image.
|
||||
#
|
||||
# @param image The image to equalize.
|
||||
# @param mask An optional mask. If given, only the pixels selected by
|
||||
# the mask are included in the analysis.
|
||||
# @return An image.
|
||||
|
||||
def equalize(image, mask=None):
|
||||
"Equalize image histogram"
|
||||
if image.mode == "P":
|
||||
image = image.convert("RGB")
|
||||
h = image.histogram(mask)
|
||||
lut = []
|
||||
for b in range(0, len(h), 256):
|
||||
histo = filter(None, h[b:b+256])
|
||||
if len(histo) <= 1:
|
||||
lut.extend(range(256))
|
||||
else:
|
||||
step = (reduce(operator.add, histo) - histo[-1]) / 255
|
||||
if not step:
|
||||
lut.extend(range(256))
|
||||
else:
|
||||
n = step / 2
|
||||
for i in range(256):
|
||||
lut.append(n / step)
|
||||
n = n + h[i+b]
|
||||
return _lut(image, lut)
|
||||
|
||||
##
|
||||
# Add border to the image
|
||||
#
|
||||
# @param image The image to expand.
|
||||
# @param border Border width, in pixels.
|
||||
# @param fill Pixel fill value (a colour value). Default is 0 (black).
|
||||
# @return An image.
|
||||
|
||||
def expand(image, border=0, fill=0):
|
||||
"Add border to image"
|
||||
left, top, right, bottom = _border(border)
|
||||
width = left + image.size[0] + right
|
||||
height = top + image.size[1] + bottom
|
||||
out = Image.new(image.mode, (width, height), _color(fill, image.mode))
|
||||
out.paste(image, (left, top))
|
||||
return out
|
||||
|
||||
##
|
||||
# Returns a sized and cropped version of the image, cropped to the
|
||||
# requested aspect ratio and size.
|
||||
# <p>
|
||||
# The <b>fit</b> function was contributed by Kevin Cazabon.
|
||||
#
|
||||
# @param size The requested output size in pixels, given as a
|
||||
# (width, height) tuple.
|
||||
# @param method What resampling method to use. Default is Image.NEAREST.
|
||||
# @param bleed Remove a border around the outside of the image (from all
|
||||
# four edges. The value is a decimal percentage (use 0.01 for one
|
||||
# percent). The default value is 0 (no border).
|
||||
# @param centering Control the cropping position. Use (0.5, 0.5) for
|
||||
# center cropping (e.g. if cropping the width, take 50% off of the
|
||||
# left side, and therefore 50% off the right side). (0.0, 0.0)
|
||||
# will crop from the top left corner (i.e. if cropping the width,
|
||||
# take all of the crop off of the right side, and if cropping the
|
||||
# height, take all of it off the bottom). (1.0, 0.0) will crop
|
||||
# from the bottom left corner, etc. (i.e. if cropping the width,
|
||||
# take all of the crop off the left side, and if cropping the height
|
||||
# take none from the top, and therefore all off the bottom).
|
||||
# @return An image.
|
||||
|
||||
def fit(image, size, method=Image.NEAREST, bleed=0.0, centering=(0.5, 0.5)):
|
||||
"""
|
||||
This method returns a sized and cropped version of the image,
|
||||
cropped to the aspect ratio and size that you request.
|
||||
"""
|
||||
|
||||
# by Kevin Cazabon, Feb 17/2000
|
||||
# kevin@cazabon.com
|
||||
# http://www.cazabon.com
|
||||
|
||||
# ensure inputs are valid
|
||||
if type(centering) != type([]):
|
||||
centering = [centering[0], centering[1]]
|
||||
|
||||
if centering[0] > 1.0 or centering[0] < 0.0:
|
||||
centering [0] = 0.50
|
||||
if centering[1] > 1.0 or centering[1] < 0.0:
|
||||
centering[1] = 0.50
|
||||
|
||||
if bleed > 0.49999 or bleed < 0.0:
|
||||
bleed = 0.0
|
||||
|
||||
# calculate the area to use for resizing and cropping, subtracting
|
||||
# the 'bleed' around the edges
|
||||
|
||||
# number of pixels to trim off on Top and Bottom, Left and Right
|
||||
bleedPixels = (
|
||||
int((float(bleed) * float(image.size[0])) + 0.5),
|
||||
int((float(bleed) * float(image.size[1])) + 0.5)
|
||||
)
|
||||
|
||||
liveArea = (
|
||||
bleedPixels[0], bleedPixels[1], image.size[0] - bleedPixels[0] - 1,
|
||||
image.size[1] - bleedPixels[1] - 1
|
||||
)
|
||||
|
||||
liveSize = (liveArea[2] - liveArea[0], liveArea[3] - liveArea[1])
|
||||
|
||||
# calculate the aspect ratio of the liveArea
|
||||
liveAreaAspectRatio = float(liveSize[0])/float(liveSize[1])
|
||||
|
||||
# calculate the aspect ratio of the output image
|
||||
aspectRatio = float(size[0]) / float(size[1])
|
||||
|
||||
# figure out if the sides or top/bottom will be cropped off
|
||||
if liveAreaAspectRatio >= aspectRatio:
|
||||
# liveArea is wider than what's needed, crop the sides
|
||||
cropWidth = int((aspectRatio * float(liveSize[1])) + 0.5)
|
||||
cropHeight = liveSize[1]
|
||||
else:
|
||||
# liveArea is taller than what's needed, crop the top and bottom
|
||||
cropWidth = liveSize[0]
|
||||
cropHeight = int((float(liveSize[0])/aspectRatio) + 0.5)
|
||||
|
||||
# make the crop
|
||||
leftSide = int(liveArea[0] + (float(liveSize[0]-cropWidth) * centering[0]))
|
||||
if leftSide < 0:
|
||||
leftSide = 0
|
||||
topSide = int(liveArea[1] + (float(liveSize[1]-cropHeight) * centering[1]))
|
||||
if topSide < 0:
|
||||
topSide = 0
|
||||
|
||||
out = image.crop(
|
||||
(leftSide, topSide, leftSide + cropWidth, topSide + cropHeight)
|
||||
)
|
||||
|
||||
# resize the image and return it
|
||||
return out.resize(size, method)
|
||||
|
||||
##
|
||||
# Flip the image vertically (top to bottom).
|
||||
#
|
||||
# @param image The image to flip.
|
||||
# @return An image.
|
||||
|
||||
def flip(image):
|
||||
"Flip image vertically"
|
||||
return image.transpose(Image.FLIP_TOP_BOTTOM)
|
||||
|
||||
##
|
||||
# Convert the image to grayscale.
|
||||
#
|
||||
# @param image The image to convert.
|
||||
# @return An image.
|
||||
|
||||
def grayscale(image):
|
||||
"Convert to grayscale"
|
||||
return image.convert("L")
|
||||
|
||||
##
|
||||
# Invert (negate) the image.
|
||||
#
|
||||
# @param image The image to invert.
|
||||
# @return An image.
|
||||
|
||||
def invert(image):
|
||||
"Invert image (negate)"
|
||||
lut = []
|
||||
for i in range(256):
|
||||
lut.append(255-i)
|
||||
return _lut(image, lut)
|
||||
|
||||
##
|
||||
# Flip image horizontally (left to right).
|
||||
#
|
||||
# @param image The image to mirror.
|
||||
# @return An image.
|
||||
|
||||
def mirror(image):
|
||||
"Flip image horizontally"
|
||||
return image.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
|
||||
##
|
||||
# Reduce the number of bits for each colour channel.
|
||||
#
|
||||
# @param image The image to posterize.
|
||||
# @param bits The number of bits to keep for each channel (1-8).
|
||||
# @return An image.
|
||||
|
||||
def posterize(image, bits):
|
||||
"Reduce the number of bits per color channel"
|
||||
lut = []
|
||||
mask = ~(2**(8-bits)-1)
|
||||
for i in range(256):
|
||||
lut.append(i & mask)
|
||||
return _lut(image, lut)
|
||||
|
||||
##
|
||||
# Invert all pixel values above a threshold.
|
||||
#
|
||||
# @param image The image to posterize.
|
||||
# @param threshold All pixels above this greyscale level are inverted.
|
||||
# @return An image.
|
||||
|
||||
def solarize(image, threshold=128):
|
||||
"Invert all values above threshold"
|
||||
lut = []
|
||||
for i in range(256):
|
||||
if i < threshold:
|
||||
lut.append(i)
|
||||
else:
|
||||
lut.append(255-i)
|
||||
return _lut(image, lut)
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PIL USM components, from Kevin Cazabon.
|
||||
|
||||
def gaussian_blur(im, radius=None):
|
||||
""" PIL_usm.gblur(im, [radius])"""
|
||||
|
||||
if radius is None:
|
||||
radius = 5.0
|
||||
|
||||
im.load()
|
||||
|
||||
return im.im.gaussian_blur(radius)
|
||||
|
||||
gblur = gaussian_blur
|
||||
|
||||
def unsharp_mask(im, radius=None, percent=None, threshold=None):
|
||||
""" PIL_usm.usm(im, [radius, percent, threshold])"""
|
||||
|
||||
if radius is None:
|
||||
radius = 5.0
|
||||
if percent is None:
|
||||
percent = 150
|
||||
if threshold is None:
|
||||
threshold = 3
|
||||
|
||||
im.load()
|
||||
|
||||
return im.im.unsharp_mask(radius, percent, threshold)
|
||||
|
||||
usm = unsharp_mask
|
||||
184
Darwin/lib/python2.7/site-packages/PIL/ImagePalette.py
Normal file
184
Darwin/lib/python2.7/site-packages/PIL/ImagePalette.py
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# image palette object
|
||||
#
|
||||
# History:
|
||||
# 1996-03-11 fl Rewritten.
|
||||
# 1997-01-03 fl Up and running.
|
||||
# 1997-08-23 fl Added load hack
|
||||
# 2001-04-16 fl Fixed randint shadow bug in random()
|
||||
#
|
||||
# Copyright (c) 1997-2001 by Secret Labs AB
|
||||
# Copyright (c) 1996-1997 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import array
|
||||
import Image, ImageColor
|
||||
|
||||
##
|
||||
# Colour palette wrapper for palette mapped images.
|
||||
|
||||
class ImagePalette:
|
||||
"Colour palette for palette mapped images"
|
||||
|
||||
def __init__(self, mode = "RGB", palette = None):
|
||||
self.mode = mode
|
||||
self.rawmode = None # if set, palette contains raw data
|
||||
self.palette = palette or range(256)*len(self.mode)
|
||||
self.colors = {}
|
||||
self.dirty = None
|
||||
if len(self.mode)*256 != len(self.palette):
|
||||
raise ValueError, "wrong palette size"
|
||||
|
||||
def getdata(self):
|
||||
# experimental: get palette contents in format suitable
|
||||
# for the low-level im.putpalette primitive
|
||||
if self.rawmode:
|
||||
return self.rawmode, self.palette
|
||||
return self.mode + ";L", self.tostring()
|
||||
|
||||
def tostring(self):
|
||||
# experimental: convert palette to string
|
||||
if self.rawmode:
|
||||
raise ValueError("palette contains raw palette data")
|
||||
if Image.isStringType(self.palette):
|
||||
return self.palette
|
||||
return array.array("B", self.palette).tostring()
|
||||
|
||||
def getcolor(self, color):
|
||||
# experimental: given an rgb tuple, allocate palette entry
|
||||
if self.rawmode:
|
||||
raise ValueError("palette contains raw palette data")
|
||||
if Image.isTupleType(color):
|
||||
try:
|
||||
return self.colors[color]
|
||||
except KeyError:
|
||||
# allocate new color slot
|
||||
if Image.isStringType(self.palette):
|
||||
self.palette = map(int, self.palette)
|
||||
index = len(self.colors)
|
||||
if index >= 256:
|
||||
raise ValueError("cannot allocate more than 256 colors")
|
||||
self.colors[color] = index
|
||||
self.palette[index] = color[0]
|
||||
self.palette[index+256] = color[1]
|
||||
self.palette[index+512] = color[2]
|
||||
self.dirty = 1
|
||||
return index
|
||||
else:
|
||||
raise ValueError("unknown color specifier: %r" % color)
|
||||
|
||||
def save(self, fp):
|
||||
# (experimental) save palette to text file
|
||||
if self.rawmode:
|
||||
raise ValueError("palette contains raw palette data")
|
||||
if type(fp) == type(""):
|
||||
fp = open(fp, "w")
|
||||
fp.write("# Palette\n")
|
||||
fp.write("# Mode: %s\n" % self.mode)
|
||||
for i in range(256):
|
||||
fp.write("%d" % i)
|
||||
for j in range(i, len(self.palette), 256):
|
||||
fp.write(" %d" % self.palette[j])
|
||||
fp.write("\n")
|
||||
fp.close()
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Internal
|
||||
|
||||
def raw(rawmode, data):
|
||||
palette = ImagePalette()
|
||||
palette.rawmode = rawmode
|
||||
palette.palette = data
|
||||
palette.dirty = 1
|
||||
return palette
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Factories
|
||||
|
||||
def _make_linear_lut(black, white):
|
||||
lut = []
|
||||
if black == 0:
|
||||
for i in range(256):
|
||||
lut.append(white*i/255)
|
||||
else:
|
||||
raise NotImplementedError # FIXME
|
||||
return lut
|
||||
|
||||
def _make_gamma_lut(exp, mode="RGB"):
|
||||
lut = []
|
||||
for i in range(256):
|
||||
lut.append(int(((i / 255.0) ** exp) * 255.0 + 0.5))
|
||||
return lut
|
||||
|
||||
def new(mode, data):
|
||||
return Image.core.new_palette(mode, data)
|
||||
|
||||
def negative(mode="RGB"):
|
||||
palette = range(256)
|
||||
palette.reverse()
|
||||
return ImagePalette(mode, palette * len(mode))
|
||||
|
||||
def random(mode="RGB"):
|
||||
from random import randint
|
||||
palette = []
|
||||
for i in range(256*len(mode)):
|
||||
palette.append(randint(0, 255))
|
||||
return ImagePalette(mode, palette)
|
||||
|
||||
def sepia(white="#fff0c0"):
|
||||
r, g, b = ImageColor.getrgb(white)
|
||||
r = _make_linear_lut(0, r)
|
||||
g = _make_linear_lut(0, g)
|
||||
b = _make_linear_lut(0, b)
|
||||
return ImagePalette("RGB", r + g + b)
|
||||
|
||||
def wedge(mode="RGB"):
|
||||
return ImagePalette(mode, range(256) * len(mode))
|
||||
|
||||
def load(filename):
|
||||
|
||||
# FIXME: supports GIMP gradients only
|
||||
|
||||
fp = open(filename, "rb")
|
||||
|
||||
lut = None
|
||||
|
||||
if not lut:
|
||||
try:
|
||||
import GimpPaletteFile
|
||||
fp.seek(0)
|
||||
p = GimpPaletteFile.GimpPaletteFile(fp)
|
||||
lut = p.getpalette()
|
||||
except (SyntaxError, ValueError):
|
||||
pass
|
||||
|
||||
if not lut:
|
||||
try:
|
||||
import GimpGradientFile
|
||||
fp.seek(0)
|
||||
p = GimpGradientFile.GimpGradientFile(fp)
|
||||
lut = p.getpalette()
|
||||
except (SyntaxError, ValueError):
|
||||
pass
|
||||
|
||||
if not lut:
|
||||
try:
|
||||
import PaletteFile
|
||||
fp.seek(0)
|
||||
p = PaletteFile.PaletteFile(fp)
|
||||
lut = p.getpalette()
|
||||
except (SyntaxError, ValueError):
|
||||
pass
|
||||
|
||||
if not lut:
|
||||
raise IOError, "cannot load palette"
|
||||
|
||||
return lut # data, rawmode
|
||||
|
||||
|
||||
# add some psuedocolour palettes as well
|
||||
71
Darwin/lib/python2.7/site-packages/PIL/ImagePath.py
Normal file
71
Darwin/lib/python2.7/site-packages/PIL/ImagePath.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# path interface
|
||||
#
|
||||
# History:
|
||||
# 1996-11-04 fl Created
|
||||
# 2002-04-14 fl Added documentation stub class
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1996.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
|
||||
##
|
||||
# Path wrapper.
|
||||
|
||||
class Path:
|
||||
|
||||
##
|
||||
# Creates a path object.
|
||||
#
|
||||
# @param xy Sequence. The sequence can contain 2-tuples [(x, y), ...]
|
||||
# or a flat list of numbers [x, y, ...].
|
||||
|
||||
def __init__(self, xy):
|
||||
pass
|
||||
|
||||
##
|
||||
# Compacts the path, by removing points that are close to each
|
||||
# other. This method modifies the path in place.
|
||||
|
||||
def compact(self, distance=2):
|
||||
pass
|
||||
|
||||
##
|
||||
# Gets the bounding box.
|
||||
|
||||
def getbbox(self):
|
||||
pass
|
||||
|
||||
##
|
||||
# Maps the path through a function.
|
||||
|
||||
def map(self, function):
|
||||
pass
|
||||
|
||||
##
|
||||
# Converts the path to Python list.
|
||||
#
|
||||
# @param flat By default, this function returns a list of 2-tuples
|
||||
# [(x, y), ...]. If this argument is true, it returns a flat
|
||||
# list [x, y, ...] instead.
|
||||
# @return A list of coordinates.
|
||||
|
||||
def tolist(self, flat=0):
|
||||
pass
|
||||
|
||||
##
|
||||
# Transforms the path.
|
||||
|
||||
def transform(self, matrix):
|
||||
pass
|
||||
|
||||
|
||||
# override with C implementation
|
||||
Path = Image.core.path
|
||||
84
Darwin/lib/python2.7/site-packages/PIL/ImageQt.py
Normal file
84
Darwin/lib/python2.7/site-packages/PIL/ImageQt.py
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# a simple Qt image interface.
|
||||
#
|
||||
# history:
|
||||
# 2006-06-03 fl: created
|
||||
# 2006-06-04 fl: inherit from QImage instead of wrapping it
|
||||
# 2006-06-05 fl: removed toimage helper; move string support to ImageQt
|
||||
#
|
||||
# Copyright (c) 2006 by Secret Labs AB
|
||||
# Copyright (c) 2006 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
|
||||
from PyQt4.QtGui import QImage, qRgb
|
||||
|
||||
##
|
||||
# (Internal) Turns an RGB color into a Qt compatible color integer.
|
||||
|
||||
def rgb(r, g, b):
|
||||
# use qRgb to pack the colors, and then turn the resulting long
|
||||
# into a negative integer with the same bitpattern.
|
||||
return (qRgb(r, g, b) & 0xffffff) - 0x1000000
|
||||
|
||||
##
|
||||
# An PIL image wrapper for Qt. This is a subclass of PyQt4's QImage
|
||||
# class.
|
||||
#
|
||||
# @param im A PIL Image object, or a file name (given either as Python
|
||||
# string or a PyQt string object).
|
||||
|
||||
class ImageQt(QImage):
|
||||
|
||||
def __init__(self, im):
|
||||
|
||||
data = None
|
||||
colortable = None
|
||||
|
||||
# handle filename, if given instead of image name
|
||||
if hasattr(im, "toUtf8"):
|
||||
# FIXME - is this really the best way to do this?
|
||||
im = unicode(im.toUtf8(), "utf-8")
|
||||
if Image.isStringType(im):
|
||||
im = Image.open(im)
|
||||
|
||||
if im.mode == "1":
|
||||
format = QImage.Format_Mono
|
||||
elif im.mode == "L":
|
||||
format = QImage.Format_Indexed8
|
||||
colortable = []
|
||||
for i in range(256):
|
||||
colortable.append(rgb(i, i, i))
|
||||
elif im.mode == "P":
|
||||
format = QImage.Format_Indexed8
|
||||
colortable = []
|
||||
palette = im.getpalette()
|
||||
for i in range(0, len(palette), 3):
|
||||
colortable.append(rgb(*palette[i:i+3]))
|
||||
elif im.mode == "RGB":
|
||||
data = im.tostring("raw", "BGRX")
|
||||
format = QImage.Format_RGB32
|
||||
elif im.mode == "RGBA":
|
||||
try:
|
||||
data = im.tostring("raw", "BGRA")
|
||||
except SystemError:
|
||||
# workaround for earlier versions
|
||||
r, g, b, a = im.split()
|
||||
im = Image.merge("RGBA", (b, g, r, a))
|
||||
format = QImage.Format_ARGB32
|
||||
else:
|
||||
raise ValueError("unsupported image mode %r" % im.mode)
|
||||
|
||||
# must keep a reference, or Qt will crash!
|
||||
self.__data = data or im.tostring()
|
||||
|
||||
QImage.__init__(self, self.__data, im.size[0], im.size[1], format)
|
||||
|
||||
if colortable:
|
||||
self.setColorTable(colortable)
|
||||
38
Darwin/lib/python2.7/site-packages/PIL/ImageSequence.py
Normal file
38
Darwin/lib/python2.7/site-packages/PIL/ImageSequence.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# sequence support classes
|
||||
#
|
||||
# history:
|
||||
# 1997-02-20 fl Created
|
||||
#
|
||||
# Copyright (c) 1997 by Secret Labs AB.
|
||||
# Copyright (c) 1997 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
##
|
||||
# This class implements an iterator object that can be used to loop
|
||||
# over an image sequence.
|
||||
|
||||
class Iterator:
|
||||
|
||||
##
|
||||
# Create an iterator.
|
||||
#
|
||||
# @param im An image object.
|
||||
|
||||
def __init__(self, im):
|
||||
if not hasattr(im, "seek"):
|
||||
raise AttributeError("im must have seek method")
|
||||
self.im = im
|
||||
|
||||
def __getitem__(self, ix):
|
||||
try:
|
||||
if ix:
|
||||
self.im.seek(ix)
|
||||
return self.im
|
||||
except EOFError:
|
||||
raise IndexError # end of sequence
|
||||
163
Darwin/lib/python2.7/site-packages/PIL/ImageShow.py
Normal file
163
Darwin/lib/python2.7/site-packages/PIL/ImageShow.py
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# im.show() drivers
|
||||
#
|
||||
# History:
|
||||
# 2008-04-06 fl Created
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 2008.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
import os, sys
|
||||
|
||||
_viewers = []
|
||||
|
||||
def register(viewer, order=1):
|
||||
try:
|
||||
if issubclass(viewer, Viewer):
|
||||
viewer = viewer()
|
||||
except TypeError:
|
||||
pass # raised if viewer wasn't a class
|
||||
if order > 0:
|
||||
_viewers.append(viewer)
|
||||
elif order < 0:
|
||||
_viewers.insert(0, viewer)
|
||||
|
||||
##
|
||||
# Displays a given image.
|
||||
#
|
||||
# @param image An image object.
|
||||
# @param title Optional title. Not all viewers can display the title.
|
||||
# @param **options Additional viewer options.
|
||||
# @return True if a suitable viewer was found, false otherwise.
|
||||
|
||||
def show(image, title=None, **options):
|
||||
for viewer in _viewers:
|
||||
if viewer.show(image, title=title, **options):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
##
|
||||
# Base class for viewers.
|
||||
|
||||
class Viewer:
|
||||
|
||||
# main api
|
||||
|
||||
def show(self, image, **options):
|
||||
|
||||
# save temporary image to disk
|
||||
if image.mode[:4] == "I;16":
|
||||
# @PIL88 @PIL101
|
||||
# "I;16" isn't an 'official' mode, but we still want to
|
||||
# provide a simple way to show 16-bit images.
|
||||
base = "L"
|
||||
# FIXME: auto-contrast if max() > 255?
|
||||
else:
|
||||
base = Image.getmodebase(image.mode)
|
||||
if base != image.mode and image.mode != "1":
|
||||
image = image.convert(base)
|
||||
|
||||
self.show_image(image, **options)
|
||||
|
||||
# hook methods
|
||||
|
||||
format = None
|
||||
|
||||
def get_format(self, image):
|
||||
# return format name, or None to save as PGM/PPM
|
||||
return self.format
|
||||
|
||||
def get_command(self, file, **options):
|
||||
raise NotImplementedError
|
||||
|
||||
def save_image(self, image):
|
||||
# save to temporary file, and return filename
|
||||
return image._dump(format=self.get_format(image))
|
||||
|
||||
def show_image(self, image, **options):
|
||||
# display given image
|
||||
return self.show_file(self.save_image(image), **options)
|
||||
|
||||
def show_file(self, file, **options):
|
||||
# display given file
|
||||
os.system(self.get_command(file, **options))
|
||||
return 1
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
if sys.platform == "win32":
|
||||
|
||||
class WindowsViewer(Viewer):
|
||||
format = "BMP"
|
||||
def get_command(self, file, **options):
|
||||
return "start /wait %s && del /f %s" % (file, file)
|
||||
|
||||
register(WindowsViewer)
|
||||
|
||||
elif sys.platform == "darwin":
|
||||
|
||||
class MacViewer(Viewer):
|
||||
format = "BMP"
|
||||
def get_command(self, file, **options):
|
||||
# on darwin open returns immediately resulting in the temp
|
||||
# file removal while app is opening
|
||||
command = "open -a /Applications/Preview.app"
|
||||
command = "(%s %s; sleep 20; rm -f %s)&" % (command, file, file)
|
||||
return command
|
||||
|
||||
register(MacViewer)
|
||||
|
||||
else:
|
||||
|
||||
# unixoids
|
||||
|
||||
def which(executable):
|
||||
path = os.environ.get("PATH")
|
||||
if not path:
|
||||
return None
|
||||
for dirname in path.split(os.pathsep):
|
||||
filename = os.path.join(dirname, executable)
|
||||
if os.path.isfile(filename):
|
||||
# FIXME: make sure it's executable
|
||||
return filename
|
||||
return None
|
||||
|
||||
class UnixViewer(Viewer):
|
||||
def show_file(self, file, **options):
|
||||
command, executable = self.get_command_ex(file, **options)
|
||||
command = "(%s %s; rm -f %s)&" % (command, file, file)
|
||||
os.system(command)
|
||||
return 1
|
||||
|
||||
# implementations
|
||||
|
||||
class DisplayViewer(UnixViewer):
|
||||
def get_command_ex(self, file, **options):
|
||||
command = executable = "display"
|
||||
return command, executable
|
||||
|
||||
if which("display"):
|
||||
register(DisplayViewer)
|
||||
|
||||
class XVViewer(UnixViewer):
|
||||
def get_command_ex(self, file, title=None, **options):
|
||||
# note: xv is pretty outdated. most modern systems have
|
||||
# imagemagick's display command instead.
|
||||
command = executable = "xv"
|
||||
if title:
|
||||
# FIXME: do full escaping
|
||||
command = command + " -name \"%s\"" % title
|
||||
return command, executable
|
||||
|
||||
if which("xv"):
|
||||
register(XVViewer)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# usage: python ImageShow.py imagefile [title]
|
||||
print show(Image.open(sys.argv[1]), *sys.argv[2:])
|
||||
164
Darwin/lib/python2.7/site-packages/PIL/ImageStat.py
Normal file
164
Darwin/lib/python2.7/site-packages/PIL/ImageStat.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# global image statistics
|
||||
#
|
||||
# History:
|
||||
# 1996-04-05 fl Created
|
||||
# 1997-05-21 fl Added mask; added rms, var, stddev attributes
|
||||
# 1997-08-05 fl Added median
|
||||
# 1998-07-05 hk Fixed integer overflow error
|
||||
#
|
||||
# Notes:
|
||||
# This class shows how to implement delayed evaluation of attributes.
|
||||
# To get a certain value, simply access the corresponding attribute.
|
||||
# The __getattr__ dispatcher takes care of the rest.
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1996-97.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
import operator, math
|
||||
|
||||
##
|
||||
# The <b>ImageStat</b> module calculates global statistics for an
|
||||
# image, or a region of an image.
|
||||
##
|
||||
|
||||
##
|
||||
# Calculate statistics for the given image. If a mask is included,
|
||||
# only the regions covered by that mask are included in the
|
||||
# statistics.
|
||||
|
||||
class Stat:
|
||||
"Get image or feature statistics"
|
||||
|
||||
##
|
||||
# Create a statistics object.
|
||||
#
|
||||
# @def __init__(image, mask=None)
|
||||
# @param image A PIL image, or a precalculate histogram.
|
||||
# @param mask An optional mask.
|
||||
|
||||
def __init__(self, image_or_list, mask = None):
|
||||
try:
|
||||
if mask:
|
||||
self.h = image_or_list.histogram(mask)
|
||||
else:
|
||||
self.h = image_or_list.histogram()
|
||||
except AttributeError:
|
||||
self.h = image_or_list # assume it to be a histogram list
|
||||
if type(self.h) != type([]):
|
||||
raise TypeError, "first argument must be image or list"
|
||||
self.bands = range(len(self.h) / 256)
|
||||
|
||||
def __getattr__(self, id):
|
||||
"Calculate missing attribute"
|
||||
if id[:4] == "_get":
|
||||
raise AttributeError, id
|
||||
# calculate missing attribute
|
||||
v = getattr(self, "_get" + id)()
|
||||
setattr(self, id, v)
|
||||
return v
|
||||
|
||||
def _getextrema(self):
|
||||
"Get min/max values for each band in the image"
|
||||
|
||||
def minmax(histogram):
|
||||
n = 255
|
||||
x = 0
|
||||
for i in range(256):
|
||||
if histogram[i]:
|
||||
n = min(n, i)
|
||||
x = max(x, i)
|
||||
return n, x # returns (255, 0) if there's no data in the histogram
|
||||
|
||||
v = []
|
||||
for i in range(0, len(self.h), 256):
|
||||
v.append(minmax(self.h[i:]))
|
||||
return v
|
||||
|
||||
def _getcount(self):
|
||||
"Get total number of pixels in each layer"
|
||||
|
||||
v = []
|
||||
for i in range(0, len(self.h), 256):
|
||||
v.append(reduce(operator.add, self.h[i:i+256]))
|
||||
return v
|
||||
|
||||
def _getsum(self):
|
||||
"Get sum of all pixels in each layer"
|
||||
|
||||
v = []
|
||||
for i in range(0, len(self.h), 256):
|
||||
sum = 0.0
|
||||
for j in range(256):
|
||||
sum = sum + j * self.h[i+j]
|
||||
v.append(sum)
|
||||
return v
|
||||
|
||||
def _getsum2(self):
|
||||
"Get squared sum of all pixels in each layer"
|
||||
|
||||
v = []
|
||||
for i in range(0, len(self.h), 256):
|
||||
sum2 = 0.0
|
||||
for j in range(256):
|
||||
sum2 = sum2 + (j ** 2) * float(self.h[i+j])
|
||||
v.append(sum2)
|
||||
return v
|
||||
|
||||
def _getmean(self):
|
||||
"Get average pixel level for each layer"
|
||||
|
||||
v = []
|
||||
for i in self.bands:
|
||||
v.append(self.sum[i] / self.count[i])
|
||||
return v
|
||||
|
||||
def _getmedian(self):
|
||||
"Get median pixel level for each layer"
|
||||
|
||||
v = []
|
||||
for i in self.bands:
|
||||
s = 0
|
||||
l = self.count[i]/2
|
||||
b = i * 256
|
||||
for j in range(256):
|
||||
s = s + self.h[b+j]
|
||||
if s > l:
|
||||
break
|
||||
v.append(j)
|
||||
return v
|
||||
|
||||
def _getrms(self):
|
||||
"Get RMS for each layer"
|
||||
|
||||
v = []
|
||||
for i in self.bands:
|
||||
v.append(math.sqrt(self.sum2[i] / self.count[i]))
|
||||
return v
|
||||
|
||||
|
||||
def _getvar(self):
|
||||
"Get variance for each layer"
|
||||
|
||||
v = []
|
||||
for i in self.bands:
|
||||
n = self.count[i]
|
||||
v.append((self.sum2[i]-(self.sum[i]**2.0)/n)/n)
|
||||
return v
|
||||
|
||||
def _getstddev(self):
|
||||
"Get standard deviation for each layer"
|
||||
|
||||
v = []
|
||||
for i in self.bands:
|
||||
v.append(math.sqrt(self.var[i]))
|
||||
return v
|
||||
|
||||
Global = Stat # compatibility
|
||||
296
Darwin/lib/python2.7/site-packages/PIL/ImageTk.py
Normal file
296
Darwin/lib/python2.7/site-packages/PIL/ImageTk.py
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# a Tk display interface
|
||||
#
|
||||
# History:
|
||||
# 96-04-08 fl Created
|
||||
# 96-09-06 fl Added getimage method
|
||||
# 96-11-01 fl Rewritten, removed image attribute and crop method
|
||||
# 97-05-09 fl Use PyImagingPaste method instead of image type
|
||||
# 97-05-12 fl Minor tweaks to match the IFUNC95 interface
|
||||
# 97-05-17 fl Support the "pilbitmap" booster patch
|
||||
# 97-06-05 fl Added file= and data= argument to image constructors
|
||||
# 98-03-09 fl Added width and height methods to Image classes
|
||||
# 98-07-02 fl Use default mode for "P" images without palette attribute
|
||||
# 98-07-02 fl Explicitly destroy Tkinter image objects
|
||||
# 99-07-24 fl Support multiple Tk interpreters (from Greg Couch)
|
||||
# 99-07-26 fl Automatically hook into Tkinter (if possible)
|
||||
# 99-08-15 fl Hook uses _imagingtk instead of _imaging
|
||||
#
|
||||
# Copyright (c) 1997-1999 by Secret Labs AB
|
||||
# Copyright (c) 1996-1997 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Tkinter, Image
|
||||
|
||||
##
|
||||
# The <b>ImageTk</b> module contains support to create and modify
|
||||
# Tkinter <b>BitmapImage</b> and <b>PhotoImage</b> objects.
|
||||
# <p>
|
||||
# For examples, see the demo programs in the <i>Scripts</i>
|
||||
# directory.
|
||||
##
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Check for Tkinter interface hooks
|
||||
|
||||
_pilbitmap_ok = None
|
||||
|
||||
def _pilbitmap_check():
|
||||
global _pilbitmap_ok
|
||||
if _pilbitmap_ok is None:
|
||||
try:
|
||||
im = Image.new("1", (1,1))
|
||||
Tkinter.BitmapImage(data="PIL:%d" % im.im.id)
|
||||
_pilbitmap_ok = 1
|
||||
except Tkinter.TclError:
|
||||
_pilbitmap_ok = 0
|
||||
return _pilbitmap_ok
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PhotoImage
|
||||
|
||||
##
|
||||
# Creates 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.
|
||||
|
||||
class PhotoImage:
|
||||
|
||||
##
|
||||
# Create a photo image object. The constructor takes either
|
||||
# a PIL image, or a mode and a size. Alternatively, you can
|
||||
# use the <b>file</b> or <b>data</b> options to initialize
|
||||
# the photo image object.
|
||||
# <p>
|
||||
# @def __init__(image=None, size=None, **options)
|
||||
# @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.
|
||||
# @keyparam file A filename to load the image from (using
|
||||
# Image.open(file)).
|
||||
# @keyparam data An 8-bit string containing image data (as
|
||||
# loaded from an image file).
|
||||
|
||||
def __init__(self, image=None, size=None, **kw):
|
||||
|
||||
# Tk compatibility: file or data
|
||||
if image is None:
|
||||
if kw.has_key("file"):
|
||||
image = Image.open(kw["file"])
|
||||
del kw["file"]
|
||||
elif kw.has_key("data"):
|
||||
from StringIO import StringIO
|
||||
image = Image.open(StringIO(kw["data"]))
|
||||
del kw["data"]
|
||||
|
||||
if hasattr(image, "mode") and hasattr(image, "size"):
|
||||
# got an image instead of a mode
|
||||
mode = image.mode
|
||||
if mode == "P":
|
||||
# palette mapped data
|
||||
image.load()
|
||||
try:
|
||||
mode = image.palette.mode
|
||||
except AttributeError:
|
||||
mode = "RGB" # default
|
||||
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 = apply(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:
|
||||
pass # ignore internal errors
|
||||
|
||||
##
|
||||
# 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).
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__photo)
|
||||
|
||||
##
|
||||
# Get the width of the image.
|
||||
#
|
||||
# @return The width, in pixels.
|
||||
|
||||
def width(self):
|
||||
return self.__size[0]
|
||||
|
||||
##
|
||||
# Get the height of the image.
|
||||
#
|
||||
# @return The height, in pixels.
|
||||
|
||||
def height(self):
|
||||
return self.__size[1]
|
||||
|
||||
##
|
||||
# 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 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):
|
||||
|
||||
# convert to blittable
|
||||
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) # convert directly between buffers
|
||||
|
||||
tk = self.__photo.tk
|
||||
|
||||
try:
|
||||
tk.call("PyImagingPhoto", self.__photo, block.id)
|
||||
except Tkinter.TclError, v:
|
||||
# activate Tkinter hook
|
||||
try:
|
||||
import _imagingtk
|
||||
try:
|
||||
_imagingtk.tkinit(tk.interpaddr(), 1)
|
||||
except AttributeError:
|
||||
_imagingtk.tkinit(id(tk), 0)
|
||||
tk.call("PyImagingPhoto", self.__photo, block.id)
|
||||
except (ImportError, AttributeError, Tkinter.TclError):
|
||||
raise # configuration problem; cannot attach to Tkinter
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# BitmapImage
|
||||
|
||||
##
|
||||
# Create a Tkinter-compatible bitmap image. This can be used
|
||||
# everywhere Tkinter expects an image object.
|
||||
|
||||
class BitmapImage:
|
||||
|
||||
##
|
||||
# Create a Tkinter-compatible bitmap image.
|
||||
# <p>
|
||||
# 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 <b>foreground</b>,
|
||||
# which is used to specify the colour for the non-transparent
|
||||
# parts. See the Tkinter documentation for information on how to
|
||||
# specify colours.
|
||||
#
|
||||
# @def __init__(image=None, **options)
|
||||
# @param image A PIL image.
|
||||
|
||||
def __init__(self, image=None, **kw):
|
||||
|
||||
# Tk compatibility: file or data
|
||||
if image is None:
|
||||
if kw.has_key("file"):
|
||||
image = Image.open(kw["file"])
|
||||
del kw["file"]
|
||||
elif kw.has_key("data"):
|
||||
from StringIO import StringIO
|
||||
image = Image.open(StringIO(kw["data"]))
|
||||
del kw["data"]
|
||||
|
||||
self.__mode = image.mode
|
||||
self.__size = image.size
|
||||
|
||||
if _pilbitmap_check():
|
||||
# fast way (requires the pilbitmap booster patch)
|
||||
image.load()
|
||||
kw["data"] = "PIL:%d" % image.im.id
|
||||
self.__im = image # must keep a reference
|
||||
else:
|
||||
# slow but safe way
|
||||
kw["data"] = image.tobitmap()
|
||||
self.__photo = apply(Tkinter.BitmapImage, (), kw)
|
||||
|
||||
def __del__(self):
|
||||
name = self.__photo.name
|
||||
self.__photo.name = None
|
||||
try:
|
||||
self.__photo.tk.call("image", "delete", name)
|
||||
except:
|
||||
pass # ignore internal errors
|
||||
|
||||
##
|
||||
# Get the width of the image.
|
||||
#
|
||||
# @return The width, in pixels.
|
||||
|
||||
def width(self):
|
||||
return self.__size[0]
|
||||
|
||||
##
|
||||
# Get the height of the image.
|
||||
#
|
||||
# @return The height, in pixels.
|
||||
|
||||
def height(self):
|
||||
return self.__size[1]
|
||||
|
||||
##
|
||||
# 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).
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__photo)
|
||||
|
||||
##
|
||||
# Copies the contents of a PhotoImage to a PIL image memory.
|
||||
|
||||
def getimage(photo):
|
||||
photo.tk.call("PyImagingPhotoGet", photo)
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Helper for the Image.show method.
|
||||
|
||||
def _show(image, title):
|
||||
|
||||
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)
|
||||
Tkinter.Label.__init__(self, master, image=self.image,
|
||||
bg="black", bd=0)
|
||||
|
||||
if not Tkinter._default_root:
|
||||
raise IOError, "tkinter not initialized"
|
||||
top = Tkinter.Toplevel()
|
||||
if title:
|
||||
top.title(title)
|
||||
UI(top, image).pack()
|
||||
95
Darwin/lib/python2.7/site-packages/PIL/ImageTransform.py
Normal file
95
Darwin/lib/python2.7/site-packages/PIL/ImageTransform.py
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# transform wrappers
|
||||
#
|
||||
# History:
|
||||
# 2002-04-08 fl Created
|
||||
#
|
||||
# Copyright (c) 2002 by Secret Labs AB
|
||||
# Copyright (c) 2002 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
|
||||
class Transform(Image.ImageTransformHandler):
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
def getdata(self):
|
||||
return self.method, self.data
|
||||
def transform(self, size, image, **options):
|
||||
# can be overridden
|
||||
method, data = self.getdata()
|
||||
return image.transform(size, method, data, **options)
|
||||
|
||||
##
|
||||
# Define an affine image transform.
|
||||
# <p>
|
||||
# This function takes a 6-tuple (<i>a, b, c, d, e, f</i>) which
|
||||
# contain the first two rows from an affine transform matrix. For
|
||||
# each pixel (<i>x, y</i>) in the output image, the new value is
|
||||
# taken from a position (a <i>x</i> + b <i>y</i> + c,
|
||||
# d <i>x</i> + e <i>y</i> + f) in the input image, rounded to
|
||||
# nearest pixel.
|
||||
# <p>
|
||||
# This function can be used to scale, translate, rotate, and shear the
|
||||
# original image.
|
||||
#
|
||||
# @def AffineTransform(matrix)
|
||||
# @param matrix A 6-tuple (<i>a, b, c, d, e, f</i>) containing
|
||||
# the first two rows from an affine transform matrix.
|
||||
# @see Image#Image.transform
|
||||
|
||||
class AffineTransform(Transform):
|
||||
method = Image.AFFINE
|
||||
|
||||
##
|
||||
# Define a transform to extract a subregion from an image.
|
||||
# <p>
|
||||
# Maps a rectangle (defined by two corners) from the image to a
|
||||
# rectangle of the given size. The resulting image will contain
|
||||
# data sampled from between the corners, such that (<i>x0, y0</i>)
|
||||
# in the input image will end up at (0,0) in the output image,
|
||||
# and (<i>x1, y1</i>) at <i>size</i>.
|
||||
# <p>
|
||||
# This method can be used to crop, stretch, shrink, or mirror an
|
||||
# arbitrary rectangle in the current image. It is slightly slower than
|
||||
# <b>crop</b>, but about as fast as a corresponding <b>resize</b>
|
||||
# operation.
|
||||
#
|
||||
# @def ExtentTransform(bbox)
|
||||
# @param bbox A 4-tuple (<i>x0, y0, x1, y1</i>) which specifies
|
||||
# two points in the input image's coordinate system.
|
||||
# @see Image#Image.transform
|
||||
|
||||
class ExtentTransform(Transform):
|
||||
method = Image.EXTENT
|
||||
|
||||
##
|
||||
# Define an quad image transform.
|
||||
# <p>
|
||||
# Maps a quadrilateral (a region defined by four corners) from the
|
||||
# image to a rectangle of the given size.
|
||||
#
|
||||
# @def QuadTransform(xy)
|
||||
# @param xy An 8-tuple (<i>x0, y0, x1, y1, x2, y2, y3, y3</i>) which
|
||||
# contain the upper left, lower left, lower right, and upper right
|
||||
# corner of the source quadrilateral.
|
||||
# @see Image#Image.transform
|
||||
|
||||
class QuadTransform(Transform):
|
||||
method = Image.QUAD
|
||||
|
||||
##
|
||||
# Define an mesh image transform. A mesh transform consists of one
|
||||
# or more individual quad transforms.
|
||||
#
|
||||
# @def MeshTransform(data)
|
||||
# @param data A list of (bbox, quad) tuples.
|
||||
# @see Image#Image.transform
|
||||
|
||||
class MeshTransform(Transform):
|
||||
method = Image.MESH
|
||||
215
Darwin/lib/python2.7/site-packages/PIL/ImageWin.py
Normal file
215
Darwin/lib/python2.7/site-packages/PIL/ImageWin.py
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
#
|
||||
# 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))
|
||||
93
Darwin/lib/python2.7/site-packages/PIL/ImtImagePlugin.py
Normal file
93
Darwin/lib/python2.7/site-packages/PIL/ImtImagePlugin.py
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# IM Tools support for PIL
|
||||
#
|
||||
# history:
|
||||
# 1996-05-27 fl Created (read 8-bit images only)
|
||||
# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.2)
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997-2001.
|
||||
# Copyright (c) Fredrik Lundh 1996-2001.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.2"
|
||||
|
||||
import re
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
field = re.compile(r"([a-z]*) ([^ \r\n]*)")
|
||||
|
||||
##
|
||||
# Image plugin for IM Tools images.
|
||||
|
||||
class ImtImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "IMT"
|
||||
format_description = "IM Tools"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# Quick rejection: if there's not a LF among the first
|
||||
# 100 bytes, this is (probably) not a text header.
|
||||
|
||||
if not "\n" in self.fp.read(100):
|
||||
raise SyntaxError, "not an IM file"
|
||||
self.fp.seek(0)
|
||||
|
||||
xsize = ysize = 0
|
||||
|
||||
while 1:
|
||||
|
||||
s = self.fp.read(1)
|
||||
if not s:
|
||||
break
|
||||
|
||||
if s == chr(12):
|
||||
|
||||
# image data begins
|
||||
self.tile = [("raw", (0,0)+self.size,
|
||||
self.fp.tell(),
|
||||
(self.mode, 0, 1))]
|
||||
|
||||
break
|
||||
|
||||
else:
|
||||
|
||||
# read key/value pair
|
||||
# FIXME: dangerous, may read whole file
|
||||
s = s + self.fp.readline()
|
||||
if len(s) == 1 or len(s) > 100:
|
||||
break
|
||||
if s[0] == "*":
|
||||
continue # comment
|
||||
|
||||
m = field.match(s)
|
||||
if not m:
|
||||
break
|
||||
k, v = m.group(1,2)
|
||||
if k == "width":
|
||||
xsize = int(v)
|
||||
self.size = xsize, ysize
|
||||
elif k == "height":
|
||||
ysize = int(v)
|
||||
self.size = xsize, ysize
|
||||
elif k == "pixel" and v == "n8":
|
||||
self.mode = "L"
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("IMT", ImtImageFile)
|
||||
|
||||
#
|
||||
# no extension registered (".im" is simply too common)
|
||||
288
Darwin/lib/python2.7/site-packages/PIL/IptcImagePlugin.py
Normal file
288
Darwin/lib/python2.7/site-packages/PIL/IptcImagePlugin.py
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# IPTC/NAA file handling
|
||||
#
|
||||
# history:
|
||||
# 1995-10-01 fl Created
|
||||
# 1998-03-09 fl Cleaned up and added to PIL
|
||||
# 2002-06-18 fl Added getiptcinfo helper
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997-2002.
|
||||
# Copyright (c) Fredrik Lundh 1995.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.3"
|
||||
|
||||
|
||||
import Image, ImageFile
|
||||
import os, tempfile
|
||||
|
||||
|
||||
COMPRESSION = {
|
||||
1: "raw",
|
||||
5: "jpeg"
|
||||
}
|
||||
|
||||
PAD = chr(0) * 4
|
||||
|
||||
#
|
||||
# Helpers
|
||||
|
||||
def i16(c):
|
||||
return ord(c[1]) + (ord(c[0])<<8)
|
||||
|
||||
def i32(c):
|
||||
return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
|
||||
|
||||
def i(c):
|
||||
return i32((PAD + c)[-4:])
|
||||
|
||||
def dump(c):
|
||||
for i in c:
|
||||
print "%02x" % ord(i),
|
||||
print
|
||||
|
||||
##
|
||||
# Image plugin for IPTC/NAA datastreams. To read IPTC/NAA fields
|
||||
# from TIFF and JPEG files, use the <b>getiptcinfo</b> function.
|
||||
|
||||
class IptcImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "IPTC"
|
||||
format_description = "IPTC/NAA"
|
||||
|
||||
def getint(self, key):
|
||||
return i(self.info[key])
|
||||
|
||||
def field(self):
|
||||
#
|
||||
# get a IPTC field header
|
||||
s = self.fp.read(5)
|
||||
if not len(s):
|
||||
return None, 0
|
||||
|
||||
tag = ord(s[1]), ord(s[2])
|
||||
|
||||
# syntax
|
||||
if ord(s[0]) != 0x1C or tag[0] < 1 or tag[0] > 9:
|
||||
raise SyntaxError, "invalid IPTC/NAA file"
|
||||
|
||||
# field size
|
||||
size = ord(s[3])
|
||||
if size > 132:
|
||||
raise IOError, "illegal field length in IPTC/NAA file"
|
||||
elif size == 128:
|
||||
size = 0
|
||||
elif size > 128:
|
||||
size = i(self.fp.read(size-128))
|
||||
else:
|
||||
size = i16(s[3:])
|
||||
|
||||
return tag, size
|
||||
|
||||
def _is_raw(self, offset, size):
|
||||
#
|
||||
# check if the file can be mapped
|
||||
|
||||
# DISABLED: the following only slows things down...
|
||||
return 0
|
||||
|
||||
self.fp.seek(offset)
|
||||
t, sz = self.field()
|
||||
if sz != size[0]:
|
||||
return 0
|
||||
y = 1
|
||||
while 1:
|
||||
self.fp.seek(sz, 1)
|
||||
t, s = self.field()
|
||||
if t != (8, 10):
|
||||
break
|
||||
if s != sz:
|
||||
return 0
|
||||
y = y + 1
|
||||
return y == size[1]
|
||||
|
||||
def _open(self):
|
||||
|
||||
# load descriptive fields
|
||||
while 1:
|
||||
offset = self.fp.tell()
|
||||
tag, size = self.field()
|
||||
if not tag or tag == (8,10):
|
||||
break
|
||||
if size:
|
||||
tagdata = self.fp.read(size)
|
||||
else:
|
||||
tagdata = None
|
||||
if tag in self.info.keys():
|
||||
if isinstance(self.info[tag], list):
|
||||
self.info[tag].append(tagdata)
|
||||
else:
|
||||
self.info[tag] = [self.info[tag], tagdata]
|
||||
else:
|
||||
self.info[tag] = tagdata
|
||||
|
||||
# print tag, self.info[tag]
|
||||
|
||||
# mode
|
||||
layers = ord(self.info[(3,60)][0])
|
||||
component = ord(self.info[(3,60)][1])
|
||||
if self.info.has_key((3,65)):
|
||||
id = ord(self.info[(3,65)][0])-1
|
||||
else:
|
||||
id = 0
|
||||
if layers == 1 and not component:
|
||||
self.mode = "L"
|
||||
elif layers == 3 and component:
|
||||
self.mode = "RGB"[id]
|
||||
elif layers == 4 and component:
|
||||
self.mode = "CMYK"[id]
|
||||
|
||||
# size
|
||||
self.size = self.getint((3,20)), self.getint((3,30))
|
||||
|
||||
# compression
|
||||
try:
|
||||
compression = COMPRESSION[self.getint((3,120))]
|
||||
except KeyError:
|
||||
raise IOError, "Unknown IPTC image compression"
|
||||
|
||||
# tile
|
||||
if tag == (8,10):
|
||||
if compression == "raw" and self._is_raw(offset, self.size):
|
||||
self.tile = [(compression, (offset, size + 5, -1),
|
||||
(0, 0, self.size[0], self.size[1]))]
|
||||
else:
|
||||
self.tile = [("iptc", (compression, offset),
|
||||
(0, 0, self.size[0], self.size[1]))]
|
||||
|
||||
def load(self):
|
||||
|
||||
if len(self.tile) != 1 or self.tile[0][0] != "iptc":
|
||||
return ImageFile.ImageFile.load(self)
|
||||
|
||||
type, tile, box = self.tile[0]
|
||||
|
||||
encoding, offset = tile
|
||||
|
||||
self.fp.seek(offset)
|
||||
|
||||
# Copy image data to temporary file
|
||||
outfile = tempfile.mktemp()
|
||||
o = open(outfile, "wb")
|
||||
if encoding == "raw":
|
||||
# To simplify access to the extracted file,
|
||||
# prepend a PPM header
|
||||
o.write("P5\n%d %d\n255\n" % self.size)
|
||||
while 1:
|
||||
type, size = self.field()
|
||||
if type != (8, 10):
|
||||
break
|
||||
while size > 0:
|
||||
s = self.fp.read(min(size, 8192))
|
||||
if not s:
|
||||
break
|
||||
o.write(s)
|
||||
size = size - len(s)
|
||||
o.close()
|
||||
|
||||
try:
|
||||
try:
|
||||
# fast
|
||||
self.im = Image.core.open_ppm(outfile)
|
||||
except:
|
||||
# slightly slower
|
||||
im = Image.open(outfile)
|
||||
im.load()
|
||||
self.im = im.im
|
||||
finally:
|
||||
try: os.unlink(outfile)
|
||||
except: pass
|
||||
|
||||
|
||||
Image.register_open("IPTC", IptcImageFile)
|
||||
|
||||
Image.register_extension("IPTC", ".iim")
|
||||
|
||||
##
|
||||
# Get IPTC information from TIFF, JPEG, or IPTC file.
|
||||
#
|
||||
# @param im An image containing IPTC data.
|
||||
# @return A dictionary containing IPTC information, or None if
|
||||
# no IPTC information block was found.
|
||||
|
||||
def getiptcinfo(im):
|
||||
|
||||
import TiffImagePlugin, JpegImagePlugin
|
||||
import StringIO
|
||||
|
||||
data = None
|
||||
|
||||
if isinstance(im, IptcImageFile):
|
||||
# return info dictionary right away
|
||||
return im.info
|
||||
|
||||
elif isinstance(im, JpegImagePlugin.JpegImageFile):
|
||||
# extract the IPTC/NAA resource
|
||||
try:
|
||||
app = im.app["APP13"]
|
||||
if app[:14] == "Photoshop 3.0\x00":
|
||||
app = app[14:]
|
||||
# parse the image resource block
|
||||
offset = 0
|
||||
while app[offset:offset+4] == "8BIM":
|
||||
offset = offset + 4
|
||||
# resource code
|
||||
code = JpegImagePlugin.i16(app, offset)
|
||||
offset = offset + 2
|
||||
# resource name (usually empty)
|
||||
name_len = ord(app[offset])
|
||||
name = app[offset+1:offset+1+name_len]
|
||||
offset = 1 + offset + name_len
|
||||
if offset & 1:
|
||||
offset = offset + 1
|
||||
# resource data block
|
||||
size = JpegImagePlugin.i32(app, offset)
|
||||
offset = offset + 4
|
||||
if code == 0x0404:
|
||||
# 0x0404 contains IPTC/NAA data
|
||||
data = app[offset:offset+size]
|
||||
break
|
||||
offset = offset + size
|
||||
if offset & 1:
|
||||
offset = offset + 1
|
||||
except (AttributeError, KeyError):
|
||||
pass
|
||||
|
||||
elif isinstance(im, TiffImagePlugin.TiffImageFile):
|
||||
# get raw data from the IPTC/NAA tag (PhotoShop tags the data
|
||||
# as 4-byte integers, so we cannot use the get method...)
|
||||
try:
|
||||
type, data = im.tag.tagdata[TiffImagePlugin.IPTC_NAA_CHUNK]
|
||||
except (AttributeError, KeyError):
|
||||
pass
|
||||
|
||||
if data is None:
|
||||
return None # no properties
|
||||
|
||||
# create an IptcImagePlugin object without initializing it
|
||||
class FakeImage:
|
||||
pass
|
||||
im = FakeImage()
|
||||
im.__class__ = IptcImageFile
|
||||
|
||||
# parse the IPTC information chunk
|
||||
im.info = {}
|
||||
im.fp = StringIO.StringIO(data)
|
||||
|
||||
try:
|
||||
im._open()
|
||||
except (IndexError, KeyError):
|
||||
pass # expected failure
|
||||
|
||||
return im.info
|
||||
492
Darwin/lib/python2.7/site-packages/PIL/JpegImagePlugin.py
Normal file
492
Darwin/lib/python2.7/site-packages/PIL/JpegImagePlugin.py
Normal file
|
|
@ -0,0 +1,492 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# JPEG (JFIF) file handling
|
||||
#
|
||||
# See "Digital Compression and Coding of Continous-Tone Still Images,
|
||||
# Part 1, Requirements and Guidelines" (CCITT T.81 / ISO 10918-1)
|
||||
#
|
||||
# History:
|
||||
# 1995-09-09 fl Created
|
||||
# 1995-09-13 fl Added full parser
|
||||
# 1996-03-25 fl Added hack to use the IJG command line utilities
|
||||
# 1996-05-05 fl Workaround Photoshop 2.5 CMYK polarity bug
|
||||
# 1996-05-28 fl Added draft support, JFIF version (0.1)
|
||||
# 1996-12-30 fl Added encoder options, added progression property (0.2)
|
||||
# 1997-08-27 fl Save mode 1 images as BW (0.3)
|
||||
# 1998-07-12 fl Added YCbCr to draft and save methods (0.4)
|
||||
# 1998-10-19 fl Don't hang on files using 16-bit DQT's (0.4.1)
|
||||
# 2001-04-16 fl Extract DPI settings from JFIF files (0.4.2)
|
||||
# 2002-07-01 fl Skip pad bytes before markers; identify Exif files (0.4.3)
|
||||
# 2003-04-25 fl Added experimental EXIF decoder (0.5)
|
||||
# 2003-06-06 fl Added experimental EXIF GPSinfo decoder
|
||||
# 2003-09-13 fl Extract COM markers
|
||||
# 2009-09-06 fl Added icc_profile support (from Florian Hoech)
|
||||
# 2009-03-06 fl Changed CMYK handling; always use Adobe polarity (0.6)
|
||||
# 2009-03-08 fl Added subsampling support (from Justin Huff).
|
||||
#
|
||||
# Copyright (c) 1997-2003 by Secret Labs AB.
|
||||
# Copyright (c) 1995-1996 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.6"
|
||||
|
||||
import array, struct
|
||||
import string
|
||||
import Image, ImageFile
|
||||
|
||||
def i16(c,o=0):
|
||||
return ord(c[o+1]) + (ord(c[o])<<8)
|
||||
|
||||
def i32(c,o=0):
|
||||
return ord(c[o+3]) + (ord(c[o+2])<<8) + (ord(c[o+1])<<16) + (ord(c[o])<<24)
|
||||
|
||||
#
|
||||
# Parser
|
||||
|
||||
def Skip(self, marker):
|
||||
n = i16(self.fp.read(2))-2
|
||||
ImageFile._safe_read(self.fp, n)
|
||||
|
||||
def APP(self, marker):
|
||||
#
|
||||
# Application marker. Store these in the APP dictionary.
|
||||
# Also look for well-known application markers.
|
||||
|
||||
n = i16(self.fp.read(2))-2
|
||||
s = ImageFile._safe_read(self.fp, n)
|
||||
|
||||
app = "APP%d" % (marker&15)
|
||||
|
||||
self.app[app] = s # compatibility
|
||||
self.applist.append((app, s))
|
||||
|
||||
if marker == 0xFFE0 and s[:4] == "JFIF":
|
||||
# extract JFIF information
|
||||
self.info["jfif"] = version = i16(s, 5) # version
|
||||
self.info["jfif_version"] = divmod(version, 256)
|
||||
# extract JFIF properties
|
||||
try:
|
||||
jfif_unit = ord(s[7])
|
||||
jfif_density = i16(s, 8), i16(s, 10)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
if jfif_unit == 1:
|
||||
self.info["dpi"] = jfif_density
|
||||
self.info["jfif_unit"] = jfif_unit
|
||||
self.info["jfif_density"] = jfif_density
|
||||
elif marker == 0xFFE1 and s[:5] == "Exif\0":
|
||||
# extract Exif information (incomplete)
|
||||
self.info["exif"] = s # FIXME: value will change
|
||||
elif marker == 0xFFE2 and s[:5] == "FPXR\0":
|
||||
# extract FlashPix information (incomplete)
|
||||
self.info["flashpix"] = s # FIXME: value will change
|
||||
elif marker == 0xFFE2 and s[:12] == "ICC_PROFILE\0":
|
||||
# Since an ICC profile can be larger than the maximum size of
|
||||
# a JPEG marker (64K), we need provisions to split it into
|
||||
# multiple markers. The format defined by the ICC specifies
|
||||
# one or more APP2 markers containing the following data:
|
||||
# Identifying string ASCII "ICC_PROFILE\0" (12 bytes)
|
||||
# Marker sequence number 1, 2, etc (1 byte)
|
||||
# Number of markers Total of APP2's used (1 byte)
|
||||
# Profile data (remainder of APP2 data)
|
||||
# Decoders should use the marker sequence numbers to
|
||||
# reassemble the profile, rather than assuming that the APP2
|
||||
# markers appear in the correct sequence.
|
||||
self.icclist.append(s)
|
||||
elif marker == 0xFFEE and s[:5] == "Adobe":
|
||||
self.info["adobe"] = i16(s, 5)
|
||||
# extract Adobe custom properties
|
||||
try:
|
||||
adobe_transform = ord(s[1])
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
self.info["adobe_transform"] = adobe_transform
|
||||
|
||||
def COM(self, marker):
|
||||
#
|
||||
# Comment marker. Store these in the APP dictionary.
|
||||
|
||||
n = i16(self.fp.read(2))-2
|
||||
s = ImageFile._safe_read(self.fp, n)
|
||||
|
||||
self.app["COM"] = s # compatibility
|
||||
self.applist.append(("COM", s))
|
||||
|
||||
def SOF(self, marker):
|
||||
#
|
||||
# Start of frame marker. Defines the size and mode of the
|
||||
# image. JPEG is colour blind, so we use some simple
|
||||
# heuristics to map the number of layers to an appropriate
|
||||
# mode. Note that this could be made a bit brighter, by
|
||||
# looking for JFIF and Adobe APP markers.
|
||||
|
||||
n = i16(self.fp.read(2))-2
|
||||
s = ImageFile._safe_read(self.fp, n)
|
||||
self.size = i16(s[3:]), i16(s[1:])
|
||||
|
||||
self.bits = ord(s[0])
|
||||
if self.bits != 8:
|
||||
raise SyntaxError("cannot handle %d-bit layers" % self.bits)
|
||||
|
||||
self.layers = ord(s[5])
|
||||
if self.layers == 1:
|
||||
self.mode = "L"
|
||||
elif self.layers == 3:
|
||||
self.mode = "RGB"
|
||||
elif self.layers == 4:
|
||||
self.mode = "CMYK"
|
||||
else:
|
||||
raise SyntaxError("cannot handle %d-layer images" % self.layers)
|
||||
|
||||
if marker in [0xFFC2, 0xFFC6, 0xFFCA, 0xFFCE]:
|
||||
self.info["progressive"] = self.info["progression"] = 1
|
||||
|
||||
if self.icclist:
|
||||
# fixup icc profile
|
||||
self.icclist.sort() # sort by sequence number
|
||||
if ord(self.icclist[0][13]) == len(self.icclist):
|
||||
profile = []
|
||||
for p in self.icclist:
|
||||
profile.append(p[14:])
|
||||
icc_profile = string.join(profile, "")
|
||||
else:
|
||||
icc_profile = None # wrong number of fragments
|
||||
self.info["icc_profile"] = icc_profile
|
||||
self.icclist = None
|
||||
|
||||
for i in range(6, len(s), 3):
|
||||
t = s[i:i+3]
|
||||
# 4-tuples: id, vsamp, hsamp, qtable
|
||||
self.layer.append((t[0], ord(t[1])/16, ord(t[1])&15, ord(t[2])))
|
||||
|
||||
def DQT(self, marker):
|
||||
#
|
||||
# Define quantization table. Support baseline 8-bit tables
|
||||
# only. Note that there might be more than one table in
|
||||
# each marker.
|
||||
|
||||
# FIXME: The quantization tables can be used to estimate the
|
||||
# compression quality.
|
||||
|
||||
n = i16(self.fp.read(2))-2
|
||||
s = ImageFile._safe_read(self.fp, n)
|
||||
while len(s):
|
||||
if len(s) < 65:
|
||||
raise SyntaxError("bad quantization table marker")
|
||||
v = ord(s[0])
|
||||
if v/16 == 0:
|
||||
self.quantization[v&15] = array.array("b", s[1:65])
|
||||
s = s[65:]
|
||||
else:
|
||||
return # FIXME: add code to read 16-bit tables!
|
||||
# raise SyntaxError, "bad quantization table element size"
|
||||
|
||||
|
||||
#
|
||||
# JPEG marker table
|
||||
|
||||
MARKER = {
|
||||
0xFFC0: ("SOF0", "Baseline DCT", SOF),
|
||||
0xFFC1: ("SOF1", "Extended Sequential DCT", SOF),
|
||||
0xFFC2: ("SOF2", "Progressive DCT", SOF),
|
||||
0xFFC3: ("SOF3", "Spatial lossless", SOF),
|
||||
0xFFC4: ("DHT", "Define Huffman table", Skip),
|
||||
0xFFC5: ("SOF5", "Differential sequential DCT", SOF),
|
||||
0xFFC6: ("SOF6", "Differential progressive DCT", SOF),
|
||||
0xFFC7: ("SOF7", "Differential spatial", SOF),
|
||||
0xFFC8: ("JPG", "Extension", None),
|
||||
0xFFC9: ("SOF9", "Extended sequential DCT (AC)", SOF),
|
||||
0xFFCA: ("SOF10", "Progressive DCT (AC)", SOF),
|
||||
0xFFCB: ("SOF11", "Spatial lossless DCT (AC)", SOF),
|
||||
0xFFCC: ("DAC", "Define arithmetic coding conditioning", Skip),
|
||||
0xFFCD: ("SOF13", "Differential sequential DCT (AC)", SOF),
|
||||
0xFFCE: ("SOF14", "Differential progressive DCT (AC)", SOF),
|
||||
0xFFCF: ("SOF15", "Differential spatial (AC)", SOF),
|
||||
0xFFD0: ("RST0", "Restart 0", None),
|
||||
0xFFD1: ("RST1", "Restart 1", None),
|
||||
0xFFD2: ("RST2", "Restart 2", None),
|
||||
0xFFD3: ("RST3", "Restart 3", None),
|
||||
0xFFD4: ("RST4", "Restart 4", None),
|
||||
0xFFD5: ("RST5", "Restart 5", None),
|
||||
0xFFD6: ("RST6", "Restart 6", None),
|
||||
0xFFD7: ("RST7", "Restart 7", None),
|
||||
0xFFD8: ("SOI", "Start of image", None),
|
||||
0xFFD9: ("EOI", "End of image", None),
|
||||
0xFFDA: ("SOS", "Start of scan", Skip),
|
||||
0xFFDB: ("DQT", "Define quantization table", DQT),
|
||||
0xFFDC: ("DNL", "Define number of lines", Skip),
|
||||
0xFFDD: ("DRI", "Define restart interval", Skip),
|
||||
0xFFDE: ("DHP", "Define hierarchical progression", SOF),
|
||||
0xFFDF: ("EXP", "Expand reference component", Skip),
|
||||
0xFFE0: ("APP0", "Application segment 0", APP),
|
||||
0xFFE1: ("APP1", "Application segment 1", APP),
|
||||
0xFFE2: ("APP2", "Application segment 2", APP),
|
||||
0xFFE3: ("APP3", "Application segment 3", APP),
|
||||
0xFFE4: ("APP4", "Application segment 4", APP),
|
||||
0xFFE5: ("APP5", "Application segment 5", APP),
|
||||
0xFFE6: ("APP6", "Application segment 6", APP),
|
||||
0xFFE7: ("APP7", "Application segment 7", APP),
|
||||
0xFFE8: ("APP8", "Application segment 8", APP),
|
||||
0xFFE9: ("APP9", "Application segment 9", APP),
|
||||
0xFFEA: ("APP10", "Application segment 10", APP),
|
||||
0xFFEB: ("APP11", "Application segment 11", APP),
|
||||
0xFFEC: ("APP12", "Application segment 12", APP),
|
||||
0xFFED: ("APP13", "Application segment 13", APP),
|
||||
0xFFEE: ("APP14", "Application segment 14", APP),
|
||||
0xFFEF: ("APP15", "Application segment 15", APP),
|
||||
0xFFF0: ("JPG0", "Extension 0", None),
|
||||
0xFFF1: ("JPG1", "Extension 1", None),
|
||||
0xFFF2: ("JPG2", "Extension 2", None),
|
||||
0xFFF3: ("JPG3", "Extension 3", None),
|
||||
0xFFF4: ("JPG4", "Extension 4", None),
|
||||
0xFFF5: ("JPG5", "Extension 5", None),
|
||||
0xFFF6: ("JPG6", "Extension 6", None),
|
||||
0xFFF7: ("JPG7", "Extension 7", None),
|
||||
0xFFF8: ("JPG8", "Extension 8", None),
|
||||
0xFFF9: ("JPG9", "Extension 9", None),
|
||||
0xFFFA: ("JPG10", "Extension 10", None),
|
||||
0xFFFB: ("JPG11", "Extension 11", None),
|
||||
0xFFFC: ("JPG12", "Extension 12", None),
|
||||
0xFFFD: ("JPG13", "Extension 13", None),
|
||||
0xFFFE: ("COM", "Comment", COM)
|
||||
}
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[0] == "\377"
|
||||
|
||||
##
|
||||
# Image plugin for JPEG and JFIF images.
|
||||
|
||||
class JpegImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "JPEG"
|
||||
format_description = "JPEG (ISO 10918)"
|
||||
|
||||
def _open(self):
|
||||
|
||||
s = self.fp.read(1)
|
||||
|
||||
if ord(s[0]) != 255:
|
||||
raise SyntaxError("not a JPEG file")
|
||||
|
||||
# Create attributes
|
||||
self.bits = self.layers = 0
|
||||
|
||||
# JPEG specifics (internal)
|
||||
self.layer = []
|
||||
self.huffman_dc = {}
|
||||
self.huffman_ac = {}
|
||||
self.quantization = {}
|
||||
self.app = {} # compatibility
|
||||
self.applist = []
|
||||
self.icclist = []
|
||||
|
||||
while 1:
|
||||
|
||||
s = s + self.fp.read(1)
|
||||
|
||||
i = i16(s)
|
||||
|
||||
if MARKER.has_key(i):
|
||||
name, description, handler = MARKER[i]
|
||||
# print hex(i), name, description
|
||||
if handler is not None:
|
||||
handler(self, i)
|
||||
if i == 0xFFDA: # start of scan
|
||||
rawmode = self.mode
|
||||
if self.mode == "CMYK":
|
||||
rawmode = "CMYK;I" # assume adobe conventions
|
||||
self.tile = [("jpeg", (0,0) + self.size, 0, (rawmode, ""))]
|
||||
# self.__offset = self.fp.tell()
|
||||
break
|
||||
s = self.fp.read(1)
|
||||
elif i == 0 or i == 65535:
|
||||
# padded marker or junk; move on
|
||||
s = "\xff"
|
||||
else:
|
||||
raise SyntaxError("no marker found")
|
||||
|
||||
def draft(self, mode, size):
|
||||
|
||||
if len(self.tile) != 1:
|
||||
return
|
||||
|
||||
d, e, o, a = self.tile[0]
|
||||
scale = 0
|
||||
|
||||
if a[0] == "RGB" and mode in ["L", "YCbCr"]:
|
||||
self.mode = mode
|
||||
a = mode, ""
|
||||
|
||||
if size:
|
||||
scale = max(self.size[0] / size[0], self.size[1] / size[1])
|
||||
for s in [8, 4, 2, 1]:
|
||||
if scale >= s:
|
||||
break
|
||||
e = e[0], e[1], (e[2]-e[0]+s-1)/s+e[0], (e[3]-e[1]+s-1)/s+e[1]
|
||||
self.size = ((self.size[0]+s-1)/s, (self.size[1]+s-1)/s)
|
||||
scale = s
|
||||
|
||||
self.tile = [(d, e, o, a)]
|
||||
self.decoderconfig = (scale, 1)
|
||||
|
||||
return self
|
||||
|
||||
def load_djpeg(self):
|
||||
|
||||
# ALTERNATIVE: handle JPEGs via the IJG command line utilities
|
||||
|
||||
import tempfile, os
|
||||
file = tempfile.mktemp()
|
||||
os.system("djpeg %s >%s" % (self.filename, file))
|
||||
|
||||
try:
|
||||
self.im = Image.core.open_ppm(file)
|
||||
finally:
|
||||
try: os.unlink(file)
|
||||
except: pass
|
||||
|
||||
self.mode = self.im.mode
|
||||
self.size = self.im.size
|
||||
|
||||
self.tile = []
|
||||
|
||||
def _getexif(self):
|
||||
# Extract EXIF information. This method is highly experimental,
|
||||
# and is likely to be replaced with something better in a future
|
||||
# version.
|
||||
import TiffImagePlugin, StringIO
|
||||
def fixup(value):
|
||||
if len(value) == 1:
|
||||
return value[0]
|
||||
return value
|
||||
# The EXIF record consists of a TIFF file embedded in a JPEG
|
||||
# application marker (!).
|
||||
try:
|
||||
data = self.info["exif"]
|
||||
except KeyError:
|
||||
return None
|
||||
file = StringIO.StringIO(data[6:])
|
||||
head = file.read(8)
|
||||
exif = {}
|
||||
# process dictionary
|
||||
info = TiffImagePlugin.ImageFileDirectory(head)
|
||||
info.load(file)
|
||||
for key, value in info.items():
|
||||
exif[key] = fixup(value)
|
||||
# get exif extension
|
||||
try:
|
||||
file.seek(exif[0x8769])
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
info = TiffImagePlugin.ImageFileDirectory(head)
|
||||
info.load(file)
|
||||
for key, value in info.items():
|
||||
exif[key] = fixup(value)
|
||||
# get gpsinfo extension
|
||||
try:
|
||||
file.seek(exif[0x8825])
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
info = TiffImagePlugin.ImageFileDirectory(head)
|
||||
info.load(file)
|
||||
exif[0x8825] = gps = {}
|
||||
for key, value in info.items():
|
||||
gps[key] = fixup(value)
|
||||
return exif
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# stuff to save JPEG files
|
||||
|
||||
RAWMODE = {
|
||||
"1": "L",
|
||||
"L": "L",
|
||||
"RGB": "RGB",
|
||||
"RGBA": "RGB",
|
||||
"RGBX": "RGB",
|
||||
"CMYK": "CMYK;I", # assume adobe conventions
|
||||
"YCbCr": "YCbCr",
|
||||
}
|
||||
|
||||
def _save(im, fp, filename):
|
||||
|
||||
try:
|
||||
rawmode = RAWMODE[im.mode]
|
||||
except KeyError:
|
||||
raise IOError("cannot write mode %s as JPEG" % im.mode)
|
||||
|
||||
info = im.encoderinfo
|
||||
|
||||
dpi = info.get("dpi", (0, 0))
|
||||
|
||||
subsampling = info.get("subsampling", -1)
|
||||
if subsampling == "4:4:4":
|
||||
subsampling = 0
|
||||
elif subsampling == "4:2:2":
|
||||
subsampling = 1
|
||||
elif subsampling == "4:1:1":
|
||||
subsampling = 2
|
||||
|
||||
extra = ""
|
||||
|
||||
icc_profile = info.get("icc_profile")
|
||||
if icc_profile:
|
||||
ICC_OVERHEAD_LEN = 14
|
||||
MAX_BYTES_IN_MARKER = 65533
|
||||
MAX_DATA_BYTES_IN_MARKER = MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN
|
||||
markers = []
|
||||
while icc_profile:
|
||||
markers.append(icc_profile[:MAX_DATA_BYTES_IN_MARKER])
|
||||
icc_profile = icc_profile[MAX_DATA_BYTES_IN_MARKER:]
|
||||
i = 1
|
||||
for marker in markers:
|
||||
size = struct.pack(">H", 2 + ICC_OVERHEAD_LEN + len(marker))
|
||||
extra = extra + ("\xFF\xE2" + size + "ICC_PROFILE\0" + chr(i) + chr(len(markers)) + marker)
|
||||
i = i + 1
|
||||
|
||||
# get keyword arguments
|
||||
im.encoderconfig = (
|
||||
info.get("quality", 0),
|
||||
# "progressive" is the official name, but older documentation
|
||||
# says "progression"
|
||||
# FIXME: issue a warning if the wrong form is used (post-1.1.7)
|
||||
info.has_key("progressive") or info.has_key("progression"),
|
||||
info.get("smooth", 0),
|
||||
info.has_key("optimize"),
|
||||
info.get("streamtype", 0),
|
||||
dpi[0], dpi[1],
|
||||
subsampling,
|
||||
extra,
|
||||
)
|
||||
|
||||
ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
|
||||
|
||||
def _save_cjpeg(im, fp, filename):
|
||||
# ALTERNATIVE: handle JPEGs via the IJG command line utilities.
|
||||
import os
|
||||
file = im._dump()
|
||||
os.system("cjpeg %s >%s" % (file, filename))
|
||||
try: os.unlink(file)
|
||||
except: pass
|
||||
|
||||
# -------------------------------------------------------------------q-
|
||||
# Registry stuff
|
||||
|
||||
Image.register_open("JPEG", JpegImageFile, _accept)
|
||||
Image.register_save("JPEG", _save)
|
||||
|
||||
Image.register_extension("JPEG", ".jfif")
|
||||
Image.register_extension("JPEG", ".jpe")
|
||||
Image.register_extension("JPEG", ".jpg")
|
||||
Image.register_extension("JPEG", ".jpeg")
|
||||
|
||||
Image.register_mime("JPEG", "image/jpeg")
|
||||
70
Darwin/lib/python2.7/site-packages/PIL/McIdasImagePlugin.py
Normal file
70
Darwin/lib/python2.7/site-packages/PIL/McIdasImagePlugin.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# Basic McIdas support for PIL
|
||||
#
|
||||
# History:
|
||||
# 1997-05-05 fl Created (8-bit images only)
|
||||
# 2009-03-08 fl Added 16/32-bit support.
|
||||
#
|
||||
# Thanks to Richard Jones and Craig Swank for specs and samples.
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1997.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.2"
|
||||
|
||||
import struct
|
||||
import Image, ImageFile
|
||||
|
||||
def _accept(s):
|
||||
return s[:8] == "\x00\x00\x00\x00\x00\x00\x00\x04"
|
||||
|
||||
##
|
||||
# Image plugin for McIdas area images.
|
||||
|
||||
class McIdasImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "MCIDAS"
|
||||
format_description = "McIdas area file"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# parse area file directory
|
||||
s = self.fp.read(256)
|
||||
if not _accept(s) or len(s) != 256:
|
||||
raise SyntaxError("not an McIdas area file")
|
||||
|
||||
self.area_descriptor_raw = s
|
||||
self.area_descriptor = w = [0] + list(struct.unpack("!64i", s))
|
||||
|
||||
# get mode
|
||||
if w[11] == 1:
|
||||
mode = rawmode = "L"
|
||||
elif w[11] == 2:
|
||||
# FIXME: add memory map support
|
||||
mode = "I"; rawmode = "I;16B"
|
||||
elif w[11] == 4:
|
||||
# FIXME: add memory map support
|
||||
mode = "I"; rawmode = "I;32B"
|
||||
else:
|
||||
raise SyntaxError("unsupported McIdas format")
|
||||
|
||||
self.mode = mode
|
||||
self.size = w[10], w[9]
|
||||
|
||||
offset = w[34] + w[15]
|
||||
stride = w[15] + w[10]*w[11]*w[14]
|
||||
|
||||
self.tile = [("raw", (0, 0) + self.size, offset, (rawmode, stride, 1))]
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# registry
|
||||
|
||||
Image.register_open("MCIDAS", McIdasImageFile, _accept)
|
||||
|
||||
# no default extension
|
||||
95
Darwin/lib/python2.7/site-packages/PIL/MicImagePlugin.py
Normal file
95
Darwin/lib/python2.7/site-packages/PIL/MicImagePlugin.py
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# Microsoft Image Composer support for PIL
|
||||
#
|
||||
# Notes:
|
||||
# uses TiffImagePlugin.py to read the actual image streams
|
||||
#
|
||||
# History:
|
||||
# 97-01-20 fl Created
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1997.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.1"
|
||||
|
||||
|
||||
import Image, TiffImagePlugin
|
||||
from OleFileIO import *
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:8] == MAGIC
|
||||
|
||||
##
|
||||
# Image plugin for Microsoft's Image Composer file format.
|
||||
|
||||
class MicImageFile(TiffImagePlugin.TiffImageFile):
|
||||
|
||||
format = "MIC"
|
||||
format_description = "Microsoft Image Composer"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# read the OLE directory and see if this is a likely
|
||||
# to be a Microsoft Image Composer file
|
||||
|
||||
try:
|
||||
self.ole = OleFileIO(self.fp)
|
||||
except IOError:
|
||||
raise SyntaxError, "not an MIC file; invalid OLE file"
|
||||
|
||||
# find ACI subfiles with Image members (maybe not the
|
||||
# best way to identify MIC files, but what the... ;-)
|
||||
|
||||
self.images = []
|
||||
for file in self.ole.listdir():
|
||||
if file[1:] and file[0][-4:] == ".ACI" and file[1] == "Image":
|
||||
self.images.append(file)
|
||||
|
||||
# if we didn't find any images, this is probably not
|
||||
# an MIC file.
|
||||
if not self.images:
|
||||
raise SyntaxError, "not an MIC file; no image entries"
|
||||
|
||||
self.__fp = self.fp
|
||||
self.frame = 0
|
||||
|
||||
if len(self.images) > 1:
|
||||
self.category = Image.CONTAINER
|
||||
|
||||
self.seek(0)
|
||||
|
||||
def seek(self, frame):
|
||||
|
||||
try:
|
||||
filename = self.images[frame]
|
||||
except IndexError:
|
||||
raise EOFError, "no such frame"
|
||||
|
||||
self.fp = self.ole.openstream(filename)
|
||||
|
||||
TiffImagePlugin.TiffImageFile._open(self)
|
||||
|
||||
self.frame = frame
|
||||
|
||||
def tell(self):
|
||||
|
||||
return self.frame
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("MIC", MicImageFile, _accept)
|
||||
|
||||
Image.register_extension("MIC", ".mic")
|
||||
82
Darwin/lib/python2.7/site-packages/PIL/MpegImagePlugin.py
Normal file
82
Darwin/lib/python2.7/site-packages/PIL/MpegImagePlugin.py
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# MPEG file handling
|
||||
#
|
||||
# History:
|
||||
# 95-09-09 fl Created
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1995.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.1"
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
#
|
||||
# Bitstream parser
|
||||
|
||||
class BitStream:
|
||||
|
||||
def __init__(self, fp):
|
||||
self.fp = fp
|
||||
self.bits = 0
|
||||
self.bitbuffer = 0
|
||||
|
||||
def next(self):
|
||||
return ord(self.fp.read(1))
|
||||
|
||||
def peek(self, bits):
|
||||
while self.bits < bits:
|
||||
c = self.next()
|
||||
if c < 0:
|
||||
self.bits = 0
|
||||
continue
|
||||
self.bitbuffer = (self.bitbuffer << 8) + c
|
||||
self.bits = self.bits + 8
|
||||
return self.bitbuffer >> (self.bits - bits) & (1L << bits) - 1
|
||||
|
||||
def skip(self, bits):
|
||||
while self.bits < bits:
|
||||
self.bitbuffer = (self.bitbuffer << 8) + ord(self.fp.read(1))
|
||||
self.bits = self.bits + 8
|
||||
self.bits = self.bits - bits
|
||||
|
||||
def read(self, bits):
|
||||
v = self.peek(bits)
|
||||
self.bits = self.bits - bits
|
||||
return v
|
||||
|
||||
##
|
||||
# Image plugin for MPEG streams. This plugin can identify a stream,
|
||||
# but it cannot read it.
|
||||
|
||||
class MpegImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "MPEG"
|
||||
format_description = "MPEG"
|
||||
|
||||
def _open(self):
|
||||
|
||||
s = BitStream(self.fp)
|
||||
|
||||
if s.read(32) != 0x1B3:
|
||||
raise SyntaxError, "not an MPEG file"
|
||||
|
||||
self.mode = "RGB"
|
||||
self.size = s.read(12), s.read(12)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Registry stuff
|
||||
|
||||
Image.register_open("MPEG", MpegImageFile)
|
||||
|
||||
Image.register_extension("MPEG", ".mpg")
|
||||
Image.register_extension("MPEG", ".mpeg")
|
||||
|
||||
Image.register_mime("MPEG", "video/mpeg")
|
||||
103
Darwin/lib/python2.7/site-packages/PIL/MspImagePlugin.py
Normal file
103
Darwin/lib/python2.7/site-packages/PIL/MspImagePlugin.py
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# MSP file handling
|
||||
#
|
||||
# This is the format used by the Paint program in Windows 1 and 2.
|
||||
#
|
||||
# History:
|
||||
# 95-09-05 fl Created
|
||||
# 97-01-03 fl Read/write MSP images
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1995-97.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.1"
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
|
||||
#
|
||||
# read MSP files
|
||||
|
||||
def i16(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8)
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] in ["DanM", "LinS"]
|
||||
|
||||
##
|
||||
# Image plugin for Windows MSP images. This plugin supports both
|
||||
# uncompressed (Windows 1.0).
|
||||
|
||||
class MspImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "MSP"
|
||||
format_description = "Windows Paint"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# Header
|
||||
s = self.fp.read(32)
|
||||
if s[:4] not in ["DanM", "LinS"]:
|
||||
raise SyntaxError, "not an MSP file"
|
||||
|
||||
# Header checksum
|
||||
sum = 0
|
||||
for i in range(0, 32, 2):
|
||||
sum = sum ^ i16(s[i:i+2])
|
||||
if sum != 0:
|
||||
raise SyntaxError, "bad MSP checksum"
|
||||
|
||||
self.mode = "1"
|
||||
self.size = i16(s[4:]), i16(s[6:])
|
||||
|
||||
if s[:4] == "DanM":
|
||||
self.tile = [("raw", (0,0)+self.size, 32, ("1", 0, 1))]
|
||||
else:
|
||||
self.tile = [("msp", (0,0)+self.size, 32+2*self.size[1], None)]
|
||||
|
||||
#
|
||||
# write MSP files (uncompressed only)
|
||||
|
||||
def o16(i):
|
||||
return chr(i&255) + chr(i>>8&255)
|
||||
|
||||
def _save(im, fp, filename):
|
||||
|
||||
if im.mode != "1":
|
||||
raise IOError, "cannot write mode %s as MSP" % im.mode
|
||||
|
||||
# create MSP header
|
||||
header = [0] * 16
|
||||
|
||||
header[0], header[1] = i16("Da"), i16("nM") # version 1
|
||||
header[2], header[3] = im.size
|
||||
header[4], header[5] = 1, 1
|
||||
header[6], header[7] = 1, 1
|
||||
header[8], header[9] = im.size
|
||||
|
||||
sum = 0
|
||||
for h in header:
|
||||
sum = sum ^ h
|
||||
header[12] = sum # FIXME: is this the right field?
|
||||
|
||||
# header
|
||||
for h in header:
|
||||
fp.write(o16(h))
|
||||
|
||||
# image body
|
||||
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 32, ("1", 0, 1))])
|
||||
|
||||
#
|
||||
# registry
|
||||
|
||||
Image.register_open("MSP", MspImageFile, _accept)
|
||||
Image.register_save("MSP", _save)
|
||||
|
||||
Image.register_extension("MSP", ".msp")
|
||||
528
Darwin/lib/python2.7/site-packages/PIL/OleFileIO.py
Normal file
528
Darwin/lib/python2.7/site-packages/PIL/OleFileIO.py
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
#
|
||||
# THIS IS WORK IN PROGRESS
|
||||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# stuff to deal with OLE2 Structured Storage files. this module is
|
||||
# used by PIL to read Image Composer and FlashPix files, but can also
|
||||
# be used to read other files of this type.
|
||||
#
|
||||
# History:
|
||||
# 1997-01-20 fl Created
|
||||
# 1997-01-22 fl Fixed 64-bit portability quirk
|
||||
# 2003-09-09 fl Fixed typo in OleFileIO.loadfat (noted by Daniel Haertle)
|
||||
# 2004-02-29 fl Changed long hex constants to signed integers
|
||||
#
|
||||
# Notes:
|
||||
# FIXME: sort out sign problem (eliminate long hex constants)
|
||||
# FIXME: change filename to use "a/b/c" instead of ["a", "b", "c"]
|
||||
# FIXME: provide a glob mechanism function (using fnmatchcase)
|
||||
#
|
||||
# Literature:
|
||||
#
|
||||
# "FlashPix Format Specification, Appendix A", Kodak and Microsoft,
|
||||
# September 1996.
|
||||
#
|
||||
# Quotes:
|
||||
#
|
||||
# "If this document and functionality of the Software conflict,
|
||||
# the actual functionality of the Software represents the correct
|
||||
# functionality" -- Microsoft, in the OLE format specification
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1997.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import string, StringIO
|
||||
|
||||
|
||||
def i16(c, o = 0):
|
||||
return ord(c[o])+(ord(c[o+1])<<8)
|
||||
|
||||
def i32(c, o = 0):
|
||||
return ord(c[o])+(ord(c[o+1])<<8)+(ord(c[o+2])<<16)+(ord(c[o+3])<<24)
|
||||
|
||||
|
||||
MAGIC = '\320\317\021\340\241\261\032\341'
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# property types
|
||||
|
||||
VT_EMPTY=0; VT_NULL=1; VT_I2=2; VT_I4=3; VT_R4=4; VT_R8=5; VT_CY=6;
|
||||
VT_DATE=7; VT_BSTR=8; VT_DISPATCH=9; VT_ERROR=10; VT_BOOL=11;
|
||||
VT_VARIANT=12; VT_UNKNOWN=13; VT_DECIMAL=14; VT_I1=16; VT_UI1=17;
|
||||
VT_UI2=18; VT_UI4=19; VT_I8=20; VT_UI8=21; VT_INT=22; VT_UINT=23;
|
||||
VT_VOID=24; VT_HRESULT=25; VT_PTR=26; VT_SAFEARRAY=27; VT_CARRAY=28;
|
||||
VT_USERDEFINED=29; VT_LPSTR=30; VT_LPWSTR=31; VT_FILETIME=64;
|
||||
VT_BLOB=65; VT_STREAM=66; VT_STORAGE=67; VT_STREAMED_OBJECT=68;
|
||||
VT_STORED_OBJECT=69; VT_BLOB_OBJECT=70; VT_CF=71; VT_CLSID=72;
|
||||
VT_VECTOR=0x1000;
|
||||
|
||||
# map property id to name (for debugging purposes)
|
||||
|
||||
VT = {}
|
||||
for k, v in vars().items():
|
||||
if k[:3] == "VT_":
|
||||
VT[v] = k
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Some common document types (root.clsid fields)
|
||||
|
||||
WORD_CLSID = "00020900-0000-0000-C000-000000000046"
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
class _OleStream(StringIO.StringIO):
|
||||
|
||||
"""OLE2 Stream
|
||||
|
||||
Returns a read-only file object which can be used to read
|
||||
the contents of a OLE stream. To open a stream, use the
|
||||
openstream method in the OleFile class.
|
||||
|
||||
This function can be used with either ordinary streams,
|
||||
or ministreams, depending on the offset, sectorsize, and
|
||||
fat table arguments.
|
||||
"""
|
||||
|
||||
# FIXME: should store the list of sects obtained by following
|
||||
# the fat chain, and load new sectors on demand instead of
|
||||
# loading it all in one go.
|
||||
|
||||
def __init__(self, fp, sect, size, offset, sectorsize, fat):
|
||||
|
||||
data = []
|
||||
|
||||
while sect != -2: # 0xFFFFFFFEL:
|
||||
fp.seek(offset + sectorsize * sect)
|
||||
data.append(fp.read(sectorsize))
|
||||
sect = fat[sect]
|
||||
|
||||
data = string.join(data, "")
|
||||
|
||||
# print len(data), size
|
||||
|
||||
StringIO.StringIO.__init__(self, data[:size])
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# FIXME: should add a counter in here to avoid looping forever
|
||||
# if the tree is broken.
|
||||
|
||||
class _OleDirectoryEntry:
|
||||
|
||||
"""OLE2 Directory Entry
|
||||
|
||||
Encapsulates a stream directory entry. Note that the
|
||||
constructor builds a tree of all subentries, so we only
|
||||
have to call it with the root object.
|
||||
"""
|
||||
|
||||
def __init__(self, sidlist, sid):
|
||||
|
||||
# store directory parameters. the caller provides
|
||||
# a complete list of directory entries, as read from
|
||||
# the directory stream.
|
||||
|
||||
name, type, sect, size, sids, clsid = sidlist[sid]
|
||||
|
||||
self.sid = sid
|
||||
self.name = name
|
||||
self.type = type # 1=storage 2=stream
|
||||
self.sect = sect
|
||||
self.size = size
|
||||
self.clsid = clsid
|
||||
|
||||
# process child nodes, if any
|
||||
|
||||
self.kids = []
|
||||
|
||||
sid = sidlist[sid][4][2]
|
||||
|
||||
if sid != -1:
|
||||
|
||||
# the directory entries are organized as a red-black tree.
|
||||
# the following piece of code does an ordered traversal of
|
||||
# such a tree (at least that's what I hope ;-)
|
||||
|
||||
stack = [self.sid]
|
||||
|
||||
# start at leftmost position
|
||||
|
||||
left, right, child = sidlist[sid][4]
|
||||
|
||||
while left != -1: # 0xFFFFFFFFL:
|
||||
stack.append(sid)
|
||||
sid = left
|
||||
left, right, child = sidlist[sid][4]
|
||||
|
||||
while sid != self.sid:
|
||||
|
||||
self.kids.append(_OleDirectoryEntry(sidlist, sid))
|
||||
|
||||
# try to move right
|
||||
left, right, child = sidlist[sid][4]
|
||||
if right != -1: # 0xFFFFFFFFL:
|
||||
# and then back to the left
|
||||
sid = right
|
||||
while 1:
|
||||
left, right, child = sidlist[sid][4]
|
||||
if left == -1: # 0xFFFFFFFFL:
|
||||
break
|
||||
stack.append(sid)
|
||||
sid = left
|
||||
else:
|
||||
# couldn't move right; move up instead
|
||||
while 1:
|
||||
ptr = stack[-1]
|
||||
del stack[-1]
|
||||
left, right, child = sidlist[ptr][4]
|
||||
if right != sid:
|
||||
break
|
||||
sid = right
|
||||
left, right, child = sidlist[sid][4]
|
||||
if right != ptr:
|
||||
sid = ptr
|
||||
|
||||
# in the OLE file, entries are sorted on (length, name).
|
||||
# for convenience, we sort them on name instead.
|
||||
|
||||
self.kids.sort()
|
||||
|
||||
def __cmp__(self, other):
|
||||
"Compare entries by name"
|
||||
|
||||
return cmp(self.name, other.name)
|
||||
|
||||
def dump(self, tab = 0):
|
||||
"Dump this entry, and all its subentries (for debug purposes only)"
|
||||
|
||||
TYPES = ["(invalid)", "(storage)", "(stream)", "(lockbytes)",
|
||||
"(property)", "(root)"]
|
||||
|
||||
print " "*tab + repr(self.name), TYPES[self.type],
|
||||
if self.type in (2, 5):
|
||||
print self.size, "bytes",
|
||||
print
|
||||
if self.type in (1, 5) and self.clsid:
|
||||
print " "*tab + "{%s}" % self.clsid
|
||||
|
||||
for kid in self.kids:
|
||||
kid.dump(tab + 2)
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
##
|
||||
# This class encapsulates the interface to an OLE 2 structured
|
||||
# storage file. Use the {@link listdir} and {@link openstream}
|
||||
# methods to access the contents of this file.
|
||||
|
||||
class OleFileIO:
|
||||
"""OLE container object
|
||||
|
||||
This class encapsulates the interface to an OLE 2 structured
|
||||
storage file. Use the listdir and openstream methods to access
|
||||
the contents of this file.
|
||||
|
||||
Object names are given as a list of strings, one for each subentry
|
||||
level. The root entry should be omitted. For example, the following
|
||||
code extracts all image streams from a Microsoft Image Composer file:
|
||||
|
||||
ole = OleFileIO("fan.mic")
|
||||
|
||||
for entry in ole.listdir():
|
||||
if entry[1:2] == "Image":
|
||||
fin = ole.openstream(entry)
|
||||
fout = open(entry[0:1], "wb")
|
||||
while 1:
|
||||
s = fin.read(8192)
|
||||
if not s:
|
||||
break
|
||||
fout.write(s)
|
||||
|
||||
You can use the viewer application provided with the Python Imaging
|
||||
Library to view the resulting files (which happens to be standard
|
||||
TIFF files).
|
||||
"""
|
||||
|
||||
def __init__(self, filename = None):
|
||||
|
||||
if filename:
|
||||
self.open(filename)
|
||||
|
||||
##
|
||||
# Open an OLE2 file.
|
||||
|
||||
def open(self, filename):
|
||||
"""Open an OLE2 file"""
|
||||
|
||||
if type(filename) == type(""):
|
||||
self.fp = open(filename, "rb")
|
||||
else:
|
||||
self.fp = filename
|
||||
|
||||
header = self.fp.read(512)
|
||||
|
||||
if len(header) != 512 or header[:8] != MAGIC:
|
||||
raise IOError, "not an OLE2 structured storage file"
|
||||
|
||||
# file clsid (probably never used, so we don't store it)
|
||||
clsid = self._clsid(header[8:24])
|
||||
|
||||
# FIXME: could check version and byte order fields
|
||||
|
||||
self.sectorsize = 1 << i16(header, 30)
|
||||
self.minisectorsize = 1 << i16(header, 32)
|
||||
|
||||
self.minisectorcutoff = i32(header, 56)
|
||||
|
||||
# Load file allocation tables
|
||||
self.loadfat(header)
|
||||
|
||||
# Load direcory. This sets both the sidlist (ordered by id)
|
||||
# and the root (ordered by hierarchy) members.
|
||||
self.loaddirectory(i32(header, 48))
|
||||
|
||||
self.ministream = None
|
||||
self.minifatsect = i32(header, 60)
|
||||
|
||||
def loadfat(self, header):
|
||||
# Load the FAT table. The header contains a sector numbers
|
||||
# for the first 109 FAT sectors. Additional sectors are
|
||||
# described by DIF blocks (FIXME: not yet implemented)
|
||||
|
||||
sect = header[76:512]
|
||||
fat = []
|
||||
for i in range(0, len(sect), 4):
|
||||
ix = i32(sect, i)
|
||||
if ix == -2 or ix == -1: # ix == 0xFFFFFFFEL or ix == 0xFFFFFFFFL:
|
||||
break
|
||||
s = self.getsect(ix)
|
||||
fat = fat + map(lambda i, s=s: i32(s, i), range(0, len(s), 4))
|
||||
self.fat = fat
|
||||
|
||||
def loadminifat(self):
|
||||
# Load the MINIFAT table. This is stored in a standard sub-
|
||||
# stream, pointed to by a header field.
|
||||
|
||||
s = self._open(self.minifatsect).read()
|
||||
|
||||
self.minifat = map(lambda i, s=s: i32(s, i), range(0, len(s), 4))
|
||||
|
||||
def getsect(self, sect):
|
||||
# Read given sector
|
||||
|
||||
self.fp.seek(512 + self.sectorsize * sect)
|
||||
return self.fp.read(self.sectorsize)
|
||||
|
||||
def _unicode(self, s):
|
||||
# Map unicode string to Latin 1
|
||||
|
||||
# FIXME: some day, Python will provide an official way to handle
|
||||
# Unicode strings, but until then, this will have to do...
|
||||
return filter(ord, s)
|
||||
|
||||
def loaddirectory(self, sect):
|
||||
# Load the directory. The directory is stored in a standard
|
||||
# substream, independent of its size.
|
||||
|
||||
# read directory stream
|
||||
fp = self._open(sect)
|
||||
|
||||
# create list of sid entries
|
||||
self.sidlist = []
|
||||
while 1:
|
||||
entry = fp.read(128)
|
||||
if not entry:
|
||||
break
|
||||
type = ord(entry[66])
|
||||
name = self._unicode(entry[0:0+i16(entry, 64)])
|
||||
ptrs = i32(entry, 68), i32(entry, 72), i32(entry, 76)
|
||||
sect, size = i32(entry, 116), i32(entry, 120)
|
||||
clsid = self._clsid(entry[80:96])
|
||||
self.sidlist.append((name, type, sect, size, ptrs, clsid))
|
||||
|
||||
# create hierarchical list of directory entries
|
||||
self.root = _OleDirectoryEntry(self.sidlist, 0)
|
||||
|
||||
def dumpdirectory(self):
|
||||
# Dump directory (for debugging only)
|
||||
|
||||
self.root.dump()
|
||||
|
||||
def _clsid(self, clsid):
|
||||
if clsid == "\0" * len(clsid):
|
||||
return ""
|
||||
return (("%08X-%04X-%04X-%02X%02X-" + "%02X" * 6) %
|
||||
((i32(clsid, 0), i16(clsid, 4), i16(clsid, 6)) +
|
||||
tuple(map(ord, clsid[8:16]))))
|
||||
|
||||
def _list(self, files, prefix, node):
|
||||
# listdir helper
|
||||
|
||||
prefix = prefix + [node.name]
|
||||
for entry in node.kids:
|
||||
if entry.kids:
|
||||
self._list(files, prefix, entry)
|
||||
else:
|
||||
files.append(prefix[1:] + [entry.name])
|
||||
|
||||
def _find(self, filename):
|
||||
# openstream helper
|
||||
|
||||
node = self.root
|
||||
for name in filename:
|
||||
for kid in node.kids:
|
||||
if kid.name == name:
|
||||
break
|
||||
else:
|
||||
raise IOError, "file not found"
|
||||
node = kid
|
||||
return node.sid
|
||||
|
||||
def _open(self, start, size = 0x7FFFFFFF):
|
||||
# openstream helper.
|
||||
|
||||
if size < self.minisectorcutoff:
|
||||
# ministream object
|
||||
if not self.ministream:
|
||||
self.loadminifat()
|
||||
self.ministream = self._open(self.sidlist[0][2])
|
||||
return _OleStream(self.ministream, start, size, 0,
|
||||
self.minisectorsize, self.minifat)
|
||||
|
||||
# standard stream
|
||||
return _OleStream(self.fp, start, size, 512,
|
||||
self.sectorsize, self.fat)
|
||||
|
||||
##
|
||||
# Returns a list of streams stored in this file.
|
||||
|
||||
def listdir(self):
|
||||
"""Return a list of streams stored in this file"""
|
||||
|
||||
files = []
|
||||
self._list(files, [], self.root)
|
||||
return files
|
||||
|
||||
##
|
||||
# Opens a stream as a read-only file object.
|
||||
|
||||
def openstream(self, filename):
|
||||
"""Open a stream as a read-only file object"""
|
||||
|
||||
slot = self._find(filename)
|
||||
name, type, sect, size, sids, clsid = self.sidlist[slot]
|
||||
if type != 2:
|
||||
raise IOError, "this file is not a stream"
|
||||
return self._open(sect, size)
|
||||
|
||||
##
|
||||
# Gets a list of properties described in substream.
|
||||
|
||||
def getproperties(self, filename):
|
||||
"""Return properties described in substream"""
|
||||
|
||||
fp = self.openstream(filename)
|
||||
|
||||
data = {}
|
||||
|
||||
# header
|
||||
s = fp.read(28)
|
||||
clsid = self._clsid(s[8:24])
|
||||
|
||||
# format id
|
||||
s = fp.read(20)
|
||||
fmtid = self._clsid(s[:16])
|
||||
fp.seek(i32(s, 16))
|
||||
|
||||
# get section
|
||||
s = "****" + fp.read(i32(fp.read(4))-4)
|
||||
|
||||
for i in range(i32(s, 4)):
|
||||
|
||||
id = i32(s, 8+i*8)
|
||||
offset = i32(s, 12+i*8)
|
||||
type = i32(s, offset)
|
||||
|
||||
# test for common types first (should perhaps use
|
||||
# a dictionary instead?)
|
||||
|
||||
if type == VT_I2:
|
||||
value = i16(s, offset+4)
|
||||
if value >= 32768:
|
||||
value = value - 65536
|
||||
elif type == VT_UI2:
|
||||
value = i16(s, offset+4)
|
||||
elif type in (VT_I4, VT_ERROR):
|
||||
value = i32(s, offset+4)
|
||||
elif type == VT_UI4:
|
||||
value = i32(s, offset+4) # FIXME
|
||||
elif type in (VT_BSTR, VT_LPSTR):
|
||||
count = i32(s, offset+4)
|
||||
value = s[offset+8:offset+8+count-1]
|
||||
elif type == VT_BLOB:
|
||||
count = i32(s, offset+4)
|
||||
value = s[offset+8:offset+8+count]
|
||||
elif type == VT_LPWSTR:
|
||||
count = i32(s, offset+4)
|
||||
value = self._unicode(s[offset+8:offset+8+count*2])
|
||||
elif type == VT_FILETIME:
|
||||
value = long(i32(s, offset+4)) + (long(i32(s, offset+8))<<32)
|
||||
# FIXME: this is a 64-bit int: "number of 100ns periods
|
||||
# since Jan 1,1601". Should map this to Python time
|
||||
value = value / 10000000L # seconds
|
||||
elif type == VT_UI1:
|
||||
value = ord(s[offset+4])
|
||||
elif type == VT_CLSID:
|
||||
value = self._clsid(s[offset+4:offset+20])
|
||||
elif type == VT_CF:
|
||||
count = i32(s, offset+4)
|
||||
value = s[offset+8:offset+8+count]
|
||||
else:
|
||||
value = None # everything else yields "None"
|
||||
|
||||
# FIXME: add support for VT_VECTOR
|
||||
|
||||
#print "%08x" % id, repr(value),
|
||||
#print "(%s)" % VT[i32(s, offset) & 0xFFF]
|
||||
|
||||
data[id] = value
|
||||
|
||||
return data
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# This script can be used to dump the directory of any OLE2 structured
|
||||
# storage file.
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import sys
|
||||
|
||||
for file in sys.argv[1:]:
|
||||
try:
|
||||
ole = OleFileIO(file)
|
||||
print "-" * 68
|
||||
print file
|
||||
print "-" * 68
|
||||
ole.dumpdirectory()
|
||||
for file in ole.listdir():
|
||||
if file[-1][0] == "\005":
|
||||
print file
|
||||
props = ole.getproperties(file)
|
||||
props = props.items()
|
||||
props.sort()
|
||||
for k, v in props:
|
||||
print " ", k, v
|
||||
except IOError, v:
|
||||
print "***", "cannot read", file, "-", v
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
Metadata-Version: 1.1
|
||||
Name: PIL
|
||||
Version: 1.1.7
|
||||
Summary: Python Imaging Library
|
||||
Home-page: http://www.pythonware.com/products/pil
|
||||
Author: Secret Labs AB (PythonWare)
|
||||
Author-email: info@pythonware.com
|
||||
License: Python (MIT style)
|
||||
Download-URL: http://effbot.org/downloads/PIL-1.1.7.tar.gz
|
||||
Description: Python Imaging Library
|
||||
Platform: Python 1.5.2 and later.
|
||||
Classifier: Development Status :: 6 - Mature
|
||||
Classifier: Topic :: Multimedia :: Graphics
|
||||
Classifier: Topic :: Multimedia :: Graphics :: Capture :: Digital Camera
|
||||
Classifier: Topic :: Multimedia :: Graphics :: Capture :: Scanners
|
||||
Classifier: Topic :: Multimedia :: Graphics :: Capture :: Screen Capture
|
||||
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
|
||||
Classifier: Topic :: Multimedia :: Graphics :: Viewers
|
||||
199
Darwin/lib/python2.7/site-packages/PIL/PSDraw.py
Normal file
199
Darwin/lib/python2.7/site-packages/PIL/PSDraw.py
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# simple postscript graphics interface
|
||||
#
|
||||
# History:
|
||||
# 1996-04-20 fl Created
|
||||
# 1999-01-10 fl Added gsave/grestore to image method
|
||||
# 2005-05-04 fl Fixed floating point issue in image (from Eric Etheridge)
|
||||
#
|
||||
# Copyright (c) 1997-2005 by Secret Labs AB. All rights reserved.
|
||||
# Copyright (c) 1996 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import EpsImagePlugin
|
||||
import string
|
||||
|
||||
##
|
||||
# Simple Postscript graphics interface.
|
||||
|
||||
class PSDraw:
|
||||
|
||||
def __init__(self, fp=None):
|
||||
if not fp:
|
||||
import sys
|
||||
fp = sys.stdout
|
||||
self.fp = fp
|
||||
|
||||
def begin_document(self, id = None):
|
||||
"Write Postscript DSC header"
|
||||
# FIXME: incomplete
|
||||
self.fp.write("%!PS-Adobe-3.0\n"
|
||||
"save\n"
|
||||
"/showpage { } def\n"
|
||||
"%%EndComments\n"
|
||||
"%%BeginDocument\n")
|
||||
#self.fp.write(ERROR_PS) # debugging!
|
||||
self.fp.write(EDROFF_PS)
|
||||
self.fp.write(VDI_PS)
|
||||
self.fp.write("%%EndProlog\n")
|
||||
self.isofont = {}
|
||||
|
||||
def end_document(self):
|
||||
"Write Postscript DSC footer"
|
||||
self.fp.write("%%EndDocument\n"
|
||||
"restore showpage\n"
|
||||
"%%End\n")
|
||||
if hasattr(self.fp, "flush"):
|
||||
self.fp.flush()
|
||||
|
||||
def setfont(self, font, size):
|
||||
if not self.isofont.has_key(font):
|
||||
# reencode font
|
||||
self.fp.write("/PSDraw-%s ISOLatin1Encoding /%s E\n" %\
|
||||
(font, font))
|
||||
self.isofont[font] = 1
|
||||
# rough
|
||||
self.fp.write("/F0 %d /PSDraw-%s F\n" % (size, font))
|
||||
|
||||
def setink(self, ink):
|
||||
print "*** NOT YET IMPLEMENTED ***"
|
||||
|
||||
def line(self, xy0, xy1):
|
||||
xy = xy0 + xy1
|
||||
self.fp.write("%d %d %d %d Vl\n" % xy)
|
||||
|
||||
def rectangle(self, box):
|
||||
self.fp.write("%d %d M %d %d 0 Vr\n" % box)
|
||||
|
||||
def text(self, xy, text):
|
||||
text = string.joinfields(string.splitfields(text, "("), "\\(")
|
||||
text = string.joinfields(string.splitfields(text, ")"), "\\)")
|
||||
xy = xy + (text,)
|
||||
self.fp.write("%d %d M (%s) S\n" % xy)
|
||||
|
||||
def image(self, box, im, dpi = None):
|
||||
"Write an PIL image"
|
||||
# default resolution depends on mode
|
||||
if not dpi:
|
||||
if im.mode == "1":
|
||||
dpi = 200 # fax
|
||||
else:
|
||||
dpi = 100 # greyscale
|
||||
# image size (on paper)
|
||||
x = float(im.size[0] * 72) / dpi
|
||||
y = float(im.size[1] * 72) / dpi
|
||||
# max allowed size
|
||||
xmax = float(box[2] - box[0])
|
||||
ymax = float(box[3] - box[1])
|
||||
if x > xmax:
|
||||
y = y * xmax / x; x = xmax
|
||||
if y > ymax:
|
||||
x = x * ymax / y; y = ymax
|
||||
dx = (xmax - x) / 2 + box[0]
|
||||
dy = (ymax - y) / 2 + box[1]
|
||||
self.fp.write("gsave\n%f %f translate\n" % (dx, dy))
|
||||
if (x, y) != im.size:
|
||||
# EpsImagePlugin._save prints the image at (0,0,xsize,ysize)
|
||||
sx = x / im.size[0]
|
||||
sy = y / im.size[1]
|
||||
self.fp.write("%f %f scale\n" % (sx, sy))
|
||||
EpsImagePlugin._save(im, self.fp, None, 0)
|
||||
self.fp.write("\ngrestore\n")
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Postscript driver
|
||||
|
||||
#
|
||||
# EDROFF.PS -- Postscript driver for Edroff 2
|
||||
#
|
||||
# History:
|
||||
# 94-01-25 fl: created (edroff 2.04)
|
||||
#
|
||||
# Copyright (c) Fredrik Lundh 1994.
|
||||
#
|
||||
|
||||
EDROFF_PS = """\
|
||||
/S { show } bind def
|
||||
/P { moveto show } bind def
|
||||
/M { moveto } bind def
|
||||
/X { 0 rmoveto } bind def
|
||||
/Y { 0 exch rmoveto } bind def
|
||||
/E { findfont
|
||||
dup maxlength dict begin
|
||||
{
|
||||
1 index /FID ne { def } { pop pop } ifelse
|
||||
} forall
|
||||
/Encoding exch def
|
||||
dup /FontName exch def
|
||||
currentdict end definefont pop
|
||||
} bind def
|
||||
/F { findfont exch scalefont dup setfont
|
||||
[ exch /setfont cvx ] cvx bind def
|
||||
} bind def
|
||||
"""
|
||||
|
||||
#
|
||||
# VDI.PS -- Postscript driver for VDI meta commands
|
||||
#
|
||||
# History:
|
||||
# 94-01-25 fl: created (edroff 2.04)
|
||||
#
|
||||
# Copyright (c) Fredrik Lundh 1994.
|
||||
#
|
||||
|
||||
VDI_PS = """\
|
||||
/Vm { moveto } bind def
|
||||
/Va { newpath arcn stroke } bind def
|
||||
/Vl { moveto lineto stroke } bind def
|
||||
/Vc { newpath 0 360 arc closepath } bind def
|
||||
/Vr { exch dup 0 rlineto
|
||||
exch dup neg 0 exch rlineto
|
||||
exch neg 0 rlineto
|
||||
0 exch rlineto
|
||||
100 div setgray fill 0 setgray } bind def
|
||||
/Tm matrix def
|
||||
/Ve { Tm currentmatrix pop
|
||||
translate scale newpath 0 0 .5 0 360 arc closepath
|
||||
Tm setmatrix
|
||||
} bind def
|
||||
/Vf { currentgray exch setgray fill setgray } bind def
|
||||
"""
|
||||
|
||||
#
|
||||
# ERROR.PS -- Error handler
|
||||
#
|
||||
# History:
|
||||
# 89-11-21 fl: created (pslist 1.10)
|
||||
#
|
||||
|
||||
ERROR_PS = """\
|
||||
/landscape false def
|
||||
/errorBUF 200 string def
|
||||
/errorNL { currentpoint 10 sub exch pop 72 exch moveto } def
|
||||
errordict begin /handleerror {
|
||||
initmatrix /Courier findfont 10 scalefont setfont
|
||||
newpath 72 720 moveto $error begin /newerror false def
|
||||
(PostScript Error) show errorNL errorNL
|
||||
(Error: ) show
|
||||
/errorname load errorBUF cvs show errorNL errorNL
|
||||
(Command: ) show
|
||||
/command load dup type /stringtype ne { errorBUF cvs } if show
|
||||
errorNL errorNL
|
||||
(VMstatus: ) show
|
||||
vmstatus errorBUF cvs show ( bytes available, ) show
|
||||
errorBUF cvs show ( bytes used at level ) show
|
||||
errorBUF cvs show errorNL errorNL
|
||||
(Operand stargck: ) show errorNL /ostargck load {
|
||||
dup type /stringtype ne { errorBUF cvs } if 72 0 rmoveto show errorNL
|
||||
} forall errorNL
|
||||
(Execution stargck: ) show errorNL /estargck load {
|
||||
dup type /stringtype ne { errorBUF cvs } if 72 0 rmoveto show errorNL
|
||||
} forall
|
||||
end showpage
|
||||
} def end
|
||||
"""
|
||||
55
Darwin/lib/python2.7/site-packages/PIL/PaletteFile.py
Normal file
55
Darwin/lib/python2.7/site-packages/PIL/PaletteFile.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#
|
||||
# Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# stuff to read simple, teragon-style palette files
|
||||
#
|
||||
# History:
|
||||
# 97-08-23 fl Created
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1997.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import string
|
||||
|
||||
##
|
||||
# File handler for Teragon-style palette files.
|
||||
|
||||
class PaletteFile:
|
||||
|
||||
rawmode = "RGB"
|
||||
|
||||
def __init__(self, fp):
|
||||
|
||||
self.palette = map(lambda i: (i, i, i), range(256))
|
||||
|
||||
while 1:
|
||||
|
||||
s = fp.readline()
|
||||
|
||||
if not s:
|
||||
break
|
||||
if s[0] == "#":
|
||||
continue
|
||||
if len(s) > 100:
|
||||
raise SyntaxError, "bad palette file"
|
||||
|
||||
v = map(int, string.split(s))
|
||||
try:
|
||||
[i, r, g, b] = v
|
||||
except ValueError:
|
||||
[i, r] = v
|
||||
g = b = r
|
||||
|
||||
if 0 <= i <= 255:
|
||||
self.palette[i] = chr(r) + chr(g) + chr(b)
|
||||
|
||||
self.palette = string.join(self.palette, "")
|
||||
|
||||
|
||||
def getpalette(self):
|
||||
|
||||
return self.palette, self.rawmode
|
||||
225
Darwin/lib/python2.7/site-packages/PIL/PalmImagePlugin.py
Normal file
225
Darwin/lib/python2.7/site-packages/PIL/PalmImagePlugin.py
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
|
||||
##
|
||||
# Image plugin for Palm pixmap images (output only).
|
||||
##
|
||||
|
||||
__version__ = "1.0"
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
_Palm8BitColormapValues = (
|
||||
( 255, 255, 255 ), ( 255, 204, 255 ), ( 255, 153, 255 ), ( 255, 102, 255 ),
|
||||
( 255, 51, 255 ), ( 255, 0, 255 ), ( 255, 255, 204 ), ( 255, 204, 204 ),
|
||||
( 255, 153, 204 ), ( 255, 102, 204 ), ( 255, 51, 204 ), ( 255, 0, 204 ),
|
||||
( 255, 255, 153 ), ( 255, 204, 153 ), ( 255, 153, 153 ), ( 255, 102, 153 ),
|
||||
( 255, 51, 153 ), ( 255, 0, 153 ), ( 204, 255, 255 ), ( 204, 204, 255 ),
|
||||
( 204, 153, 255 ), ( 204, 102, 255 ), ( 204, 51, 255 ), ( 204, 0, 255 ),
|
||||
( 204, 255, 204 ), ( 204, 204, 204 ), ( 204, 153, 204 ), ( 204, 102, 204 ),
|
||||
( 204, 51, 204 ), ( 204, 0, 204 ), ( 204, 255, 153 ), ( 204, 204, 153 ),
|
||||
( 204, 153, 153 ), ( 204, 102, 153 ), ( 204, 51, 153 ), ( 204, 0, 153 ),
|
||||
( 153, 255, 255 ), ( 153, 204, 255 ), ( 153, 153, 255 ), ( 153, 102, 255 ),
|
||||
( 153, 51, 255 ), ( 153, 0, 255 ), ( 153, 255, 204 ), ( 153, 204, 204 ),
|
||||
( 153, 153, 204 ), ( 153, 102, 204 ), ( 153, 51, 204 ), ( 153, 0, 204 ),
|
||||
( 153, 255, 153 ), ( 153, 204, 153 ), ( 153, 153, 153 ), ( 153, 102, 153 ),
|
||||
( 153, 51, 153 ), ( 153, 0, 153 ), ( 102, 255, 255 ), ( 102, 204, 255 ),
|
||||
( 102, 153, 255 ), ( 102, 102, 255 ), ( 102, 51, 255 ), ( 102, 0, 255 ),
|
||||
( 102, 255, 204 ), ( 102, 204, 204 ), ( 102, 153, 204 ), ( 102, 102, 204 ),
|
||||
( 102, 51, 204 ), ( 102, 0, 204 ), ( 102, 255, 153 ), ( 102, 204, 153 ),
|
||||
( 102, 153, 153 ), ( 102, 102, 153 ), ( 102, 51, 153 ), ( 102, 0, 153 ),
|
||||
( 51, 255, 255 ), ( 51, 204, 255 ), ( 51, 153, 255 ), ( 51, 102, 255 ),
|
||||
( 51, 51, 255 ), ( 51, 0, 255 ), ( 51, 255, 204 ), ( 51, 204, 204 ),
|
||||
( 51, 153, 204 ), ( 51, 102, 204 ), ( 51, 51, 204 ), ( 51, 0, 204 ),
|
||||
( 51, 255, 153 ), ( 51, 204, 153 ), ( 51, 153, 153 ), ( 51, 102, 153 ),
|
||||
( 51, 51, 153 ), ( 51, 0, 153 ), ( 0, 255, 255 ), ( 0, 204, 255 ),
|
||||
( 0, 153, 255 ), ( 0, 102, 255 ), ( 0, 51, 255 ), ( 0, 0, 255 ),
|
||||
( 0, 255, 204 ), ( 0, 204, 204 ), ( 0, 153, 204 ), ( 0, 102, 204 ),
|
||||
( 0, 51, 204 ), ( 0, 0, 204 ), ( 0, 255, 153 ), ( 0, 204, 153 ),
|
||||
( 0, 153, 153 ), ( 0, 102, 153 ), ( 0, 51, 153 ), ( 0, 0, 153 ),
|
||||
( 255, 255, 102 ), ( 255, 204, 102 ), ( 255, 153, 102 ), ( 255, 102, 102 ),
|
||||
( 255, 51, 102 ), ( 255, 0, 102 ), ( 255, 255, 51 ), ( 255, 204, 51 ),
|
||||
( 255, 153, 51 ), ( 255, 102, 51 ), ( 255, 51, 51 ), ( 255, 0, 51 ),
|
||||
( 255, 255, 0 ), ( 255, 204, 0 ), ( 255, 153, 0 ), ( 255, 102, 0 ),
|
||||
( 255, 51, 0 ), ( 255, 0, 0 ), ( 204, 255, 102 ), ( 204, 204, 102 ),
|
||||
( 204, 153, 102 ), ( 204, 102, 102 ), ( 204, 51, 102 ), ( 204, 0, 102 ),
|
||||
( 204, 255, 51 ), ( 204, 204, 51 ), ( 204, 153, 51 ), ( 204, 102, 51 ),
|
||||
( 204, 51, 51 ), ( 204, 0, 51 ), ( 204, 255, 0 ), ( 204, 204, 0 ),
|
||||
( 204, 153, 0 ), ( 204, 102, 0 ), ( 204, 51, 0 ), ( 204, 0, 0 ),
|
||||
( 153, 255, 102 ), ( 153, 204, 102 ), ( 153, 153, 102 ), ( 153, 102, 102 ),
|
||||
( 153, 51, 102 ), ( 153, 0, 102 ), ( 153, 255, 51 ), ( 153, 204, 51 ),
|
||||
( 153, 153, 51 ), ( 153, 102, 51 ), ( 153, 51, 51 ), ( 153, 0, 51 ),
|
||||
( 153, 255, 0 ), ( 153, 204, 0 ), ( 153, 153, 0 ), ( 153, 102, 0 ),
|
||||
( 153, 51, 0 ), ( 153, 0, 0 ), ( 102, 255, 102 ), ( 102, 204, 102 ),
|
||||
( 102, 153, 102 ), ( 102, 102, 102 ), ( 102, 51, 102 ), ( 102, 0, 102 ),
|
||||
( 102, 255, 51 ), ( 102, 204, 51 ), ( 102, 153, 51 ), ( 102, 102, 51 ),
|
||||
( 102, 51, 51 ), ( 102, 0, 51 ), ( 102, 255, 0 ), ( 102, 204, 0 ),
|
||||
( 102, 153, 0 ), ( 102, 102, 0 ), ( 102, 51, 0 ), ( 102, 0, 0 ),
|
||||
( 51, 255, 102 ), ( 51, 204, 102 ), ( 51, 153, 102 ), ( 51, 102, 102 ),
|
||||
( 51, 51, 102 ), ( 51, 0, 102 ), ( 51, 255, 51 ), ( 51, 204, 51 ),
|
||||
( 51, 153, 51 ), ( 51, 102, 51 ), ( 51, 51, 51 ), ( 51, 0, 51 ),
|
||||
( 51, 255, 0 ), ( 51, 204, 0 ), ( 51, 153, 0 ), ( 51, 102, 0 ),
|
||||
( 51, 51, 0 ), ( 51, 0, 0 ), ( 0, 255, 102 ), ( 0, 204, 102 ),
|
||||
( 0, 153, 102 ), ( 0, 102, 102 ), ( 0, 51, 102 ), ( 0, 0, 102 ),
|
||||
( 0, 255, 51 ), ( 0, 204, 51 ), ( 0, 153, 51 ), ( 0, 102, 51 ),
|
||||
( 0, 51, 51 ), ( 0, 0, 51 ), ( 0, 255, 0 ), ( 0, 204, 0 ),
|
||||
( 0, 153, 0 ), ( 0, 102, 0 ), ( 0, 51, 0 ), ( 17, 17, 17 ),
|
||||
( 34, 34, 34 ), ( 68, 68, 68 ), ( 85, 85, 85 ), ( 119, 119, 119 ),
|
||||
( 136, 136, 136 ), ( 170, 170, 170 ), ( 187, 187, 187 ), ( 221, 221, 221 ),
|
||||
( 238, 238, 238 ), ( 192, 192, 192 ), ( 128, 0, 0 ), ( 128, 0, 128 ),
|
||||
( 0, 128, 0 ), ( 0, 128, 128 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
|
||||
( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
|
||||
( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
|
||||
( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
|
||||
( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
|
||||
( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ),
|
||||
( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ), ( 0, 0, 0 ))
|
||||
|
||||
# so build a prototype image to be used for palette resampling
|
||||
def build_prototype_image():
|
||||
image = Image.new("L", (1,len(_Palm8BitColormapValues),))
|
||||
image.putdata(range(len(_Palm8BitColormapValues)))
|
||||
palettedata = ()
|
||||
for i in range(len(_Palm8BitColormapValues)):
|
||||
palettedata = palettedata + _Palm8BitColormapValues[i]
|
||||
for i in range(256 - len(_Palm8BitColormapValues)):
|
||||
palettedata = palettedata + (0, 0, 0)
|
||||
image.putpalette(palettedata)
|
||||
return image
|
||||
|
||||
Palm8BitColormapImage = build_prototype_image()
|
||||
|
||||
# OK, we now have in Palm8BitColormapImage, a "P"-mode image with the right palette
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
_FLAGS = {
|
||||
"custom-colormap": 0x4000,
|
||||
"is-compressed": 0x8000,
|
||||
"has-transparent": 0x2000,
|
||||
}
|
||||
|
||||
_COMPRESSION_TYPES = {
|
||||
"none": 0xFF,
|
||||
"rle": 0x01,
|
||||
"scanline": 0x00,
|
||||
}
|
||||
|
||||
def o16b(i):
|
||||
return chr(i>>8&255) + chr(i&255)
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
##
|
||||
# (Internal) Image save plugin for the Palm format.
|
||||
|
||||
def _save(im, fp, filename, check=0):
|
||||
|
||||
if im.mode == "P":
|
||||
|
||||
# we assume this is a color Palm image with the standard colormap,
|
||||
# unless the "info" dict has a "custom-colormap" field
|
||||
|
||||
rawmode = "P"
|
||||
bpp = 8
|
||||
version = 1
|
||||
|
||||
elif im.mode == "L" and im.encoderinfo.has_key("bpp") and im.encoderinfo["bpp"] in (1, 2, 4):
|
||||
|
||||
# this is 8-bit grayscale, so we shift it to get the high-order bits, and invert it because
|
||||
# Palm does greyscale from white (0) to black (1)
|
||||
bpp = im.encoderinfo["bpp"]
|
||||
im = im.point(lambda x, shift=8-bpp, maxval=(1 << bpp)-1: maxval - (x >> shift))
|
||||
# we ignore the palette here
|
||||
im.mode = "P"
|
||||
rawmode = "P;" + str(bpp)
|
||||
version = 1
|
||||
|
||||
elif im.mode == "L" and im.info.has_key("bpp") and im.info["bpp"] in (1, 2, 4):
|
||||
|
||||
# here we assume that even though the inherent mode is 8-bit grayscale, only
|
||||
# the lower bpp bits are significant. We invert them to match the Palm.
|
||||
bpp = im.info["bpp"]
|
||||
im = im.point(lambda x, maxval=(1 << bpp)-1: maxval - (x & maxval))
|
||||
# we ignore the palette here
|
||||
im.mode = "P"
|
||||
rawmode = "P;" + str(bpp)
|
||||
version = 1
|
||||
|
||||
elif im.mode == "1":
|
||||
|
||||
# monochrome -- write it inverted, as is the Palm standard
|
||||
rawmode = "1;I"
|
||||
bpp = 1
|
||||
version = 0
|
||||
|
||||
else:
|
||||
|
||||
raise IOError, "cannot write mode %s as Palm" % im.mode
|
||||
|
||||
if check:
|
||||
return check
|
||||
|
||||
#
|
||||
# make sure image data is available
|
||||
im.load()
|
||||
|
||||
# write header
|
||||
|
||||
cols = im.size[0]
|
||||
rows = im.size[1]
|
||||
|
||||
rowbytes = ((cols + (16/bpp - 1)) / (16 / bpp)) * 2;
|
||||
transparent_index = 0
|
||||
compression_type = _COMPRESSION_TYPES["none"]
|
||||
|
||||
flags = 0;
|
||||
if im.mode == "P" and im.info.has_key("custom-colormap"):
|
||||
flags = flags & _FLAGS["custom-colormap"]
|
||||
colormapsize = 4 * 256 + 2;
|
||||
colormapmode = im.palette.mode
|
||||
colormap = im.getdata().getpalette()
|
||||
else:
|
||||
colormapsize = 0
|
||||
|
||||
if im.info.has_key("offset"):
|
||||
offset = (rowbytes * rows + 16 + 3 + colormapsize) / 4;
|
||||
else:
|
||||
offset = 0
|
||||
|
||||
fp.write(o16b(cols) + o16b(rows) + o16b(rowbytes) + o16b(flags))
|
||||
fp.write(chr(bpp))
|
||||
fp.write(chr(version))
|
||||
fp.write(o16b(offset))
|
||||
fp.write(chr(transparent_index))
|
||||
fp.write(chr(compression_type))
|
||||
fp.write(o16b(0)) # reserved by Palm
|
||||
|
||||
# now write colormap if necessary
|
||||
|
||||
if colormapsize > 0:
|
||||
fp.write(o16b(256))
|
||||
for i in range(256):
|
||||
fp.write(chr(i))
|
||||
if colormapmode == 'RGB':
|
||||
fp.write(chr(colormap[3 * i]) + chr(colormap[3 * i + 1]) + chr(colormap[3 * i + 2]))
|
||||
elif colormapmode == 'RGBA':
|
||||
fp.write(chr(colormap[4 * i]) + chr(colormap[4 * i + 1]) + chr(colormap[4 * i + 2]))
|
||||
|
||||
# now convert data to raw form
|
||||
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, rowbytes, 1))])
|
||||
|
||||
fp.flush()
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_save("Palm", _save)
|
||||
|
||||
Image.register_extension("Palm", ".palm")
|
||||
|
||||
Image.register_mime("Palm", "image/palm")
|
||||
76
Darwin/lib/python2.7/site-packages/PIL/PcdImagePlugin.py
Normal file
76
Darwin/lib/python2.7/site-packages/PIL/PcdImagePlugin.py
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# PCD file handling
|
||||
#
|
||||
# History:
|
||||
# 96-05-10 fl Created
|
||||
# 96-05-27 fl Added draft mode (128x192, 256x384)
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1996.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.1"
|
||||
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
##
|
||||
# Image plugin for PhotoCD images. This plugin only reads the 768x512
|
||||
# image from the file; higher resolutions are encoded in a proprietary
|
||||
# encoding.
|
||||
|
||||
class PcdImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "PCD"
|
||||
format_description = "Kodak PhotoCD"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# rough
|
||||
self.fp.seek(2048)
|
||||
s = self.fp.read(2048)
|
||||
|
||||
if s[:4] != "PCD_":
|
||||
raise SyntaxError, "not a PCD file"
|
||||
|
||||
orientation = ord(s[1538]) & 3
|
||||
if orientation == 1:
|
||||
self.tile_post_rotate = 90 # hack
|
||||
elif orientation == 3:
|
||||
self.tile_post_rotate = -90
|
||||
|
||||
self.mode = "RGB"
|
||||
self.size = 768, 512 # FIXME: not correct for rotated images!
|
||||
self.tile = [("pcd", (0,0)+self.size, 96*2048, None)]
|
||||
|
||||
def draft(self, mode, size):
|
||||
|
||||
if len(self.tile) != 1:
|
||||
return
|
||||
|
||||
d, e, o, a = self.tile[0]
|
||||
|
||||
if size:
|
||||
scale = max(self.size[0] / size[0], self.size[1] / size[1])
|
||||
for s, o in [(4,0*2048), (2,0*2048), (1,96*2048)]:
|
||||
if scale >= s:
|
||||
break
|
||||
# e = e[0], e[1], (e[2]-e[0]+s-1)/s+e[0], (e[3]-e[1]+s-1)/s+e[1]
|
||||
# self.size = ((self.size[0]+s-1)/s, (self.size[1]+s-1)/s)
|
||||
|
||||
self.tile = [(d, e, o, a)]
|
||||
|
||||
return self
|
||||
|
||||
#
|
||||
# registry
|
||||
|
||||
Image.register_open("PCD", PcdImageFile)
|
||||
|
||||
Image.register_extension("PCD", ".pcd")
|
||||
256
Darwin/lib/python2.7/site-packages/PIL/PcfFontFile.py
Normal file
256
Darwin/lib/python2.7/site-packages/PIL/PcfFontFile.py
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
#
|
||||
# THIS IS WORK IN PROGRESS
|
||||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# portable compiled font file parser
|
||||
#
|
||||
# history:
|
||||
# 1997-08-19 fl created
|
||||
# 2003-09-13 fl fixed loading of unicode fonts
|
||||
#
|
||||
# Copyright (c) 1997-2003 by Secret Labs AB.
|
||||
# Copyright (c) 1997-2003 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import Image
|
||||
import FontFile
|
||||
|
||||
import string
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# declarations
|
||||
|
||||
PCF_MAGIC = 0x70636601 # "\x01fcp"
|
||||
|
||||
PCF_PROPERTIES = (1<<0)
|
||||
PCF_ACCELERATORS = (1<<1)
|
||||
PCF_METRICS = (1<<2)
|
||||
PCF_BITMAPS = (1<<3)
|
||||
PCF_INK_METRICS = (1<<4)
|
||||
PCF_BDF_ENCODINGS = (1<<5)
|
||||
PCF_SWIDTHS = (1<<6)
|
||||
PCF_GLYPH_NAMES = (1<<7)
|
||||
PCF_BDF_ACCELERATORS = (1<<8)
|
||||
|
||||
BYTES_PER_ROW = [
|
||||
lambda bits: ((bits+7) >> 3),
|
||||
lambda bits: ((bits+15) >> 3) & ~1,
|
||||
lambda bits: ((bits+31) >> 3) & ~3,
|
||||
lambda bits: ((bits+63) >> 3) & ~7,
|
||||
]
|
||||
|
||||
|
||||
def l16(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8)
|
||||
def l32(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
|
||||
|
||||
def b16(c):
|
||||
return ord(c[1]) + (ord(c[0])<<8)
|
||||
def b32(c):
|
||||
return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
|
||||
|
||||
def sz(s, o):
|
||||
return s[o:string.index(s, "\0", o)]
|
||||
|
||||
##
|
||||
# Font file plugin for the X11 PCF format.
|
||||
|
||||
class PcfFontFile(FontFile.FontFile):
|
||||
|
||||
name = "name"
|
||||
|
||||
def __init__(self, fp):
|
||||
|
||||
magic = l32(fp.read(4))
|
||||
if magic != PCF_MAGIC:
|
||||
raise SyntaxError, "not a PCF file"
|
||||
|
||||
FontFile.FontFile.__init__(self)
|
||||
|
||||
count = l32(fp.read(4))
|
||||
self.toc = {}
|
||||
for i in range(count):
|
||||
type = l32(fp.read(4))
|
||||
self.toc[type] = l32(fp.read(4)), l32(fp.read(4)), l32(fp.read(4))
|
||||
|
||||
self.fp = fp
|
||||
|
||||
self.info = self._load_properties()
|
||||
|
||||
metrics = self._load_metrics()
|
||||
bitmaps = self._load_bitmaps(metrics)
|
||||
encoding = self._load_encoding()
|
||||
|
||||
#
|
||||
# create glyph structure
|
||||
|
||||
for ch in range(256):
|
||||
ix = encoding[ch]
|
||||
if ix is not None:
|
||||
x, y, l, r, w, a, d, f = metrics[ix]
|
||||
glyph = (w, 0), (l, d-y, x+l, d), (0, 0, x, y), bitmaps[ix]
|
||||
self.glyph[ch] = glyph
|
||||
|
||||
def _getformat(self, tag):
|
||||
|
||||
format, size, offset = self.toc[tag]
|
||||
|
||||
fp = self.fp
|
||||
fp.seek(offset)
|
||||
|
||||
format = l32(fp.read(4))
|
||||
|
||||
if format & 4:
|
||||
i16, i32 = b16, b32
|
||||
else:
|
||||
i16, i32 = l16, l32
|
||||
|
||||
return fp, format, i16, i32
|
||||
|
||||
def _load_properties(self):
|
||||
|
||||
#
|
||||
# font properties
|
||||
|
||||
properties = {}
|
||||
|
||||
fp, format, i16, i32 = self._getformat(PCF_PROPERTIES)
|
||||
|
||||
nprops = i32(fp.read(4))
|
||||
|
||||
# read property description
|
||||
p = []
|
||||
for i in range(nprops):
|
||||
p.append((i32(fp.read(4)), ord(fp.read(1)), i32(fp.read(4))))
|
||||
if nprops & 3:
|
||||
fp.seek(4 - (nprops & 3), 1) # pad
|
||||
|
||||
data = fp.read(i32(fp.read(4)))
|
||||
|
||||
for k, s, v in p:
|
||||
k = sz(data, k)
|
||||
if s:
|
||||
v = sz(data, v)
|
||||
properties[k] = v
|
||||
|
||||
return properties
|
||||
|
||||
def _load_metrics(self):
|
||||
|
||||
#
|
||||
# font metrics
|
||||
|
||||
metrics = []
|
||||
|
||||
fp, format, i16, i32 = self._getformat(PCF_METRICS)
|
||||
|
||||
append = metrics.append
|
||||
|
||||
if (format & 0xff00) == 0x100:
|
||||
|
||||
# "compressed" metrics
|
||||
for i in range(i16(fp.read(2))):
|
||||
left = ord(fp.read(1)) - 128
|
||||
right = ord(fp.read(1)) - 128
|
||||
width = ord(fp.read(1)) - 128
|
||||
ascent = ord(fp.read(1)) - 128
|
||||
descent = ord(fp.read(1)) - 128
|
||||
xsize = right - left
|
||||
ysize = ascent + descent
|
||||
append(
|
||||
(xsize, ysize, left, right, width,
|
||||
ascent, descent, 0)
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
# "jumbo" metrics
|
||||
for i in range(i32(fp.read(4))):
|
||||
left = i16(fp.read(2))
|
||||
right = i16(fp.read(2))
|
||||
width = i16(fp.read(2))
|
||||
ascent = i16(fp.read(2))
|
||||
descent = i16(fp.read(2))
|
||||
attributes = i16(fp.read(2))
|
||||
xsize = right - left
|
||||
ysize = ascent + descent
|
||||
append(
|
||||
(xsize, ysize, left, right, width,
|
||||
ascent, descent, attributes)
|
||||
)
|
||||
|
||||
return metrics
|
||||
|
||||
def _load_bitmaps(self, metrics):
|
||||
|
||||
#
|
||||
# bitmap data
|
||||
|
||||
bitmaps = []
|
||||
|
||||
fp, format, i16, i32 = self._getformat(PCF_BITMAPS)
|
||||
|
||||
nbitmaps = i32(fp.read(4))
|
||||
|
||||
if nbitmaps != len(metrics):
|
||||
raise IOError, "Wrong number of bitmaps"
|
||||
|
||||
offsets = []
|
||||
for i in range(nbitmaps):
|
||||
offsets.append(i32(fp.read(4)))
|
||||
|
||||
bitmapSizes = []
|
||||
for i in range(4):
|
||||
bitmapSizes.append(i32(fp.read(4)))
|
||||
|
||||
byteorder = format & 4 # non-zero => MSB
|
||||
bitorder = format & 8 # non-zero => MSB
|
||||
padindex = format & 3
|
||||
|
||||
bitmapsize = bitmapSizes[padindex]
|
||||
offsets.append(bitmapsize)
|
||||
|
||||
data = fp.read(bitmapsize)
|
||||
|
||||
pad = BYTES_PER_ROW[padindex]
|
||||
mode = "1;R"
|
||||
if bitorder:
|
||||
mode = "1"
|
||||
|
||||
for i in range(nbitmaps):
|
||||
x, y, l, r, w, a, d, f = metrics[i]
|
||||
b, e = offsets[i], offsets[i+1]
|
||||
bitmaps.append(
|
||||
Image.fromstring("1", (x, y), data[b:e], "raw", mode, pad(x))
|
||||
)
|
||||
|
||||
return bitmaps
|
||||
|
||||
def _load_encoding(self):
|
||||
|
||||
# map character code to bitmap index
|
||||
encoding = [None] * 256
|
||||
|
||||
fp, format, i16, i32 = self._getformat(PCF_BDF_ENCODINGS)
|
||||
|
||||
firstCol, lastCol = i16(fp.read(2)), i16(fp.read(2))
|
||||
firstRow, lastRow = i16(fp.read(2)), i16(fp.read(2))
|
||||
|
||||
default = i16(fp.read(2))
|
||||
|
||||
nencoding = (lastCol - firstCol + 1) * (lastRow - firstRow + 1)
|
||||
|
||||
for i in range(nencoding):
|
||||
encodingOffset = i16(fp.read(2))
|
||||
if encodingOffset != 0xFFFF:
|
||||
try:
|
||||
encoding[i+firstCol] = encodingOffset
|
||||
except IndexError:
|
||||
break # only load ISO-8859-1 glyphs
|
||||
|
||||
return encoding
|
||||
167
Darwin/lib/python2.7/site-packages/PIL/PcxImagePlugin.py
Normal file
167
Darwin/lib/python2.7/site-packages/PIL/PcxImagePlugin.py
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# PCX file handling
|
||||
#
|
||||
# This format was originally used by ZSoft's popular PaintBrush
|
||||
# program for the IBM PC. It is also supported by many MS-DOS and
|
||||
# Windows applications, including the Windows PaintBrush program in
|
||||
# Windows 3.
|
||||
#
|
||||
# history:
|
||||
# 1995-09-01 fl Created
|
||||
# 1996-05-20 fl Fixed RGB support
|
||||
# 1997-01-03 fl Fixed 2-bit and 4-bit support
|
||||
# 1999-02-03 fl Fixed 8-bit support (broken in 1.0b1)
|
||||
# 1999-02-07 fl Added write support
|
||||
# 2002-06-09 fl Made 2-bit and 4-bit support a bit more robust
|
||||
# 2002-07-30 fl Seek from to current position, not beginning of file
|
||||
# 2003-06-03 fl Extract DPI settings (info["dpi"])
|
||||
#
|
||||
# Copyright (c) 1997-2003 by Secret Labs AB.
|
||||
# Copyright (c) 1995-2003 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.6"
|
||||
|
||||
import Image, ImageFile, ImagePalette
|
||||
|
||||
def i16(c,o):
|
||||
return ord(c[o]) + (ord(c[o+1])<<8)
|
||||
|
||||
def _accept(prefix):
|
||||
return ord(prefix[0]) == 10 and ord(prefix[1]) in [0, 2, 3, 5]
|
||||
|
||||
##
|
||||
# Image plugin for Paintbrush images.
|
||||
|
||||
class PcxImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "PCX"
|
||||
format_description = "Paintbrush"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# header
|
||||
s = self.fp.read(128)
|
||||
if not _accept(s):
|
||||
raise SyntaxError, "not a PCX file"
|
||||
|
||||
# image
|
||||
bbox = i16(s,4), i16(s,6), i16(s,8)+1, i16(s,10)+1
|
||||
if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]:
|
||||
raise SyntaxError, "bad PCX image size"
|
||||
|
||||
# format
|
||||
version = ord(s[1])
|
||||
bits = ord(s[3])
|
||||
planes = ord(s[65])
|
||||
stride = i16(s,66)
|
||||
|
||||
self.info["dpi"] = i16(s,12), i16(s,14)
|
||||
|
||||
if bits == 1 and planes == 1:
|
||||
mode = rawmode = "1"
|
||||
|
||||
elif bits == 1 and planes in (2, 4):
|
||||
mode = "P"
|
||||
rawmode = "P;%dL" % planes
|
||||
self.palette = ImagePalette.raw("RGB", s[16:64])
|
||||
|
||||
elif version == 5 and bits == 8 and planes == 1:
|
||||
mode = rawmode = "L"
|
||||
# FIXME: hey, this doesn't work with the incremental loader !!!
|
||||
self.fp.seek(-769, 2)
|
||||
s = self.fp.read(769)
|
||||
if len(s) == 769 and ord(s[0]) == 12:
|
||||
# check if the palette is linear greyscale
|
||||
for i in range(256):
|
||||
if s[i*3+1:i*3+4] != chr(i)*3:
|
||||
mode = rawmode = "P"
|
||||
break
|
||||
if mode == "P":
|
||||
self.palette = ImagePalette.raw("RGB", s[1:])
|
||||
self.fp.seek(128)
|
||||
|
||||
elif version == 5 and bits == 8 and planes == 3:
|
||||
mode = "RGB"
|
||||
rawmode = "RGB;L"
|
||||
|
||||
else:
|
||||
raise IOError, "unknown PCX mode"
|
||||
|
||||
self.mode = mode
|
||||
self.size = bbox[2]-bbox[0], bbox[3]-bbox[1]
|
||||
|
||||
bbox = (0, 0) + self.size
|
||||
|
||||
self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))]
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# save PCX files
|
||||
|
||||
SAVE = {
|
||||
# mode: (version, bits, planes, raw mode)
|
||||
"1": (2, 1, 1, "1"),
|
||||
"L": (5, 8, 1, "L"),
|
||||
"P": (5, 8, 1, "P"),
|
||||
"RGB": (5, 8, 3, "RGB;L"),
|
||||
}
|
||||
|
||||
def o16(i):
|
||||
return chr(i&255) + chr(i>>8&255)
|
||||
|
||||
def _save(im, fp, filename, check=0):
|
||||
|
||||
try:
|
||||
version, bits, planes, rawmode = SAVE[im.mode]
|
||||
except KeyError:
|
||||
raise ValueError, "Cannot save %s images as PCX" % im.mode
|
||||
|
||||
if check:
|
||||
return check
|
||||
|
||||
# bytes per plane
|
||||
stride = (im.size[0] * bits + 7) / 8
|
||||
|
||||
# under windows, we could determine the current screen size with
|
||||
# "Image.core.display_mode()[1]", but I think that's overkill...
|
||||
|
||||
screen = im.size
|
||||
|
||||
dpi = 100, 100
|
||||
|
||||
# PCX header
|
||||
fp.write(
|
||||
chr(10) + chr(version) + chr(1) + chr(bits) + o16(0) +
|
||||
o16(0) + o16(im.size[0]-1) + o16(im.size[1]-1) + o16(dpi[0]) +
|
||||
o16(dpi[1]) + chr(0)*24 + chr(255)*24 + chr(0) + chr(planes) +
|
||||
o16(stride) + o16(1) + o16(screen[0]) + o16(screen[1]) +
|
||||
chr(0)*54
|
||||
)
|
||||
|
||||
assert fp.tell() == 128
|
||||
|
||||
ImageFile._save(im, fp, [("pcx", (0,0)+im.size, 0,
|
||||
(rawmode, bits*planes))])
|
||||
|
||||
if im.mode == "P":
|
||||
# colour palette
|
||||
fp.write(chr(12))
|
||||
fp.write(im.im.getpalette("RGB", "RGB")) # 768 bytes
|
||||
elif im.mode == "L":
|
||||
# greyscale palette
|
||||
fp.write(chr(12))
|
||||
for i in range(256):
|
||||
fp.write(chr(i)*3)
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# registry
|
||||
|
||||
Image.register_open("PCX", PcxImageFile, _accept)
|
||||
Image.register_save("PCX", _save)
|
||||
|
||||
Image.register_extension("PCX", ".pcx")
|
||||
211
Darwin/lib/python2.7/site-packages/PIL/PdfImagePlugin.py
Normal file
211
Darwin/lib/python2.7/site-packages/PIL/PdfImagePlugin.py
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# PDF (Acrobat) file handling
|
||||
#
|
||||
# History:
|
||||
# 1996-07-16 fl Created
|
||||
# 1997-01-18 fl Fixed header
|
||||
# 2004-02-21 fl Fixes for 1/L/CMYK images, etc.
|
||||
# 2004-02-24 fl Fixes for 1 and P images.
|
||||
#
|
||||
# Copyright (c) 1997-2004 by Secret Labs AB. All rights reserved.
|
||||
# Copyright (c) 1996-1997 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
##
|
||||
# Image plugin for PDF images (output only).
|
||||
##
|
||||
|
||||
__version__ = "0.4"
|
||||
|
||||
import Image, ImageFile
|
||||
import StringIO
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# object ids:
|
||||
# 1. catalogue
|
||||
# 2. pages
|
||||
# 3. image
|
||||
# 4. page
|
||||
# 5. page contents
|
||||
|
||||
def _obj(fp, obj, **dict):
|
||||
fp.write("%d 0 obj\n" % obj)
|
||||
if dict:
|
||||
fp.write("<<\n")
|
||||
for k, v in dict.items():
|
||||
if v is not None:
|
||||
fp.write("/%s %s\n" % (k, v))
|
||||
fp.write(">>\n")
|
||||
|
||||
def _endobj(fp):
|
||||
fp.write("endobj\n")
|
||||
|
||||
##
|
||||
# (Internal) Image save plugin for the PDF format.
|
||||
|
||||
def _save(im, fp, filename):
|
||||
resolution = im.encoderinfo.get("resolution", 72.0)
|
||||
|
||||
#
|
||||
# make sure image data is available
|
||||
im.load()
|
||||
|
||||
xref = [0]*(5+1) # placeholders
|
||||
|
||||
fp.write("%PDF-1.2\n")
|
||||
fp.write("% created by PIL PDF driver " + __version__ + "\n")
|
||||
|
||||
#
|
||||
# Get image characteristics
|
||||
|
||||
width, height = im.size
|
||||
|
||||
# FIXME: Should replace ASCIIHexDecode with RunLengthDecode (packbits)
|
||||
# or LZWDecode (tiff/lzw compression). Note that PDF 1.2 also supports
|
||||
# Flatedecode (zip compression).
|
||||
|
||||
bits = 8
|
||||
params = None
|
||||
|
||||
if im.mode == "1":
|
||||
filter = "/ASCIIHexDecode"
|
||||
colorspace = "/DeviceGray"
|
||||
procset = "/ImageB" # grayscale
|
||||
bits = 1
|
||||
elif im.mode == "L":
|
||||
filter = "/DCTDecode"
|
||||
# params = "<< /Predictor 15 /Columns %d >>" % (width-2)
|
||||
colorspace = "/DeviceGray"
|
||||
procset = "/ImageB" # grayscale
|
||||
elif im.mode == "P":
|
||||
filter = "/ASCIIHexDecode"
|
||||
colorspace = "[ /Indexed /DeviceRGB 255 <"
|
||||
palette = im.im.getpalette("RGB")
|
||||
for i in range(256):
|
||||
r = ord(palette[i*3])
|
||||
g = ord(palette[i*3+1])
|
||||
b = ord(palette[i*3+2])
|
||||
colorspace = colorspace + "%02x%02x%02x " % (r, g, b)
|
||||
colorspace = colorspace + "> ]"
|
||||
procset = "/ImageI" # indexed color
|
||||
elif im.mode == "RGB":
|
||||
filter = "/DCTDecode"
|
||||
colorspace = "/DeviceRGB"
|
||||
procset = "/ImageC" # color images
|
||||
elif im.mode == "CMYK":
|
||||
filter = "/DCTDecode"
|
||||
colorspace = "/DeviceCMYK"
|
||||
procset = "/ImageC" # color images
|
||||
else:
|
||||
raise ValueError("cannot save mode %s" % im.mode)
|
||||
|
||||
#
|
||||
# catalogue
|
||||
|
||||
xref[1] = fp.tell()
|
||||
_obj(fp, 1, Type = "/Catalog",
|
||||
Pages = "2 0 R")
|
||||
_endobj(fp)
|
||||
|
||||
#
|
||||
# pages
|
||||
|
||||
xref[2] = fp.tell()
|
||||
_obj(fp, 2, Type = "/Pages",
|
||||
Count = 1,
|
||||
Kids = "[4 0 R]")
|
||||
_endobj(fp)
|
||||
|
||||
#
|
||||
# image
|
||||
|
||||
op = StringIO.StringIO()
|
||||
|
||||
if filter == "/ASCIIHexDecode":
|
||||
if bits == 1:
|
||||
# FIXME: the hex encoder doesn't support packed 1-bit
|
||||
# images; do things the hard way...
|
||||
data = im.tostring("raw", "1")
|
||||
im = Image.new("L", (len(data), 1), None)
|
||||
im.putdata(data)
|
||||
ImageFile._save(im, op, [("hex", (0,0)+im.size, 0, im.mode)])
|
||||
elif filter == "/DCTDecode":
|
||||
ImageFile._save(im, op, [("jpeg", (0,0)+im.size, 0, im.mode)])
|
||||
elif filter == "/FlateDecode":
|
||||
ImageFile._save(im, op, [("zip", (0,0)+im.size, 0, im.mode)])
|
||||
elif filter == "/RunLengthDecode":
|
||||
ImageFile._save(im, op, [("packbits", (0,0)+im.size, 0, im.mode)])
|
||||
else:
|
||||
raise ValueError("unsupported PDF filter (%s)" % filter)
|
||||
|
||||
xref[3] = fp.tell()
|
||||
_obj(fp, 3, Type = "/XObject",
|
||||
Subtype = "/Image",
|
||||
Width = width, # * 72.0 / resolution,
|
||||
Height = height, # * 72.0 / resolution,
|
||||
Length = len(op.getvalue()),
|
||||
Filter = filter,
|
||||
BitsPerComponent = bits,
|
||||
DecodeParams = params,
|
||||
ColorSpace = colorspace)
|
||||
|
||||
fp.write("stream\n")
|
||||
fp.write(op.getvalue())
|
||||
fp.write("\nendstream\n")
|
||||
|
||||
_endobj(fp)
|
||||
|
||||
#
|
||||
# page
|
||||
|
||||
xref[4] = fp.tell()
|
||||
_obj(fp, 4)
|
||||
fp.write("<<\n/Type /Page\n/Parent 2 0 R\n"\
|
||||
"/Resources <<\n/ProcSet [ /PDF %s ]\n"\
|
||||
"/XObject << /image 3 0 R >>\n>>\n"\
|
||||
"/MediaBox [ 0 0 %d %d ]\n/Contents 5 0 R\n>>\n" %\
|
||||
(procset, int(width * 72.0 /resolution) , int(height * 72.0 / resolution)))
|
||||
_endobj(fp)
|
||||
|
||||
#
|
||||
# page contents
|
||||
|
||||
op = StringIO.StringIO()
|
||||
|
||||
op.write("q %d 0 0 %d 0 0 cm /image Do Q\n" % (int(width * 72.0 / resolution), int(height * 72.0 / resolution)))
|
||||
|
||||
xref[5] = fp.tell()
|
||||
_obj(fp, 5, Length = len(op.getvalue()))
|
||||
|
||||
fp.write("stream\n")
|
||||
fp.write(op.getvalue())
|
||||
fp.write("\nendstream\n")
|
||||
|
||||
_endobj(fp)
|
||||
|
||||
#
|
||||
# trailer
|
||||
startxref = fp.tell()
|
||||
fp.write("xref\n0 %d\n0000000000 65535 f \n" % len(xref))
|
||||
for x in xref[1:]:
|
||||
fp.write("%010d 00000 n \n" % x)
|
||||
fp.write("trailer\n<<\n/Size %d\n/Root 1 0 R\n>>\n" % len(xref))
|
||||
fp.write("startxref\n%d\n%%%%EOF\n" % startxref)
|
||||
fp.flush()
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_save("PDF", _save)
|
||||
|
||||
Image.register_extension("PDF", ".pdf")
|
||||
|
||||
Image.register_mime("PDF", "application/pdf")
|
||||
71
Darwin/lib/python2.7/site-packages/PIL/PixarImagePlugin.py
Normal file
71
Darwin/lib/python2.7/site-packages/PIL/PixarImagePlugin.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# PIXAR raster support for PIL
|
||||
#
|
||||
# history:
|
||||
# 97-01-29 fl Created
|
||||
#
|
||||
# notes:
|
||||
# This is incomplete; it is based on a few samples created with
|
||||
# Photoshop 2.5 and 3.0, and a summary description provided by
|
||||
# Greg Coats <gcoats@labiris.er.usgs.gov>. Hopefully, "L" and
|
||||
# "RGBA" support will be added in future versions.
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1997.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.1"
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
#
|
||||
# helpers
|
||||
|
||||
def i16(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8)
|
||||
|
||||
def i32(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
|
||||
|
||||
##
|
||||
# Image plugin for PIXAR raster images.
|
||||
|
||||
class PixarImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "PIXAR"
|
||||
format_description = "PIXAR raster image"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# assuming a 4-byte magic label (FIXME: add "_accept" hook)
|
||||
s = self.fp.read(4)
|
||||
if s != "\200\350\000\000":
|
||||
raise SyntaxError, "not a PIXAR file"
|
||||
|
||||
# read rest of header
|
||||
s = s + self.fp.read(508)
|
||||
|
||||
self.size = i16(s[418:420]), i16(s[416:418])
|
||||
|
||||
# get channel/depth descriptions
|
||||
mode = i16(s[424:426]), i16(s[426:428])
|
||||
|
||||
if mode == (14, 2):
|
||||
self.mode = "RGB"
|
||||
# FIXME: to be continued...
|
||||
|
||||
# create tile descriptor (assuming "dumped")
|
||||
self.tile = [("raw", (0,0)+self.size, 1024, (self.mode, 0, 1))]
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("PIXAR", PixarImageFile)
|
||||
|
||||
#
|
||||
# FIXME: what's the standard extension?
|
||||
620
Darwin/lib/python2.7/site-packages/PIL/PngImagePlugin.py
Normal file
620
Darwin/lib/python2.7/site-packages/PIL/PngImagePlugin.py
Normal file
|
|
@ -0,0 +1,620 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# PNG support code
|
||||
#
|
||||
# See "PNG (Portable Network Graphics) Specification, version 1.0;
|
||||
# W3C Recommendation", 1996-10-01, Thomas Boutell (ed.).
|
||||
#
|
||||
# history:
|
||||
# 1996-05-06 fl Created (couldn't resist it)
|
||||
# 1996-12-14 fl Upgraded, added read and verify support (0.2)
|
||||
# 1996-12-15 fl Separate PNG stream parser
|
||||
# 1996-12-29 fl Added write support, added getchunks
|
||||
# 1996-12-30 fl Eliminated circular references in decoder (0.3)
|
||||
# 1998-07-12 fl Read/write 16-bit images as mode I (0.4)
|
||||
# 2001-02-08 fl Added transparency support (from Zircon) (0.5)
|
||||
# 2001-04-16 fl Don't close data source in "open" method (0.6)
|
||||
# 2004-02-24 fl Don't even pretend to support interlaced files (0.7)
|
||||
# 2004-08-31 fl Do basic sanity check on chunk identifiers (0.8)
|
||||
# 2004-09-20 fl Added PngInfo chunk container
|
||||
# 2004-12-18 fl Added DPI read support (based on code by Niki Spahiev)
|
||||
# 2008-08-13 fl Added tRNS support for RGB images
|
||||
# 2009-03-06 fl Support for preserving ICC profiles (by Florian Hoech)
|
||||
# 2009-03-08 fl Added zTXT support (from Lowell Alleman)
|
||||
# 2009-03-29 fl Read interlaced PNG files (from Conrado Porto Lopes Gouvua)
|
||||
#
|
||||
# Copyright (c) 1997-2009 by Secret Labs AB
|
||||
# Copyright (c) 1996 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.9"
|
||||
|
||||
import re, string
|
||||
|
||||
import Image, ImageFile, ImagePalette, zlib
|
||||
|
||||
|
||||
def i16(c):
|
||||
return ord(c[1]) + (ord(c[0])<<8)
|
||||
def i32(c):
|
||||
return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
|
||||
|
||||
is_cid = re.compile("\w\w\w\w").match
|
||||
|
||||
|
||||
_MAGIC = "\211PNG\r\n\032\n"
|
||||
|
||||
|
||||
_MODES = {
|
||||
# supported bits/color combinations, and corresponding modes/rawmodes
|
||||
(1, 0): ("1", "1"),
|
||||
(2, 0): ("L", "L;2"),
|
||||
(4, 0): ("L", "L;4"),
|
||||
(8, 0): ("L", "L"),
|
||||
(16,0): ("I", "I;16B"),
|
||||
(8, 2): ("RGB", "RGB"),
|
||||
(16,2): ("RGB", "RGB;16B"),
|
||||
(1, 3): ("P", "P;1"),
|
||||
(2, 3): ("P", "P;2"),
|
||||
(4, 3): ("P", "P;4"),
|
||||
(8, 3): ("P", "P"),
|
||||
(8, 4): ("LA", "LA"),
|
||||
(16,4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available
|
||||
(8, 6): ("RGBA", "RGBA"),
|
||||
(16,6): ("RGBA", "RGBA;16B"),
|
||||
}
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Support classes. Suitable for PNG and related formats like MNG etc.
|
||||
|
||||
class ChunkStream:
|
||||
|
||||
def __init__(self, fp):
|
||||
|
||||
self.fp = fp
|
||||
self.queue = []
|
||||
|
||||
if not hasattr(Image.core, "crc32"):
|
||||
self.crc = self.crc_skip
|
||||
|
||||
def read(self):
|
||||
"Fetch a new chunk. Returns header information."
|
||||
|
||||
if self.queue:
|
||||
cid, pos, len = self.queue[-1]
|
||||
del self.queue[-1]
|
||||
self.fp.seek(pos)
|
||||
else:
|
||||
s = self.fp.read(8)
|
||||
cid = s[4:]
|
||||
pos = self.fp.tell()
|
||||
len = i32(s)
|
||||
|
||||
if not is_cid(cid):
|
||||
raise SyntaxError, "broken PNG file (chunk %s)" % repr(cid)
|
||||
|
||||
return cid, pos, len
|
||||
|
||||
def close(self):
|
||||
self.queue = self.crc = self.fp = None
|
||||
|
||||
def push(self, cid, pos, len):
|
||||
|
||||
self.queue.append((cid, pos, len))
|
||||
|
||||
def call(self, cid, pos, len):
|
||||
"Call the appropriate chunk handler"
|
||||
|
||||
if Image.DEBUG:
|
||||
print "STREAM", cid, pos, len
|
||||
return getattr(self, "chunk_" + cid)(pos, len)
|
||||
|
||||
def crc(self, cid, data):
|
||||
"Read and verify checksum"
|
||||
|
||||
crc1 = Image.core.crc32(data, Image.core.crc32(cid))
|
||||
crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))
|
||||
if crc1 != crc2:
|
||||
raise SyntaxError, "broken PNG file"\
|
||||
"(bad header checksum in %s)" % cid
|
||||
|
||||
def crc_skip(self, cid, data):
|
||||
"Read checksum. Used if the C module is not present"
|
||||
|
||||
self.fp.read(4)
|
||||
|
||||
def verify(self, endchunk = "IEND"):
|
||||
|
||||
# Simple approach; just calculate checksum for all remaining
|
||||
# blocks. Must be called directly after open.
|
||||
|
||||
cids = []
|
||||
|
||||
while 1:
|
||||
cid, pos, len = self.read()
|
||||
if cid == endchunk:
|
||||
break
|
||||
self.crc(cid, ImageFile._safe_read(self.fp, len))
|
||||
cids.append(cid)
|
||||
|
||||
return cids
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PNG chunk container (for use with save(pnginfo=))
|
||||
|
||||
class PngInfo:
|
||||
|
||||
def __init__(self):
|
||||
self.chunks = []
|
||||
|
||||
def add(self, cid, data):
|
||||
self.chunks.append((cid, data))
|
||||
|
||||
def add_text(self, key, value, zip=0):
|
||||
if zip:
|
||||
import zlib
|
||||
self.add("zTXt", key + "\0\0" + zlib.compress(value))
|
||||
else:
|
||||
self.add("tEXt", key + "\0" + value)
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PNG image stream (IHDR/IEND)
|
||||
|
||||
class PngStream(ChunkStream):
|
||||
|
||||
def __init__(self, fp):
|
||||
|
||||
ChunkStream.__init__(self, fp)
|
||||
|
||||
# local copies of Image attributes
|
||||
self.im_info = {}
|
||||
self.im_text = {}
|
||||
self.im_size = (0,0)
|
||||
self.im_mode = None
|
||||
self.im_tile = None
|
||||
self.im_palette = None
|
||||
|
||||
def chunk_iCCP(self, pos, len):
|
||||
|
||||
# ICC profile
|
||||
s = ImageFile._safe_read(self.fp, len)
|
||||
# according to PNG spec, the iCCP chunk contains:
|
||||
# Profile name 1-79 bytes (character string)
|
||||
# Null separator 1 byte (null character)
|
||||
# Compression method 1 byte (0)
|
||||
# Compressed profile n bytes (zlib with deflate compression)
|
||||
i = string.find(s, chr(0))
|
||||
if Image.DEBUG:
|
||||
print "iCCP profile name", s[:i]
|
||||
print "Compression method", ord(s[i])
|
||||
comp_method = ord(s[i])
|
||||
if comp_method != 0:
|
||||
raise SyntaxError("Unknown compression method %s in iCCP chunk" % comp_method)
|
||||
try:
|
||||
icc_profile = zlib.decompress(s[i+2:])
|
||||
except zlib.error:
|
||||
icc_profile = None # FIXME
|
||||
self.im_info["icc_profile"] = icc_profile
|
||||
return s
|
||||
|
||||
def chunk_IHDR(self, pos, len):
|
||||
|
||||
# image header
|
||||
s = ImageFile._safe_read(self.fp, len)
|
||||
self.im_size = i32(s), i32(s[4:])
|
||||
try:
|
||||
self.im_mode, self.im_rawmode = _MODES[(ord(s[8]), ord(s[9]))]
|
||||
except:
|
||||
pass
|
||||
if ord(s[12]):
|
||||
self.im_info["interlace"] = 1
|
||||
if ord(s[11]):
|
||||
raise SyntaxError, "unknown filter category"
|
||||
return s
|
||||
|
||||
def chunk_IDAT(self, pos, len):
|
||||
|
||||
# image data
|
||||
self.im_tile = [("zip", (0,0)+self.im_size, pos, self.im_rawmode)]
|
||||
self.im_idat = len
|
||||
raise EOFError
|
||||
|
||||
def chunk_IEND(self, pos, len):
|
||||
|
||||
# end of PNG image
|
||||
raise EOFError
|
||||
|
||||
def chunk_PLTE(self, pos, len):
|
||||
|
||||
# palette
|
||||
s = ImageFile._safe_read(self.fp, len)
|
||||
if self.im_mode == "P":
|
||||
self.im_palette = "RGB", s
|
||||
return s
|
||||
|
||||
def chunk_tRNS(self, pos, len):
|
||||
|
||||
# transparency
|
||||
s = ImageFile._safe_read(self.fp, len)
|
||||
if self.im_mode == "P":
|
||||
i = string.find(s, chr(0))
|
||||
if i >= 0:
|
||||
self.im_info["transparency"] = i
|
||||
elif self.im_mode == "L":
|
||||
self.im_info["transparency"] = i16(s)
|
||||
elif self.im_mode == "RGB":
|
||||
self.im_info["transparency"] = i16(s), i16(s[2:]), i16(s[4:])
|
||||
return s
|
||||
|
||||
def chunk_gAMA(self, pos, len):
|
||||
|
||||
# gamma setting
|
||||
s = ImageFile._safe_read(self.fp, len)
|
||||
self.im_info["gamma"] = i32(s) / 100000.0
|
||||
return s
|
||||
|
||||
def chunk_pHYs(self, pos, len):
|
||||
|
||||
# pixels per unit
|
||||
s = ImageFile._safe_read(self.fp, len)
|
||||
px, py = i32(s), i32(s[4:])
|
||||
unit = ord(s[8])
|
||||
if unit == 1: # meter
|
||||
dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5)
|
||||
self.im_info["dpi"] = dpi
|
||||
elif unit == 0:
|
||||
self.im_info["aspect"] = px, py
|
||||
return s
|
||||
|
||||
def chunk_tEXt(self, pos, len):
|
||||
|
||||
# text
|
||||
s = ImageFile._safe_read(self.fp, len)
|
||||
try:
|
||||
k, v = string.split(s, "\0", 1)
|
||||
except ValueError:
|
||||
k = s; v = "" # fallback for broken tEXt tags
|
||||
if k:
|
||||
self.im_info[k] = self.im_text[k] = v
|
||||
return s
|
||||
|
||||
def chunk_zTXt(self, pos, len):
|
||||
|
||||
# compressed text
|
||||
s = ImageFile._safe_read(self.fp, len)
|
||||
k, v = string.split(s, "\0", 1)
|
||||
comp_method = ord(v[0])
|
||||
if comp_method != 0:
|
||||
raise SyntaxError("Unknown compression method %s in zTXt chunk" % comp_method)
|
||||
import zlib
|
||||
self.im_info[k] = self.im_text[k] = zlib.decompress(v[1:])
|
||||
return s
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PNG reader
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:8] == _MAGIC
|
||||
|
||||
##
|
||||
# Image plugin for PNG images.
|
||||
|
||||
class PngImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "PNG"
|
||||
format_description = "Portable network graphics"
|
||||
|
||||
def _open(self):
|
||||
|
||||
if self.fp.read(8) != _MAGIC:
|
||||
raise SyntaxError, "not a PNG file"
|
||||
|
||||
#
|
||||
# Parse headers up to the first IDAT chunk
|
||||
|
||||
self.png = PngStream(self.fp)
|
||||
|
||||
while 1:
|
||||
|
||||
#
|
||||
# get next chunk
|
||||
|
||||
cid, pos, len = self.png.read()
|
||||
|
||||
try:
|
||||
s = self.png.call(cid, pos, len)
|
||||
except EOFError:
|
||||
break
|
||||
except AttributeError:
|
||||
if Image.DEBUG:
|
||||
print cid, pos, len, "(unknown)"
|
||||
s = ImageFile._safe_read(self.fp, len)
|
||||
|
||||
self.png.crc(cid, s)
|
||||
|
||||
#
|
||||
# Copy relevant attributes from the PngStream. An alternative
|
||||
# would be to let the PngStream class modify these attributes
|
||||
# directly, but that introduces circular references which are
|
||||
# difficult to break if things go wrong in the decoder...
|
||||
# (believe me, I've tried ;-)
|
||||
|
||||
self.mode = self.png.im_mode
|
||||
self.size = self.png.im_size
|
||||
self.info = self.png.im_info
|
||||
self.text = self.png.im_text # experimental
|
||||
self.tile = self.png.im_tile
|
||||
|
||||
if self.png.im_palette:
|
||||
rawmode, data = self.png.im_palette
|
||||
self.palette = ImagePalette.raw(rawmode, data)
|
||||
|
||||
self.__idat = len # used by load_read()
|
||||
|
||||
|
||||
def verify(self):
|
||||
"Verify PNG file"
|
||||
|
||||
if self.fp is None:
|
||||
raise RuntimeError("verify must be called directly after open")
|
||||
|
||||
# back up to beginning of IDAT block
|
||||
self.fp.seek(self.tile[0][2] - 8)
|
||||
|
||||
self.png.verify()
|
||||
self.png.close()
|
||||
|
||||
self.fp = None
|
||||
|
||||
def load_prepare(self):
|
||||
"internal: prepare to read PNG file"
|
||||
|
||||
if self.info.get("interlace"):
|
||||
self.decoderconfig = self.decoderconfig + (1,)
|
||||
|
||||
ImageFile.ImageFile.load_prepare(self)
|
||||
|
||||
def load_read(self, bytes):
|
||||
"internal: read more image data"
|
||||
|
||||
while self.__idat == 0:
|
||||
# end of chunk, skip forward to next one
|
||||
|
||||
self.fp.read(4) # CRC
|
||||
|
||||
cid, pos, len = self.png.read()
|
||||
|
||||
if cid not in ["IDAT", "DDAT"]:
|
||||
self.png.push(cid, pos, len)
|
||||
return ""
|
||||
|
||||
self.__idat = len # empty chunks are allowed
|
||||
|
||||
# read more data from this chunk
|
||||
if bytes <= 0:
|
||||
bytes = self.__idat
|
||||
else:
|
||||
bytes = min(bytes, self.__idat)
|
||||
|
||||
self.__idat = self.__idat - bytes
|
||||
|
||||
return self.fp.read(bytes)
|
||||
|
||||
|
||||
def load_end(self):
|
||||
"internal: finished reading image data"
|
||||
|
||||
self.png.close()
|
||||
self.png = None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PNG writer
|
||||
|
||||
def o16(i):
|
||||
return chr(i>>8&255) + chr(i&255)
|
||||
|
||||
def o32(i):
|
||||
return chr(i>>24&255) + chr(i>>16&255) + chr(i>>8&255) + chr(i&255)
|
||||
|
||||
_OUTMODES = {
|
||||
# supported PIL modes, and corresponding rawmodes/bits/color combinations
|
||||
"1": ("1", chr(1)+chr(0)),
|
||||
"L;1": ("L;1", chr(1)+chr(0)),
|
||||
"L;2": ("L;2", chr(2)+chr(0)),
|
||||
"L;4": ("L;4", chr(4)+chr(0)),
|
||||
"L": ("L", chr(8)+chr(0)),
|
||||
"LA": ("LA", chr(8)+chr(4)),
|
||||
"I": ("I;16B", chr(16)+chr(0)),
|
||||
"P;1": ("P;1", chr(1)+chr(3)),
|
||||
"P;2": ("P;2", chr(2)+chr(3)),
|
||||
"P;4": ("P;4", chr(4)+chr(3)),
|
||||
"P": ("P", chr(8)+chr(3)),
|
||||
"RGB": ("RGB", chr(8)+chr(2)),
|
||||
"RGBA":("RGBA", chr(8)+chr(6)),
|
||||
}
|
||||
|
||||
def putchunk(fp, cid, *data):
|
||||
"Write a PNG chunk (including CRC field)"
|
||||
|
||||
data = string.join(data, "")
|
||||
|
||||
fp.write(o32(len(data)) + cid)
|
||||
fp.write(data)
|
||||
hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
|
||||
fp.write(o16(hi) + o16(lo))
|
||||
|
||||
class _idat:
|
||||
# wrap output from the encoder in IDAT chunks
|
||||
|
||||
def __init__(self, fp, chunk):
|
||||
self.fp = fp
|
||||
self.chunk = chunk
|
||||
def write(self, data):
|
||||
self.chunk(self.fp, "IDAT", data)
|
||||
|
||||
def _save(im, fp, filename, chunk=putchunk, check=0):
|
||||
# save an image to disk (called by the save method)
|
||||
|
||||
mode = im.mode
|
||||
|
||||
if mode == "P":
|
||||
|
||||
#
|
||||
# attempt to minimize storage requirements for palette images
|
||||
|
||||
if im.encoderinfo.has_key("bits"):
|
||||
|
||||
# number of bits specified by user
|
||||
n = 1 << im.encoderinfo["bits"]
|
||||
|
||||
else:
|
||||
|
||||
# check palette contents
|
||||
n = 256 # FIXME
|
||||
|
||||
if n <= 2:
|
||||
bits = 1
|
||||
elif n <= 4:
|
||||
bits = 2
|
||||
elif n <= 16:
|
||||
bits = 4
|
||||
else:
|
||||
bits = 8
|
||||
|
||||
if bits != 8:
|
||||
mode = "%s;%d" % (mode, bits)
|
||||
|
||||
# encoder options
|
||||
if im.encoderinfo.has_key("dictionary"):
|
||||
dictionary = im.encoderinfo["dictionary"]
|
||||
else:
|
||||
dictionary = ""
|
||||
|
||||
im.encoderconfig = (im.encoderinfo.has_key("optimize"), dictionary)
|
||||
|
||||
# get the corresponding PNG mode
|
||||
try:
|
||||
rawmode, mode = _OUTMODES[mode]
|
||||
except KeyError:
|
||||
raise IOError, "cannot write mode %s as PNG" % mode
|
||||
|
||||
if check:
|
||||
return check
|
||||
|
||||
#
|
||||
# write minimal PNG file
|
||||
|
||||
fp.write(_MAGIC)
|
||||
|
||||
chunk(fp, "IHDR",
|
||||
o32(im.size[0]), o32(im.size[1]), # 0: size
|
||||
mode, # 8: depth/type
|
||||
chr(0), # 10: compression
|
||||
chr(0), # 11: filter category
|
||||
chr(0)) # 12: interlace flag
|
||||
|
||||
if im.mode == "P":
|
||||
chunk(fp, "PLTE", im.im.getpalette("RGB"))
|
||||
|
||||
if im.encoderinfo.has_key("transparency"):
|
||||
if im.mode == "P":
|
||||
transparency = max(0, min(255, im.encoderinfo["transparency"]))
|
||||
chunk(fp, "tRNS", chr(255) * transparency + chr(0))
|
||||
elif im.mode == "L":
|
||||
transparency = max(0, min(65535, im.encoderinfo["transparency"]))
|
||||
chunk(fp, "tRNS", o16(transparency))
|
||||
elif im.mode == "RGB":
|
||||
red, green, blue = im.encoderinfo["transparency"]
|
||||
chunk(fp, "tRNS", o16(red) + o16(green) + o16(blue))
|
||||
else:
|
||||
raise IOError("cannot use transparency for this mode")
|
||||
|
||||
if 0:
|
||||
# FIXME: to be supported some day
|
||||
chunk(fp, "gAMA", o32(int(gamma * 100000.0)))
|
||||
|
||||
dpi = im.encoderinfo.get("dpi")
|
||||
if dpi:
|
||||
chunk(fp, "pHYs",
|
||||
o32(int(dpi[0] / 0.0254 + 0.5)),
|
||||
o32(int(dpi[1] / 0.0254 + 0.5)),
|
||||
chr(1))
|
||||
|
||||
info = im.encoderinfo.get("pnginfo")
|
||||
if info:
|
||||
for cid, data in info.chunks:
|
||||
chunk(fp, cid, data)
|
||||
|
||||
# ICC profile writing support -- 2008-06-06 Florian Hoech
|
||||
if im.info.has_key("icc_profile"):
|
||||
# ICC profile
|
||||
# according to PNG spec, the iCCP chunk contains:
|
||||
# Profile name 1-79 bytes (character string)
|
||||
# Null separator 1 byte (null character)
|
||||
# Compression method 1 byte (0)
|
||||
# Compressed profile n bytes (zlib with deflate compression)
|
||||
try:
|
||||
import ICCProfile
|
||||
p = ICCProfile.ICCProfile(im.info["icc_profile"])
|
||||
name = p.tags.desc.get("ASCII", p.tags.desc.get("Unicode", p.tags.desc.get("Macintosh", p.tags.desc.get("en", {}).get("US", "ICC Profile")))).encode("latin1", "replace")[:79]
|
||||
except ImportError:
|
||||
name = "ICC Profile"
|
||||
data = name + "\0\0" + zlib.compress(im.info["icc_profile"])
|
||||
chunk(fp, "iCCP", data)
|
||||
|
||||
ImageFile._save(im, _idat(fp, chunk), [("zip", (0,0)+im.size, 0, rawmode)])
|
||||
|
||||
chunk(fp, "IEND", "")
|
||||
|
||||
try:
|
||||
fp.flush()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PNG chunk converter
|
||||
|
||||
def getchunks(im, **params):
|
||||
"""Return a list of PNG chunks representing this image."""
|
||||
|
||||
class collector:
|
||||
data = []
|
||||
def write(self, data):
|
||||
pass
|
||||
def append(self, chunk):
|
||||
self.data.append(chunk)
|
||||
|
||||
def append(fp, cid, *data):
|
||||
data = string.join(data, "")
|
||||
hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
|
||||
crc = o16(hi) + o16(lo)
|
||||
fp.append((cid, data, crc))
|
||||
|
||||
fp = collector()
|
||||
|
||||
try:
|
||||
im.encoderinfo = params
|
||||
_save(im, fp, None, append)
|
||||
finally:
|
||||
del im.encoderinfo
|
||||
|
||||
return fp.data
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Registry
|
||||
|
||||
Image.register_open("PNG", PngImageFile, _accept)
|
||||
Image.register_save("PNG", _save)
|
||||
|
||||
Image.register_extension("PNG", ".png")
|
||||
|
||||
Image.register_mime("PNG", "image/png")
|
||||
131
Darwin/lib/python2.7/site-packages/PIL/PpmImagePlugin.py
Normal file
131
Darwin/lib/python2.7/site-packages/PIL/PpmImagePlugin.py
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# PPM support for PIL
|
||||
#
|
||||
# History:
|
||||
# 96-03-24 fl Created
|
||||
# 98-03-06 fl Write RGBA images (as RGB, that is)
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997-98.
|
||||
# Copyright (c) Fredrik Lundh 1996.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.2"
|
||||
|
||||
import string
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
MODES = {
|
||||
# standard
|
||||
"P4": "1",
|
||||
"P5": "L",
|
||||
"P6": "RGB",
|
||||
# extensions
|
||||
"P0CMYK": "CMYK",
|
||||
# PIL extensions (for test purposes only)
|
||||
"PyP": "P",
|
||||
"PyRGBA": "RGBA",
|
||||
"PyCMYK": "CMYK"
|
||||
}
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[0] == "P" and prefix[1] in "0456y"
|
||||
|
||||
##
|
||||
# Image plugin for PBM, PGM, and PPM images.
|
||||
|
||||
class PpmImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "PPM"
|
||||
format_description = "Pbmplus image"
|
||||
|
||||
def _token(self, s = ""):
|
||||
while 1: # read until next whitespace
|
||||
c = self.fp.read(1)
|
||||
if not c or c in string.whitespace:
|
||||
break
|
||||
s = s + c
|
||||
return s
|
||||
|
||||
def _open(self):
|
||||
|
||||
# check magic
|
||||
s = self.fp.read(1)
|
||||
if s != "P":
|
||||
raise SyntaxError, "not a PPM file"
|
||||
mode = MODES[self._token(s)]
|
||||
|
||||
if mode == "1":
|
||||
self.mode = "1"
|
||||
rawmode = "1;I"
|
||||
else:
|
||||
self.mode = rawmode = mode
|
||||
|
||||
for ix in range(3):
|
||||
while 1:
|
||||
while 1:
|
||||
s = self.fp.read(1)
|
||||
if s not in string.whitespace:
|
||||
break
|
||||
if s != "#":
|
||||
break
|
||||
s = self.fp.readline()
|
||||
s = int(self._token(s))
|
||||
if ix == 0:
|
||||
xsize = s
|
||||
elif ix == 1:
|
||||
ysize = s
|
||||
if mode == "1":
|
||||
break
|
||||
|
||||
self.size = xsize, ysize
|
||||
self.tile = [("raw",
|
||||
(0, 0, xsize, ysize),
|
||||
self.fp.tell(),
|
||||
(rawmode, 0, 1))]
|
||||
|
||||
# ALTERNATIVE: load via builtin debug function
|
||||
# self.im = Image.core.open_ppm(self.filename)
|
||||
# self.mode = self.im.mode
|
||||
# self.size = self.im.size
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
def _save(im, fp, filename):
|
||||
if im.mode == "1":
|
||||
rawmode, head = "1;I", "P4"
|
||||
elif im.mode == "L":
|
||||
rawmode, head = "L", "P5"
|
||||
elif im.mode == "RGB":
|
||||
rawmode, head = "RGB", "P6"
|
||||
elif im.mode == "RGBA":
|
||||
rawmode, head = "RGB", "P6"
|
||||
else:
|
||||
raise IOError, "cannot write mode %s as PPM" % im.mode
|
||||
fp.write(head + "\n%d %d\n" % im.size)
|
||||
if head != "P4":
|
||||
fp.write("255\n")
|
||||
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, 1))])
|
||||
|
||||
# ALTERNATIVE: save via builtin debug function
|
||||
# im._dump(filename)
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("PPM", PpmImageFile, _accept)
|
||||
Image.register_save("PPM", _save)
|
||||
|
||||
Image.register_extension("PPM", ".pbm")
|
||||
Image.register_extension("PPM", ".pgm")
|
||||
Image.register_extension("PPM", ".ppm")
|
||||
291
Darwin/lib/python2.7/site-packages/PIL/PsdImagePlugin.py
Normal file
291
Darwin/lib/python2.7/site-packages/PIL/PsdImagePlugin.py
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# Adobe PSD 2.5/3.0 file handling
|
||||
#
|
||||
# History:
|
||||
# 1995-09-01 fl Created
|
||||
# 1997-01-03 fl Read most PSD images
|
||||
# 1997-01-18 fl Fixed P and CMYK support
|
||||
# 2001-10-21 fl Added seek/tell support (for layers)
|
||||
#
|
||||
# Copyright (c) 1997-2001 by Secret Labs AB.
|
||||
# Copyright (c) 1995-2001 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.4"
|
||||
|
||||
import Image, ImageFile, ImagePalette
|
||||
|
||||
MODES = {
|
||||
# (photoshop mode, bits) -> (pil mode, required channels)
|
||||
(0, 1): ("1", 1),
|
||||
(0, 8): ("L", 1),
|
||||
(1, 8): ("L", 1),
|
||||
(2, 8): ("P", 1),
|
||||
(3, 8): ("RGB", 3),
|
||||
(4, 8): ("CMYK", 4),
|
||||
(7, 8): ("L", 1), # FIXME: multilayer
|
||||
(8, 8): ("L", 1), # duotone
|
||||
(9, 8): ("LAB", 3)
|
||||
}
|
||||
|
||||
#
|
||||
# helpers
|
||||
|
||||
def i16(c):
|
||||
return ord(c[1]) + (ord(c[0])<<8)
|
||||
|
||||
def i32(c):
|
||||
return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
|
||||
|
||||
# --------------------------------------------------------------------.
|
||||
# read PSD images
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] == "8BPS"
|
||||
|
||||
##
|
||||
# Image plugin for Photoshop images.
|
||||
|
||||
class PsdImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "PSD"
|
||||
format_description = "Adobe Photoshop"
|
||||
|
||||
def _open(self):
|
||||
|
||||
read = self.fp.read
|
||||
|
||||
#
|
||||
# header
|
||||
|
||||
s = read(26)
|
||||
if s[:4] != "8BPS" or i16(s[4:]) != 1:
|
||||
raise SyntaxError, "not a PSD file"
|
||||
|
||||
psd_bits = i16(s[22:])
|
||||
psd_channels = i16(s[12:])
|
||||
psd_mode = i16(s[24:])
|
||||
|
||||
mode, channels = MODES[(psd_mode, psd_bits)]
|
||||
|
||||
if channels > psd_channels:
|
||||
raise IOError, "not enough channels"
|
||||
|
||||
self.mode = mode
|
||||
self.size = i32(s[18:]), i32(s[14:])
|
||||
|
||||
#
|
||||
# color mode data
|
||||
|
||||
size = i32(read(4))
|
||||
if size:
|
||||
data = read(size)
|
||||
if mode == "P" and size == 768:
|
||||
self.palette = ImagePalette.raw("RGB;L", data)
|
||||
|
||||
#
|
||||
# image resources
|
||||
|
||||
self.resources = []
|
||||
|
||||
size = i32(read(4))
|
||||
if size:
|
||||
# load resources
|
||||
end = self.fp.tell() + size
|
||||
while self.fp.tell() < end:
|
||||
signature = read(4)
|
||||
id = i16(read(2))
|
||||
name = read(ord(read(1)))
|
||||
if not (len(name) & 1):
|
||||
read(1) # padding
|
||||
data = read(i32(read(4)))
|
||||
if (len(data) & 1):
|
||||
read(1) # padding
|
||||
self.resources.append((id, name, data))
|
||||
if id == 1039: # ICC profile
|
||||
self.info["icc_profile"] = data
|
||||
|
||||
#
|
||||
# layer and mask information
|
||||
|
||||
self.layers = []
|
||||
|
||||
size = i32(read(4))
|
||||
if size:
|
||||
end = self.fp.tell() + size
|
||||
size = i32(read(4))
|
||||
if size:
|
||||
self.layers = _layerinfo(self.fp)
|
||||
self.fp.seek(end)
|
||||
|
||||
#
|
||||
# image descriptor
|
||||
|
||||
self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)
|
||||
|
||||
# keep the file open
|
||||
self._fp = self.fp
|
||||
self.frame = 0
|
||||
|
||||
def seek(self, layer):
|
||||
# seek to given layer (1..max)
|
||||
if layer == self.frame:
|
||||
return
|
||||
try:
|
||||
if layer <= 0:
|
||||
raise IndexError
|
||||
name, mode, bbox, tile = self.layers[layer-1]
|
||||
self.mode = mode
|
||||
self.tile = tile
|
||||
self.frame = layer
|
||||
self.fp = self._fp
|
||||
return name, bbox
|
||||
except IndexError:
|
||||
raise EOFError, "no such layer"
|
||||
|
||||
def tell(self):
|
||||
# return layer number (0=image, 1..max=layers)
|
||||
return self.frame
|
||||
|
||||
def load_prepare(self):
|
||||
# create image memory if necessary
|
||||
if not self.im or\
|
||||
self.im.mode != self.mode or self.im.size != self.size:
|
||||
self.im = Image.core.fill(self.mode, self.size, 0)
|
||||
# create palette (optional)
|
||||
if self.mode == "P":
|
||||
Image.Image.load(self)
|
||||
|
||||
def _layerinfo(file):
|
||||
# read layerinfo block
|
||||
layers = []
|
||||
read = file.read
|
||||
|
||||
for i in range(abs(i16(read(2)))):
|
||||
|
||||
# bounding box
|
||||
y0 = i32(read(4)); x0 = i32(read(4))
|
||||
y1 = i32(read(4)); x1 = i32(read(4))
|
||||
|
||||
# image info
|
||||
info = []
|
||||
mode = []
|
||||
for i in range(i16(read(2))):
|
||||
type = i16(read(2))
|
||||
if type == 65535:
|
||||
m = "A"
|
||||
else:
|
||||
m = "RGB"[type]
|
||||
mode.append(m)
|
||||
size = i32(read(4))
|
||||
info.append((m, size))
|
||||
|
||||
# figure out the image mode
|
||||
mode.sort()
|
||||
if mode == ["R"]:
|
||||
mode = "L"
|
||||
elif mode == ["B", "G", "R"]:
|
||||
mode = "RGB"
|
||||
elif mode == ["A", "B", "G", "R"]:
|
||||
mode = "RGBA"
|
||||
else:
|
||||
mode = None # unknown
|
||||
|
||||
# skip over blend flags and extra information
|
||||
filler = read(12)
|
||||
name = ""
|
||||
size = i32(read(4))
|
||||
combined = 0
|
||||
if size:
|
||||
length = i32(read(4))
|
||||
if length:
|
||||
mask_y = i32(read(4)); mask_x = i32(read(4))
|
||||
mask_h = i32(read(4)) - mask_y; mask_w = i32(read(4)) - mask_x
|
||||
file.seek(length - 16, 1)
|
||||
combined += length + 4
|
||||
|
||||
length = i32(read(4))
|
||||
if length:
|
||||
file.seek(length, 1)
|
||||
combined += length + 4
|
||||
|
||||
length = ord(read(1))
|
||||
if length:
|
||||
name = read(length)
|
||||
combined += length + 1
|
||||
|
||||
file.seek(size - combined, 1)
|
||||
layers.append((name, mode, (x0, y0, x1, y1)))
|
||||
|
||||
# get tiles
|
||||
i = 0
|
||||
for name, mode, bbox in layers:
|
||||
tile = []
|
||||
for m in mode:
|
||||
t = _maketile(file, m, bbox, 1)
|
||||
if t:
|
||||
tile.extend(t)
|
||||
layers[i] = name, mode, bbox, tile
|
||||
i = i + 1
|
||||
|
||||
return layers
|
||||
|
||||
def _maketile(file, mode, bbox, channels):
|
||||
|
||||
tile = None
|
||||
read = file.read
|
||||
|
||||
compression = i16(read(2))
|
||||
|
||||
xsize = bbox[2] - bbox[0]
|
||||
ysize = bbox[3] - bbox[1]
|
||||
|
||||
offset = file.tell()
|
||||
|
||||
if compression == 0:
|
||||
#
|
||||
# raw compression
|
||||
tile = []
|
||||
for channel in range(channels):
|
||||
layer = mode[channel]
|
||||
if mode == "CMYK":
|
||||
layer = layer + ";I"
|
||||
tile.append(("raw", bbox, offset, layer))
|
||||
offset = offset + xsize*ysize
|
||||
|
||||
elif compression == 1:
|
||||
#
|
||||
# packbits compression
|
||||
i = 0
|
||||
tile = []
|
||||
bytecount = read(channels * ysize * 2)
|
||||
offset = file.tell()
|
||||
for channel in range(channels):
|
||||
layer = mode[channel]
|
||||
if mode == "CMYK":
|
||||
layer = layer + ";I"
|
||||
tile.append(
|
||||
("packbits", bbox, offset, layer)
|
||||
)
|
||||
for y in range(ysize):
|
||||
offset = offset + i16(bytecount[i:i+2])
|
||||
i = i + 2
|
||||
|
||||
file.seek(offset)
|
||||
|
||||
if offset & 1:
|
||||
read(1) # padding
|
||||
|
||||
return tile
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# registry
|
||||
|
||||
Image.register_open("PSD", PsdImageFile, _accept)
|
||||
|
||||
Image.register_extension("PSD", ".psd")
|
||||
92
Darwin/lib/python2.7/site-packages/PIL/SgiImagePlugin.py
Normal file
92
Darwin/lib/python2.7/site-packages/PIL/SgiImagePlugin.py
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# SGI image file handling
|
||||
#
|
||||
# See "The SGI Image File Format (Draft version 0.97)", Paul Haeberli.
|
||||
# <ftp://ftp.sgi.com/graphics/SGIIMAGESPEC>
|
||||
#
|
||||
# History:
|
||||
# 1995-09-10 fl Created
|
||||
#
|
||||
# Copyright (c) 2008 by Karsten Hiddemann.
|
||||
# Copyright (c) 1997 by Secret Labs AB.
|
||||
# Copyright (c) 1995 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.2"
|
||||
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
|
||||
def i16(c):
|
||||
return ord(c[1]) + (ord(c[0])<<8)
|
||||
|
||||
def i32(c):
|
||||
return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return i16(prefix) == 474
|
||||
|
||||
##
|
||||
# Image plugin for SGI images.
|
||||
|
||||
class SgiImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "SGI"
|
||||
format_description = "SGI Image File Format"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# HEAD
|
||||
s = self.fp.read(512)
|
||||
if i16(s) != 474:
|
||||
raise SyntaxError("not an SGI image file")
|
||||
|
||||
# relevant header entries
|
||||
compression = ord(s[2])
|
||||
|
||||
# bytes, dimension, zsize
|
||||
layout = ord(s[3]), i16(s[4:]), i16(s[10:])
|
||||
|
||||
# determine mode from bytes/zsize
|
||||
if layout == (1, 2, 1) or layout == (1, 1, 1):
|
||||
self.mode = "L"
|
||||
elif layout == (1, 3, 3):
|
||||
self.mode = "RGB"
|
||||
elif layout == (1, 3, 4):
|
||||
self.mode = "RGBA"
|
||||
else:
|
||||
raise SyntaxError("unsupported SGI image mode")
|
||||
|
||||
# size
|
||||
self.size = i16(s[6:]), i16(s[8:])
|
||||
|
||||
|
||||
# decoder info
|
||||
if compression == 0:
|
||||
offset = 512
|
||||
pagesize = self.size[0]*self.size[1]*layout[0]
|
||||
self.tile = []
|
||||
for layer in self.mode:
|
||||
self.tile.append(("raw", (0,0)+self.size, offset, (layer,0,-1)))
|
||||
offset = offset + pagesize
|
||||
elif compression == 1:
|
||||
self.tile = [("sgi_rle", (0,0)+self.size, 512, (self.mode, 0, -1))]
|
||||
|
||||
#
|
||||
# registry
|
||||
|
||||
Image.register_open("SGI", SgiImageFile, _accept)
|
||||
|
||||
Image.register_extension("SGI", ".bw")
|
||||
Image.register_extension("SGI", ".rgb")
|
||||
Image.register_extension("SGI", ".rgba")
|
||||
|
||||
Image.register_extension("SGI", ".sgi") # really?
|
||||
294
Darwin/lib/python2.7/site-packages/PIL/SpiderImagePlugin.py
Normal file
294
Darwin/lib/python2.7/site-packages/PIL/SpiderImagePlugin.py
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
#
|
||||
# SPIDER image file handling
|
||||
#
|
||||
# History:
|
||||
# 2004-08-02 Created BB
|
||||
# 2006-03-02 added save method
|
||||
# 2006-03-13 added support for stack images
|
||||
#
|
||||
# Copyright (c) 2004 by Health Research Inc. (HRI) RENSSELAER, NY 12144.
|
||||
# Copyright (c) 2004 by William Baxter.
|
||||
# Copyright (c) 2004 by Secret Labs AB.
|
||||
# Copyright (c) 2004 by Fredrik Lundh.
|
||||
#
|
||||
|
||||
##
|
||||
# Image plugin for the Spider image format. This format is is used
|
||||
# by the SPIDER software, in processing image data from electron
|
||||
# microscopy and tomography.
|
||||
##
|
||||
|
||||
#
|
||||
# SpiderImagePlugin.py
|
||||
#
|
||||
# The Spider image format is used by SPIDER software, in processing
|
||||
# image data from electron microscopy and tomography.
|
||||
#
|
||||
# Spider home page:
|
||||
# http://www.wadsworth.org/spider_doc/spider/docs/spider.html
|
||||
#
|
||||
# Details about the Spider image format:
|
||||
# http://www.wadsworth.org/spider_doc/spider/docs/image_doc.html
|
||||
#
|
||||
|
||||
import Image, ImageFile
|
||||
import os, struct, sys
|
||||
|
||||
def isInt(f):
|
||||
try:
|
||||
i = int(f)
|
||||
if f-i == 0: return 1
|
||||
else: return 0
|
||||
except:
|
||||
return 0
|
||||
|
||||
iforms = [1,3,-11,-12,-21,-22]
|
||||
|
||||
# There is no magic number to identify Spider files, so just check a
|
||||
# series of header locations to see if they have reasonable values.
|
||||
# Returns no.of bytes in the header, if it is a valid Spider header,
|
||||
# otherwise returns 0
|
||||
|
||||
def isSpiderHeader(t):
|
||||
h = (99,) + t # add 1 value so can use spider header index start=1
|
||||
# header values 1,2,5,12,13,22,23 should be integers
|
||||
for i in [1,2,5,12,13,22,23]:
|
||||
if not isInt(h[i]): return 0
|
||||
# check iform
|
||||
iform = int(h[5])
|
||||
if not iform in iforms: return 0
|
||||
# check other header values
|
||||
labrec = int(h[13]) # no. records in file header
|
||||
labbyt = int(h[22]) # total no. of bytes in header
|
||||
lenbyt = int(h[23]) # record length in bytes
|
||||
#print "labrec = %d, labbyt = %d, lenbyt = %d" % (labrec,labbyt,lenbyt)
|
||||
if labbyt != (labrec * lenbyt): return 0
|
||||
# looks like a valid header
|
||||
return labbyt
|
||||
|
||||
def isSpiderImage(filename):
|
||||
fp = open(filename,'rb')
|
||||
f = fp.read(92) # read 23 * 4 bytes
|
||||
fp.close()
|
||||
bigendian = 1
|
||||
t = struct.unpack('>23f',f) # try big-endian first
|
||||
hdrlen = isSpiderHeader(t)
|
||||
if hdrlen == 0:
|
||||
bigendian = 0
|
||||
t = struct.unpack('<23f',f) # little-endian
|
||||
hdrlen = isSpiderHeader(t)
|
||||
return hdrlen
|
||||
|
||||
|
||||
class SpiderImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "SPIDER"
|
||||
format_description = "Spider 2D image"
|
||||
|
||||
def _open(self):
|
||||
# check header
|
||||
n = 27 * 4 # read 27 float values
|
||||
f = self.fp.read(n)
|
||||
|
||||
try:
|
||||
self.bigendian = 1
|
||||
t = struct.unpack('>27f',f) # try big-endian first
|
||||
hdrlen = isSpiderHeader(t)
|
||||
if hdrlen == 0:
|
||||
self.bigendian = 0
|
||||
t = struct.unpack('<27f',f) # little-endian
|
||||
hdrlen = isSpiderHeader(t)
|
||||
if hdrlen == 0:
|
||||
raise SyntaxError, "not a valid Spider file"
|
||||
except struct.error:
|
||||
raise SyntaxError, "not a valid Spider file"
|
||||
|
||||
h = (99,) + t # add 1 value : spider header index starts at 1
|
||||
iform = int(h[5])
|
||||
if iform != 1:
|
||||
raise SyntaxError, "not a Spider 2D image"
|
||||
|
||||
self.size = int(h[12]), int(h[2]) # size in pixels (width, height)
|
||||
self.istack = int(h[24])
|
||||
self.imgnumber = int(h[27])
|
||||
|
||||
if self.istack == 0 and self.imgnumber == 0:
|
||||
# stk=0, img=0: a regular 2D image
|
||||
offset = hdrlen
|
||||
self.nimages = 1
|
||||
elif self.istack > 0 and self.imgnumber == 0:
|
||||
# stk>0, img=0: Opening the stack for the first time
|
||||
self.imgbytes = int(h[12]) * int(h[2]) * 4
|
||||
self.hdrlen = hdrlen
|
||||
self.nimages = int(h[26])
|
||||
# Point to the first image in the stack
|
||||
offset = hdrlen * 2
|
||||
self.imgnumber = 1
|
||||
elif self.istack == 0 and self.imgnumber > 0:
|
||||
# stk=0, img>0: an image within the stack
|
||||
offset = hdrlen + self.stkoffset
|
||||
self.istack = 2 # So Image knows it's still a stack
|
||||
else:
|
||||
raise SyntaxError, "inconsistent stack header values"
|
||||
|
||||
if self.bigendian:
|
||||
self.rawmode = "F;32BF"
|
||||
else:
|
||||
self.rawmode = "F;32F"
|
||||
self.mode = "F"
|
||||
|
||||
self.tile = [("raw", (0, 0) + self.size, offset,
|
||||
(self.rawmode, 0, 1))]
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
|
||||
# 1st image index is zero (although SPIDER imgnumber starts at 1)
|
||||
def tell(self):
|
||||
if self.imgnumber < 1:
|
||||
return 0
|
||||
else:
|
||||
return self.imgnumber - 1
|
||||
|
||||
def seek(self, frame):
|
||||
if self.istack == 0:
|
||||
return
|
||||
if frame >= self.nimages:
|
||||
raise EOFError, "attempt to seek past end of file"
|
||||
self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
|
||||
self.fp = self.__fp
|
||||
self.fp.seek(self.stkoffset)
|
||||
self._open()
|
||||
|
||||
# returns a byte image after rescaling to 0..255
|
||||
def convert2byte(self, depth=255):
|
||||
(min, max) = self.getextrema()
|
||||
m = 1
|
||||
if max != min:
|
||||
m = depth / (max-min)
|
||||
b = -m * min
|
||||
return self.point(lambda i, m=m, b=b: i * m + b).convert("L")
|
||||
|
||||
# returns a ImageTk.PhotoImage object, after rescaling to 0..255
|
||||
def tkPhotoImage(self):
|
||||
import ImageTk
|
||||
return ImageTk.PhotoImage(self.convert2byte(), palette=256)
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Image series
|
||||
|
||||
# given a list of filenames, return a list of images
|
||||
def loadImageSeries(filelist=None):
|
||||
" create a list of Image.images for use in montage "
|
||||
if filelist == None or len(filelist) < 1:
|
||||
return
|
||||
|
||||
imglist = []
|
||||
for img in filelist:
|
||||
if not os.path.exists(img):
|
||||
print "unable to find %s" % img
|
||||
continue
|
||||
try:
|
||||
im = Image.open(img).convert2byte()
|
||||
except:
|
||||
if not isSpiderImage(img):
|
||||
print img + " is not a Spider image file"
|
||||
continue
|
||||
im.info['filename'] = img
|
||||
imglist.append(im)
|
||||
return imglist
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# For saving images in Spider format
|
||||
|
||||
def makeSpiderHeader(im):
|
||||
nsam,nrow = im.size
|
||||
lenbyt = nsam * 4 # There are labrec records in the header
|
||||
labrec = 1024 / lenbyt
|
||||
if 1024%lenbyt != 0: labrec += 1
|
||||
labbyt = labrec * lenbyt
|
||||
hdr = []
|
||||
nvalues = labbyt / 4
|
||||
for i in range(nvalues):
|
||||
hdr.append(0.0)
|
||||
|
||||
if len(hdr) < 23:
|
||||
return []
|
||||
|
||||
# NB these are Fortran indices
|
||||
hdr[1] = 1.0 # nslice (=1 for an image)
|
||||
hdr[2] = float(nrow) # number of rows per slice
|
||||
hdr[5] = 1.0 # iform for 2D image
|
||||
hdr[12] = float(nsam) # number of pixels per line
|
||||
hdr[13] = float(labrec) # number of records in file header
|
||||
hdr[22] = float(labbyt) # total number of bytes in header
|
||||
hdr[23] = float(lenbyt) # record length in bytes
|
||||
|
||||
# adjust for Fortran indexing
|
||||
hdr = hdr[1:]
|
||||
hdr.append(0.0)
|
||||
# pack binary data into a string
|
||||
hdrstr = []
|
||||
for v in hdr:
|
||||
hdrstr.append(struct.pack('f',v))
|
||||
return hdrstr
|
||||
|
||||
def _save(im, fp, filename):
|
||||
if im.mode[0] != "F":
|
||||
im = im.convert('F')
|
||||
|
||||
hdr = makeSpiderHeader(im)
|
||||
if len(hdr) < 256:
|
||||
raise IOError, "Error creating Spider header"
|
||||
|
||||
# write the SPIDER header
|
||||
try:
|
||||
fp = open(filename, 'wb')
|
||||
except:
|
||||
raise IOError, "Unable to open %s for writing" % filename
|
||||
fp.writelines(hdr)
|
||||
|
||||
rawmode = "F;32NF" #32-bit native floating point
|
||||
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode,0,1))])
|
||||
|
||||
fp.close()
|
||||
|
||||
def _save_spider(im, fp, filename):
|
||||
# get the filename extension and register it with Image
|
||||
fn, ext = os.path.splitext(filename)
|
||||
Image.register_extension("SPIDER", ext)
|
||||
_save(im, fp, filename)
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("SPIDER", SpiderImageFile)
|
||||
Image.register_save("SPIDER", _save_spider)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
if not sys.argv[1:]:
|
||||
print "Syntax: python SpiderImagePlugin.py Spiderimage [outfile]"
|
||||
sys.exit()
|
||||
|
||||
filename = sys.argv[1]
|
||||
if not isSpiderImage(filename):
|
||||
print "input image must be in Spider format"
|
||||
sys.exit()
|
||||
|
||||
outfile = ""
|
||||
if len(sys.argv[1:]) > 1:
|
||||
outfile = sys.argv[2]
|
||||
|
||||
im = Image.open(filename)
|
||||
print "image: " + str(im)
|
||||
print "format: " + str(im.format)
|
||||
print "size: " + str(im.size)
|
||||
print "mode: " + str(im.mode)
|
||||
print "max, min: ",
|
||||
print im.getextrema()
|
||||
|
||||
if outfile != "":
|
||||
# perform some image operation
|
||||
im = im.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
print "saving a flipped version of %s as %s " % (os.path.basename(filename), outfile)
|
||||
im.save(outfile, "SPIDER")
|
||||
86
Darwin/lib/python2.7/site-packages/PIL/SunImagePlugin.py
Normal file
86
Darwin/lib/python2.7/site-packages/PIL/SunImagePlugin.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# Sun image file handling
|
||||
#
|
||||
# History:
|
||||
# 1995-09-10 fl Created
|
||||
# 1996-05-28 fl Fixed 32-bit alignment
|
||||
# 1998-12-29 fl Import ImagePalette module
|
||||
# 2001-12-18 fl Fixed palette loading (from Jean-Claude Rimbault)
|
||||
#
|
||||
# Copyright (c) 1997-2001 by Secret Labs AB
|
||||
# Copyright (c) 1995-1996 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.3"
|
||||
|
||||
|
||||
import Image, ImageFile, ImagePalette
|
||||
|
||||
|
||||
def i16(c):
|
||||
return ord(c[1]) + (ord(c[0])<<8)
|
||||
|
||||
def i32(c):
|
||||
return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return i32(prefix) == 0x59a66a95
|
||||
|
||||
##
|
||||
# Image plugin for Sun raster files.
|
||||
|
||||
class SunImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "SUN"
|
||||
format_description = "Sun Raster File"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# HEAD
|
||||
s = self.fp.read(32)
|
||||
if i32(s) != 0x59a66a95:
|
||||
raise SyntaxError, "not an SUN raster file"
|
||||
|
||||
offset = 32
|
||||
|
||||
self.size = i32(s[4:8]), i32(s[8:12])
|
||||
|
||||
depth = i32(s[12:16])
|
||||
if depth == 1:
|
||||
self.mode, rawmode = "1", "1;I"
|
||||
elif depth == 8:
|
||||
self.mode = rawmode = "L"
|
||||
elif depth == 24:
|
||||
self.mode, rawmode = "RGB", "BGR"
|
||||
else:
|
||||
raise SyntaxError, "unsupported mode"
|
||||
|
||||
compression = i32(s[20:24])
|
||||
|
||||
if i32(s[24:28]) != 0:
|
||||
length = i32(s[28:32])
|
||||
offset = offset + length
|
||||
self.palette = ImagePalette.raw("RGB;L", self.fp.read(length))
|
||||
if self.mode == "L":
|
||||
self.mode = rawmode = "P"
|
||||
|
||||
stride = (((self.size[0] * depth + 7) / 8) + 3) & (~3)
|
||||
|
||||
if compression == 1:
|
||||
self.tile = [("raw", (0,0)+self.size, offset, (rawmode, stride))]
|
||||
elif compression == 2:
|
||||
self.tile = [("sun_rle", (0,0)+self.size, offset, rawmode)]
|
||||
|
||||
#
|
||||
# registry
|
||||
|
||||
Image.register_open("SUN", SunImageFile, _accept)
|
||||
|
||||
Image.register_extension("SUN", ".ras")
|
||||
57
Darwin/lib/python2.7/site-packages/PIL/TarIO.py
Normal file
57
Darwin/lib/python2.7/site-packages/PIL/TarIO.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# read files from within a tar file
|
||||
#
|
||||
# History:
|
||||
# 95-06-18 fl Created
|
||||
# 96-05-28 fl Open files in binary mode
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997.
|
||||
# Copyright (c) Fredrik Lundh 1995-96.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import ContainerIO
|
||||
import string
|
||||
|
||||
##
|
||||
# A file object that provides read access to a given member of a TAR
|
||||
# file.
|
||||
|
||||
class TarIO(ContainerIO.ContainerIO):
|
||||
|
||||
##
|
||||
# Create file object.
|
||||
#
|
||||
# @param tarfile Name of TAR file.
|
||||
# @param file Name of member file.
|
||||
|
||||
def __init__(self, tarfile, file):
|
||||
|
||||
fh = open(tarfile, "rb")
|
||||
|
||||
while 1:
|
||||
|
||||
s = fh.read(512)
|
||||
if len(s) != 512:
|
||||
raise IOError, "unexpected end of tar file"
|
||||
|
||||
name = s[:100]
|
||||
i = string.find(name, chr(0))
|
||||
if i == 0:
|
||||
raise IOError, "cannot find subfile"
|
||||
if i > 0:
|
||||
name = name[:i]
|
||||
|
||||
size = string.atoi(s[124:136], 8)
|
||||
|
||||
if file == name:
|
||||
break
|
||||
|
||||
fh.seek((size + 511) & (~511), 1)
|
||||
|
||||
# Open region
|
||||
ContainerIO.ContainerIO.__init__(self, fh, fh.tell(), size)
|
||||
201
Darwin/lib/python2.7/site-packages/PIL/TgaImagePlugin.py
Normal file
201
Darwin/lib/python2.7/site-packages/PIL/TgaImagePlugin.py
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# TGA file handling
|
||||
#
|
||||
# History:
|
||||
# 95-09-01 fl created (reads 24-bit files only)
|
||||
# 97-01-04 fl support more TGA versions, including compressed images
|
||||
# 98-07-04 fl fixed orientation and alpha layer bugs
|
||||
# 98-09-11 fl fixed orientation for runlength decoder
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997-98.
|
||||
# Copyright (c) Fredrik Lundh 1995-97.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.3"
|
||||
|
||||
import Image, ImageFile, ImagePalette
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Read RGA file
|
||||
|
||||
def i16(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8)
|
||||
|
||||
def i32(c):
|
||||
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
|
||||
|
||||
|
||||
MODES = {
|
||||
# map imagetype/depth to rawmode
|
||||
(1, 8): "P",
|
||||
(3, 1): "1",
|
||||
(3, 8): "L",
|
||||
(2, 16): "BGR;5",
|
||||
(2, 24): "BGR",
|
||||
(2, 32): "BGRA",
|
||||
}
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[0] == "\0"
|
||||
|
||||
##
|
||||
# Image plugin for Targa files.
|
||||
|
||||
class TgaImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "TGA"
|
||||
format_description = "Targa"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# process header
|
||||
s = self.fp.read(18)
|
||||
|
||||
id = ord(s[0])
|
||||
|
||||
colormaptype = ord(s[1])
|
||||
imagetype = ord(s[2])
|
||||
|
||||
depth = ord(s[16])
|
||||
|
||||
flags = ord(s[17])
|
||||
|
||||
self.size = i16(s[12:]), i16(s[14:])
|
||||
|
||||
# validate header fields
|
||||
if id != 0 or colormaptype not in (0, 1) or\
|
||||
self.size[0] <= 0 or self.size[1] <= 0 or\
|
||||
depth not in (1, 8, 16, 24, 32):
|
||||
raise SyntaxError, "not a TGA file"
|
||||
|
||||
# image mode
|
||||
if imagetype in (3, 11):
|
||||
self.mode = "L"
|
||||
if depth == 1:
|
||||
self.mode = "1" # ???
|
||||
elif imagetype in (1, 9):
|
||||
self.mode = "P"
|
||||
elif imagetype in (2, 10):
|
||||
self.mode = "RGB"
|
||||
if depth == 32:
|
||||
self.mode = "RGBA"
|
||||
else:
|
||||
raise SyntaxError, "unknown TGA mode"
|
||||
|
||||
# orientation
|
||||
orientation = flags & 0x30
|
||||
if orientation == 0x20:
|
||||
orientation = 1
|
||||
elif not orientation:
|
||||
orientation = -1
|
||||
else:
|
||||
raise SyntaxError, "unknown TGA orientation"
|
||||
|
||||
self.info["orientation"] = orientation
|
||||
|
||||
if imagetype & 8:
|
||||
self.info["compression"] = "tga_rle"
|
||||
|
||||
if colormaptype:
|
||||
# read palette
|
||||
start, size, mapdepth = i16(s[3:]), i16(s[5:]), i16(s[7:])
|
||||
if mapdepth == 16:
|
||||
self.palette = ImagePalette.raw("BGR;16",
|
||||
"\0"*2*start + self.fp.read(2*size))
|
||||
elif mapdepth == 24:
|
||||
self.palette = ImagePalette.raw("BGR",
|
||||
"\0"*3*start + self.fp.read(3*size))
|
||||
elif mapdepth == 32:
|
||||
self.palette = ImagePalette.raw("BGRA",
|
||||
"\0"*4*start + self.fp.read(4*size))
|
||||
|
||||
# setup tile descriptor
|
||||
try:
|
||||
rawmode = MODES[(imagetype&7, depth)]
|
||||
if imagetype & 8:
|
||||
# compressed
|
||||
self.tile = [("tga_rle", (0, 0)+self.size,
|
||||
self.fp.tell(), (rawmode, orientation, depth))]
|
||||
else:
|
||||
self.tile = [("raw", (0, 0)+self.size,
|
||||
self.fp.tell(), (rawmode, 0, orientation))]
|
||||
except KeyError:
|
||||
pass # cannot decode
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Write TGA file
|
||||
|
||||
def o16(i):
|
||||
return chr(i&255) + chr(i>>8&255)
|
||||
|
||||
def o32(i):
|
||||
return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
|
||||
|
||||
SAVE = {
|
||||
"1": ("1", 1, 0, 3),
|
||||
"L": ("L", 8, 0, 3),
|
||||
"P": ("P", 8, 1, 1),
|
||||
"RGB": ("BGR", 24, 0, 2),
|
||||
"RGBA": ("BGRA", 32, 0, 2),
|
||||
}
|
||||
|
||||
def _save(im, fp, filename, check=0):
|
||||
|
||||
try:
|
||||
rawmode, bits, colormaptype, imagetype = SAVE[im.mode]
|
||||
except KeyError:
|
||||
raise IOError("cannot write mode %s as TGA" % im.mode)
|
||||
|
||||
if check:
|
||||
return check
|
||||
|
||||
if colormaptype:
|
||||
colormapfirst, colormaplength, colormapentry = 0, 256, 24
|
||||
else:
|
||||
colormapfirst, colormaplength, colormapentry = 0, 0, 0
|
||||
|
||||
if im.mode == "RGBA":
|
||||
flags = 8
|
||||
else:
|
||||
flags = 0
|
||||
|
||||
orientation = im.info.get("orientation", -1)
|
||||
if orientation > 0:
|
||||
flags = flags | 0x20
|
||||
|
||||
fp.write("\000" +
|
||||
chr(colormaptype) +
|
||||
chr(imagetype) +
|
||||
o16(colormapfirst) +
|
||||
o16(colormaplength) +
|
||||
chr(colormapentry) +
|
||||
o16(0) +
|
||||
o16(0) +
|
||||
o16(im.size[0]) +
|
||||
o16(im.size[1]) +
|
||||
chr(bits) +
|
||||
chr(flags))
|
||||
|
||||
if colormaptype:
|
||||
fp.write(im.im.getpalette("RGB", "BGR"))
|
||||
|
||||
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, orientation))])
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Registry
|
||||
|
||||
Image.register_open("TGA", TgaImageFile, _accept)
|
||||
Image.register_save("TGA", _save)
|
||||
|
||||
Image.register_extension("TGA", ".tga")
|
||||
860
Darwin/lib/python2.7/site-packages/PIL/TiffImagePlugin.py
Normal file
860
Darwin/lib/python2.7/site-packages/PIL/TiffImagePlugin.py
Normal file
|
|
@ -0,0 +1,860 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# TIFF file handling
|
||||
#
|
||||
# TIFF is a flexible, if somewhat aged, image file format originally
|
||||
# defined by Aldus. Although TIFF supports a wide variety of pixel
|
||||
# layouts and compression methods, the name doesn't really stand for
|
||||
# "thousands of incompatible file formats," it just feels that way.
|
||||
#
|
||||
# To read TIFF data from a stream, the stream must be seekable. For
|
||||
# progressive decoding, make sure to use TIFF files where the tag
|
||||
# directory is placed first in the file.
|
||||
#
|
||||
# History:
|
||||
# 1995-09-01 fl Created
|
||||
# 1996-05-04 fl Handle JPEGTABLES tag
|
||||
# 1996-05-18 fl Fixed COLORMAP support
|
||||
# 1997-01-05 fl Fixed PREDICTOR support
|
||||
# 1997-08-27 fl Added support for rational tags (from Perry Stoll)
|
||||
# 1998-01-10 fl Fixed seek/tell (from Jan Blom)
|
||||
# 1998-07-15 fl Use private names for internal variables
|
||||
# 1999-06-13 fl Rewritten for PIL 1.0 (1.0)
|
||||
# 2000-10-11 fl Additional fixes for Python 2.0 (1.1)
|
||||
# 2001-04-17 fl Fixed rewind support (seek to frame 0) (1.2)
|
||||
# 2001-05-12 fl Added write support for more tags (from Greg Couch) (1.3)
|
||||
# 2001-12-18 fl Added workaround for broken Matrox library
|
||||
# 2002-01-18 fl Don't mess up if photometric tag is missing (D. Alan Stewart)
|
||||
# 2003-05-19 fl Check FILLORDER tag
|
||||
# 2003-09-26 fl Added RGBa support
|
||||
# 2004-02-24 fl Added DPI support; fixed rational write support
|
||||
# 2005-02-07 fl Added workaround for broken Corel Draw 10 files
|
||||
# 2006-01-09 fl Added support for float/double tags (from Russell Nelson)
|
||||
#
|
||||
# Copyright (c) 1997-2006 by Secret Labs AB. All rights reserved.
|
||||
# Copyright (c) 1995-1997 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "1.3.5"
|
||||
|
||||
import Image, ImageFile
|
||||
import ImagePalette
|
||||
|
||||
import array, string, sys
|
||||
|
||||
II = "II" # little-endian (intel-style)
|
||||
MM = "MM" # big-endian (motorola-style)
|
||||
|
||||
try:
|
||||
if sys.byteorder == "little":
|
||||
native_prefix = II
|
||||
else:
|
||||
native_prefix = MM
|
||||
except AttributeError:
|
||||
if ord(array.array("i",[1]).tostring()[0]):
|
||||
native_prefix = II
|
||||
else:
|
||||
native_prefix = MM
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Read TIFF files
|
||||
|
||||
def il16(c,o=0):
|
||||
return ord(c[o]) + (ord(c[o+1])<<8)
|
||||
def il32(c,o=0):
|
||||
return ord(c[o]) + (ord(c[o+1])<<8) + (ord(c[o+2])<<16) + (ord(c[o+3])<<24)
|
||||
def ol16(i):
|
||||
return chr(i&255) + chr(i>>8&255)
|
||||
def ol32(i):
|
||||
return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
|
||||
|
||||
def ib16(c,o=0):
|
||||
return ord(c[o+1]) + (ord(c[o])<<8)
|
||||
def ib32(c,o=0):
|
||||
return ord(c[o+3]) + (ord(c[o+2])<<8) + (ord(c[o+1])<<16) + (ord(c[o])<<24)
|
||||
def ob16(i):
|
||||
return chr(i>>8&255) + chr(i&255)
|
||||
def ob32(i):
|
||||
return chr(i>>24&255) + chr(i>>16&255) + chr(i>>8&255) + chr(i&255)
|
||||
|
||||
# a few tag names, just to make the code below a bit more readable
|
||||
IMAGEWIDTH = 256
|
||||
IMAGELENGTH = 257
|
||||
BITSPERSAMPLE = 258
|
||||
COMPRESSION = 259
|
||||
PHOTOMETRIC_INTERPRETATION = 262
|
||||
FILLORDER = 266
|
||||
IMAGEDESCRIPTION = 270
|
||||
STRIPOFFSETS = 273
|
||||
SAMPLESPERPIXEL = 277
|
||||
ROWSPERSTRIP = 278
|
||||
STRIPBYTECOUNTS = 279
|
||||
X_RESOLUTION = 282
|
||||
Y_RESOLUTION = 283
|
||||
PLANAR_CONFIGURATION = 284
|
||||
RESOLUTION_UNIT = 296
|
||||
SOFTWARE = 305
|
||||
DATE_TIME = 306
|
||||
ARTIST = 315
|
||||
PREDICTOR = 317
|
||||
COLORMAP = 320
|
||||
TILEOFFSETS = 324
|
||||
EXTRASAMPLES = 338
|
||||
SAMPLEFORMAT = 339
|
||||
JPEGTABLES = 347
|
||||
COPYRIGHT = 33432
|
||||
IPTC_NAA_CHUNK = 33723 # newsphoto properties
|
||||
PHOTOSHOP_CHUNK = 34377 # photoshop properties
|
||||
ICCPROFILE = 34675
|
||||
EXIFIFD = 34665
|
||||
XMP = 700
|
||||
|
||||
COMPRESSION_INFO = {
|
||||
# Compression => pil compression name
|
||||
1: "raw",
|
||||
2: "tiff_ccitt",
|
||||
3: "group3",
|
||||
4: "group4",
|
||||
5: "tiff_lzw",
|
||||
6: "tiff_jpeg", # obsolete
|
||||
7: "jpeg",
|
||||
32771: "tiff_raw_16", # 16-bit padding
|
||||
32773: "packbits"
|
||||
}
|
||||
|
||||
OPEN_INFO = {
|
||||
# (ByteOrder, PhotoInterpretation, SampleFormat, FillOrder, BitsPerSample,
|
||||
# ExtraSamples) => mode, rawmode
|
||||
(II, 0, 1, 1, (1,), ()): ("1", "1;I"),
|
||||
(II, 0, 1, 2, (1,), ()): ("1", "1;IR"),
|
||||
(II, 0, 1, 1, (8,), ()): ("L", "L;I"),
|
||||
(II, 0, 1, 2, (8,), ()): ("L", "L;IR"),
|
||||
(II, 1, 1, 1, (1,), ()): ("1", "1"),
|
||||
(II, 1, 1, 2, (1,), ()): ("1", "1;R"),
|
||||
(II, 1, 1, 1, (8,), ()): ("L", "L"),
|
||||
(II, 1, 1, 1, (8,8), (2,)): ("LA", "LA"),
|
||||
(II, 1, 1, 2, (8,), ()): ("L", "L;R"),
|
||||
(II, 1, 1, 1, (16,), ()): ("I;16", "I;16"),
|
||||
(II, 1, 2, 1, (16,), ()): ("I;16S", "I;16S"),
|
||||
(II, 1, 2, 1, (32,), ()): ("I", "I;32S"),
|
||||
(II, 1, 3, 1, (32,), ()): ("F", "F;32F"),
|
||||
(II, 2, 1, 1, (8,8,8), ()): ("RGB", "RGB"),
|
||||
(II, 2, 1, 2, (8,8,8), ()): ("RGB", "RGB;R"),
|
||||
(II, 2, 1, 1, (8,8,8,8), (0,)): ("RGBX", "RGBX"),
|
||||
(II, 2, 1, 1, (8,8,8,8), (1,)): ("RGBA", "RGBa"),
|
||||
(II, 2, 1, 1, (8,8,8,8), (2,)): ("RGBA", "RGBA"),
|
||||
(II, 2, 1, 1, (8,8,8,8), (999,)): ("RGBA", "RGBA"), # corel draw 10
|
||||
(II, 3, 1, 1, (1,), ()): ("P", "P;1"),
|
||||
(II, 3, 1, 2, (1,), ()): ("P", "P;1R"),
|
||||
(II, 3, 1, 1, (2,), ()): ("P", "P;2"),
|
||||
(II, 3, 1, 2, (2,), ()): ("P", "P;2R"),
|
||||
(II, 3, 1, 1, (4,), ()): ("P", "P;4"),
|
||||
(II, 3, 1, 2, (4,), ()): ("P", "P;4R"),
|
||||
(II, 3, 1, 1, (8,), ()): ("P", "P"),
|
||||
(II, 3, 1, 1, (8,8), (2,)): ("PA", "PA"),
|
||||
(II, 3, 1, 2, (8,), ()): ("P", "P;R"),
|
||||
(II, 5, 1, 1, (8,8,8,8), ()): ("CMYK", "CMYK"),
|
||||
(II, 6, 1, 1, (8,8,8), ()): ("YCbCr", "YCbCr"),
|
||||
(II, 8, 1, 1, (8,8,8), ()): ("LAB", "LAB"),
|
||||
|
||||
(MM, 0, 1, 1, (1,), ()): ("1", "1;I"),
|
||||
(MM, 0, 1, 2, (1,), ()): ("1", "1;IR"),
|
||||
(MM, 0, 1, 1, (8,), ()): ("L", "L;I"),
|
||||
(MM, 0, 1, 2, (8,), ()): ("L", "L;IR"),
|
||||
(MM, 1, 1, 1, (1,), ()): ("1", "1"),
|
||||
(MM, 1, 1, 2, (1,), ()): ("1", "1;R"),
|
||||
(MM, 1, 1, 1, (8,), ()): ("L", "L"),
|
||||
(MM, 1, 1, 1, (8,8), (2,)): ("LA", "LA"),
|
||||
(MM, 1, 1, 2, (8,), ()): ("L", "L;R"),
|
||||
(MM, 1, 1, 1, (16,), ()): ("I;16B", "I;16B"),
|
||||
(MM, 1, 2, 1, (16,), ()): ("I;16BS", "I;16BS"),
|
||||
(MM, 1, 2, 1, (32,), ()): ("I;32BS", "I;32BS"),
|
||||
(MM, 1, 3, 1, (32,), ()): ("F;32BF", "F;32BF"),
|
||||
(MM, 2, 1, 1, (8,8,8), ()): ("RGB", "RGB"),
|
||||
(MM, 2, 1, 2, (8,8,8), ()): ("RGB", "RGB;R"),
|
||||
(MM, 2, 1, 1, (8,8,8,8), (0,)): ("RGBX", "RGBX"),
|
||||
(MM, 2, 1, 1, (8,8,8,8), (1,)): ("RGBA", "RGBa"),
|
||||
(MM, 2, 1, 1, (8,8,8,8), (2,)): ("RGBA", "RGBA"),
|
||||
(MM, 2, 1, 1, (8,8,8,8), (999,)): ("RGBA", "RGBA"), # corel draw 10
|
||||
(MM, 3, 1, 1, (1,), ()): ("P", "P;1"),
|
||||
(MM, 3, 1, 2, (1,), ()): ("P", "P;1R"),
|
||||
(MM, 3, 1, 1, (2,), ()): ("P", "P;2"),
|
||||
(MM, 3, 1, 2, (2,), ()): ("P", "P;2R"),
|
||||
(MM, 3, 1, 1, (4,), ()): ("P", "P;4"),
|
||||
(MM, 3, 1, 2, (4,), ()): ("P", "P;4R"),
|
||||
(MM, 3, 1, 1, (8,), ()): ("P", "P"),
|
||||
(MM, 3, 1, 1, (8,8), (2,)): ("PA", "PA"),
|
||||
(MM, 3, 1, 2, (8,), ()): ("P", "P;R"),
|
||||
(MM, 5, 1, 1, (8,8,8,8), ()): ("CMYK", "CMYK"),
|
||||
(MM, 6, 1, 1, (8,8,8), ()): ("YCbCr", "YCbCr"),
|
||||
(MM, 8, 1, 1, (8,8,8), ()): ("LAB", "LAB"),
|
||||
|
||||
}
|
||||
|
||||
PREFIXES = ["MM\000\052", "II\052\000", "II\xBC\000"]
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] in PREFIXES
|
||||
|
||||
##
|
||||
# Wrapper for TIFF IFDs.
|
||||
|
||||
class ImageFileDirectory:
|
||||
|
||||
# represents a TIFF tag directory. to speed things up,
|
||||
# we don't decode tags unless they're asked for.
|
||||
|
||||
def __init__(self, prefix):
|
||||
self.prefix = prefix[:2]
|
||||
if self.prefix == MM:
|
||||
self.i16, self.i32 = ib16, ib32
|
||||
self.o16, self.o32 = ob16, ob32
|
||||
elif self.prefix == II:
|
||||
self.i16, self.i32 = il16, il32
|
||||
self.o16, self.o32 = ol16, ol32
|
||||
else:
|
||||
raise SyntaxError("not a TIFF IFD")
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.tags = {}
|
||||
self.tagdata = {}
|
||||
self.tagtype = {} # added 2008-06-05 by Florian Hoech
|
||||
self.next = None
|
||||
|
||||
# dictionary API (sort of)
|
||||
|
||||
def keys(self):
|
||||
return self.tagdata.keys() + self.tags.keys()
|
||||
|
||||
def items(self):
|
||||
items = self.tags.items()
|
||||
for tag in self.tagdata.keys():
|
||||
items.append((tag, self[tag]))
|
||||
return items
|
||||
|
||||
def __len__(self):
|
||||
return len(self.tagdata) + len(self.tags)
|
||||
|
||||
def __getitem__(self, tag):
|
||||
try:
|
||||
return self.tags[tag]
|
||||
except KeyError:
|
||||
type, data = self.tagdata[tag] # unpack on the fly
|
||||
size, handler = self.load_dispatch[type]
|
||||
self.tags[tag] = data = handler(self, data)
|
||||
del self.tagdata[tag]
|
||||
return data
|
||||
|
||||
def get(self, tag, default=None):
|
||||
try:
|
||||
return self[tag]
|
||||
except KeyError:
|
||||
return default
|
||||
|
||||
def getscalar(self, tag, default=None):
|
||||
try:
|
||||
value = self[tag]
|
||||
if len(value) != 1:
|
||||
if tag == SAMPLEFORMAT:
|
||||
# work around broken (?) matrox library
|
||||
# (from Ted Wright, via Bob Klimek)
|
||||
raise KeyError # use default
|
||||
raise ValueError, "not a scalar"
|
||||
return value[0]
|
||||
except KeyError:
|
||||
if default is None:
|
||||
raise
|
||||
return default
|
||||
|
||||
def has_key(self, tag):
|
||||
return self.tags.has_key(tag) or self.tagdata.has_key(tag)
|
||||
|
||||
def __setitem__(self, tag, value):
|
||||
if type(value) is not type(()):
|
||||
value = (value,)
|
||||
self.tags[tag] = value
|
||||
|
||||
# load primitives
|
||||
|
||||
load_dispatch = {}
|
||||
|
||||
def load_byte(self, data):
|
||||
l = []
|
||||
for i in range(len(data)):
|
||||
l.append(ord(data[i]))
|
||||
return tuple(l)
|
||||
load_dispatch[1] = (1, load_byte)
|
||||
|
||||
def load_string(self, data):
|
||||
if data[-1:] == '\0':
|
||||
data = data[:-1]
|
||||
return data
|
||||
load_dispatch[2] = (1, load_string)
|
||||
|
||||
def load_short(self, data):
|
||||
l = []
|
||||
for i in range(0, len(data), 2):
|
||||
l.append(self.i16(data, i))
|
||||
return tuple(l)
|
||||
load_dispatch[3] = (2, load_short)
|
||||
|
||||
def load_long(self, data):
|
||||
l = []
|
||||
for i in range(0, len(data), 4):
|
||||
l.append(self.i32(data, i))
|
||||
return tuple(l)
|
||||
load_dispatch[4] = (4, load_long)
|
||||
|
||||
def load_rational(self, data):
|
||||
l = []
|
||||
for i in range(0, len(data), 8):
|
||||
l.append((self.i32(data, i), self.i32(data, i+4)))
|
||||
return tuple(l)
|
||||
load_dispatch[5] = (8, load_rational)
|
||||
|
||||
def load_float(self, data):
|
||||
a = array.array("f", data)
|
||||
if self.prefix != native_prefix:
|
||||
a.byteswap()
|
||||
return tuple(a)
|
||||
load_dispatch[11] = (4, load_float)
|
||||
|
||||
def load_double(self, data):
|
||||
a = array.array("d", data)
|
||||
if self.prefix != native_prefix:
|
||||
a.byteswap()
|
||||
return tuple(a)
|
||||
load_dispatch[12] = (8, load_double)
|
||||
|
||||
def load_undefined(self, data):
|
||||
# Untyped data
|
||||
return data
|
||||
load_dispatch[7] = (1, load_undefined)
|
||||
|
||||
def load(self, fp):
|
||||
# load tag dictionary
|
||||
|
||||
self.reset()
|
||||
|
||||
i16 = self.i16
|
||||
i32 = self.i32
|
||||
|
||||
for i in range(i16(fp.read(2))):
|
||||
|
||||
ifd = fp.read(12)
|
||||
|
||||
tag, typ = i16(ifd), i16(ifd, 2)
|
||||
|
||||
if Image.DEBUG:
|
||||
import TiffTags
|
||||
tagname = TiffTags.TAGS.get(tag, "unknown")
|
||||
typname = TiffTags.TYPES.get(typ, "unknown")
|
||||
print "tag: %s (%d)" % (tagname, tag),
|
||||
print "- type: %s (%d)" % (typname, typ),
|
||||
|
||||
try:
|
||||
dispatch = self.load_dispatch[typ]
|
||||
except KeyError:
|
||||
if Image.DEBUG:
|
||||
print "- unsupported type", typ
|
||||
continue # ignore unsupported type
|
||||
|
||||
size, handler = dispatch
|
||||
|
||||
size = size * i32(ifd, 4)
|
||||
|
||||
# Get and expand tag value
|
||||
if size > 4:
|
||||
here = fp.tell()
|
||||
fp.seek(i32(ifd, 8))
|
||||
data = ImageFile._safe_read(fp, size)
|
||||
fp.seek(here)
|
||||
else:
|
||||
data = ifd[8:8+size]
|
||||
|
||||
if len(data) != size:
|
||||
raise IOError, "not enough data"
|
||||
|
||||
self.tagdata[tag] = typ, data
|
||||
self.tagtype[tag] = typ
|
||||
|
||||
if Image.DEBUG:
|
||||
if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, ICCPROFILE, XMP):
|
||||
print "- value: <table: %d bytes>" % size
|
||||
else:
|
||||
print "- value:", self[tag]
|
||||
|
||||
self.next = i32(fp.read(4))
|
||||
|
||||
# save primitives
|
||||
|
||||
def save(self, fp):
|
||||
|
||||
o16 = self.o16
|
||||
o32 = self.o32
|
||||
|
||||
fp.write(o16(len(self.tags)))
|
||||
|
||||
# always write in ascending tag order
|
||||
tags = self.tags.items()
|
||||
tags.sort()
|
||||
|
||||
directory = []
|
||||
append = directory.append
|
||||
|
||||
offset = fp.tell() + len(self.tags) * 12 + 4
|
||||
|
||||
stripoffsets = None
|
||||
|
||||
# pass 1: convert tags to binary format
|
||||
for tag, value in tags:
|
||||
|
||||
typ = None
|
||||
|
||||
if self.tagtype.has_key(tag):
|
||||
typ = self.tagtype[tag]
|
||||
|
||||
if typ == 1:
|
||||
# byte data
|
||||
data = value = string.join(map(chr, value), "")
|
||||
elif typ == 7:
|
||||
# untyped data
|
||||
data = value = string.join(value, "")
|
||||
elif type(value[0]) is type(""):
|
||||
# string data
|
||||
typ = 2
|
||||
data = value = string.join(value, "\0") + "\0"
|
||||
else:
|
||||
# integer data
|
||||
if tag == STRIPOFFSETS:
|
||||
stripoffsets = len(directory)
|
||||
typ = 4 # to avoid catch-22
|
||||
elif tag in (X_RESOLUTION, Y_RESOLUTION):
|
||||
# identify rational data fields
|
||||
typ = 5
|
||||
elif not typ:
|
||||
typ = 3
|
||||
for v in value:
|
||||
if v >= 65536:
|
||||
typ = 4
|
||||
if typ == 3:
|
||||
data = string.join(map(o16, value), "")
|
||||
else:
|
||||
data = string.join(map(o32, value), "")
|
||||
|
||||
if Image.DEBUG:
|
||||
import TiffTags
|
||||
tagname = TiffTags.TAGS.get(tag, "unknown")
|
||||
typname = TiffTags.TYPES.get(typ, "unknown")
|
||||
print "save: %s (%d)" % (tagname, tag),
|
||||
print "- type: %s (%d)" % (typname, typ),
|
||||
if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, ICCPROFILE, XMP):
|
||||
size = len(data)
|
||||
print "- value: <table: %d bytes>" % size
|
||||
else:
|
||||
print "- value:", value
|
||||
|
||||
# figure out if data fits into the directory
|
||||
if len(data) == 4:
|
||||
append((tag, typ, len(value), data, ""))
|
||||
elif len(data) < 4:
|
||||
append((tag, typ, len(value), data + (4-len(data))*"\0", ""))
|
||||
else:
|
||||
count = len(value)
|
||||
if typ == 5:
|
||||
count = count / 2 # adjust for rational data field
|
||||
append((tag, typ, count, o32(offset), data))
|
||||
offset = offset + len(data)
|
||||
if offset & 1:
|
||||
offset = offset + 1 # word padding
|
||||
|
||||
# update strip offset data to point beyond auxiliary data
|
||||
if stripoffsets is not None:
|
||||
tag, typ, count, value, data = directory[stripoffsets]
|
||||
assert not data, "multistrip support not yet implemented"
|
||||
value = o32(self.i32(value) + offset)
|
||||
directory[stripoffsets] = tag, typ, count, value, data
|
||||
|
||||
# pass 2: write directory to file
|
||||
for tag, typ, count, value, data in directory:
|
||||
if Image.DEBUG > 1:
|
||||
print tag, typ, count, repr(value), repr(data)
|
||||
fp.write(o16(tag) + o16(typ) + o32(count) + value)
|
||||
|
||||
# -- overwrite here for multi-page --
|
||||
fp.write("\0\0\0\0") # end of directory
|
||||
|
||||
# pass 3: write auxiliary data to file
|
||||
for tag, typ, count, value, data in directory:
|
||||
fp.write(data)
|
||||
if len(data) & 1:
|
||||
fp.write("\0")
|
||||
|
||||
return offset
|
||||
|
||||
##
|
||||
# Image plugin for TIFF files.
|
||||
|
||||
class TiffImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "TIFF"
|
||||
format_description = "Adobe TIFF"
|
||||
|
||||
def _open(self):
|
||||
"Open the first image in a TIFF file"
|
||||
|
||||
# Header
|
||||
ifh = self.fp.read(8)
|
||||
|
||||
if ifh[:4] not in PREFIXES:
|
||||
raise SyntaxError, "not a TIFF file"
|
||||
|
||||
# image file directory (tag dictionary)
|
||||
self.tag = self.ifd = ImageFileDirectory(ifh[:2])
|
||||
|
||||
# setup frame pointers
|
||||
self.__first = self.__next = self.ifd.i32(ifh, 4)
|
||||
self.__frame = -1
|
||||
self.__fp = self.fp
|
||||
|
||||
# and load the first frame
|
||||
self._seek(0)
|
||||
|
||||
def seek(self, frame):
|
||||
"Select a given frame as current image"
|
||||
|
||||
if frame < 0:
|
||||
frame = 0
|
||||
self._seek(frame)
|
||||
|
||||
def tell(self):
|
||||
"Return the current frame number"
|
||||
|
||||
return self._tell()
|
||||
|
||||
def _seek(self, frame):
|
||||
|
||||
self.fp = self.__fp
|
||||
if frame < self.__frame:
|
||||
# rewind file
|
||||
self.__frame = -1
|
||||
self.__next = self.__first
|
||||
while self.__frame < frame:
|
||||
if not self.__next:
|
||||
raise EOFError, "no more images in TIFF file"
|
||||
self.fp.seek(self.__next)
|
||||
self.tag.load(self.fp)
|
||||
self.__next = self.tag.next
|
||||
self.__frame = self.__frame + 1
|
||||
self._setup()
|
||||
|
||||
def _tell(self):
|
||||
|
||||
return self.__frame
|
||||
|
||||
def _decoder(self, rawmode, layer):
|
||||
"Setup decoder contexts"
|
||||
|
||||
args = None
|
||||
if rawmode == "RGB" and self._planar_configuration == 2:
|
||||
rawmode = rawmode[layer]
|
||||
compression = self._compression
|
||||
if compression == "raw":
|
||||
args = (rawmode, 0, 1)
|
||||
elif compression == "jpeg":
|
||||
args = rawmode, ""
|
||||
if self.tag.has_key(JPEGTABLES):
|
||||
# Hack to handle abbreviated JPEG headers
|
||||
self.tile_prefix = self.tag[JPEGTABLES]
|
||||
elif compression == "packbits":
|
||||
args = rawmode
|
||||
elif compression == "tiff_lzw":
|
||||
args = rawmode
|
||||
if self.tag.has_key(317):
|
||||
# Section 14: Differencing Predictor
|
||||
self.decoderconfig = (self.tag[PREDICTOR][0],)
|
||||
|
||||
if self.tag.has_key(ICCPROFILE):
|
||||
self.info['icc_profile'] = self.tag[ICCPROFILE]
|
||||
|
||||
return args
|
||||
|
||||
def _setup(self):
|
||||
"Setup this image object based on current tags"
|
||||
|
||||
if self.tag.has_key(0xBC01):
|
||||
raise IOError, "Windows Media Photo files not yet supported"
|
||||
|
||||
getscalar = self.tag.getscalar
|
||||
|
||||
# extract relevant tags
|
||||
self._compression = COMPRESSION_INFO[getscalar(COMPRESSION, 1)]
|
||||
self._planar_configuration = getscalar(PLANAR_CONFIGURATION, 1)
|
||||
|
||||
# photometric is a required tag, but not everyone is reading
|
||||
# the specification
|
||||
photo = getscalar(PHOTOMETRIC_INTERPRETATION, 0)
|
||||
|
||||
fillorder = getscalar(FILLORDER, 1)
|
||||
|
||||
if Image.DEBUG:
|
||||
print "*** Summary ***"
|
||||
print "- compression:", self._compression
|
||||
print "- photometric_interpretation:", photo
|
||||
print "- planar_configuration:", self._planar_configuration
|
||||
print "- fill_order:", fillorder
|
||||
|
||||
# size
|
||||
xsize = getscalar(IMAGEWIDTH)
|
||||
ysize = getscalar(IMAGELENGTH)
|
||||
self.size = xsize, ysize
|
||||
|
||||
if Image.DEBUG:
|
||||
print "- size:", self.size
|
||||
|
||||
format = getscalar(SAMPLEFORMAT, 1)
|
||||
|
||||
# mode: check photometric interpretation and bits per pixel
|
||||
key = (
|
||||
self.tag.prefix, photo, format, fillorder,
|
||||
self.tag.get(BITSPERSAMPLE, (1,)),
|
||||
self.tag.get(EXTRASAMPLES, ())
|
||||
)
|
||||
if Image.DEBUG:
|
||||
print "format key:", key
|
||||
try:
|
||||
self.mode, rawmode = OPEN_INFO[key]
|
||||
except KeyError:
|
||||
if Image.DEBUG:
|
||||
print "- unsupported format"
|
||||
raise SyntaxError, "unknown pixel mode"
|
||||
|
||||
if Image.DEBUG:
|
||||
print "- raw mode:", rawmode
|
||||
print "- pil mode:", self.mode
|
||||
|
||||
self.info["compression"] = self._compression
|
||||
|
||||
xres = getscalar(X_RESOLUTION, (1, 1))
|
||||
yres = getscalar(Y_RESOLUTION, (1, 1))
|
||||
|
||||
if xres and yres:
|
||||
xres = xres[0] / (xres[1] or 1)
|
||||
yres = yres[0] / (yres[1] or 1)
|
||||
resunit = getscalar(RESOLUTION_UNIT, 1)
|
||||
if resunit == 2: # dots per inch
|
||||
self.info["dpi"] = xres, yres
|
||||
elif resunit == 3: # dots per centimeter. convert to dpi
|
||||
self.info["dpi"] = xres * 2.54, yres * 2.54
|
||||
else: # No absolute unit of measurement
|
||||
self.info["resolution"] = xres, yres
|
||||
|
||||
# build tile descriptors
|
||||
x = y = l = 0
|
||||
self.tile = []
|
||||
if self.tag.has_key(STRIPOFFSETS):
|
||||
# striped image
|
||||
h = getscalar(ROWSPERSTRIP, ysize)
|
||||
w = self.size[0]
|
||||
a = None
|
||||
for o in self.tag[STRIPOFFSETS]:
|
||||
if not a:
|
||||
a = self._decoder(rawmode, l)
|
||||
self.tile.append(
|
||||
(self._compression,
|
||||
(0, min(y, ysize), w, min(y+h, ysize)),
|
||||
o, a))
|
||||
y = y + h
|
||||
if y >= self.size[1]:
|
||||
x = y = 0
|
||||
l = l + 1
|
||||
a = None
|
||||
elif self.tag.has_key(TILEOFFSETS):
|
||||
# tiled image
|
||||
w = getscalar(322)
|
||||
h = getscalar(323)
|
||||
a = None
|
||||
for o in self.tag[TILEOFFSETS]:
|
||||
if not a:
|
||||
a = self._decoder(rawmode, l)
|
||||
# FIXME: this doesn't work if the image size
|
||||
# is not a multiple of the tile size...
|
||||
self.tile.append(
|
||||
(self._compression,
|
||||
(x, y, x+w, y+h),
|
||||
o, a))
|
||||
x = x + w
|
||||
if x >= self.size[0]:
|
||||
x, y = 0, y + h
|
||||
if y >= self.size[1]:
|
||||
x = y = 0
|
||||
l = l + 1
|
||||
a = None
|
||||
else:
|
||||
if Image.DEBUG:
|
||||
print "- unsupported data organization"
|
||||
raise SyntaxError("unknown data organization")
|
||||
|
||||
# fixup palette descriptor
|
||||
|
||||
if self.mode == "P":
|
||||
palette = map(lambda a: chr(a / 256), self.tag[COLORMAP])
|
||||
self.palette = ImagePalette.raw("RGB;L", string.join(palette, ""))
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Write TIFF files
|
||||
|
||||
# little endian is default except for image modes with explict big endian byte-order
|
||||
|
||||
SAVE_INFO = {
|
||||
# mode => rawmode, byteorder, photometrics, sampleformat, bitspersample, extra
|
||||
"1": ("1", II, 1, 1, (1,), None),
|
||||
"L": ("L", II, 1, 1, (8,), None),
|
||||
"LA": ("LA", II, 1, 1, (8,8), 2),
|
||||
"P": ("P", II, 3, 1, (8,), None),
|
||||
"PA": ("PA", II, 3, 1, (8,8), 2),
|
||||
"I": ("I;32S", II, 1, 2, (32,), None),
|
||||
"I;16": ("I;16", II, 1, 1, (16,), None),
|
||||
"I;16S": ("I;16S", II, 1, 2, (16,), None),
|
||||
"F": ("F;32F", II, 1, 3, (32,), None),
|
||||
"RGB": ("RGB", II, 2, 1, (8,8,8), None),
|
||||
"RGBX": ("RGBX", II, 2, 1, (8,8,8,8), 0),
|
||||
"RGBA": ("RGBA", II, 2, 1, (8,8,8,8), 2),
|
||||
"CMYK": ("CMYK", II, 5, 1, (8,8,8,8), None),
|
||||
"YCbCr": ("YCbCr", II, 6, 1, (8,8,8), None),
|
||||
"LAB": ("LAB", II, 8, 1, (8,8,8), None),
|
||||
|
||||
"I;32BS": ("I;32BS", MM, 1, 2, (32,), None),
|
||||
"I;16B": ("I;16B", MM, 1, 1, (16,), None),
|
||||
"I;16BS": ("I;16BS", MM, 1, 2, (16,), None),
|
||||
"F;32BF": ("F;32BF", MM, 1, 3, (32,), None),
|
||||
}
|
||||
|
||||
def _cvt_res(value):
|
||||
# convert value to TIFF rational number -- (numerator, denominator)
|
||||
if type(value) in (type([]), type(())):
|
||||
assert(len(value) % 2 == 0)
|
||||
return value
|
||||
if type(value) == type(1):
|
||||
return (value, 1)
|
||||
value = float(value)
|
||||
return (int(value * 65536), 65536)
|
||||
|
||||
def _save(im, fp, filename):
|
||||
|
||||
try:
|
||||
rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
|
||||
except KeyError:
|
||||
raise IOError, "cannot write mode %s as TIFF" % im.mode
|
||||
|
||||
ifd = ImageFileDirectory(prefix)
|
||||
|
||||
# -- multi-page -- skip TIFF header on subsequent pages
|
||||
if fp.tell() == 0:
|
||||
# tiff header (write via IFD to get everything right)
|
||||
# PIL always starts the first IFD at offset 8
|
||||
fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))
|
||||
|
||||
ifd[IMAGEWIDTH] = im.size[0]
|
||||
ifd[IMAGELENGTH] = im.size[1]
|
||||
|
||||
# additions written by Greg Couch, gregc@cgl.ucsf.edu
|
||||
# inspired by image-sig posting from Kevin Cazabon, kcazabon@home.com
|
||||
if hasattr(im, 'tag'):
|
||||
# preserve tags from original TIFF image file
|
||||
for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION):
|
||||
if im.tag.tagdata.has_key(key):
|
||||
ifd[key] = im.tag.tagdata.get(key)
|
||||
# preserve some more tags from original TIFF image file
|
||||
# -- 2008-06-06 Florian Hoech
|
||||
ifd.tagtype = im.tag.tagtype
|
||||
for key in (IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, XMP):
|
||||
if im.tag.has_key(key):
|
||||
ifd[key] = im.tag[key]
|
||||
# preserve ICC profile (should also work when saving other formats
|
||||
# which support profiles as TIFF) -- 2008-06-06 Florian Hoech
|
||||
if im.info.has_key("icc_profile"):
|
||||
ifd[ICCPROFILE] = im.info["icc_profile"]
|
||||
if im.encoderinfo.has_key("description"):
|
||||
ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"]
|
||||
if im.encoderinfo.has_key("resolution"):
|
||||
ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] \
|
||||
= _cvt_res(im.encoderinfo["resolution"])
|
||||
if im.encoderinfo.has_key("x resolution"):
|
||||
ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo["x resolution"])
|
||||
if im.encoderinfo.has_key("y resolution"):
|
||||
ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo["y resolution"])
|
||||
if im.encoderinfo.has_key("resolution unit"):
|
||||
unit = im.encoderinfo["resolution unit"]
|
||||
if unit == "inch":
|
||||
ifd[RESOLUTION_UNIT] = 2
|
||||
elif unit == "cm" or unit == "centimeter":
|
||||
ifd[RESOLUTION_UNIT] = 3
|
||||
else:
|
||||
ifd[RESOLUTION_UNIT] = 1
|
||||
if im.encoderinfo.has_key("software"):
|
||||
ifd[SOFTWARE] = im.encoderinfo["software"]
|
||||
if im.encoderinfo.has_key("date time"):
|
||||
ifd[DATE_TIME] = im.encoderinfo["date time"]
|
||||
if im.encoderinfo.has_key("artist"):
|
||||
ifd[ARTIST] = im.encoderinfo["artist"]
|
||||
if im.encoderinfo.has_key("copyright"):
|
||||
ifd[COPYRIGHT] = im.encoderinfo["copyright"]
|
||||
|
||||
dpi = im.encoderinfo.get("dpi")
|
||||
if dpi:
|
||||
ifd[RESOLUTION_UNIT] = 2
|
||||
ifd[X_RESOLUTION] = _cvt_res(dpi[0])
|
||||
ifd[Y_RESOLUTION] = _cvt_res(dpi[1])
|
||||
|
||||
if bits != (1,):
|
||||
ifd[BITSPERSAMPLE] = bits
|
||||
if len(bits) != 1:
|
||||
ifd[SAMPLESPERPIXEL] = len(bits)
|
||||
if extra is not None:
|
||||
ifd[EXTRASAMPLES] = extra
|
||||
if format != 1:
|
||||
ifd[SAMPLEFORMAT] = format
|
||||
|
||||
ifd[PHOTOMETRIC_INTERPRETATION] = photo
|
||||
|
||||
if im.mode == "P":
|
||||
lut = im.im.getpalette("RGB", "RGB;L")
|
||||
ifd[COLORMAP] = tuple(map(lambda v: ord(v) * 256, lut))
|
||||
|
||||
# data orientation
|
||||
stride = len(bits) * ((im.size[0]*bits[0]+7)/8)
|
||||
ifd[ROWSPERSTRIP] = im.size[1]
|
||||
ifd[STRIPBYTECOUNTS] = stride * im.size[1]
|
||||
ifd[STRIPOFFSETS] = 0 # this is adjusted by IFD writer
|
||||
ifd[COMPRESSION] = 1 # no compression
|
||||
|
||||
offset = ifd.save(fp)
|
||||
|
||||
ImageFile._save(im, fp, [
|
||||
("raw", (0,0)+im.size, offset, (rawmode, stride, 1))
|
||||
])
|
||||
|
||||
|
||||
# -- helper for multi-page save --
|
||||
if im.encoderinfo.has_key("_debug_multipage"):
|
||||
#just to access o32 and o16 (using correct byte order)
|
||||
im._debug_multipage = ifd
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Register
|
||||
|
||||
Image.register_open("TIFF", TiffImageFile, _accept)
|
||||
Image.register_save("TIFF", _save)
|
||||
|
||||
Image.register_extension("TIFF", ".tif")
|
||||
Image.register_extension("TIFF", ".tiff")
|
||||
|
||||
Image.register_mime("TIFF", "image/tiff")
|
||||
209
Darwin/lib/python2.7/site-packages/PIL/TiffTags.py
Normal file
209
Darwin/lib/python2.7/site-packages/PIL/TiffTags.py
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# TIFF tags
|
||||
#
|
||||
# This module provides clear-text names for various well-known
|
||||
# TIFF tags. the TIFF codec works just fine without it.
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1999.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
##
|
||||
# This module provides constants and clear-text names for various
|
||||
# well-known TIFF tags.
|
||||
##
|
||||
|
||||
##
|
||||
# Map tag numbers (or tag number, tag value tuples) to tag names.
|
||||
|
||||
TAGS = {
|
||||
|
||||
254: "NewSubfileType",
|
||||
255: "SubfileType",
|
||||
256: "ImageWidth",
|
||||
257: "ImageLength",
|
||||
258: "BitsPerSample",
|
||||
|
||||
259: "Compression",
|
||||
(259, 1): "Uncompressed",
|
||||
(259, 2): "CCITT 1d",
|
||||
(259, 3): "Group 3 Fax",
|
||||
(259, 4): "Group 4 Fax",
|
||||
(259, 5): "LZW",
|
||||
(259, 6): "JPEG",
|
||||
(259, 32773): "PackBits",
|
||||
|
||||
262: "PhotometricInterpretation",
|
||||
(262, 0): "WhiteIsZero",
|
||||
(262, 1): "BlackIsZero",
|
||||
(262, 2): "RGB",
|
||||
(262, 3): "RGB Palette",
|
||||
(262, 4): "Transparency Mask",
|
||||
(262, 5): "CMYK",
|
||||
(262, 6): "YCbCr",
|
||||
(262, 8): "CieLAB",
|
||||
(262, 32803): "CFA", # TIFF/EP, Adobe DNG
|
||||
(262, 32892): "LinearRaw", # Adobe DNG
|
||||
|
||||
263: "Thresholding",
|
||||
264: "CellWidth",
|
||||
265: "CellHeight",
|
||||
266: "FillOrder",
|
||||
269: "DocumentName",
|
||||
|
||||
270: "ImageDescription",
|
||||
271: "Make",
|
||||
272: "Model",
|
||||
273: "StripOffsets",
|
||||
274: "Orientation",
|
||||
277: "SamplesPerPixel",
|
||||
278: "RowsPerStrip",
|
||||
279: "StripByteCounts",
|
||||
|
||||
280: "MinSampleValue",
|
||||
281: "MaxSampleValue",
|
||||
282: "XResolution",
|
||||
283: "YResolution",
|
||||
284: "PlanarConfiguration",
|
||||
(284, 1): "Contigous",
|
||||
(284, 2): "Separate",
|
||||
|
||||
285: "PageName",
|
||||
286: "XPosition",
|
||||
287: "YPosition",
|
||||
288: "FreeOffsets",
|
||||
289: "FreeByteCounts",
|
||||
|
||||
290: "GrayResponseUnit",
|
||||
291: "GrayResponseCurve",
|
||||
292: "T4Options",
|
||||
293: "T6Options",
|
||||
296: "ResolutionUnit",
|
||||
297: "PageNumber",
|
||||
|
||||
301: "TransferFunction",
|
||||
305: "Software",
|
||||
306: "DateTime",
|
||||
|
||||
315: "Artist",
|
||||
316: "HostComputer",
|
||||
317: "Predictor",
|
||||
318: "WhitePoint",
|
||||
319: "PrimaryChromaticies",
|
||||
|
||||
320: "ColorMap",
|
||||
321: "HalftoneHints",
|
||||
322: "TileWidth",
|
||||
323: "TileLength",
|
||||
324: "TileOffsets",
|
||||
325: "TileByteCounts",
|
||||
|
||||
332: "InkSet",
|
||||
333: "InkNames",
|
||||
334: "NumberOfInks",
|
||||
336: "DotRange",
|
||||
337: "TargetPrinter",
|
||||
338: "ExtraSamples",
|
||||
339: "SampleFormat",
|
||||
|
||||
340: "SMinSampleValue",
|
||||
341: "SMaxSampleValue",
|
||||
342: "TransferRange",
|
||||
|
||||
347: "JPEGTables",
|
||||
|
||||
# obsolete JPEG tags
|
||||
512: "JPEGProc",
|
||||
513: "JPEGInterchangeFormat",
|
||||
514: "JPEGInterchangeFormatLength",
|
||||
515: "JPEGRestartInterval",
|
||||
517: "JPEGLosslessPredictors",
|
||||
518: "JPEGPointTransforms",
|
||||
519: "JPEGQTables",
|
||||
520: "JPEGDCTables",
|
||||
521: "JPEGACTables",
|
||||
|
||||
529: "YCbCrCoefficients",
|
||||
530: "YCbCrSubSampling",
|
||||
531: "YCbCrPositioning",
|
||||
532: "ReferenceBlackWhite",
|
||||
|
||||
# XMP
|
||||
700: "XMP",
|
||||
|
||||
33432: "Copyright",
|
||||
|
||||
# various extensions (should check specs for "official" names)
|
||||
33723: "IptcNaaInfo",
|
||||
34377: "PhotoshopInfo",
|
||||
|
||||
# Exif IFD
|
||||
34665: "ExifIFD",
|
||||
|
||||
# ICC Profile
|
||||
34675: "ICCProfile",
|
||||
|
||||
# Adobe DNG
|
||||
50706: "DNGVersion",
|
||||
50707: "DNGBackwardVersion",
|
||||
50708: "UniqueCameraModel",
|
||||
50709: "LocalizedCameraModel",
|
||||
50710: "CFAPlaneColor",
|
||||
50711: "CFALayout",
|
||||
50712: "LinearizationTable",
|
||||
50713: "BlackLevelRepeatDim",
|
||||
50714: "BlackLevel",
|
||||
50715: "BlackLevelDeltaH",
|
||||
50716: "BlackLevelDeltaV",
|
||||
50717: "WhiteLevel",
|
||||
50718: "DefaultScale",
|
||||
50741: "BestQualityScale",
|
||||
50719: "DefaultCropOrigin",
|
||||
50720: "DefaultCropSize",
|
||||
50778: "CalibrationIlluminant1",
|
||||
50779: "CalibrationIlluminant2",
|
||||
50721: "ColorMatrix1",
|
||||
50722: "ColorMatrix2",
|
||||
50723: "CameraCalibration1",
|
||||
50724: "CameraCalibration2",
|
||||
50725: "ReductionMatrix1",
|
||||
50726: "ReductionMatrix2",
|
||||
50727: "AnalogBalance",
|
||||
50728: "AsShotNeutral",
|
||||
50729: "AsShotWhiteXY",
|
||||
50730: "BaselineExposure",
|
||||
50731: "BaselineNoise",
|
||||
50732: "BaselineSharpness",
|
||||
50733: "BayerGreenSplit",
|
||||
50734: "LinearResponseLimit",
|
||||
50735: "CameraSerialNumber",
|
||||
50736: "LensInfo",
|
||||
50737: "ChromaBlurRadius",
|
||||
50738: "AntiAliasStrength",
|
||||
50740: "DNGPrivateData",
|
||||
50741: "MakerNoteSafety",
|
||||
}
|
||||
|
||||
##
|
||||
# Map type numbers to type names.
|
||||
|
||||
TYPES = {
|
||||
|
||||
1: "byte",
|
||||
2: "ascii",
|
||||
3: "short",
|
||||
4: "long",
|
||||
5: "rational",
|
||||
6: "signed byte",
|
||||
7: "undefined",
|
||||
8: "signed short",
|
||||
9: "signed long",
|
||||
10: "signed rational",
|
||||
11: "float",
|
||||
12: "double",
|
||||
|
||||
}
|
||||
126
Darwin/lib/python2.7/site-packages/PIL/WalImageFile.py
Normal file
126
Darwin/lib/python2.7/site-packages/PIL/WalImageFile.py
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# WAL file handling
|
||||
#
|
||||
# History:
|
||||
# 2003-04-23 fl created
|
||||
#
|
||||
# Copyright (c) 2003 by Fredrik Lundh.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
# NOTE: This format cannot be automatically recognized, so the reader
|
||||
# is not registered for use with Image.open(). To open a WEL file, use
|
||||
# the WalImageFile.open() function instead.
|
||||
|
||||
# This reader is based on the specification available from:
|
||||
# http://www.flipcode.com/tutorials/tut_q2levels.shtml
|
||||
# and has been tested with a few sample files found using google.
|
||||
|
||||
import Image
|
||||
|
||||
def i32(c, o=0):
|
||||
return ord(c[o])+(ord(c[o+1])<<8)+(ord(c[o+2])<<16)+(ord(c[o+3])<<24)
|
||||
|
||||
##
|
||||
# Load texture from a Quake2 WAL texture file.
|
||||
# <p>
|
||||
# By default, a Quake2 standard palette is attached to the texture.
|
||||
# To override the palette, use the <b>putpalette</b> method.
|
||||
#
|
||||
# @param filename WAL file name, or an opened file handle.
|
||||
# @return An image instance.
|
||||
|
||||
def open(filename):
|
||||
# FIXME: modify to return a WalImageFile instance instead of
|
||||
# plain Image object ?
|
||||
|
||||
if hasattr(filename, "read"):
|
||||
fp = filename
|
||||
else:
|
||||
import __builtin__
|
||||
fp = __builtin__.open(filename, "rb")
|
||||
|
||||
# read header fields
|
||||
header = fp.read(32+24+32+12)
|
||||
size = i32(header, 32), i32(header, 36)
|
||||
offset = i32(header, 40)
|
||||
|
||||
# load pixel data
|
||||
fp.seek(offset)
|
||||
|
||||
im = Image.fromstring("P", size, fp.read(size[0] * size[1]))
|
||||
im.putpalette(quake2palette)
|
||||
|
||||
im.format = "WAL"
|
||||
im.format_description = "Quake2 Texture"
|
||||
|
||||
# strings are null-terminated
|
||||
im.info["name"] = header[:32].split("\0", 1)[0]
|
||||
next_name = header[56:56+32].split("\0", 1)[0]
|
||||
if next_name:
|
||||
im.info["next_name"] = next_name
|
||||
|
||||
return im
|
||||
|
||||
|
||||
quake2palette = (
|
||||
# default palette taken from piffo 0.93 by Hans Häggström
|
||||
"\x01\x01\x01\x0b\x0b\x0b\x12\x12\x12\x17\x17\x17\x1b\x1b\x1b\x1e"
|
||||
"\x1e\x1e\x22\x22\x22\x26\x26\x26\x29\x29\x29\x2c\x2c\x2c\x2f\x2f"
|
||||
"\x2f\x32\x32\x32\x35\x35\x35\x37\x37\x37\x3a\x3a\x3a\x3c\x3c\x3c"
|
||||
"\x24\x1e\x13\x22\x1c\x12\x20\x1b\x12\x1f\x1a\x10\x1d\x19\x10\x1b"
|
||||
"\x17\x0f\x1a\x16\x0f\x18\x14\x0d\x17\x13\x0d\x16\x12\x0d\x14\x10"
|
||||
"\x0b\x13\x0f\x0b\x10\x0d\x0a\x0f\x0b\x0a\x0d\x0b\x07\x0b\x0a\x07"
|
||||
"\x23\x23\x26\x22\x22\x25\x22\x20\x23\x21\x1f\x22\x20\x1e\x20\x1f"
|
||||
"\x1d\x1e\x1d\x1b\x1c\x1b\x1a\x1a\x1a\x19\x19\x18\x17\x17\x17\x16"
|
||||
"\x16\x14\x14\x14\x13\x13\x13\x10\x10\x10\x0f\x0f\x0f\x0d\x0d\x0d"
|
||||
"\x2d\x28\x20\x29\x24\x1c\x27\x22\x1a\x25\x1f\x17\x38\x2e\x1e\x31"
|
||||
"\x29\x1a\x2c\x25\x17\x26\x20\x14\x3c\x30\x14\x37\x2c\x13\x33\x28"
|
||||
"\x12\x2d\x24\x10\x28\x1f\x0f\x22\x1a\x0b\x1b\x14\x0a\x13\x0f\x07"
|
||||
"\x31\x1a\x16\x30\x17\x13\x2e\x16\x10\x2c\x14\x0d\x2a\x12\x0b\x27"
|
||||
"\x0f\x0a\x25\x0f\x07\x21\x0d\x01\x1e\x0b\x01\x1c\x0b\x01\x1a\x0b"
|
||||
"\x01\x18\x0a\x01\x16\x0a\x01\x13\x0a\x01\x10\x07\x01\x0d\x07\x01"
|
||||
"\x29\x23\x1e\x27\x21\x1c\x26\x20\x1b\x25\x1f\x1a\x23\x1d\x19\x21"
|
||||
"\x1c\x18\x20\x1b\x17\x1e\x19\x16\x1c\x18\x14\x1b\x17\x13\x19\x14"
|
||||
"\x10\x17\x13\x0f\x14\x10\x0d\x12\x0f\x0b\x0f\x0b\x0a\x0b\x0a\x07"
|
||||
"\x26\x1a\x0f\x23\x19\x0f\x20\x17\x0f\x1c\x16\x0f\x19\x13\x0d\x14"
|
||||
"\x10\x0b\x10\x0d\x0a\x0b\x0a\x07\x33\x22\x1f\x35\x29\x26\x37\x2f"
|
||||
"\x2d\x39\x35\x34\x37\x39\x3a\x33\x37\x39\x30\x34\x36\x2b\x31\x34"
|
||||
"\x27\x2e\x31\x22\x2b\x2f\x1d\x28\x2c\x17\x25\x2a\x0f\x20\x26\x0d"
|
||||
"\x1e\x25\x0b\x1c\x22\x0a\x1b\x20\x07\x19\x1e\x07\x17\x1b\x07\x14"
|
||||
"\x18\x01\x12\x16\x01\x0f\x12\x01\x0b\x0d\x01\x07\x0a\x01\x01\x01"
|
||||
"\x2c\x21\x21\x2a\x1f\x1f\x29\x1d\x1d\x27\x1c\x1c\x26\x1a\x1a\x24"
|
||||
"\x18\x18\x22\x17\x17\x21\x16\x16\x1e\x13\x13\x1b\x12\x12\x18\x10"
|
||||
"\x10\x16\x0d\x0d\x12\x0b\x0b\x0d\x0a\x0a\x0a\x07\x07\x01\x01\x01"
|
||||
"\x2e\x30\x29\x2d\x2e\x27\x2b\x2c\x26\x2a\x2a\x24\x28\x29\x23\x27"
|
||||
"\x27\x21\x26\x26\x1f\x24\x24\x1d\x22\x22\x1c\x1f\x1f\x1a\x1c\x1c"
|
||||
"\x18\x19\x19\x16\x17\x17\x13\x13\x13\x10\x0f\x0f\x0d\x0b\x0b\x0a"
|
||||
"\x30\x1e\x1b\x2d\x1c\x19\x2c\x1a\x17\x2a\x19\x14\x28\x17\x13\x26"
|
||||
"\x16\x10\x24\x13\x0f\x21\x12\x0d\x1f\x10\x0b\x1c\x0f\x0a\x19\x0d"
|
||||
"\x0a\x16\x0b\x07\x12\x0a\x07\x0f\x07\x01\x0a\x01\x01\x01\x01\x01"
|
||||
"\x28\x29\x38\x26\x27\x36\x25\x26\x34\x24\x24\x31\x22\x22\x2f\x20"
|
||||
"\x21\x2d\x1e\x1f\x2a\x1d\x1d\x27\x1b\x1b\x25\x19\x19\x21\x17\x17"
|
||||
"\x1e\x14\x14\x1b\x13\x12\x17\x10\x0f\x13\x0d\x0b\x0f\x0a\x07\x07"
|
||||
"\x2f\x32\x29\x2d\x30\x26\x2b\x2e\x24\x29\x2c\x21\x27\x2a\x1e\x25"
|
||||
"\x28\x1c\x23\x26\x1a\x21\x25\x18\x1e\x22\x14\x1b\x1f\x10\x19\x1c"
|
||||
"\x0d\x17\x1a\x0a\x13\x17\x07\x10\x13\x01\x0d\x0f\x01\x0a\x0b\x01"
|
||||
"\x01\x3f\x01\x13\x3c\x0b\x1b\x39\x10\x20\x35\x14\x23\x31\x17\x23"
|
||||
"\x2d\x18\x23\x29\x18\x3f\x3f\x3f\x3f\x3f\x39\x3f\x3f\x31\x3f\x3f"
|
||||
"\x2a\x3f\x3f\x20\x3f\x3f\x14\x3f\x3c\x12\x3f\x39\x0f\x3f\x35\x0b"
|
||||
"\x3f\x32\x07\x3f\x2d\x01\x3d\x2a\x01\x3b\x26\x01\x39\x21\x01\x37"
|
||||
"\x1d\x01\x34\x1a\x01\x32\x16\x01\x2f\x12\x01\x2d\x0f\x01\x2a\x0b"
|
||||
"\x01\x27\x07\x01\x23\x01\x01\x1d\x01\x01\x17\x01\x01\x10\x01\x01"
|
||||
"\x3d\x01\x01\x19\x19\x3f\x3f\x01\x01\x01\x01\x3f\x16\x16\x13\x10"
|
||||
"\x10\x0f\x0d\x0d\x0b\x3c\x2e\x2a\x36\x27\x20\x30\x21\x18\x29\x1b"
|
||||
"\x10\x3c\x39\x37\x37\x32\x2f\x31\x2c\x28\x2b\x26\x21\x30\x22\x20"
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
im = open("../hacks/sample.wal")
|
||||
print im.info, im.mode, im.size
|
||||
im.save("../out.png")
|
||||
167
Darwin/lib/python2.7/site-packages/PIL/WmfImagePlugin.py
Normal file
167
Darwin/lib/python2.7/site-packages/PIL/WmfImagePlugin.py
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
#
|
||||
# The Python Imaging Library
|
||||
# $Id$
|
||||
#
|
||||
# WMF stub codec
|
||||
#
|
||||
# history:
|
||||
# 1996-12-14 fl Created
|
||||
# 2004-02-22 fl Turned into a stub driver
|
||||
# 2004-02-23 fl Added EMF support
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997-2004. All rights reserved.
|
||||
# Copyright (c) Fredrik Lundh 1996.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.2"
|
||||
|
||||
import Image, ImageFile
|
||||
|
||||
_handler = None
|
||||
|
||||
##
|
||||
# Install application-specific WMF image handler.
|
||||
#
|
||||
# @param handler Handler object.
|
||||
|
||||
def register_handler(handler):
|
||||
global _handler
|
||||
_handler = handler
|
||||
|
||||
if hasattr(Image.core, "drawwmf"):
|
||||
# install default handler (windows only)
|
||||
|
||||
class WmfHandler:
|
||||
|
||||
def open(self, im):
|
||||
im.mode = "RGB"
|
||||
self.bbox = im.info["wmf_bbox"]
|
||||
|
||||
def load(self, im):
|
||||
im.fp.seek(0) # rewind
|
||||
return Image.fromstring(
|
||||
"RGB", im.size,
|
||||
Image.core.drawwmf(im.fp.read(), im.size, self.bbox),
|
||||
"raw", "BGR", (im.size[0]*3 + 3) & -4, -1
|
||||
)
|
||||
|
||||
register_handler(WmfHandler())
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
def word(c, o=0):
|
||||
return ord(c[o]) + (ord(c[o+1])<<8)
|
||||
|
||||
def short(c, o=0):
|
||||
v = ord(c[o]) + (ord(c[o+1])<<8)
|
||||
if v >= 32768:
|
||||
v = v - 65536
|
||||
return v
|
||||
|
||||
def dword(c, o=0):
|
||||
return ord(c[o]) + (ord(c[o+1])<<8) + (ord(c[o+2])<<16) + (ord(c[o+3])<<24)
|
||||
|
||||
def long(c, o=0):
|
||||
return dword(c, o)
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Read WMF file
|
||||
|
||||
def _accept(prefix):
|
||||
return (
|
||||
prefix[:6] == "\xd7\xcd\xc6\x9a\x00\x00" or
|
||||
prefix[:4] == "\x01\x00\x00\x00"
|
||||
)
|
||||
|
||||
##
|
||||
# Image plugin for Windows metafiles.
|
||||
|
||||
class WmfStubImageFile(ImageFile.StubImageFile):
|
||||
|
||||
format = "WMF"
|
||||
format_description = "Windows Metafile"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# check placable header
|
||||
s = self.fp.read(80)
|
||||
|
||||
if s[:6] == "\xd7\xcd\xc6\x9a\x00\x00":
|
||||
|
||||
# placeable windows metafile
|
||||
|
||||
# get units per inch
|
||||
inch = word(s, 14)
|
||||
|
||||
# get bounding box
|
||||
x0 = short(s, 6); y0 = short(s, 8)
|
||||
x1 = short(s, 10); y1 = short(s, 12)
|
||||
|
||||
# normalize size to 72 dots per inch
|
||||
size = (x1 - x0) * 72 / inch, (y1 - y0) * 72 / inch
|
||||
|
||||
self.info["wmf_bbox"] = x0, y0, x1, y1
|
||||
|
||||
self.info["dpi"] = 72
|
||||
|
||||
# print self.mode, self.size, self.info
|
||||
|
||||
# sanity check (standard metafile header)
|
||||
if s[22:26] != "\x01\x00\t\x00":
|
||||
raise SyntaxError("Unsupported WMF file format")
|
||||
|
||||
elif long(s) == 1 and s[40:44] == " EMF":
|
||||
# enhanced metafile
|
||||
|
||||
# get bounding box
|
||||
x0 = long(s, 8); y0 = long(s, 12)
|
||||
x1 = long(s, 16); y1 = long(s, 20)
|
||||
|
||||
# get frame (in 0.01 millimeter units)
|
||||
frame = long(s, 24), long(s, 28), long(s, 32), long(s, 36)
|
||||
|
||||
# normalize size to 72 dots per inch
|
||||
size = x1 - x0, y1 - y0
|
||||
|
||||
# calculate dots per inch from bbox and frame
|
||||
xdpi = 2540 * (x1 - y0) / (frame[2] - frame[0])
|
||||
ydpi = 2540 * (y1 - y0) / (frame[3] - frame[1])
|
||||
|
||||
self.info["wmf_bbox"] = x0, y0, x1, y1
|
||||
|
||||
if xdpi == ydpi:
|
||||
self.info["dpi"] = xdpi
|
||||
else:
|
||||
self.info["dpi"] = xdpi, ydpi
|
||||
|
||||
else:
|
||||
raise SyntaxError("Unsupported file format")
|
||||
|
||||
self.mode = "RGB"
|
||||
self.size = size
|
||||
|
||||
loader = self._load()
|
||||
if loader:
|
||||
loader.open(self)
|
||||
|
||||
def _load(self):
|
||||
return _handler
|
||||
|
||||
|
||||
def _save(im, fp, filename):
|
||||
if _handler is None or not hasattr("_handler", "save"):
|
||||
raise IOError("WMF save handler not installed")
|
||||
_handler.save(im, fp, filename)
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Registry stuff
|
||||
|
||||
Image.register_open(WmfStubImageFile.format, WmfStubImageFile, _accept)
|
||||
Image.register_save(WmfStubImageFile.format, _save)
|
||||
|
||||
Image.register_extension(WmfStubImageFile.format, ".wmf")
|
||||
Image.register_extension(WmfStubImageFile.format, ".emf")
|
||||
73
Darwin/lib/python2.7/site-packages/PIL/XVThumbImagePlugin.py
Normal file
73
Darwin/lib/python2.7/site-packages/PIL/XVThumbImagePlugin.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# XV Thumbnail file handler by Charles E. "Gene" Cash
|
||||
# (gcash@magicnet.net)
|
||||
#
|
||||
# see xvcolor.c and xvbrowse.c in the sources to John Bradley's XV,
|
||||
# available from ftp://ftp.cis.upenn.edu/pub/xv/
|
||||
#
|
||||
# history:
|
||||
# 98-08-15 cec created (b/w only)
|
||||
# 98-12-09 cec added color palette
|
||||
# 98-12-28 fl added to PIL (with only a few very minor modifications)
|
||||
#
|
||||
# To do:
|
||||
# FIXME: make save work (this requires quantization support)
|
||||
#
|
||||
|
||||
__version__ = "0.1"
|
||||
|
||||
import string
|
||||
import Image, ImageFile, ImagePalette
|
||||
|
||||
# standard color palette for thumbnails (RGB332)
|
||||
PALETTE = ""
|
||||
for r in range(8):
|
||||
for g in range(8):
|
||||
for b in range(4):
|
||||
PALETTE = PALETTE + (chr((r*255)/7)+chr((g*255)/7)+chr((b*255)/3))
|
||||
|
||||
##
|
||||
# Image plugin for XV thumbnail images.
|
||||
|
||||
class XVThumbImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "XVThumb"
|
||||
format_description = "XV thumbnail image"
|
||||
|
||||
def _open(self):
|
||||
|
||||
# check magic
|
||||
s = self.fp.read(6)
|
||||
if s != "P7 332":
|
||||
raise SyntaxError, "not an XV thumbnail file"
|
||||
|
||||
# Skip to beginning of next line
|
||||
self.fp.readline()
|
||||
|
||||
# skip info comments
|
||||
while 1:
|
||||
s = self.fp.readline()
|
||||
if not s:
|
||||
raise SyntaxError, "Unexpected EOF reading XV thumbnail file"
|
||||
if s[0] != '#':
|
||||
break
|
||||
|
||||
# parse header line (already read)
|
||||
s = string.split(s.strip())
|
||||
|
||||
self.mode = "P"
|
||||
self.size = int(s[0]), int(s[1])
|
||||
|
||||
self.palette = ImagePalette.raw("RGB", PALETTE)
|
||||
|
||||
self.tile = [
|
||||
("raw", (0, 0)+self.size,
|
||||
self.fp.tell(), (self.mode, 0, 1)
|
||||
)]
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("XVThumb", XVThumbImageFile)
|
||||
94
Darwin/lib/python2.7/site-packages/PIL/XbmImagePlugin.py
Normal file
94
Darwin/lib/python2.7/site-packages/PIL/XbmImagePlugin.py
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# XBM File handling
|
||||
#
|
||||
# History:
|
||||
# 1995-09-08 fl Created
|
||||
# 1996-11-01 fl Added save support
|
||||
# 1997-07-07 fl Made header parser more tolerant
|
||||
# 1997-07-22 fl Fixed yet another parser bug
|
||||
# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.4)
|
||||
# 2001-05-13 fl Added hotspot handling (based on code from Bernhard Herzog)
|
||||
# 2004-02-24 fl Allow some whitespace before first #define
|
||||
#
|
||||
# Copyright (c) 1997-2004 by Secret Labs AB
|
||||
# Copyright (c) 1996-1997 by Fredrik Lundh
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
__version__ = "0.6"
|
||||
|
||||
import re, string
|
||||
import Image, ImageFile
|
||||
|
||||
# XBM header
|
||||
xbm_head = re.compile(
|
||||
"\s*#define[ \t]+[^_]*_width[ \t]+(?P<width>[0-9]+)[\r\n]+"
|
||||
"#define[ \t]+[^_]*_height[ \t]+(?P<height>[0-9]+)[\r\n]+"
|
||||
"(?P<hotspot>"
|
||||
"#define[ \t]+[^_]*_x_hot[ \t]+(?P<xhot>[0-9]+)[\r\n]+"
|
||||
"#define[ \t]+[^_]*_y_hot[ \t]+(?P<yhot>[0-9]+)[\r\n]+"
|
||||
")?"
|
||||
"[\\000-\\377]*_bits\\[\\]"
|
||||
)
|
||||
|
||||
def _accept(prefix):
|
||||
return string.lstrip(prefix)[:7] == "#define"
|
||||
|
||||
##
|
||||
# Image plugin for X11 bitmaps.
|
||||
|
||||
class XbmImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "XBM"
|
||||
format_description = "X11 Bitmap"
|
||||
|
||||
def _open(self):
|
||||
|
||||
m = xbm_head.match(self.fp.read(512))
|
||||
|
||||
if m:
|
||||
|
||||
xsize = int(m.group("width"))
|
||||
ysize = int(m.group("height"))
|
||||
|
||||
if m.group("hotspot"):
|
||||
self.info["hotspot"] = (
|
||||
int(m.group("xhot")), int(m.group("yhot"))
|
||||
)
|
||||
|
||||
self.mode = "1"
|
||||
self.size = xsize, ysize
|
||||
|
||||
self.tile = [("xbm", (0, 0)+self.size, m.end(), None)]
|
||||
|
||||
|
||||
def _save(im, fp, filename):
|
||||
|
||||
if im.mode != "1":
|
||||
raise IOError, "cannot write mode %s as XBM" % im.mode
|
||||
|
||||
fp.write("#define im_width %d\n" % im.size[0])
|
||||
fp.write("#define im_height %d\n" % im.size[1])
|
||||
|
||||
hotspot = im.encoderinfo.get("hotspot")
|
||||
if hotspot:
|
||||
fp.write("#define im_x_hot %d\n" % hotspot[0])
|
||||
fp.write("#define im_y_hot %d\n" % hotspot[1])
|
||||
|
||||
fp.write("static char im_bits[] = {\n")
|
||||
|
||||
ImageFile._save(im, fp, [("xbm", (0,0)+im.size, 0, None)])
|
||||
|
||||
fp.write("};\n")
|
||||
|
||||
|
||||
Image.register_open("XBM", XbmImageFile, _accept)
|
||||
Image.register_save("XBM", _save)
|
||||
|
||||
Image.register_extension("XBM", ".xbm")
|
||||
|
||||
Image.register_mime("XBM", "image/xbm")
|
||||
129
Darwin/lib/python2.7/site-packages/PIL/XpmImagePlugin.py
Normal file
129
Darwin/lib/python2.7/site-packages/PIL/XpmImagePlugin.py
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# XPM File handling
|
||||
#
|
||||
# History:
|
||||
# 1996-12-29 fl Created
|
||||
# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.7)
|
||||
#
|
||||
# Copyright (c) Secret Labs AB 1997-2001.
|
||||
# Copyright (c) Fredrik Lundh 1996-2001.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
|
||||
__version__ = "0.2"
|
||||
|
||||
|
||||
import re, string
|
||||
import Image, ImageFile, ImagePalette
|
||||
|
||||
# XPM header
|
||||
xpm_head = re.compile("\"([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*)")
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:9] == "/* XPM */"
|
||||
|
||||
##
|
||||
# Image plugin for X11 pixel maps.
|
||||
|
||||
class XpmImageFile(ImageFile.ImageFile):
|
||||
|
||||
format = "XPM"
|
||||
format_description = "X11 Pixel Map"
|
||||
|
||||
def _open(self):
|
||||
|
||||
if not _accept(self.fp.read(9)):
|
||||
raise SyntaxError, "not an XPM file"
|
||||
|
||||
# skip forward to next string
|
||||
while 1:
|
||||
s = self.fp.readline()
|
||||
if not s:
|
||||
raise SyntaxError, "broken XPM file"
|
||||
m = xpm_head.match(s)
|
||||
if m:
|
||||
break
|
||||
|
||||
self.size = int(m.group(1)), int(m.group(2))
|
||||
|
||||
pal = int(m.group(3))
|
||||
bpp = int(m.group(4))
|
||||
|
||||
if pal > 256 or bpp != 1:
|
||||
raise ValueError, "cannot read this XPM file"
|
||||
|
||||
#
|
||||
# load palette description
|
||||
|
||||
palette = ["\0\0\0"] * 256
|
||||
|
||||
for i in range(pal):
|
||||
|
||||
s = self.fp.readline()
|
||||
if s[-2:] == '\r\n':
|
||||
s = s[:-2]
|
||||
elif s[-1:] in '\r\n':
|
||||
s = s[:-1]
|
||||
|
||||
c = ord(s[1])
|
||||
s = string.split(s[2:-2])
|
||||
|
||||
for i in range(0, len(s), 2):
|
||||
|
||||
if s[i] == "c":
|
||||
|
||||
# process colour key
|
||||
rgb = s[i+1]
|
||||
if rgb == "None":
|
||||
self.info["transparency"] = c
|
||||
elif rgb[0] == "#":
|
||||
# FIXME: handle colour names (see ImagePalette.py)
|
||||
rgb = string.atoi(rgb[1:], 16)
|
||||
palette[c] = chr((rgb >> 16) & 255) +\
|
||||
chr((rgb >> 8) & 255) +\
|
||||
chr(rgb & 255)
|
||||
else:
|
||||
# unknown colour
|
||||
raise ValueError, "cannot read this XPM file"
|
||||
break
|
||||
|
||||
else:
|
||||
|
||||
# missing colour key
|
||||
raise ValueError, "cannot read this XPM file"
|
||||
|
||||
self.mode = "P"
|
||||
self.palette = ImagePalette.raw("RGB", string.join(palette, ""))
|
||||
|
||||
self.tile = [("raw", (0, 0)+self.size, self.fp.tell(), ("P", 0, 1))]
|
||||
|
||||
def load_read(self, bytes):
|
||||
|
||||
#
|
||||
# load all image data in one chunk
|
||||
|
||||
xsize, ysize = self.size
|
||||
|
||||
s = [None] * ysize
|
||||
|
||||
for i in range(ysize):
|
||||
s[i] = string.ljust(self.fp.readline()[1:xsize+1], xsize)
|
||||
|
||||
self.fp = None
|
||||
|
||||
return string.join(s, "")
|
||||
|
||||
#
|
||||
# Registry
|
||||
|
||||
Image.register_open("XPM", XpmImageFile, _accept)
|
||||
|
||||
Image.register_extension("XPM", ".xpm")
|
||||
|
||||
Image.register_mime("XPM", "image/xpm")
|
||||
12
Darwin/lib/python2.7/site-packages/PIL/__init__.py
Normal file
12
Darwin/lib/python2.7/site-packages/PIL/__init__.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#
|
||||
# The Python Imaging Library.
|
||||
# $Id$
|
||||
#
|
||||
# package placeholder
|
||||
#
|
||||
# Copyright (c) 1999 by Secret Labs AB.
|
||||
#
|
||||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
# ;-)
|
||||
BIN
Darwin/lib/python2.7/site-packages/PIL/_imaging.so
Executable file
BIN
Darwin/lib/python2.7/site-packages/PIL/_imaging.so
Executable file
Binary file not shown.
BIN
Darwin/lib/python2.7/site-packages/PIL/_imagingft.so
Executable file
BIN
Darwin/lib/python2.7/site-packages/PIL/_imagingft.so
Executable file
Binary file not shown.
BIN
Darwin/lib/python2.7/site-packages/PIL/_imagingmath.so
Executable file
BIN
Darwin/lib/python2.7/site-packages/PIL/_imagingmath.so
Executable file
Binary file not shown.
BIN
Darwin/lib/python2.7/site-packages/PIL/_imagingtk.so
Executable file
BIN
Darwin/lib/python2.7/site-packages/PIL/_imagingtk.so
Executable file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue