From 37096ab43aa041ab13c7cafbdf4957a01a182ffe Mon Sep 17 00:00:00 2001 From: Keshav Sharma Date: Wed, 13 Jul 2011 07:23:54 +0000 Subject: added camera feature and save on exit --- diff --git a/AUTHORS.txt b/AUTHORS.txt deleted file mode 100644 index bf4dfb3..0000000 --- a/AUTHORS.txt +++ /dev/null @@ -1,12 +0,0 @@ -Contributors -============ -Keshav Sharma -Vaibhav Sharma - -Original author ---------------- -Keshav Sharma - -Maintainers ------------ -Vaibhav Sharma diff --git a/ImageProcess.py b/ImageProcess.py index 26506a5..430b852 100644 --- a/ImageProcess.py +++ b/ImageProcess.py @@ -528,7 +528,11 @@ class ImageProcessor(gtk.DrawingArea): rect = gdk.Rectangle(alloc.x, alloc.y, alloc.width, alloc.height) self.window.invalidate_rect(rect, True) self.window.process_updates(True) - + + def save_cb(self,file_path): + pixbuf=self.pixbuf + pixbuf.save(file_path, 'png', {}) + #check working of functions def update(view_object): view.grey("g") diff --git a/ImageProcessorActivity.py b/ImageProcessorActivity.py index 7d41306..a3382e1 100644 --- a/ImageProcessorActivity.py +++ b/ImageProcessorActivity.py @@ -184,6 +184,7 @@ class ImageProcessorActivity(activity.Activity): self._view_toolbar.connect('redo', self.__redo_cb) self._view_toolbar.connect('save', self.__save_cb) self._view_toolbar.connect('paste',self.__paste_cb) + self._view_toolbar.connect('original',self.view.original_cb) view_toolbar_button = ToolbarButton(page=self._view_toolbar, icon_name='toolbar-view') self._view_toolbar.show() toolbar_box.toolbar.insert(view_toolbar_button, -1) @@ -232,18 +233,18 @@ class ImageProcessorActivity(activity.Activity): spacer.props.draw = False toolbar_box.toolbar.insert(spacer, -1) spacer.show() - - original_button = ToolButton('original') - original_button.set_tooltip(_('original pic')) - original_button.connect('clicked', self.view.original_cb) - toolbar_box.toolbar.insert(original_button, -1) - original_button.show() fullscreen_button = ToolButton('view-fullscreen') fullscreen_button.set_tooltip(_('Fullscreen')) fullscreen_button.connect('clicked', self.__fullscreen_cb) toolbar_box.toolbar.insert(fullscreen_button, -1) fullscreen_button.show() + + cam_button = ToolButton('camera') + cam_button.set_tooltip(_('take a pic')) + cam_button.connect('clicked', self.cam_cb) + toolbar_box.toolbar.insert(cam_button, -1) + cam_button.show() @@ -258,6 +259,24 @@ class ImageProcessorActivity(activity.Activity): stop_button.show() + def cam_cb(self, button): + import gst, sys, time + from random import * + from sugar.datastore import datastore + photocmd = 'v4l2src ! ffmpegcolorspace ! jpegenc ! filesink location=/tmp/photo' + '.jpg' + # take photo + pipeline = gst.parse_launch (photocmd) + pipeline.set_state(gst.STATE_PLAYING) + time.sleep(3) + pipeline.set_state(gst.STATE_NULL) + journal_object = datastore.create() + journal_object.metadata['title'] = 'new-image' + journal_object.metadata['mime_type'] = 'image/jpeg57' + journal_object.file_path = '/tmp/photo' + '.jpg' + self.view.set_file_location(journal_object.file_path) + datastore.write( journal_object ) + journal_object.destroy() + def watermrk_cb(self, button,pos): self.w="kuch" self.do_load_an_image_cb(button) @@ -381,8 +400,7 @@ class ImageProcessorActivity(activity.Activity): self.metadata['activity'] = self.get_bundle_id() self.metadata['zoom'] = str(self.zoom) if self._close_requested: - os.link(self._tempfile, file_path) - os.unlink(self._tempfile) + self.view.save_cb(file_path) self._tempfile = None else: raise NotImplementedError diff --git a/PIL/ArgImagePlugin.py b/PIL/ArgImagePlugin.py deleted file mode 100644 index 48582d9..0000000 --- a/PIL/ArgImagePlugin.py +++ /dev/null @@ -1,498 +0,0 @@ -# -# THIS IS WORK IN PROGRESS -# -# The Python Imaging Library. -# $Id: ArgImagePlugin.py 2309 2005-03-02 15:06:34Z fredrik $ -# -# 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 marshal, string - -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 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") diff --git a/PIL/BdfFontFile.py b/PIL/BdfFontFile.py deleted file mode 100644 index 9297a18..0000000 --- a/PIL/BdfFontFile.py +++ /dev/null @@ -1,133 +0,0 @@ -# -# The Python Imaging Library -# $Id: BdfFontFile.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 diff --git a/PIL/BmpImagePlugin.py b/PIL/BmpImagePlugin.py deleted file mode 100644 index a939d9b..0000000 --- a/PIL/BmpImagePlugin.py +++ /dev/null @@ -1,245 +0,0 @@ -# -# The Python Imaging Library. -# $Id: BmpImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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;16"), - 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 - - 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:]) - - 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), -1))] - - 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") diff --git a/PIL/BufrStubImagePlugin.py b/PIL/BufrStubImagePlugin.py deleted file mode 100644 index ee02659..0000000 --- a/PIL/BufrStubImagePlugin.py +++ /dev/null @@ -1,68 +0,0 @@ -# -# The Python Imaging Library -# $Id: BufrStubImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/ContainerIO.py b/PIL/ContainerIO.py deleted file mode 100644 index 7b7283f..0000000 --- a/PIL/ContainerIO.py +++ /dev/null @@ -1,116 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ContainerIO.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 diff --git a/PIL/CurImagePlugin.py b/PIL/CurImagePlugin.py deleted file mode 100644 index b879da3..0000000 --- a/PIL/CurImagePlugin.py +++ /dev/null @@ -1,90 +0,0 @@ -# -# The Python Imaging Library. -# $Id: CurImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 string - -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") diff --git a/PIL/DcxImagePlugin.py b/PIL/DcxImagePlugin.py deleted file mode 100644 index 3a0df01..0000000 --- a/PIL/DcxImagePlugin.py +++ /dev/null @@ -1,78 +0,0 @@ -# -# The Python Imaging Library. -# $Id: DcxImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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, ImageFile - -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") diff --git a/PIL/EpsImagePlugin.py b/PIL/EpsImagePlugin.py deleted file mode 100644 index e0a608e..0000000 --- a/PIL/EpsImagePlugin.py +++ /dev/null @@ -1,349 +0,0 @@ -# -# The Python Imaging Library. -# $Id: EpsImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/ExifTags.py b/PIL/ExifTags.py deleted file mode 100644 index 01a6b74..0000000 --- a/PIL/ExifTags.py +++ /dev/null @@ -1,157 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ExifTags.py 2631 2006-02-12 23:41:52Z fredrik $ -# -# 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" -} diff --git a/PIL/FitsStubImagePlugin.py b/PIL/FitsStubImagePlugin.py deleted file mode 100644 index 05f5d46..0000000 --- a/PIL/FitsStubImagePlugin.py +++ /dev/null @@ -1,73 +0,0 @@ -# -# The Python Imaging Library -# $Id: FitsStubImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/FliImagePlugin.py b/PIL/FliImagePlugin.py deleted file mode 100644 index 5b1bf8e..0000000 --- a/PIL/FliImagePlugin.py +++ /dev/null @@ -1,142 +0,0 @@ -# -# The Python Imaging Library. -# $Id: FliImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 seek -# 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") diff --git a/PIL/FontFile.py b/PIL/FontFile.py deleted file mode 100644 index bf4b905..0000000 --- a/PIL/FontFile.py +++ /dev/null @@ -1,146 +0,0 @@ -# -# The Python Imaging Library -# $Id: FontFile.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 diff --git a/PIL/FpxImagePlugin.py b/PIL/FpxImagePlugin.py deleted file mode 100644 index d4a1aef..0000000 --- a/PIL/FpxImagePlugin.py +++ /dev/null @@ -1,226 +0,0 @@ -# -# THIS IS WORK IN PROGRESS -# -# The Python Imaging Library. -# $Id: FpxImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 string - -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") diff --git a/PIL/GbrImagePlugin.py b/PIL/GbrImagePlugin.py deleted file mode 100644 index 273e1f8..0000000 --- a/PIL/GbrImagePlugin.py +++ /dev/null @@ -1,70 +0,0 @@ -# -# The Python Imaging Library -# $Id: GbrImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/GdImageFile.py b/PIL/GdImageFile.py deleted file mode 100644 index e6ddfa7..0000000 --- a/PIL/GdImageFile.py +++ /dev/null @@ -1,86 +0,0 @@ -# -# The Python Imaging Library. -# $Id: GdImageFile.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 string -import Image, 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 Image.open function. To use -# this plugin, you have to import the GdImageFile module and -# use the GdImageFile.open 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") diff --git a/PIL/GifImagePlugin.py b/PIL/GifImagePlugin.py deleted file mode 100644 index cce0fe2..0000000 --- a/PIL/GifImagePlugin.py +++ /dev/null @@ -1,405 +0,0 @@ -# -# The Python Imaging Library. -# $Id: GifImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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<%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) diff --git a/PIL/GimpGradientFile.py b/PIL/GimpGradientFile.py deleted file mode 100644 index e246d6d..0000000 --- a/PIL/GimpGradientFile.py +++ /dev/null @@ -1,124 +0,0 @@ -# -# Python Imaging Library -# $Id: GimpGradientFile.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 diff --git a/PIL/GimpPaletteFile.py b/PIL/GimpPaletteFile.py deleted file mode 100644 index 3939147..0000000 --- a/PIL/GimpPaletteFile.py +++ /dev/null @@ -1,61 +0,0 @@ -# -# Python Imaging Library -# $Id: GimpPaletteFile.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 diff --git a/PIL/GribStubImagePlugin.py b/PIL/GribStubImagePlugin.py deleted file mode 100644 index 73d5404..0000000 --- a/PIL/GribStubImagePlugin.py +++ /dev/null @@ -1,68 +0,0 @@ -# -# The Python Imaging Library -# $Id: GribStubImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/Hdf5StubImagePlugin.py b/PIL/Hdf5StubImagePlugin.py deleted file mode 100644 index 31d4f6e..0000000 --- a/PIL/Hdf5StubImagePlugin.py +++ /dev/null @@ -1,70 +0,0 @@ -# -# The Python Imaging Library -# $Id: Hdf5StubImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/IcnsImagePlugin.py b/PIL/IcnsImagePlugin.py deleted file mode 100644 index a85695d..0000000 --- a/PIL/IcnsImagePlugin.py +++ /dev/null @@ -1,211 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 %r channel [%r]" % (channel, 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") diff --git a/PIL/IcoImagePlugin.py b/PIL/IcoImagePlugin.py deleted file mode 100644 index 5cdd284..0000000 --- a/PIL/IcoImagePlugin.py +++ /dev/null @@ -1,88 +0,0 @@ -# -# The Python Imaging Library. -# $Id: IcoImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 string - -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") diff --git a/PIL/ImImagePlugin.py b/PIL/ImImagePlugin.py deleted file mode 100644 index 17b8c0e..0000000 --- a/PIL/ImImagePlugin.py +++ /dev/null @@ -1,335 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImImagePlugin.py 2285 2005-02-07 23:52:14Z fredrik $ -# -# 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", "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;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") diff --git a/PIL/Image.py b/PIL/Image.py deleted file mode 100644 index 04ed316..0000000 --- a/PIL/Image.py +++ /dev/null @@ -1,2093 +0,0 @@ -# -# The Python Imaging Library. -# $Id: Image.py 2933 2006-12-03 12:08:22Z fredrik $ -# -# the Image class wrapper -# -# partial release history: -# 1995-09-09 fl Created -# 1996-03-11 fl PIL release 0.0 (proof of concept) -# 1996-04-30 fl PIL release 0.1b1 -# 1999-07-28 fl PIL release 1.0 final -# 2000-06-07 fl PIL release 1.1 -# 2000-10-20 fl PIL release 1.1.1 -# 2001-05-07 fl PIL release 1.1.2 -# 2002-03-15 fl PIL release 1.1.3 -# 2003-05-10 fl PIL release 1.1.4 -# 2005-03-28 fl PIL release 1.1.5 -# 2006-12-02 fl PIL release 1.1.6 -# -# Copyright (c) 1997-2006 by Secret Labs AB. All rights reserved. -# Copyright (c) 1995-2006 by Fredrik Lundh. -# -# See the README file for information on usage and redistribution. -# - -VERSION = "1.1.6" - -try: - import warnings -except ImportError: - warnings = None - -class _imaging_not_installed: - # module placeholder - def __getattr__(self, id): - raise ImportError("The _imaging C module is not installed") - -try: - # give Tk a chance to set up the environment, in case we're - # using an _imaging module linked against libtcl/libtk (use - # __import__ to hide this from naive packagers; we don't really - # depend on Tk unless ImageTk is used, and that module already - # imports Tkinter) - __import__("FixTk") -except ImportError: - pass - -try: - # If the _imaging C module is not present, you can still use - # the "open" function to identify files, but you cannot load - # them. Note that other modules should not refer to _imaging - # directly; import Image and use the Image.core variable instead. - import _imaging - core = _imaging - del _imaging -except ImportError, v: - core = _imaging_not_installed() - if str(v)[:20] == "Module use of python" and warnings: - # The _imaging C module is present, but not compiled for - # the right version (windows only). Print a warning, if - # possible. - warnings.warn( - "The _imaging extension was built for another version " - "of Python; most PIL functions will be disabled", - RuntimeWarning - ) - -import ImageMode -import ImagePalette - -import os, string, sys - -# type stuff -from types import IntType, StringType, TupleType - -try: - UnicodeStringType = type(unicode("")) - ## - # (Internal) Checks if an object is a string. If the current - # Python version supports Unicode, this checks for both 8-bit - # and Unicode strings. - def isStringType(t): - return isinstance(t, StringType) or isinstance(t, UnicodeStringType) -except NameError: - def isStringType(t): - return isinstance(t, StringType) - -## -# (Internal) Checks if an object is a tuple. - -def isTupleType(t): - return isinstance(t, TupleType) - -## -# (Internal) Checks if an object is an image object. - -def isImageType(t): - return hasattr(t, "im") - -## -# (Internal) Checks if an object is a string, and that it points to a -# directory. - -def isDirectory(f): - return isStringType(f) and os.path.isdir(f) - -from operator import isNumberType, isSequenceType - -# -# Debug level - -DEBUG = 0 - -# -# Constants (also defined in _imagingmodule.c!) - -NONE = 0 - -# transpose -FLIP_LEFT_RIGHT = 0 -FLIP_TOP_BOTTOM = 1 -ROTATE_90 = 2 -ROTATE_180 = 3 -ROTATE_270 = 4 - -# transforms -AFFINE = 0 -EXTENT = 1 -PERSPECTIVE = 2 -QUAD = 3 -MESH = 4 - -# resampling filters -NONE = 0 -NEAREST = 0 -ANTIALIAS = 1 # 3-lobed lanczos -LINEAR = BILINEAR = 2 -CUBIC = BICUBIC = 3 - -# dithers -NONE = 0 -NEAREST = 0 -ORDERED = 1 # Not yet implemented -RASTERIZE = 2 # Not yet implemented -FLOYDSTEINBERG = 3 # default - -# palettes/quantizers -WEB = 0 -ADAPTIVE = 1 - -# categories -NORMAL = 0 -SEQUENCE = 1 -CONTAINER = 2 - -# -------------------------------------------------------------------- -# Registries - -ID = [] -OPEN = {} -MIME = {} -SAVE = {} -EXTENSION = {} - -# -------------------------------------------------------------------- -# Modes supported by this version - -_MODEINFO = { - # NOTE: this table will be removed in future versions. use - # getmode* functions or ImageMode descriptors instead. - - # official modes - "1": ("L", "L", ("1",)), - "L": ("L", "L", ("L",)), - "I": ("L", "I", ("I",)), - "F": ("L", "F", ("F",)), - "P": ("RGB", "L", ("P",)), - "RGB": ("RGB", "L", ("R", "G", "B")), - "RGBX": ("RGB", "L", ("R", "G", "B", "X")), - "RGBA": ("RGB", "L", ("R", "G", "B", "A")), - "CMYK": ("RGB", "L", ("C", "M", "Y", "K")), - "YCbCr": ("RGB", "L", ("Y", "Cb", "Cr")), - - # Experimental modes include I;16, I;16B, RGBa, BGR;15, - # and BGR;24. Use these modes only if you know exactly - # what you're doing... - -} - -if sys.byteorder == 'little': - _ENDIAN = '<' -else: - _ENDIAN = '>' - -_MODE_CONV = { - # official modes - "1": ('|b1', None), - "L": ('|u1', None), - "I": ('%si4' % _ENDIAN, None), # FIXME: is this correct? - "F": ('%sf4' % _ENDIAN, None), # FIXME: is this correct? - "P": ('|u1', None), - "RGB": ('|u1', 3), - "RGBX": ('|u1', 4), - "RGBA": ('|u1', 4), - "CMYK": ('|u1', 4), - "YCbCr": ('|u1', 4), -} - -def _conv_type_shape(im): - shape = im.size[::-1] - typ, extra = _MODE_CONV[im.mode] - if extra is None: - return shape, typ - else: - return shape+(extra,), typ - - -MODES = _MODEINFO.keys() -MODES.sort() - -# raw modes that may be memory mapped. NOTE: if you change this, you -# may have to modify the stride calculation in map.c too! -_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16B") - -## -# Gets the "base" mode for given mode. This function returns "L" for -# images that contain grayscale data, and "RGB" for images that -# contain color data. -# -# @param mode Input mode. -# @return "L" or "RGB". -# @exception KeyError If the input mode was not a standard mode. - -def getmodebase(mode): - return ImageMode.getmode(mode).basemode - -## -# Gets the storage type mode. Given a mode, this function returns a -# single-layer mode suitable for storing individual bands. -# -# @param mode Input mode. -# @return "L", "I", or "F". -# @exception KeyError If the input mode was not a standard mode. - -def getmodetype(mode): - return ImageMode.getmode(mode).basetype - -## -# Gets a list of individual band names. Given a mode, this function -# returns a tuple containing the names of individual bands (use -# {@link #getmodetype} to get the mode used to store each individual -# band. -# -# @param mode Input mode. -# @return A tuple containing band names. The length of the tuple -# gives the number of bands in an image of the given mode. -# @exception KeyError If the input mode was not a standard mode. - -def getmodebandnames(mode): - return ImageMode.getmode(mode).bands - -## -# Gets the number of individual bands for this mode. -# -# @param mode Input mode. -# @return The number of bands in this mode. -# @exception KeyError If the input mode was not a standard mode. - -def getmodebands(mode): - return len(ImageMode.getmode(mode).bands) - -# -------------------------------------------------------------------- -# Helpers - -_initialized = 0 - -## -# Explicitly loads standard file format drivers. - -def preinit(): - "Load standard file format drivers." - - global _initialized - if _initialized >= 1: - return - - try: - import BmpImagePlugin - except ImportError: - pass - try: - import GifImagePlugin - except ImportError: - pass - try: - import JpegImagePlugin - except ImportError: - pass - try: - import PpmImagePlugin - except ImportError: - pass - try: - import PngImagePlugin - except ImportError: - pass -# try: -# import TiffImagePlugin -# except ImportError: -# pass - - _initialized = 1 - -## -# Explicitly initializes the Python Imaging Library. This function -# loads all available file format drivers. - -def init(): - "Load all file format drivers." - - global _initialized - if _initialized >= 2: - return - - visited = {} - - directories = sys.path - - try: - directories = directories + [os.path.dirname(__file__)] - except NameError: - pass - - # only check directories (including current, if present in the path) - for directory in filter(isDirectory, directories): - fullpath = os.path.abspath(directory) - if visited.has_key(fullpath): - continue - for file in os.listdir(directory): - if file[-14:] == "ImagePlugin.py": - f, e = os.path.splitext(file) - try: - sys.path.insert(0, directory) - try: - __import__(f, globals(), locals(), []) - finally: - del sys.path[0] - except ImportError: - if DEBUG: - print "Image: failed to import", - print f, ":", sys.exc_value - visited[fullpath] = None - - if OPEN or SAVE: - _initialized = 2 - - -# -------------------------------------------------------------------- -# Codec factories (used by tostring/fromstring and ImageFile.load) - -def _getdecoder(mode, decoder_name, args, extra=()): - - # tweak arguments - if args is None: - args = () - elif not isTupleType(args): - args = (args,) - - try: - # get decoder - decoder = getattr(core, decoder_name + "_decoder") - # print decoder, (mode,) + args + extra - return apply(decoder, (mode,) + args + extra) - except AttributeError: - raise IOError("decoder %s not available" % decoder_name) - -def _getencoder(mode, encoder_name, args, extra=()): - - # tweak arguments - if args is None: - args = () - elif not isTupleType(args): - args = (args,) - - try: - # get encoder - encoder = getattr(core, encoder_name + "_encoder") - # print encoder, (mode,) + args + extra - return apply(encoder, (mode,) + args + extra) - except AttributeError: - raise IOError("encoder %s not available" % encoder_name) - - -# -------------------------------------------------------------------- -# Simple expression analyzer - -class _E: - def __init__(self, data): self.data = data - def __coerce__(self, other): return self, _E(other) - def __add__(self, other): return _E((self.data, "__add__", other.data)) - def __mul__(self, other): return _E((self.data, "__mul__", other.data)) - -def _getscaleoffset(expr): - stub = ["stub"] - data = expr(_E(stub)).data - try: - (a, b, c) = data # simplified syntax - if (a is stub and b == "__mul__" and isNumberType(c)): - return c, 0.0 - if (a is stub and b == "__add__" and isNumberType(c)): - return 1.0, c - except TypeError: pass - try: - ((a, b, c), d, e) = data # full syntax - if (a is stub and b == "__mul__" and isNumberType(c) and - d == "__add__" and isNumberType(e)): - return c, e - except TypeError: pass - raise ValueError("illegal expression") - - -# -------------------------------------------------------------------- -# Implementation wrapper - -## -# This class represents an image object. To create Image objects, use -# the appropriate factory functions. There's hardly ever any reason -# to call the Image constructor directly. -# -# @see #open -# @see #new -# @see #fromstring - -class Image: - - format = None - format_description = None - - def __init__(self): - self.im = None - self.mode = "" - self.size = (0, 0) - self.palette = None - self.info = {} - self.category = NORMAL - self.readonly = 0 - - def _new(self, im): - new = Image() - new.im = im - new.mode = im.mode - new.size = im.size - new.palette = self.palette - if im.mode == "P": - new.palette = ImagePalette.ImagePalette() - try: - new.info = self.info.copy() - except AttributeError: - # fallback (pre-1.5.2) - new.info = {} - for k, v in self.info: - new.info[k] = v - return new - - _makeself = _new # compatibility - - def _copy(self): - self.load() - self.im = self.im.copy() - self.readonly = 0 - - def _dump(self, file=None, format=None): - import tempfile - if not file: - file = tempfile.mktemp() - self.load() - if not format or format == "PPM": - self.im.save_ppm(file) - else: - file = file + "." + format - self.save(file, format) - return file - - def __getattr__(self, name): - if name == "__array_interface__": - # numpy array interface support - new = {} - shape, typestr = _conv_type_shape(self) - new['shape'] = shape - new['typestr'] = typestr - new['data'] = self.tostring() - return new - raise AttributeError(name) - - ## - # Returns a string containing pixel data. - # - # @param encoder_name What encoder to use. The default is to - # use the standard "raw" encoder. - # @param *args Extra arguments to the encoder. - # @return An 8-bit string. - - def tostring(self, encoder_name="raw", *args): - "Return image as a binary string" - - # may pass tuple instead of argument list - if len(args) == 1 and isTupleType(args[0]): - args = args[0] - - if encoder_name == "raw" and args == (): - args = self.mode - - self.load() - - # unpack data - e = _getencoder(self.mode, encoder_name, args) - e.setimage(self.im) - - bufsize = max(65536, self.size[0] * 4) # see RawEncode.c - - data = [] - while 1: - l, s, d = e.encode(bufsize) - data.append(d) - if s: - break - if s < 0: - raise RuntimeError("encoder error %d in tostring" % s) - - return string.join(data, "") - - ## - # Returns the image converted to an X11 bitmap. This method - # only works for mode "1" images. - # - # @param name The name prefix to use for the bitmap variables. - # @return A string containing an X11 bitmap. - # @exception ValueError If the mode is not "1" - - def tobitmap(self, name="image"): - "Return image as an XBM bitmap" - - self.load() - if self.mode != "1": - raise ValueError("not a bitmap") - data = self.tostring("xbm") - return string.join(["#define %s_width %d\n" % (name, self.size[0]), - "#define %s_height %d\n"% (name, self.size[1]), - "static char %s_bits[] = {\n" % name, data, "};"], "") - - ## - # Loads this image with pixel data from a string. - #

- # This method is similar to the {@link #fromstring} function, but - # loads data into this image instead of creating a new image - # object. - - def fromstring(self, data, decoder_name="raw", *args): - "Load data to image from binary string" - - # may pass tuple instead of argument list - if len(args) == 1 and isTupleType(args[0]): - args = args[0] - - # default format - if decoder_name == "raw" and args == (): - args = self.mode - - # unpack data - d = _getdecoder(self.mode, decoder_name, args) - d.setimage(self.im) - s = d.decode(data) - - if s[0] >= 0: - raise ValueError("not enough image data") - if s[1] != 0: - raise ValueError("cannot decode image data") - - ## - # Allocates storage for the image and loads the pixel data. In - # normal cases, you don't need to call this method, since the - # Image class automatically loads an opened image when it is - # accessed for the first time. - # - # @return An image access object. - - def load(self): - "Explicitly load pixel data." - if self.im and self.palette and self.palette.dirty: - # realize palette - apply(self.im.putpalette, self.palette.getdata()) - self.palette.dirty = 0 - self.palette.mode = "RGB" - self.palette.rawmode = None - if self.info.has_key("transparency"): - self.im.putpalettealpha(self.info["transparency"], 0) - self.palette.mode = "RGBA" - if self.im: - return self.im.pixel_access(self.readonly) - - ## - # Verifies the contents of a file. For data read from a file, this - # method attempts to determine if the file is broken, without - # actually decoding the image data. If this method finds any - # problems, it raises suitable exceptions. If you need to load - # the image after using this method, you must reopen the image - # file. - - def verify(self): - "Verify file contents." - pass - - - ## - # Returns a converted copy of this image. For the "P" mode, this - # method translates pixels through the palette. If mode is - # omitted, a mode is chosen so that all information in the image - # and the palette can be represented without a palette. - #

- # The current version supports all possible conversions between - # "L", "RGB" and "CMYK." - #

- # When translating a colour image to black and white (mode "L"), - # the library uses the ITU-R 601-2 luma transform: - #

- # L = R * 299/1000 + G * 587/1000 + B * 114/1000 - #

- # When translating a greyscale image into a bilevel image (mode - # "1"), all non-zero values are set to 255 (white). To use other - # thresholds, use the {@link #Image.point} method. - # - # @def convert(mode, matrix=None) - # @param mode The requested mode. - # @param matrix An optional conversion matrix. If given, this - # should be 4- or 16-tuple containing floating point values. - # @return An Image object. - - def convert(self, mode=None, data=None, dither=None, - palette=WEB, colors=256): - "Convert to other pixel format" - - if not mode: - # determine default mode - if self.mode == "P": - self.load() - if self.palette: - mode = self.palette.mode - else: - mode = "RGB" - else: - return self.copy() - - self.load() - - if data: - # matrix conversion - if mode not in ("L", "RGB"): - raise ValueError("illegal conversion") - im = self.im.convert_matrix(mode, data) - return self._new(im) - - if mode == "P" and palette == ADAPTIVE: - im = self.im.quantize(colors) - return self._new(im) - - # colourspace conversion - if dither is None: - dither = FLOYDSTEINBERG - - try: - im = self.im.convert(mode, dither) - except ValueError: - try: - # normalize source image and try again - im = self.im.convert(getmodebase(self.mode)) - im = im.convert(mode, dither) - except KeyError: - raise ValueError("illegal conversion") - - return self._new(im) - - def quantize(self, colors=256, method=0, kmeans=0, palette=None): - - # methods: - # 0 = median cut - # 1 = maximum coverage - - # NOTE: this functionality will be moved to the extended - # quantizer interface in a later version of PIL. - - self.load() - - if palette: - # use palette from reference image - palette.load() - if palette.mode != "P": - raise ValueError("bad mode for palette image") - if self.mode != "RGB" and self.mode != "L": - raise ValueError( - "only RGB or L mode images can be quantized to a palette" - ) - im = self.im.convert("P", 1, palette.im) - return self._makeself(im) - - im = self.im.quantize(colors, method, kmeans) - return self._new(im) - - ## - # Copies this image. Use this method if you wish to paste things - # into an image, but still retain the original. - # - # @return An Image object. - - def copy(self): - "Copy raster data" - - self.load() - im = self.im.copy() - return self._new(im) - - ## - # Returns a rectangular region from this image. The box is a - # 4-tuple defining the left, upper, right, and lower pixel - # coordinate. - #

- # This is a lazy operation. Changes to the source image may or - # may not be reflected in the cropped image. To break the - # connection, call the {@link #Image.load} method on the cropped - # copy. - # - # @param The crop rectangle, as a (left, upper, right, lower)-tuple. - # @return An Image object. - - def crop(self, box=None): - "Crop region from image" - - self.load() - if box is None: - return self.copy() - - # lazy operation - return _ImageCrop(self, box) - - ## - # Configures the image file loader so it returns a version of the - # image that as closely as possible matches the given mode and - # size. For example, you can use this method to convert a colour - # JPEG to greyscale while loading it, or to extract a 128x192 - # version from a PCD file. - #

- # Note that this method modifies the Image object in place. If - # the image has already been loaded, this method has no effect. - # - # @param mode The requested mode. - # @param size The requested size. - - def draft(self, mode, size): - "Configure image decoder" - - pass - - def _expand(self, xmargin, ymargin=None): - if ymargin is None: - ymargin = xmargin - self.load() - return self._new(self.im.expand(xmargin, ymargin, 0)) - - ## - # Filters this image using the given filter. For a list of - # available filters, see the ImageFilter module. - # - # @param filter Filter kernel. - # @return An Image object. - # @see ImageFilter - - def filter(self, filter): - "Apply environment filter to image" - - self.load() - - from ImageFilter import Filter - if not isinstance(filter, Filter): - filter = filter() - - if self.im.bands == 1: - return self._new(filter.filter(self.im)) - # fix to handle multiband images since _imaging doesn't - ims = [] - for c in range(self.im.bands): - ims.append(self._new(filter.filter(self.im.getband(c)))) - return merge(self.mode, ims) - - ## - # Returns a tuple containing the name of each band in this image. - # For example, getbands on an RGB image returns ("R", "G", "B"). - # - # @return A tuple containing band names. - - def getbands(self): - "Get band names" - - return ImageMode.getmode(self.mode).bands - - ## - # Calculates the bounding box of the non-zero regions in the - # image. - # - # @return The bounding box is returned as a 4-tuple defining the - # left, upper, right, and lower pixel coordinate. If the image - # is completely empty, this method returns None. - - def getbbox(self): - "Get bounding box of actual data (non-zero pixels) in image" - - self.load() - return self.im.getbbox() - - ## - # Returns a list of colors used in this image. - # - # @param maxcolors Maximum number of colors. If this number is - # exceeded, this method returns None. The default limit is - # 256 colors. - # @return An unsorted list of (count, pixel) values. - - def getcolors(self, maxcolors=256): - "Get colors from image, up to given limit" - - self.load() - if self.mode in ("1", "L", "P"): - h = self.im.histogram() - out = [] - for i in range(256): - if h[i]: - out.append((h[i], i)) - if len(out) > maxcolors: - return None - return out - return self.im.getcolors(maxcolors) - - ## - # Returns the contents of this image as a sequence object - # containing pixel values. The sequence object is flattened, so - # that values for line one follow directly after the values of - # line zero, and so on. - #

- # Note that the sequence object returned by this method is an - # internal PIL data type, which only supports certain sequence - # operations. To convert it to an ordinary sequence (e.g. for - # printing), use list(im.getdata()). - # - # @param band What band to return. The default is to return - # all bands. To return a single band, pass in the index - # value (e.g. 0 to get the "R" band from an "RGB" image). - # @return A sequence-like object. - - def getdata(self, band = None): - "Get image data as sequence object." - - self.load() - if band is not None: - return self.im.getband(band) - return self.im # could be abused - - ## - # Gets the the minimum and maximum pixel values for each band in - # the image. - # - # @return For a single-band image, a 2-tuple containing the - # minimum and maximum pixel value. For a multi-band image, - # a tuple containing one 2-tuple for each band. - - def getextrema(self): - "Get min/max value" - - self.load() - if self.im.bands > 1: - extrema = [] - for i in range(self.im.bands): - extrema.append(self.im.getband(i).getextrema()) - return tuple(extrema) - return self.im.getextrema() - - ## - # Returns a PyCObject that points to the internal image memory. - # - # @return A PyCObject object. - - def getim(self): - "Get PyCObject pointer to internal image memory" - - self.load() - return self.im.ptr - - - ## - # Returns the image palette as a list. - # - # @return A list of color values [r, g, b, ...], or None if the - # image has no palette. - - def getpalette(self): - "Get palette contents." - - self.load() - try: - return map(ord, self.im.getpalette()) - except ValueError: - return None # no palette - - - ## - # Returns the pixel value at a given position. - # - # @param xy The coordinate, given as (x, y). - # @return The pixel value. If the image is a multi-layer image, - # this method returns a tuple. - - def getpixel(self, xy): - "Get pixel value" - - self.load() - return self.im.getpixel(xy) - - ## - # Returns the horizontal and vertical projection. - # - # @return Two sequences, indicating where there are non-zero - # pixels along the X-axis and the Y-axis, respectively. - - def getprojection(self): - "Get projection to x and y axes" - - self.load() - x, y = self.im.getprojection() - return map(ord, x), map(ord, y) - - ## - # Returns a histogram for the image. The histogram is returned as - # a list of pixel counts, one for each pixel value in the source - # image. If the image has more than one band, the histograms for - # all bands are concatenated (for example, the histogram for an - # "RGB" image contains 768 values). - #

- # A bilevel image (mode "1") is treated as a greyscale ("L") image - # by this method. - #

- # If a mask is provided, the method returns a histogram for those - # parts of the image where the mask image is non-zero. The mask - # image must have the same size as the image, and be either a - # bi-level image (mode "1") or a greyscale image ("L"). - # - # @def histogram(mask=None) - # @param mask An optional mask. - # @return A list containing pixel counts. - - def histogram(self, mask=None, extrema=None): - "Take histogram of image" - - self.load() - if mask: - mask.load() - return self.im.histogram((0, 0), mask.im) - if self.mode in ("I", "F"): - if extrema is None: - extrema = self.getextrema() - return self.im.histogram(extrema) - return self.im.histogram() - - ## - # (Deprecated) Returns a copy of the image where the 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. - #

- # This method is deprecated. New code should use the offset - # function in the ImageChops module. - # - # @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(self, xoffset, yoffset=None): - "(deprecated) Offset image in horizontal and/or vertical direction" - if warnings: - warnings.warn( - "'offset' is deprecated; use 'ImageChops.offset' instead", - DeprecationWarning, stacklevel=2 - ) - import ImageChops - return ImageChops.offset(self, xoffset, yoffset) - - ## - # Pastes another image into this image. The box argument is either - # a 2-tuple giving the upper left corner, a 4-tuple defining the - # left, upper, right, and lower pixel coordinate, or None (same as - # (0, 0)). If a 4-tuple is given, the size of the pasted image - # must match the size of the region. - #

- # If the modes don't match, the pasted image is converted to the - # mode of this image (see the {@link #Image.convert} method for - # details). - #

- # Instead of an image, the source can be a integer or tuple - # containing pixel values. The method then fills the region - # with the given colour. When creating RGB images, you can - # also use colour strings as supported by the ImageColor module. - #

- # If a mask is given, this method updates only the regions - # indicated by the mask. You can use either "1", "L" or "RGBA" - # images (in the latter case, the alpha band is used as mask). - # Where the mask is 255, the given image is copied as is. Where - # the mask is 0, the current value is preserved. Intermediate - # values can be used for transparency effects. - #

- # Note that if you paste an "RGBA" image, the alpha band is - # ignored. You can work around this by using the same image as - # both source image and mask. - # - # @param im Source image or pixel value (integer or tuple). - # @param box An optional 4-tuple giving the region to paste into. - # If a 2-tuple is used instead, it's treated as the upper left - # corner. If omitted or None, the source is pasted into the - # upper left corner. - #

- # If an image is given as the second argument and there is no - # third, the box defaults to (0, 0), and the second argument - # is interpreted as a mask image. - # @param mask An optional mask image. - # @return An Image object. - - def paste(self, im, box=None, mask=None): - "Paste other image into region" - - if isImageType(box) and mask is None: - # abbreviated paste(im, mask) syntax - mask = box; box = None - - if box is None: - # cover all of self - box = (0, 0) + self.size - - if len(box) == 2: - # lower left corner given; get size from image or mask - if isImageType(im): - size = im.size - elif isImageType(mask): - size = mask.size - else: - # FIXME: use self.size here? - raise ValueError( - "cannot determine region size; use 4-item box" - ) - box = box + (box[0]+size[0], box[1]+size[1]) - - if isStringType(im): - import ImageColor - im = ImageColor.getcolor(im, self.mode) - - elif isImageType(im): - im.load() - if self.mode != im.mode: - if self.mode != "RGB" or im.mode not in ("RGBA", "RGBa"): - # should use an adapter for this! - im = im.convert(self.mode) - im = im.im - - self.load() - if self.readonly: - self._copy() - - if mask: - mask.load() - self.im.paste(im, box, mask.im) - else: - self.im.paste(im, box) - - ## - # Maps this image through a lookup table or function. - # - # @param lut A lookup table, containing 256 values per band in the - # image. A function can be used instead, it should take a single - # argument. The function is called once for each possible pixel - # value, and the resulting table is applied to all bands of the - # image. - # @param mode Output mode (default is same as input). In the - # current version, this can only be used if the source image - # has mode "L" or "P", and the output has mode "1". - # @return An Image object. - - def point(self, lut, mode=None): - "Map image through lookup table" - - self.load() - - if not isSequenceType(lut): - # if it isn't a list, it should be a function - if self.mode in ("I", "I;16", "F"): - # check if the function can be used with point_transform - scale, offset = _getscaleoffset(lut) - return self._new(self.im.point_transform(scale, offset)) - # for other modes, convert the function to a table - lut = map(lut, range(256)) * self.im.bands - - if self.mode == "F": - # FIXME: _imaging returns a confusing error message for this case - raise ValueError("point operation not supported for this mode") - - return self._new(self.im.point(lut, mode)) - - ## - # Adds or replaces the alpha layer in this image. If the image - # does not have an alpha layer, it's converted to "LA" or "RGBA". - # The new layer must be either "L" or "1". - # - # @param im The new alpha layer. This can either be an "L" or "1" - # image having the same size as this image, or an integer or - # other color value. - - def putalpha(self, alpha): - "Set alpha layer" - - self.load() - if self.readonly: - self._copy() - - if self.mode not in ("LA", "RGBA"): - # attempt to promote self to a matching alpha mode - try: - mode = getmodebase(self.mode) + "A" - try: - self.im.setmode(mode) - except (AttributeError, ValueError): - # do things the hard way - im = self.im.convert(mode) - if im.mode not in ("LA", "RGBA"): - raise ValueError # sanity check - self.im = im - self.mode = self.im.mode - except (KeyError, ValueError): - raise ValueError("illegal image mode") - - if self.mode == "LA": - band = 1 - else: - band = 3 - - if isImageType(alpha): - # alpha layer - if alpha.mode not in ("1", "L"): - raise ValueError("illegal image mode") - alpha.load() - if alpha.mode == "1": - alpha = alpha.convert("L") - else: - # constant alpha - try: - self.im.fillband(band, alpha) - except (AttributeError, ValueError): - # do things the hard way - alpha = new("L", self.size, alpha) - else: - return - - self.im.putband(alpha.im, band) - - ## - # Copies pixel data to this image. This method copies data from a - # sequence object into the image, starting at the upper left - # corner (0, 0), and continuing until either the image or the - # sequence ends. The scale and offset values are used to adjust - # the sequence values: pixel = value*scale + offset. - # - # @param data A sequence object. - # @param scale An optional scale value. The default is 1.0. - # @param offset An optional offset value. The default is 0.0. - - def putdata(self, data, scale=1.0, offset=0.0): - "Put data from a sequence object into an image." - - self.load() - if self.readonly: - self._copy() - - self.im.putdata(data, scale, offset) - - ## - # Attaches a palette to this image. The image must be a "P" or - # "L" image, and the palette sequence must contain 768 integer - # values, where each group of three values represent the red, - # green, and blue values for the corresponding pixel - # index. Instead of an integer sequence, you can use an 8-bit - # string. - # - # @def putpalette(data) - # @param data A palette sequence (either a list or a string). - - def putpalette(self, data, rawmode="RGB"): - "Put palette data into an image." - - self.load() - if self.mode not in ("L", "P"): - raise ValueError("illegal image mode") - if not isStringType(data): - data = string.join(map(chr, data), "") - self.mode = "P" - self.palette = ImagePalette.raw(rawmode, data) - self.palette.mode = "RGB" - self.load() # install new palette - - ## - # Modifies the pixel at the given position. The colour is given as - # a single numerical value for single-band images, and a tuple for - # multi-band images. - #

- # Note that this method is relatively slow. For more extensive - # changes, use {@link #Image.paste} or the ImageDraw module - # instead. - # - # @param xy The pixel coordinate, given as (x, y). - # @param value The pixel value. - # @see #Image.paste - # @see #Image.putdata - # @see ImageDraw - - def putpixel(self, xy, value): - "Set pixel value" - - self.load() - if self.readonly: - self._copy() - - return self.im.putpixel(xy, value) - - ## - # Returns a resized copy of this image. - # - # @def resize(size, filter=NEAREST) - # @param size The requested size in pixels, as a 2-tuple: - # (width, height). - # @param filter An optional resampling filter. This can be - # one of NEAREST (use nearest neighbour), BILINEAR - # (linear interpolation in a 2x2 environment), BICUBIC - # (cubic spline interpolation in a 4x4 environment), or - # ANTIALIAS (a high-quality downsampling filter). - # If omitted, or if the image has mode "1" or "P", it is - # set NEAREST. - # @return An Image object. - - def resize(self, size, resample=NEAREST): - "Resize image" - - if resample not in (NEAREST, BILINEAR, BICUBIC, ANTIALIAS): - raise ValueError("unknown resampling filter") - - self.load() - - if self.mode in ("1", "P"): - resample = NEAREST - - if resample == ANTIALIAS: - # requires stretch support (imToolkit & PIL 1.1.3) - try: - im = self.im.stretch(size, resample) - except AttributeError: - raise ValueError("unsupported resampling filter") - else: - im = self.im.resize(size, resample) - - return self._new(im) - - ## - # Returns a rotated copy of this image. This method returns a - # copy of this image, rotated the given number of degrees counter - # clockwise around its centre. - # - # @def rotate(angle, filter=NEAREST) - # @param angle In degrees counter clockwise. - # @param filter An optional resampling filter. This can be - # one of NEAREST (use nearest neighbour), BILINEAR - # (linear interpolation in a 2x2 environment), or BICUBIC - # (cubic spline interpolation in a 4x4 environment). - # If omitted, or if the image has mode "1" or "P", it is - # set NEAREST. - # @param expand Optional expansion flag. If true, expands the output - # image to make it large enough to hold the entire rotated image. - # If false or omitted, make the output image the same size as the - # input image. - # @return An Image object. - - def rotate(self, angle, resample=NEAREST, expand=0): - "Rotate image. Angle given as degrees counter-clockwise." - - if expand: - import math - angle = -angle * math.pi / 180 - matrix = [ - math.cos(angle), math.sin(angle), 0.0, - -math.sin(angle), math.cos(angle), 0.0 - ] - def transform(x, y, (a, b, c, d, e, f)=matrix): - return a*x + b*y + c, d*x + e*y + f - - # calculate output size - w, h = self.size - xx = [] - yy = [] - for x, y in ((0, 0), (w, 0), (w, h), (0, h)): - x, y = transform(x, y) - xx.append(x) - yy.append(y) - w = int(math.ceil(max(xx)) - math.floor(min(xx))) - h = int(math.ceil(max(yy)) - math.floor(min(yy))) - - # adjust center - x, y = transform(w / 2.0, h / 2.0) - matrix[2] = self.size[0] / 2.0 - x - matrix[5] = self.size[1] / 2.0 - y - - return self.transform((w, h), AFFINE, matrix) - - if resample not in (NEAREST, BILINEAR, BICUBIC): - raise ValueError("unknown resampling filter") - - self.load() - - if self.mode in ("1", "P"): - resample = NEAREST - - return self._new(self.im.rotate(angle, resample)) - - ## - # Saves this image under the given filename. If no format is - # specified, the format to use is determined from the filename - # extension, if possible. - #

- # Keyword options can be used to provide additional instructions - # to the writer. If a writer doesn't recognise an option, it is - # silently ignored. The available options are described later in - # this handbook. - #

- # You can use a file object instead of a filename. In this case, - # you must always specify the format. The file object must - # implement the seek, tell, and write - # methods, and be opened in binary mode. - # - # @def save(file, format=None, **options) - # @param file File name or file object. - # @param format Optional format override. If omitted, the - # format to use is determined from the filename extension. - # If a file object was used instead of a filename, this - # parameter should always be used. - # @param **options Extra parameters to the image writer. - # @return None - # @exception KeyError If the output format could not be determined - # from the file name. Use the format option to solve this. - # @exception IOError If the file could not be written. The file - # may have been created, and may contain partial data. - - def save(self, fp, format=None, **params): - "Save image to file or stream" - - if isStringType(fp): - filename = fp - else: - if hasattr(fp, "name") and isStringType(fp.name): - filename = fp.name - else: - filename = "" - - # may mutate self! - self.load() - - self.encoderinfo = params - self.encoderconfig = () - - preinit() - - ext = string.lower(os.path.splitext(filename)[1]) - - if not format: - try: - format = EXTENSION[ext] - except KeyError: - init() - try: - format = EXTENSION[ext] - except KeyError: - raise KeyError(ext) # unknown extension - - try: - save_handler = SAVE[string.upper(format)] - except KeyError: - init() - save_handler = SAVE[string.upper(format)] # unknown format - - if isStringType(fp): - import __builtin__ - fp = __builtin__.open(fp, "wb") - close = 1 - else: - close = 0 - - try: - save_handler(self, fp, filename) - finally: - # do what we can to clean up - if close: - fp.close() - - ## - # Seeks to the given frame in this sequence file. If you seek - # beyond the end of the sequence, the method raises an - # EOFError exception. When a sequence file is opened, the - # library automatically seeks to frame 0. - #

- # Note that in the current version of the library, most sequence - # formats only allows you to seek to the next frame. - # - # @param frame Frame number, starting at 0. - # @exception EOFError If the call attempts to seek beyond the end - # of the sequence. - # @see #Image.tell - - def seek(self, frame): - "Seek to given frame in sequence file" - - # overridden by file handlers - if frame != 0: - raise EOFError - - ## - # Displays this image. This method is mainly intended for - # debugging purposes. - #

- # On Unix platforms, this method saves the image to a temporary - # PPM file, and calls the xv utility. - #

- # On Windows, it saves the image to a temporary BMP file, and uses - # the standard BMP display utility to show it (usually Paint). - # - # @def show(title=None) - # @param title Optional title to use for the image window, - # where possible. - - def show(self, title=None, command=None): - "Display image (for debug purposes only)" - - _showxv(self, title, command) - - ## - # Split this image into individual bands. This method returns a - # tuple of individual image bands from an image. For example, - # splitting an "RGB" image creates three new images each - # containing a copy of one of the original bands (red, green, - # blue). - # - # @return A tuple containing bands. - - def split(self): - "Split image into bands" - - ims = [] - self.load() - for i in range(self.im.bands): - ims.append(self._new(self.im.getband(i))) - return tuple(ims) - - ## - # Returns the current frame number. - # - # @return Frame number, starting with 0. - # @see #Image.seek - - def tell(self): - "Return current frame number" - - return 0 - - ## - # Make this image into a thumbnail. This method modifies the - # image to contain a thumbnail version of itself, no larger than - # the given size. This method calculates an appropriate thumbnail - # size to preserve the aspect of the image, calls the {@link - # #Image.draft} method to configure the file reader (where - # applicable), and finally resizes the image. - #

- # Note that the bilinear and bicubic filters in the current - # version of PIL are not well-suited for thumbnail generation. - # You should use ANTIALIAS unless speed is much more - # important than quality. - #

- # Also note that this function modifies the Image object in place. - # If you need to use the full resolution image as well, apply this - # method to a {@link #Image.copy} of the original image. - # - # @param size Requested size. - # @param resample Optional resampling filter. This can be one - # of NEAREST, BILINEAR, BICUBIC, or - # ANTIALIAS (best quality). If omitted, it defaults - # to NEAREST (this will be changed to ANTIALIAS in a - # future version). - # @return None - - def thumbnail(self, size, resample=NEAREST): - "Create thumbnail representation (modifies image in place)" - - # FIXME: the default resampling filter will be changed - # to ANTIALIAS in future versions - - # preserve aspect ratio - x, y = self.size - if x > size[0]: y = max(y * size[0] / x, 1); x = size[0] - if y > size[1]: x = max(x * size[1] / y, 1); y = size[1] - size = x, y - - if size == self.size: - return - - self.draft(None, size) - - self.load() - - try: - im = self.resize(size, resample) - except ValueError: - if resample != ANTIALIAS: - raise - im = self.resize(size, NEAREST) # fallback - - self.im = im.im - self.mode = im.mode - self.size = size - - self.readonly = 0 - - # FIXME: the different tranform methods need further explanation - # instead of bloating the method docs, add a separate chapter. - - ## - # Transforms this image. This method creates a new image with the - # given size, and the same mode as the original, and copies data - # to the new image using the given transform. - #

- # @def transform(size, method, data, resample=NEAREST) - # @param size The output size. - # @param method The transformation method. This is one of - # EXTENT (cut out a rectangular subregion), AFFINE - # (affine transform), PERSPECTIVE (perspective - # transform), QUAD (map a quadrilateral to a - # rectangle), or MESH (map a number of source quadrilaterals - # in one operation). - # @param data Extra data to the transformation method. - # @param resample Optional resampling filter. It can be one of - # NEAREST (use nearest neighbour), BILINEAR - # (linear interpolation in a 2x2 environment), or - # BICUBIC (cubic spline interpolation in a 4x4 - # environment). If omitted, or if the image has mode - # "1" or "P", it is set to NEAREST. - # @return An Image object. - - def transform(self, size, method, data=None, resample=NEAREST, fill=1): - "Transform image" - - import ImageTransform - if isinstance(method, ImageTransform.Transform): - method, data = method.getdata() - if data is None: - raise ValueError("missing method data") - im = new(self.mode, size, None) - if method == MESH: - # list of quads - for box, quad in data: - im.__transformer(box, self, QUAD, quad, resample, fill) - else: - im.__transformer((0, 0)+size, self, method, data, resample, fill) - - return im - - def __transformer(self, box, image, method, data, - resample=NEAREST, fill=1): - - # FIXME: this should be turned into a lazy operation (?) - - w = box[2]-box[0] - h = box[3]-box[1] - - if method == AFFINE: - # change argument order to match implementation - data = (data[2], data[0], data[1], - data[5], data[3], data[4]) - elif method == EXTENT: - # convert extent to an affine transform - x0, y0, x1, y1 = data - xs = float(x1 - x0) / w - ys = float(y1 - y0) / h - method = AFFINE - data = (x0 + xs/2, xs, 0, y0 + ys/2, 0, ys) - elif method == PERSPECTIVE: - # change argument order to match implementation - data = (data[2], data[0], data[1], - data[5], data[3], data[4], - data[6], data[7]) - elif method == QUAD: - # quadrilateral warp. data specifies the four corners - # given as NW, SW, SE, and NE. - nw = data[0:2]; sw = data[2:4]; se = data[4:6]; ne = data[6:8] - x0, y0 = nw; As = 1.0 / w; At = 1.0 / h - data = (x0, (ne[0]-x0)*As, (sw[0]-x0)*At, - (se[0]-sw[0]-ne[0]+x0)*As*At, - y0, (ne[1]-y0)*As, (sw[1]-y0)*At, - (se[1]-sw[1]-ne[1]+y0)*As*At) - else: - raise ValueError("unknown transformation method") - - if resample not in (NEAREST, BILINEAR, BICUBIC): - raise ValueError("unknown resampling filter") - - image.load() - - self.load() - - if image.mode in ("1", "P"): - resample = NEAREST - - self.im.transform2(box, image.im, method, data, resample, fill) - - ## - # Returns a flipped or rotated copy of this image. - # - # @param method One of FLIP_LEFT_RIGHT, FLIP_TOP_BOTTOM, - # ROTATE_90, ROTATE_180, or ROTATE_270. - - def transpose(self, method): - "Transpose image (flip or rotate in 90 degree steps)" - - self.load() - im = self.im.transpose(method) - return self._new(im) - -# -------------------------------------------------------------------- -# Lazy operations - -class _ImageCrop(Image): - - def __init__(self, im, box): - - Image.__init__(self) - - x0, y0, x1, y1 = box - if x1 < x0: - x1 = x0 - if y1 < y0: - y1 = y0 - - self.mode = im.mode - self.size = x1-x0, y1-y0 - - self.__crop = x0, y0, x1, y1 - - self.im = im.im - - def load(self): - - # lazy evaluation! - if self.__crop: - self.im = self.im.crop(self.__crop) - self.__crop = None - - # FIXME: future versions should optimize crop/paste - # sequences! - -# -------------------------------------------------------------------- -# Factories - -# -# Debugging - -def _wedge(): - "Create greyscale wedge (for debugging only)" - - return Image()._new(core.wedge("L")) - -## -# Creates a new image with the given mode and size. -# -# @param mode The mode to use for the new image. -# @param size A 2-tuple, containing (width, height) in pixels. -# @param color What colour to use for the image. Default is black. -# If given, this should be a single integer or floating point value -# for single-band modes, and a tuple for multi-band modes (one value -# per band). When creating RGB images, you can also use colour -# strings as supported by the ImageColor module. If the colour is -# None, the image is not initialised. -# @return An Image object. - -def new(mode, size, color=0): - "Create a new image" - - if color is None: - # don't initialize - return Image()._new(core.new(mode, size)) - - if isStringType(color): - # css3-style specifier - - import ImageColor - color = ImageColor.getcolor(color, mode) - - return Image()._new(core.fill(mode, size, color)) - -## -# Creates an image memory from pixel data in a string. -#

-# In its simplest form, this function takes three arguments -# (mode, size, and unpacked pixel data). -#

-# You can also use any pixel decoder supported by PIL. For more -# information on available decoders, see the section Writing Your Own File Decoder. -#

-# Note that this function decodes pixel data only, not entire images. -# If you have an entire image in a string, wrap it in a -# StringIO object, and use {@link #open} to load it. -# -# @param mode The image mode. -# @param size The image size. -# @param data An 8-bit string containing raw data for the given mode. -# @param decoder_name What decoder to use. -# @param *args Additional parameters for the given decoder. -# @return An Image object. - -def fromstring(mode, size, data, decoder_name="raw", *args): - "Load image from string" - - # may pass tuple instead of argument list - if len(args) == 1 and isTupleType(args[0]): - args = args[0] - - if decoder_name == "raw" and args == (): - args = mode - - im = new(mode, size) - im.fromstring(data, decoder_name, args) - return im - -## -# (New in 1.1.4) Creates an image memory from pixel data in a string -# or byte buffer. -#

-# This function is similar to {@link #fromstring}, but uses data in -# the byte buffer, where possible. This means that changes to the -# original buffer object are reflected in this image). Not all modes -# can share memory; supported modes include "L", "RGBX", "RGBA", and -# "CMYK". -#

-# Note that this function decodes pixel data only, not entire images. -# If you have an entire image file in a string, wrap it in a -# StringIO object, and use {@link #open} to load it. -#

-# In the current version, the default parameters used for the "raw" -# decoder differs from that used for {@link fromstring}. This is a -# bug, and will probably be fixed in a future release. The current -# release issues a warning if you do this; to disable the warning, -# you should provide the full set of parameters. See below for -# details. -# -# @param mode The image mode. -# @param size The image size. -# @param data An 8-bit string or other buffer object containing raw -# data for the given mode. -# @param decoder_name What decoder to use. -# @param *args Additional parameters for the given decoder. For the -# default encoder ("raw"), it's recommended that you provide the -# full set of parameters: -# frombuffer(mode, size, data, "raw", mode, 0, 1). -# @return An Image object. -# @since 1.1.4 - -def frombuffer(mode, size, data, decoder_name="raw", *args): - "Load image from string or buffer" - - # may pass tuple instead of argument list - if len(args) == 1 and isTupleType(args[0]): - args = args[0] - - if decoder_name == "raw": - if args == (): - if warnings: - warnings.warn( - "the frombuffer defaults may change in a future release; " - "for portability, change the call to read:\n" - " frombuffer(mode, size, data, 'raw', mode, 0, 1)", - RuntimeWarning, stacklevel=2 - ) - args = mode, 0, -1 # may change to (mode, 0, 1) post-1.1.6 - if args[0] in _MAPMODES: - im = new(mode, (1,1)) - im = im._new( - core.map_buffer(data, size, decoder_name, None, 0, args) - ) - im.readonly = 1 - return im - - return apply(fromstring, (mode, size, data, decoder_name, args)) - - -## -# (New in 1.1.6) Create an image memory from an object exporting -# the array interface (using the buffer protocol). -# -# If obj is not contiguous, then the tostring method is called -# and {@link frombuffer} is used. -# -# @param obj Object with array interface -# @param mode Mode to use (will be determined from type if None) -# @return An image memory. - -def fromarray(obj, mode=None): - arr = obj.__array_interface__ - shape = arr['shape'] - ndim = len(shape) - try: - strides = arr['strides'] - except KeyError: - strides = None - if mode is None: - typestr = arr['typestr'] - if not (typestr[0] == '|' or typestr[0] == _ENDIAN or - typestr[1:] not in ['u1', 'b1', 'i4', 'f4']): - raise TypeError("cannot handle data-type") - typestr = typestr[:2] - if typestr == 'i4': - mode = 'I' - elif typestr == 'f4': - mode = 'F' - elif typestr == 'b1': - mode = '1' - elif ndim == 2: - mode = 'L' - elif ndim == 3: - mode = 'RGB' - elif ndim == 4: - mode = 'RGBA' - else: - raise TypeError("Do not understand data.") - ndmax = 4 - bad_dims=0 - if mode in ['1','L','I','P','F']: - ndmax = 2 - elif mode == 'RGB': - ndmax = 3 - if ndim > ndmax: - raise ValueError("Too many dimensions.") - - size = shape[:2][::-1] - if strides is not None: - obj = obj.tostring() - - return frombuffer(mode, size, obj, "raw", mode, 0, 1) - -## -# Opens and identifies the given image file. -#

-# This is a lazy operation; this function identifies the file, but the -# actual image data is not read from the file until you try to process -# the data (or call the {@link #Image.load} method). -# -# @def open(file, mode="r") -# @param file A filename (string) or a file object. The file object -# must implement read, seek, and tell methods, -# and be opened in binary mode. -# @param mode The mode. If given, this argument must be "r". -# @return An Image object. -# @exception IOError If the file cannot be found, or the image cannot be -# opened and identified. -# @see #new - -def open(fp, mode="r"): - "Open an image file, without loading the raster data" - - if mode != "r": - raise ValueError("bad mode") - - if isStringType(fp): - import __builtin__ - filename = fp - fp = __builtin__.open(fp, "rb") - else: - filename = "" - - prefix = fp.read(16) - - preinit() - - for i in ID: - try: - factory, accept = OPEN[i] - if not accept or accept(prefix): - fp.seek(0) - return factory(fp, filename) - except (SyntaxError, IndexError, TypeError): - pass - - init() - - for i in ID: - try: - factory, accept = OPEN[i] - if not accept or accept(prefix): - fp.seek(0) - return factory(fp, filename) - except (SyntaxError, IndexError, TypeError): - pass - - raise IOError("cannot identify image file") - -# -# Image processing. - -## -# Creates a new image by interpolating between two input images, using -# a constant alpha. -# -#

-#    out = image1 * (1.0 - alpha) + image2 * alpha
-# 
-# -# @param im1 The first image. -# @param im2 The second image. Must have the same mode and size as -# the first image. -# @param alpha The interpolation alpha factor. If alpha is 0.0, a -# copy of the first image is returned. If alpha is 1.0, a copy of -# the second image is returned. There are no restrictions on the -# alpha value. If necessary, the result is clipped to fit into -# the allowed output range. -# @return An Image object. - -def blend(im1, im2, alpha): - "Interpolate between images." - - im1.load() - im2.load() - return im1._new(core.blend(im1.im, im2.im, alpha)) - -## -# Creates a new image by interpolating between two input images, -# using the mask as alpha. -# -# @param image1 The first image. -# @param image2 The second image. Must have the same mode and -# size as the first image. -# @param mask A mask image. This image can can have mode -# "1", "L", or "RGBA", and must have the same size as the -# other two images. - -def composite(image1, image2, mask): - "Create composite image by blending images using a transparency mask" - - image = image2.copy() - image.paste(image1, None, mask) - return image - -## -# Applies the function (which should take one argument) to each pixel -# in the given image. If the image has more than one band, the same -# function is applied to each band. Note that the function is -# evaluated once for each possible pixel value, so you cannot use -# random components or other generators. -# -# @def eval(image, function) -# @param image The input image. -# @param function A function object, taking one integer argument. -# @return An Image object. - -def eval(image, *args): - "Evaluate image expression" - - return image.point(args[0]) - -## -# Creates a new image from a number of single-band images. -# -# @param mode The mode to use for the output image. -# @param bands A sequence containing one single-band image for -# each band in the output image. All bands must have the -# same size. -# @return An Image object. - -def merge(mode, bands): - "Merge a set of single band images into a new multiband image." - - if getmodebands(mode) != len(bands) or "*" in mode: - raise ValueError("wrong number of bands") - for im in bands[1:]: - if im.mode != getmodetype(mode): - raise ValueError("mode mismatch") - if im.size != bands[0].size: - raise ValueError("size mismatch") - im = core.new(mode, bands[0].size) - for i in range(getmodebands(mode)): - bands[i].load() - im.putband(bands[i].im, i) - return bands[0]._new(im) - -# -------------------------------------------------------------------- -# Plugin registry - -## -# Register an image file plugin. This function should not be used -# in application code. -# -# @param id An image format identifier. -# @param factory An image file factory method. -# @param accept An optional function that can be used to quickly -# reject images having another format. - -def register_open(id, factory, accept=None): - id = string.upper(id) - ID.append(id) - OPEN[id] = factory, accept - -## -# Registers an image MIME type. This function should not be used -# in application code. -# -# @param id An image format identifier. -# @param mimetype The image MIME type for this format. - -def register_mime(id, mimetype): - MIME[string.upper(id)] = mimetype - -## -# Registers an image save function. This function should not be -# used in application code. -# -# @param id An image format identifier. -# @param driver A function to save images in this format. - -def register_save(id, driver): - SAVE[string.upper(id)] = driver - -## -# Registers an image extension. This function should not be -# used in application code. -# -# @param id An image format identifier. -# @param extension An extension used for this format. - -def register_extension(id, extension): - EXTENSION[string.lower(extension)] = string.upper(id) - - -# -------------------------------------------------------------------- -# Simple display support - -def _showxv(image, title=None, command=None): - - if os.name == "nt": - format = "BMP" - elif sys.platform == "darwin": - format = "JPEG" - if not command: - command = "open -a /Applications/Preview.app" - else: - format = None - if not command: - command = "xv" - if title: - command = command + " -name \"%s\"" % title - - if image.mode == "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" - else: - base = getmodebase(image.mode) - if base != image.mode and image.mode != "1": - file = image.convert(base)._dump(format=format) - else: - file = image._dump(format=format) - - if os.name == "nt": - command = "start /wait %s && del /f %s" % (file, file) - elif sys.platform == "darwin": - # on darwin open returns immediately resulting in the temp - # file removal while app is opening - command = "(%s %s; sleep 20; rm -f %s)&" % (command, file, file) - else: - command = "(%s %s; rm -f %s)&" % (command, file, file) - - os.system(command) diff --git a/PIL/ImageChops.py b/PIL/ImageChops.py deleted file mode 100644 index 6db0710..0000000 --- a/PIL/ImageChops.py +++ /dev/null @@ -1,302 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageChops.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 ImageChops module contains a number of arithmetical image -# operations, called channel operations ("chops"). These can be -# used for various purposes, including special effects, image -# compositions, algorithmic painting, and more. -#

-# At this time, channel operations are only implemented for 8-bit -# images (e.g. "L" and "RGB"). -#

-# 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)). -#

-# 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)). -#

-# 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)). -#

-# 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). -#

-# 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)). -#

-# 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). -#

-# 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). -#

-# 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). -#

-# 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). -#

-# 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. -#

-# Same as the blend function in the Image 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. -#

-# Same as the composite function in the Image 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. -#

-# 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)) diff --git a/PIL/ImageColor.py b/PIL/ImageColor.py deleted file mode 100644 index d97c0c4..0000000 --- a/PIL/ImageColor.py +++ /dev/null @@ -1,262 +0,0 @@ -# -# The Python Imaging Library -# $Id: ImageColor.py 2813 2006-10-07 10:11:35Z fredrik $ -# -# 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 -# -# 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/1000 + g*587/1000 + 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", -} diff --git a/PIL/ImageDraw.py b/PIL/ImageDraw.py deleted file mode 100644 index 7f9107b..0000000 --- a/PIL/ImageDraw.py +++ /dev/null @@ -1,378 +0,0 @@ -# -# The Python Imaging Library -# $Id: ImageDraw.py 2817 2006-10-07 15:34:03Z fredrik $ -# -# 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. -#

-# Application code should use the Draw 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 diff --git a/PIL/ImageDraw2.py b/PIL/ImageDraw2.py deleted file mode 100644 index 65c8cbb..0000000 --- a/PIL/ImageDraw2.py +++ /dev/null @@ -1,108 +0,0 @@ -# -# The Python Imaging Library -# $Id: ImageDraw.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 pieslice(self, xy, start, end, *options): - self.render("pieslice", xy, start, end, *options) - - def line(self, xy, *options): - self.render("line", xy, *options) - - def rectangle(self, xy, *options): - self.render("rectangle", xy, *options) - - def ellipse(self, xy, *options): - self.render("ellipse", xy, *options) - - def polygon(self, xy, *options): - self.render("polygon", 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) diff --git a/PIL/ImageEnhance.py b/PIL/ImageEnhance.py deleted file mode 100644 index cddd084..0000000 --- a/PIL/ImageEnhance.py +++ /dev/null @@ -1,89 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageEnhance.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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: -# 96-03-23 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, ImageFilter - -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. -#

-# 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. -#

-# 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 an solid grey image, factor 1.0 gives the original image. - -class Contrast(_Enhance): - "Adjust image contrast" - def __init__(self, image): - self.image = image - mean = reduce(lambda a,b: a+b, image.convert("L").histogram())/256.0 - self.degenerate = Image.new("L", image.size, mean).convert(image.mode) - -## -# Brightness enhancement object. -#

-# 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. -#

-# 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) diff --git a/PIL/ImageFile.py b/PIL/ImageFile.py deleted file mode 100644 index d51aff3..0000000 --- a/PIL/ImageFile.py +++ /dev/null @@ -1,520 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageFile.py 2930 2006-12-02 13:50:40Z fredrik $ -# -# 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, sys, 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" -} - -# -# -------------------------------------------------------------------- -# 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: - error = ERRORS.get(e, "decoder error %d" % e) - raise IOError(error + " when reading image file") - - # 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. -#

-# 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 Parser 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 - error = ERRORS.get(e, "decoder error %d" % e) - raise IOError(error + " when reading image file") - 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: - 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 read method. -# @param size Number of bytes to read. -# @return A string containing up to size 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, "") diff --git a/PIL/ImageFileIO.py b/PIL/ImageFileIO.py deleted file mode 100644 index 7c6a5c1..0000000 --- a/PIL/ImageFileIO.py +++ /dev/null @@ -1,47 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageFileIO.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 ImageFileIO module can be used to read an image from a -# socket, or any other stream device. -#

-# This module is deprecated. New code should use the Parser -# class in the ImageFile module instead. -# -# @see ImageFile#Parser - -class ImageFileIO(StringIO): - - ## - # Adds buffering to a stream file object, in order to - # provide seek and tell methods required - # by the Image.open method. The stream object must - # implement read and close methods. - # - # @param fp Stream file handle. - # @see Image#open - - def __init__(self, fp): - data = fp.read() - StringIO.__init__(self, data) - -if __name__ == "__main__": - - import Image - fp = open("/images/clenna.im", "rb") - im = Image.open(ImageFileIO(fp)) - im.load() # make sure we can read the raster data - print im.mode, im.size diff --git a/PIL/ImageFilter.py b/PIL/ImageFilter.py deleted file mode 100644 index 5857686..0000000 --- a/PIL/ImageFilter.py +++ /dev/null @@ -1,263 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageFilter.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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. - #

- # 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): - 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) - -## -# 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 - ) - -## -# Contour filter. - -class CONTOUR(BuiltinFilter): - name = "Contour" - filterargs = (3, 3), 1, 255, ( - -1, -1, -1, - -1, 8, -1, - -1, -1, -1 - ) - -## -# Detail filter. - -class DETAIL(BuiltinFilter): - name = "Detail" - filterargs = (3, 3), 6, 0, ( - 0, -1, 0, - -1, 10, -1, - 0, -1, 0 - ) - -## -# Edge enhancement filter. - -class EDGE_ENHANCE(BuiltinFilter): - name = "Edge-enhance" - filterargs = (3, 3), 2, 0, ( - -1, -1, -1, - -1, 10, -1, - -1, -1, -1 - ) - -## -# 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 - ) - -## -# Embossing filter. - -class EMBOSS(BuiltinFilter): - name = "Emboss" - filterargs = (3, 3), 1, 128, ( - -1, 0, 0, - 0, 1, 0, - 0, 0, 0 - ) - -## -# Edge-finding filter. - -class FIND_EDGES(BuiltinFilter): - name = "Find Edges" - filterargs = (3, 3), 1, 0, ( - -1, -1, -1, - -1, 8, -1, - -1, -1, -1 - ) - -## -# Smoothing filter. - -class SMOOTH(BuiltinFilter): - name = "Smooth" - filterargs = (3, 3), 13, 0, ( - 1, 1, 1, - 1, 5, 1, - 1, 1, 1 - ) - -## -# 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 - ) - -## -# Sharpening filter. - -class SHARPEN(BuiltinFilter): - name = "Sharpen" - filterargs = (3, 3), 16, 0, ( - -2, -2, -2, - -2, 32, -2, - -2, -2, -2 - ) diff --git a/PIL/ImageFont.py b/PIL/ImageFont.py deleted file mode 100644 index b987a33..0000000 --- a/PIL/ImageFont.py +++ /dev/null @@ -1,377 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageFont.py 2813 2006-10-07 10:11:35Z fredrik $ -# -# 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 - -# 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 ImageFont module defines a class with the same name. -# Instances of this class store bitmap fonts, and are used with the -# text method of the ImageDraw class. -#

-# PIL uses it's own font file format to store bitmap fonts. You can -# use the pilfont utility to convert BDF and PCF font -# descriptors (X window font formats) to this format. -#

-# 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 - s = file.readline() - while s and s != "DATA\n": - 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 -# truetype 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 - import _imagingft - self.font = _imagingft.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. -#

-# 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 -# fonts 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 "'''))))" diff --git a/PIL/ImageGL.py b/PIL/ImageGL.py deleted file mode 100644 index 482f42d..0000000 --- a/PIL/ImageGL.py +++ /dev/null @@ -1,28 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageGL.py 2438 2005-05-25 21:09:48Z Fredrik $ -# -# 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 * diff --git a/PIL/ImageGrab.py b/PIL/ImageGrab.py deleted file mode 100644 index ecbfbac..0000000 --- a/PIL/ImageGrab.py +++ /dev/null @@ -1,71 +0,0 @@ -# -# The Python Imaging Library -# $Id: ImageGrab.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 ImageGrab module can be used to copy -# the contents of the screen to a PIL image memory. -#

-# The current version works on Windows only.

-# -# @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 diff --git a/PIL/ImageMath.py b/PIL/ImageMath.py deleted file mode 100644 index 117a5ae..0000000 --- a/PIL/ImageMath.py +++ /dev/null @@ -1,207 +0,0 @@ -# -# The Python Imaging Library -# $Id: ImageMath.py 2508 2005-09-12 19:01:03Z fredrik $ -# -# 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 diff --git a/PIL/ImageMode.py b/PIL/ImageMode.py deleted file mode 100644 index 87a0e5a..0000000 --- a/PIL/ImageMode.py +++ /dev/null @@ -1,46 +0,0 @@ -# -# The Python Imaging Library. -# $Id: /work/modules/pil/PIL/ImageFilter.py 486 2004-10-06T08:55:20.930352Z fredrik $ -# -# 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") - return _modes[mode] diff --git a/PIL/ImageOps.py b/PIL/ImageOps.py deleted file mode 100644 index 89b5e72..0000000 --- a/PIL/ImageOps.py +++ /dev/null @@ -1,408 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageOps.py 2760 2006-06-19 13:31:40Z fredrik $ -# -# 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 ImageOps 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 cutoff 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 black and white -# 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 -# getmesh 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. -#

-# The fit 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) diff --git a/PIL/ImagePalette.py b/PIL/ImagePalette.py deleted file mode 100644 index 0e9a93a..0000000 --- a/PIL/ImagePalette.py +++ /dev/null @@ -1,161 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImagePalette.py 2339 2005-03-25 08:02:17Z fredrik $ -# -# 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 - -## -# 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 contains 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 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 = map(lambda a, randint=randint: - randint(0, 255), [0]*256*len(mode)) - return ImagePalette(mode, palette) - -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 diff --git a/PIL/ImagePath.py b/PIL/ImagePath.py deleted file mode 100644 index 120a607..0000000 --- a/PIL/ImagePath.py +++ /dev/null @@ -1,71 +0,0 @@ -# -# The Python Imaging Library -# $Id: ImagePath.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 diff --git a/PIL/ImageQt.py b/PIL/ImageQt.py deleted file mode 100644 index 2e9f476..0000000 --- a/PIL/ImageQt.py +++ /dev/null @@ -1,84 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageQt.py 2741 2006-06-18 16:17:20Z fredrik $ -# -# 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) diff --git a/PIL/ImageSequence.py b/PIL/ImageSequence.py deleted file mode 100644 index 452b096..0000000 --- a/PIL/ImageSequence.py +++ /dev/null @@ -1,38 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageSequence.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 diff --git a/PIL/ImageStat.py b/PIL/ImageStat.py deleted file mode 100644 index d53e645..0000000 --- a/PIL/ImageStat.py +++ /dev/null @@ -1,179 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageStat.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 ImageStat 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 - -if __name__ == "__main__": - - im = Image.open("Images/lena.ppm") - - st = Stat(im) - - print "extrema", st.extrema - print "sum ", st.sum - print "mean ", st.mean - print "median ", st.median - print "rms ", st.rms - print "sum2 ", st.sum2 - print "var ", st.var - print "stddev ", st.stddev diff --git a/PIL/ImageTk.py b/PIL/ImageTk.py deleted file mode 100644 index 30f7c0e..0000000 --- a/PIL/ImageTk.py +++ /dev/null @@ -1,296 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageTk.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 ImageTk module contains support to create and modify -# Tkinter BitmapImage and PhotoImage objects. -#

-# For examples, see the demo programs in the Scripts -# 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 file or data options to initialize - # the photo image object. - #

- # @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. - #

- # 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 foreground, - # 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() diff --git a/PIL/ImageTransform.py b/PIL/ImageTransform.py deleted file mode 100644 index 2944cd3..0000000 --- a/PIL/ImageTransform.py +++ /dev/null @@ -1,91 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageTransform.py 2813 2006-10-07 10:11:35Z fredrik $ -# -# 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: - def __init__(self, data): - self.data = data - def getdata(self): - return self.method, self.data - -## -# Define an affine image transform. -#

-# This function takes a 6-tuple (a, b, c, d, e, f) which -# contain the first two rows from an affine transform matrix. For -# each pixel (x, y) in the output image, the new value is -# taken from a position (a x + b y + c, -# d x + e y + f) in the input image, rounded to -# nearest pixel. -#

-# This function can be used to scale, translate, rotate, and shear the -# original image. -# -# @def AffineTransform(matrix) -# @param matrix A 6-tuple (a, b, c, d, e, f) 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. -#

-# 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 (x0, y0) -# in the input image will end up at (0,0) in the output image, -# and (x1, y1) at size. -#

-# This method can be used to crop, stretch, shrink, or mirror an -# arbitrary rectangle in the current image. It is slightly slower than -# crop, but about as fast as a corresponding resize -# operation. -# -# @def ExtentTransform(bbox) -# @param bbox A 4-tuple (x0, y0, x1, y1) 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. -#

-# 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 (x0, y0, x1, y1, x2, y2, y3, y3) 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 diff --git a/PIL/ImageWin.py b/PIL/ImageWin.py deleted file mode 100644 index 13c56b9..0000000 --- a/PIL/ImageWin.py +++ /dev/null @@ -1,215 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImageWin.py 2662 2006-03-21 22:41:02Z fredrik $ -# -# 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 ImageWin 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 palette 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 - # GetHandleAttrib method of the CDC 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. - #

- # This method should be called upon QUERYNEWPALETTE - # and PALETTECHANGED events from Windows. If this - # method returns a non-zero value, one or more display - # palette entries were changed, and the image should be - # redrawn. - # - # @param handle Device context (HDC), cast to a Python integer, - # or an HDC or HWND instance. - # @return A true value if one or more entries were changed - # (this indicates that the image should be redrawn). - - 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 tostring) - - 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)) diff --git a/PIL/ImtImagePlugin.py b/PIL/ImtImagePlugin.py deleted file mode 100644 index f321ae3..0000000 --- a/PIL/ImtImagePlugin.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# The Python Imaging Library. -# $Id: ImtImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 string, 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) diff --git a/PIL/IptcImagePlugin.py b/PIL/IptcImagePlugin.py deleted file mode 100644 index 3535759..0000000 --- a/PIL/IptcImagePlugin.py +++ /dev/null @@ -1,280 +0,0 @@ -# -# The Python Imaging Library. -# $Id: IptcImagePlugin.py 2813 2006-10-07 10:11:35Z fredrik $ -# -# 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 getiptcinfo 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: - self.info[tag] = self.fp.read(size) - else: - self.info[tag] = None - # 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 diff --git a/PIL/JpegImagePlugin.py b/PIL/JpegImagePlugin.py deleted file mode 100644 index b8ba8e4..0000000 --- a/PIL/JpegImagePlugin.py +++ /dev/null @@ -1,430 +0,0 @@ -# -# The Python Imaging Library. -# $Id: JpegImagePlugin.py 2763 2006-06-22 21:43:28Z fredrik $ -# -# 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 -# -# 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.5" - -import array, 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 == 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["progression"] = 1 - - 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 = [] - - 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" - 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 - file.seek(exif[0x8769]) - 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", - "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)) - - # 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.5) - 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] - ) - - 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") diff --git a/PIL/McIdasImagePlugin.py b/PIL/McIdasImagePlugin.py deleted file mode 100644 index b3b48ec..0000000 --- a/PIL/McIdasImagePlugin.py +++ /dev/null @@ -1,74 +0,0 @@ -# -# The Python Imaging Library. -# $Id: McIdasImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# Basic McIdas support for PIL -# -# History: -# 97-05-05 fl Created (8-bit images only) -# -# Thanks to Richard Jones 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.1" - -import string - -import Image, ImageFile - -def i16(c,i=0): - return ord(c[1+i])+(ord(c[i])<<8) - -def i32(c,i=0): - return ord(c[3+i])+(ord(c[2+i])<<8)+(ord(c[1+i])<<16)+(ord(c[i])<<24) - -def _accept(s): - return i32(s) == 0 and i32(s, 4) == 4 - -## -# 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): - raise SyntaxError, "not an McIdas area file" - - # get mode - if i32(s, 40) != 1 or i32(s, 52) != 1: - raise SyntaxError, "unsupported McIdas format" - - self.mode = "L" - - # get size - self.size = i32(s, 36), i32(s, 32) - - # setup image descriptor - prefix = i32(s, 56) - offset = i32(s, 132) - - self.tile = [("raw", (0, 0) + self.size, offset, - ("L", prefix + self.size[0], 1))] - - # FIXME: should store the navigation and calibration blocks - # somewhere (or perhaps extract some basic information from - # them...) - -# -------------------------------------------------------------------- -# registry - -Image.register_open("MCIDAS", McIdasImageFile, _accept) - -# no default extension diff --git a/PIL/MicImagePlugin.py b/PIL/MicImagePlugin.py deleted file mode 100644 index b7b108e..0000000 --- a/PIL/MicImagePlugin.py +++ /dev/null @@ -1,96 +0,0 @@ -# -# The Python Imaging Library. -# $Id: MicImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 string - -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") diff --git a/PIL/MpegImagePlugin.py b/PIL/MpegImagePlugin.py deleted file mode 100644 index 9623c7a..0000000 --- a/PIL/MpegImagePlugin.py +++ /dev/null @@ -1,83 +0,0 @@ -# -# The Python Imaging Library. -# $Id: MpegImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 array, string -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") diff --git a/PIL/MspImagePlugin.py b/PIL/MspImagePlugin.py deleted file mode 100644 index 40aac19..0000000 --- a/PIL/MspImagePlugin.py +++ /dev/null @@ -1,103 +0,0 @@ -# -# The Python Imaging Library. -# $Id: MspImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/OleFileIO.py b/PIL/OleFileIO.py deleted file mode 100644 index 9383eca..0000000 --- a/PIL/OleFileIO.py +++ /dev/null @@ -1,528 +0,0 @@ -# -# THIS IS WORK IN PROGRESS -# -# The Python Imaging Library -# $Id: OleFileIO.py 2339 2005-03-25 08:02:17Z fredrik $ -# -# 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 diff --git a/PIL/PSDraw.py b/PIL/PSDraw.py deleted file mode 100644 index 7e88f55..0000000 --- a/PIL/PSDraw.py +++ /dev/null @@ -1,199 +0,0 @@ -# -# The Python Imaging Library -# $Id: PSDraw.py 2813 2006-10-07 10:11:35Z fredrik $ -# -# 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 -""" diff --git a/PIL/PaletteFile.py b/PIL/PaletteFile.py deleted file mode 100644 index bbbebfa..0000000 --- a/PIL/PaletteFile.py +++ /dev/null @@ -1,53 +0,0 @@ -# -# Python Imaging Library -# $Id: PaletteFile.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 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 diff --git a/PIL/PalmImagePlugin.py b/PIL/PalmImagePlugin.py deleted file mode 100644 index 19f0c2f..0000000 --- a/PIL/PalmImagePlugin.py +++ /dev/null @@ -1,226 +0,0 @@ -# -# The Python Imaging Library. -# $Id: PalmImagePlugin.py 2438 2005-05-25 21:09:48Z Fredrik $ -# - -## -# Image plugin for Palm pixmap images (output only). -## - -__version__ = "1.0" - -import Image, ImageFile -import StringIO - -_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") diff --git a/PIL/PcdImagePlugin.py b/PIL/PcdImagePlugin.py deleted file mode 100644 index 957da24..0000000 --- a/PIL/PcdImagePlugin.py +++ /dev/null @@ -1,76 +0,0 @@ -# -# The Python Imaging Library. -# $Id: PcdImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/PcfFontFile.py b/PIL/PcfFontFile.py deleted file mode 100644 index 9a689b2..0000000 --- a/PIL/PcfFontFile.py +++ /dev/null @@ -1,256 +0,0 @@ -# -# THIS IS WORK IN PROGRESS -# -# The Python Imaging Library -# $Id: PcfFontFile.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 diff --git a/PIL/PcxImagePlugin.py b/PIL/PcxImagePlugin.py deleted file mode 100644 index 8c0cd11..0000000 --- a/PIL/PcxImagePlugin.py +++ /dev/null @@ -1,167 +0,0 @@ -# -# The Python Imaging Library. -# $Id: PcxImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/PdfImagePlugin.py b/PIL/PdfImagePlugin.py deleted file mode 100644 index 86567d6..0000000 --- a/PIL/PdfImagePlugin.py +++ /dev/null @@ -1,210 +0,0 @@ -# -# The Python Imaging Library. -# $Id: PdfImagePlugin.py 2438 2005-05-25 21:09:48Z Fredrik $ -# -# 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): - - # - # 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, - Height = height, - 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, width, height)) - _endobj(fp) - - # - # page contents - - op = StringIO.StringIO() - - op.write("q %d 0 0 %d 0 0 cm /image Do Q\n" % (width, height)) - - 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") diff --git a/PIL/PixarImagePlugin.py b/PIL/PixarImagePlugin.py deleted file mode 100644 index d4b136f..0000000 --- a/PIL/PixarImagePlugin.py +++ /dev/null @@ -1,71 +0,0 @@ -# -# The Python Imaging Library. -# $Id: PixarImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 . 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? diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py deleted file mode 100644 index 0e8ce9f..0000000 --- a/PIL/PngImagePlugin.py +++ /dev/null @@ -1,558 +0,0 @@ -# -# The Python Imaging Library. -# $Id: PngImagePlugin.py 2203 2004-12-19 14:32:32Z fredrik $ -# -# 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) -# -# Copyright (c) 1997-2004 by Secret Labs AB -# Copyright (c) 1996 by Fredrik Lundh -# -# See the README file for information on usage and redistribution. -# - -__version__ = "0.8.2" - -import re, string - -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) - -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_size = (0,0) - self.im_mode = None - self.im_tile = None - self.im_palette = None - - 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) - 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] = v - 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.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"): - raise IOError("cannot read interlaced PNG files") - - 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)) - 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) - - 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") diff --git a/PIL/PpmImagePlugin.py b/PIL/PpmImagePlugin.py deleted file mode 100644 index b9b9f81..0000000 --- a/PIL/PpmImagePlugin.py +++ /dev/null @@ -1,131 +0,0 @@ -# -# The Python Imaging Library. -# $Id: PpmImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/PsdImagePlugin.py b/PIL/PsdImagePlugin.py deleted file mode 100644 index 1e68c0d..0000000 --- a/PIL/PsdImagePlugin.py +++ /dev/null @@ -1,271 +0,0 @@ -# -# The Python Imaging Library -# $Id: PsdImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 string -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)) - - # - # 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 = None # FIXME - file.seek(i32(read(4)), 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") diff --git a/PIL/SgiImagePlugin.py b/PIL/SgiImagePlugin.py deleted file mode 100644 index 0ab741e..0000000 --- a/PIL/SgiImagePlugin.py +++ /dev/null @@ -1,91 +0,0 @@ -# -# The Python Imaging Library. -# $Id: SgiImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# SGI image file handling -# -# See "The SGI Image File Format (Draft version 0.97)", Paul Haeberli. -# -# -# History: -# 1995-09-10 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 string -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): - self.mode = "L" - elif layout == (1, 3, 3): - self.mode = "RGB" - else: - raise SyntaxError, "unsupported SGI image mode" - - # size - self.size = i16(s[6:]), i16(s[8:]) - - # decoder info - if compression == 0: - if self.mode == "RGB": - # RGB images are band interleaved - size = self.size[0]*self.size[1] - self.tile = [("raw", (0,0)+self.size, 512, ("R",0,1)), - ("raw", (0,0)+self.size, 512+size, ("G",0,1)), - ("raw", (0,0)+self.size, 512+2*size, ("B",0,1))] - else: - self.tile = [("raw", (0,0)+self.size, 512, (self.mode, 0, 1))] - if 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? diff --git a/PIL/SpiderImagePlugin.py b/PIL/SpiderImagePlugin.py deleted file mode 100644 index e0fd045..0000000 --- a/PIL/SpiderImagePlugin.py +++ /dev/null @@ -1,294 +0,0 @@ -# -# 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, string, 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") diff --git a/PIL/SunImagePlugin.py b/PIL/SunImagePlugin.py deleted file mode 100644 index 2e7fe52..0000000 --- a/PIL/SunImagePlugin.py +++ /dev/null @@ -1,87 +0,0 @@ -# -# The Python Imaging Library. -# $Id: SunImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 string -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") diff --git a/PIL/TarIO.py b/PIL/TarIO.py deleted file mode 100644 index fbab8ca..0000000 --- a/PIL/TarIO.py +++ /dev/null @@ -1,57 +0,0 @@ -# -# The Python Imaging Library. -# $Id: TarIO.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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) diff --git a/PIL/TgaImagePlugin.py b/PIL/TgaImagePlugin.py deleted file mode 100644 index e709de8..0000000 --- a/PIL/TgaImagePlugin.py +++ /dev/null @@ -1,133 +0,0 @@ -# -# The Python Imaging Library. -# $Id: TgaImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 - - -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 (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" - - 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 - -# -# registry - -Image.register_open("TGA", TgaImageFile, _accept) - -Image.register_extension("TGA", ".tga") diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py deleted file mode 100644 index 178066c..0000000 --- a/PIL/TiffImagePlugin.py +++ /dev/null @@ -1,763 +0,0 @@ -# -# The Python Imaging Library. -# $Id: TiffImagePlugin.py 2803 2006-07-31 19:18:57Z fredrik $ -# -# 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 - -try: - if sys.byteorder == "little": - byteorder = "II" - else: - byteorder = "MM" -except AttributeError: - if ord(array.array("i",[1]).tostring()[0]): - byteorder = "II" - else: - byteorder = "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) - -# 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 -EXTRASAMPLES = 338 -SAMPLEFORMAT = 339 -JPEGTABLES = 347 -COPYRIGHT = 33432 -IPTC_NAA_CHUNK = 33723 # newsphoto properties -PHOTOSHOP_CHUNK = 34377 # photoshop properties - -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 = { - # (PhotoInterpretation, SampleFormat, FillOrder, BitsPerSample, - # ExtraSamples) => mode, rawmode - (0, 1, 1, (1,), ()): ("1", "1;I"), - (0, 1, 2, (1,), ()): ("1", "1;IR"), - (0, 1, 1, (8,), ()): ("L", "L;I"), - (0, 1, 2, (8,), ()): ("L", "L;IR"), - (1, 1, 1, (1,), ()): ("1", "1"), - (1, 1, 2, (1,), ()): ("1", "1;R"), - (1, 1, 1, (8,), ()): ("L", "L"), - (1, 1, 1, (8,8), (2,)): ("LA", "LA"), - (1, 1, 2, (8,), ()): ("L", "L;R"), - (1, 1, 1, (16,), ()): ("I;16", "I;16"), - (1, 2, 1, (16,), ()): ("I;16S", "I;16S"), - (1, 2, 1, (32,), ()): ("I", "I;32S"), - (1, 3, 1, (32,), ()): ("F", "F;32F"), - (2, 1, 1, (8,8,8), ()): ("RGB", "RGB"), - (2, 1, 2, (8,8,8), ()): ("RGB", "RGB;R"), - (2, 1, 1, (8,8,8,8), (0,)): ("RGBX", "RGBX"), - (2, 1, 1, (8,8,8,8), (1,)): ("RGBA", "RGBa"), - (2, 1, 1, (8,8,8,8), (2,)): ("RGBA", "RGBA"), - (2, 1, 1, (8,8,8,8), (999,)): ("RGBA", "RGBA"), # corel draw 10 - (3, 1, 1, (1,), ()): ("P", "P;1"), - (3, 1, 2, (1,), ()): ("P", "P;1R"), - (3, 1, 1, (2,), ()): ("P", "P;2"), - (3, 1, 2, (2,), ()): ("P", "P;2R"), - (3, 1, 1, (4,), ()): ("P", "P;4"), - (3, 1, 2, (4,), ()): ("P", "P;4R"), - (3, 1, 1, (8,), ()): ("P", "P"), - (3, 1, 1, (8,8), (2,)): ("PA", "PA"), - (3, 1, 2, (8,), ()): ("P", "P;R"), - (5, 1, 1, (8,8,8,8), ()): ("CMYK", "CMYK"), - (6, 1, 1, (8,8,8), ()): ("YCbCr", "YCbCr"), - (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="II"): - self.prefix = prefix[:2] - if self.prefix == "MM": - self.i16, self.i32 = ib16, ib32 - # FIXME: save doesn't yet support big-endian mode... - 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.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 != byteorder: - a.byteswap() - return tuple(a) - load_dispatch[11] = (4, load_float) - - def load_double(self, data): - a = array.array("d", data) - if self.prefix != byteorder: - 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 - - if Image.DEBUG: - if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK): - print "- value: " % 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: - - if Image.DEBUG: - import TiffTags - tagname = TiffTags.TAGS.get(tag, "unknown") - print "save: %s (%d)" % (tagname, tag), - print "- value:", value - - if 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 - else: - 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), "") - - # 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) - 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],) - - 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 = ( - 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 - - xdpi = getscalar(X_RESOLUTION, (1, 1)) - ydpi = getscalar(Y_RESOLUTION, (1, 1)) - - if xdpi and ydpi and getscalar(RESOLUTION_UNIT, 1) == 1: - xdpi = xdpi[0] / (xdpi[1] or 1) - ydpi = ydpi[0] / (ydpi[1] or 1) - self.info["dpi"] = xdpi, ydpi - - # 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(324): - # tiled image - w = getscalar(322) - h = getscalar(323) - a = None - for o in self.tag[324]: - 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 - -SAVE_INFO = { - # mode => rawmode, photometrics, sampleformat, bitspersample, extra - "1": ("1", 1, 1, (1,), None), - "L": ("L", 1, 1, (8,), None), - "LA": ("LA", 1, 1, (8,8), 2), - "P": ("P", 3, 1, (8,), None), - "PA": ("PA", 3, 1, (8,8), 2), - "I": ("I;32S", 1, 2, (32,), None), - "I;16": ("I;16", 1, 1, (16,), None), - "I;16S": ("I;16S", 1, 2, (16,), None), - "F": ("F;32F", 1, 3, (32,), None), - "RGB": ("RGB", 2, 1, (8,8,8), None), - "RGBX": ("RGBX", 2, 1, (8,8,8,8), 0), - "RGBA": ("RGBA", 2, 1, (8,8,8,8), 2), - "CMYK": ("CMYK", 5, 1, (8,8,8,8), None), - "YCbCr": ("YCbCr", 6, 1, (8,8,8), None), - "LAB": ("LAB", 8, 1, (8,8,8), 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, photo, format, bits, extra = SAVE_INFO[im.mode] - except KeyError: - raise IOError, "cannot write mode %s as TIFF" % im.mode - - ifd = ImageFileDirectory() - - # tiff header (write via IFD to get everything right) - 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) - 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] = 1 - 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)) - ]) - -# -# -------------------------------------------------------------------- -# 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") diff --git a/PIL/TiffTags.py b/PIL/TiffTags.py deleted file mode 100644 index 2795fc3..0000000 --- a/PIL/TiffTags.py +++ /dev/null @@ -1,200 +0,0 @@ -# -# The Python Imaging Library. -# $Id: TiffTags.py 2340 2005-03-25 08:05:37Z fredrik $ -# -# 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", - - 33432: "Copyright", - - # various extensions (should check specs for "official" names) - 33723: "IptcNaaInfo", - 34377: "PhotoshopInfo", - - # 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", - -} diff --git a/PIL/WalImageFile.py b/PIL/WalImageFile.py deleted file mode 100644 index 34e7fc2..0000000 --- a/PIL/WalImageFile.py +++ /dev/null @@ -1,125 +0,0 @@ -# -# The Python Imaging Library. -# $Id: WalImageFile.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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. -#

-# By default, a Quake2 standard palette is attached to the texture. -# To override the palette, use the putpalette 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") diff --git a/PIL/WmfImagePlugin.py b/PIL/WmfImagePlugin.py deleted file mode 100644 index 2191160..0000000 --- a/PIL/WmfImagePlugin.py +++ /dev/null @@ -1,148 +0,0 @@ -# -# The Python Imaging Library -# $Id: WmfImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 - -# -------------------------------------------------------------------- - -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") diff --git a/PIL/XVThumbImagePlugin.py b/PIL/XVThumbImagePlugin.py deleted file mode 100644 index 4a9c0d6..0000000 --- a/PIL/XVThumbImagePlugin.py +++ /dev/null @@ -1,68 +0,0 @@ -# -# The Python Imaging Library. -# $Id: XVThumbImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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 info comments - while 1: - s = string.strip(self.fp.readline()) - if s == "#END_OF_COMMENTS": - break - - # read header line - s = string.split(self.fp.readline()) - - 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) diff --git a/PIL/XbmImagePlugin.py b/PIL/XbmImagePlugin.py deleted file mode 100644 index a1dccea..0000000 --- a/PIL/XbmImagePlugin.py +++ /dev/null @@ -1,94 +0,0 @@ -# -# The Python Imaging Library. -# $Id: XbmImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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[0-9]+)[\r\n]+" - "#define[ \t]+[^_]*_height[ \t]+(?P[0-9]+)[\r\n]+" - "(?P" - "#define[ \t]+[^_]*_x_hot[ \t]+(?P[0-9]+)[\r\n]+" - "#define[ \t]+[^_]*_y_hot[ \t]+(?P[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") diff --git a/PIL/XpmImagePlugin.py b/PIL/XpmImagePlugin.py deleted file mode 100644 index b8ac01f..0000000 --- a/PIL/XpmImagePlugin.py +++ /dev/null @@ -1,129 +0,0 @@ -# -# The Python Imaging Library. -# $Id: XpmImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# 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") diff --git a/PIL/__init__.py b/PIL/__init__.py deleted file mode 100644 index 3290883..0000000 --- a/PIL/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -# -# The Python Imaging Library. -# $Id: __init__.py 2134 2004-10-06 08:55:20Z fredrik $ -# -# package placeholder -# -# Copyright (c) 1999 by Secret Labs AB. -# -# See the README file for information on usage and redistribution. -# - -# ;-) diff --git a/activity/activity.info b/activity/activity.info index 4ca109b..ad03094 100644 --- a/activity/activity.info +++ b/activity/activity.info @@ -4,5 +4,5 @@ license = GPLv2+ icon = activity-imageprocessor exec = sugar-activity ImageProcessorActivity.ImageProcessorActivity mime_types = image/bmp;image/gif;image/jpeg;image/png;image/tiff;image/svg+xml -activity_version = 4 +activity_version = 6 bundle_id = org.laptop.ImageProcessorActivity diff --git a/activity/activity.info.rtf b/activity/activity.info.rtf deleted file mode 100644 index a393820..0000000 --- a/activity/activity.info.rtf +++ /dev/null Binary files differ diff --git a/toolbar.py b/toolbar.py index d08f886..2f71ba8 100644 --- a/toolbar.py +++ b/toolbar.py @@ -71,6 +71,11 @@ class ViewToolbar(gtk.Toolbar): ([])), 'paste': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + + ([])), + 'original': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([])), } @@ -147,7 +152,15 @@ class ViewToolbar(gtk.Toolbar): self.paste_button.connect('clicked', self.paste_cb) self.insert(self.paste_button, -1) self.paste_button.show() + + self.original_button = ToolButton('original') + self.original_button.set_tooltip(_('original pic')) + self.original_button.connect('clicked', self.original_cb) + self.insert(self.original_button, -1) + self.original_button.show() + def original_cb(self, button): + self.emit('original') def zoom_in_cb(self, button): self.emit('zoom_in') -- cgit v0.9.1