Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/PIL/ImageFile.py
diff options
context:
space:
mode:
Diffstat (limited to 'PIL/ImageFile.py')
-rw-r--r--PIL/ImageFile.py520
1 files changed, 0 insertions, 520 deletions
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.
-# <p>
-# A stub loader is an image loader that can identify files of a
-# certain format, but relies on external code to load the file.
-
-class StubImageFile(ImageFile):
- "Base class for stub image loaders."
-
- def _open(self):
- raise NotImplementedError(
- "StubImageFile subclass must implement _open"
- )
-
- def load(self):
- loader = self._load()
- if loader is None:
- raise IOError("cannot find loader for this %s file" % self.format)
- image = loader.load(self)
- assert image is not None
- # become the other object (!)
- self.__class__ = image.__class__
- self.__dict__ = image.__dict__
-
- ##
- # (Hook) Find actual image loader.
-
- def _load(self):
- raise NotImplementedError(
- "StubImageFile subclass must implement _load"
- )
-
-##
-# (Internal) Support class for the <b>Parser</b> file.
-
-class _ParserFile:
- # parser support class.
-
- def __init__(self, data):
- self.data = data
- self.offset = 0
-
- def close(self):
- self.data = self.offset = None
-
- def tell(self):
- return self.offset
-
- def seek(self, offset, whence=0):
- if whence == 0:
- self.offset = offset
- elif whence == 1:
- self.offset = self.offset + offset
- else:
- # force error in Image.open
- raise IOError("illegal argument to seek")
-
- def read(self, bytes=0):
- pos = self.offset
- if bytes:
- data = self.data[pos:pos+bytes]
- else:
- data = self.data[pos:]
- self.offset = pos + len(data)
- return data
-
- def readline(self):
- # FIXME: this is slow!
- s = ""
- while 1:
- c = self.read(1)
- if not c:
- break
- s = s + c
- if c == "\n":
- break
- return s
-
-##
-# Incremental image parser. This class implements the standard
-# feed/close consumer interface.
-
-class Parser:
-
- incremental = None
- image = None
- data = None
- decoder = None
- finished = 0
-
- ##
- # (Consumer) Reset the parser. Note that you can only call this
- # method immediately after you've created a parser; parser
- # instances cannot be reused.
-
- def reset(self):
- assert self.data is None, "cannot reuse parsers"
-
- ##
- # (Consumer) Feed data to the parser.
- #
- # @param data A string buffer.
- # @exception IOError If the parser failed to parse the image file.
-
- def feed(self, data):
- # collect data
-
- if self.finished:
- return
-
- if self.data is None:
- self.data = data
- else:
- self.data = self.data + data
-
- # parse what we have
- if self.decoder:
-
- if self.offset > 0:
- # skip header
- skip = min(len(self.data), self.offset)
- self.data = self.data[skip:]
- self.offset = self.offset - skip
- if self.offset > 0 or not self.data:
- return
-
- n, e = self.decoder.decode(self.data)
-
- if n < 0:
- # end of stream
- self.data = None
- self.finished = 1
- if e < 0:
- # decoding error
- self.image = None
- 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 <b>read</b> method.
-# @param size Number of bytes to read.
-# @return A string containing up to <i>size</i> bytes of data.
-
-def _safe_read(fp, size):
- if size <= 0:
- return ""
- if size <= SAFEBLOCK:
- return fp.read(size)
- data = []
- while size > 0:
- block = fp.read(min(size, SAFEBLOCK))
- if not block:
- break
- data.append(block)
- size = size - len(block)
- return string.join(data, "")