home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / xbmc-9.11.exe / scripts / AppleMovieTrailers / resources / lib / PIL / ImageFile.py < prev    next >
Encoding:
Python Source  |  2008-08-06  |  15.3 KB  |  519 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id: ImageFile.py 2134 2004-10-06 08:55:20Z fredrik $
  4. #
  5. # base class for image file handlers
  6. #
  7. # history:
  8. # 1995-09-09 fl   Created
  9. # 1996-03-11 fl   Fixed load mechanism.
  10. # 1996-04-15 fl   Added pcx/xbm decoders.
  11. # 1996-04-30 fl   Added encoders.
  12. # 1996-12-14 fl   Added load helpers
  13. # 1997-01-11 fl   Use encode_to_file where possible
  14. # 1997-08-27 fl   Flush output in _save
  15. # 1998-03-05 fl   Use memory mapping for some modes
  16. # 1999-02-04 fl   Use memory mapping also for "I;16" and "I;16B"
  17. # 1999-05-31 fl   Added image parser
  18. # 2000-10-12 fl   Set readonly flag on memory-mapped images
  19. # 2002-03-20 fl   Use better messages for common decoder errors
  20. # 2003-04-21 fl   Fall back on mmap/map_buffer if map is not available
  21. # 2003-10-30 fl   Added StubImageFile class
  22. # 2004-02-25 fl   Made incremental parser more robust
  23. #
  24. # Copyright (c) 1997-2004 by Secret Labs AB
  25. # Copyright (c) 1995-2004 by Fredrik Lundh
  26. #
  27. # See the README file for information on usage and redistribution.
  28. #
  29.  
  30. import Image
  31. import traceback, sys, string, os
  32.  
  33. MAXBLOCK = 65536
  34.  
  35. SAFEBLOCK = 1024*1024
  36.  
  37. ERRORS = {
  38.     -1: "image buffer overrun error",
  39.     -2: "decoding error",
  40.     -3: "unknown error",
  41.     -8: "bad configuration",
  42.     -9: "out of memory error"
  43. }
  44.  
  45. #
  46. # --------------------------------------------------------------------
  47. # Helpers
  48.  
  49. def _tilesort(t1, t2):
  50.     # sort on offset
  51.     return cmp(t1[2], t2[2])
  52.  
  53. #
  54. # --------------------------------------------------------------------
  55. # ImageFile base class
  56.  
  57. ##
  58. # Base class for image file handlers.
  59.  
  60. class ImageFile(Image.Image):
  61.     "Base class for image file format handlers."
  62.  
  63.     def __init__(self, fp=None, filename=None):
  64.         Image.Image.__init__(self)
  65.  
  66.         self.tile = None
  67.         self.readonly = 1 # until we know better
  68.  
  69.         self.decoderconfig = ()
  70.         self.decodermaxblock = MAXBLOCK
  71.  
  72.         if Image.isStringType(fp):
  73.             # filename
  74.             self.fp = open(fp, "rb")
  75.             self.filename = fp
  76.         else:
  77.             # stream
  78.             self.fp = fp
  79.             self.filename = filename
  80.  
  81.         try:
  82.             self._open()
  83.         except IndexError, v: # end of data
  84.             if Image.DEBUG > 1:
  85.                 traceback.print_exc()
  86.             raise SyntaxError, v
  87.         except TypeError, v: # end of data (ord)
  88.             if Image.DEBUG > 1:
  89.                 traceback.print_exc()
  90.             raise SyntaxError, v
  91.         except KeyError, v: # unsupported mode
  92.             if Image.DEBUG > 1:
  93.                 traceback.print_exc()
  94.             raise SyntaxError, v
  95.         except EOFError, v: # got header but not the first frame
  96.             if Image.DEBUG > 1:
  97.                 traceback.print_exc()
  98.             raise SyntaxError, v
  99.  
  100.         if not self.mode or self.size[0] <= 0:
  101.             raise SyntaxError, "not identified by this driver"
  102.  
  103.     def draft(self, mode, size):
  104.         "Set draft mode"
  105.  
  106.         pass
  107.  
  108.     def verify(self):
  109.         "Check file integrity"
  110.  
  111.         # raise exception if something's wrong.  must be called
  112.         # directly after open, and closes file when finished.
  113.         self.fp = None
  114.  
  115.     def load(self):
  116.         "Load image data based on tile list"
  117.  
  118.         Image.Image.load(self)
  119.  
  120.         if self.tile is None:
  121.             raise IOError("cannot load this image")
  122.         if not self.tile:
  123.             return
  124.  
  125.         self.map = None
  126.  
  127.         readonly = 0
  128.  
  129.         if self.filename and len(self.tile) == 1:
  130.             # try memory mapping
  131.             d, e, o, a = self.tile[0]
  132.             if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES:
  133.                 try:
  134.                     if hasattr(Image.core, "map"):
  135.                         # use built-in mapper
  136.                         self.map = Image.core.map(self.filename)
  137.                         self.map.seek(o)
  138.                         self.im = self.map.readimage(
  139.                             self.mode, self.size, a[1], a[2]
  140.                             )
  141.                     else:
  142.                         # use mmap, if possible
  143.                         import mmap
  144.                         file = open(self.filename, "r+")
  145.                         size = os.path.getsize(self.filename)
  146.                         # FIXME: on Unix, use PROT_READ etc
  147.                         self.map = mmap.mmap(file.fileno(), size)
  148.                         self.im = Image.core.map_buffer(
  149.                             self.map, self.size, d, e, o, a
  150.                             )
  151.                     readonly = 1
  152.                 except (AttributeError, IOError, ImportError):
  153.                     self.map = None
  154.  
  155.         self.load_prepare()
  156.  
  157.         # look for read/seek overrides
  158.         try:
  159.             read = self.load_read
  160.         except AttributeError:
  161.             read = self.fp.read
  162.  
  163.         try:
  164.             seek = self.load_seek
  165.         except AttributeError:
  166.             seek = self.fp.seek
  167.  
  168.         if not self.map:
  169.  
  170.             # sort tiles in file order
  171.             self.tile.sort(_tilesort)
  172.  
  173.             try:
  174.                 # FIXME: This is a hack to handle TIFF's JpegTables tag.
  175.                 prefix = self.tile_prefix
  176.             except AttributeError:
  177.                 prefix = ""
  178.  
  179.             for d, e, o, a in self.tile:
  180.                 d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
  181.                 seek(o)
  182.                 try:
  183.                     d.setimage(self.im, e)
  184.                 except ValueError:
  185.                     continue
  186.                 b = prefix
  187.                 t = len(b)
  188.                 while 1:
  189.                     s = read(self.decodermaxblock)
  190.                     if not s:
  191.                         self.tile = []
  192.                         raise IOError("image file is truncated (%d bytes not processed)" % len(b))
  193.                     b = b + s
  194.                     n, e = d.decode(b)
  195.                     if n < 0:
  196.                         break
  197.                     b = b[n:]
  198.                     t = t + n
  199.  
  200.         self.tile = []
  201.         self.readonly = readonly
  202.  
  203.         self.fp = None # might be shared
  204.  
  205.         if not self.map and e < 0:
  206.             error = ERRORS.get(e, "decoder error %d" % e)
  207.             raise IOError(error + " when reading image file")
  208.  
  209.         # post processing
  210.         if hasattr(self, "tile_post_rotate"):
  211.             # FIXME: This is a hack to handle rotated PCD's
  212.             self.im = self.im.rotate(self.tile_post_rotate)
  213.             self.size = self.im.size
  214.  
  215.         self.load_end()
  216.  
  217.     def load_prepare(self):
  218.         # create image memory if necessary
  219.         if not self.im or\
  220.            self.im.mode != self.mode or self.im.size != self.size:
  221.             self.im = Image.core.new(self.mode, self.size)
  222.         # create palette (optional)
  223.         if self.mode == "P":
  224.             Image.Image.load(self)
  225.  
  226.     def load_end(self):
  227.         # may be overridden
  228.         pass
  229.  
  230.     # may be defined for contained formats
  231.     # def load_seek(self, pos):
  232.     #     pass
  233.  
  234.     # may be defined for blocked formats (e.g. PNG)
  235.     # def load_read(self, bytes):
  236.     #     pass
  237.  
  238. ##
  239. # Base class for stub image loaders.
  240. # <p>
  241. # A stub loader is an image loader that can identify files of a
  242. # certain format, but relies on external code to load the file.
  243.  
  244. class StubImageFile(ImageFile):
  245.     "Base class for stub image loaders."
  246.  
  247.     def _open(self):
  248.         raise NotImplementedError(
  249.             "StubImageFile subclass must implement _open"
  250.             )
  251.  
  252.     def load(self):
  253.         loader = self._load()
  254.         if loader is None:
  255.             raise IOError("cannot find loader for this %s file" % self.format)
  256.         image = loader.load(self)
  257.         assert image is not None
  258.         # become the other object (!)
  259.         self.__class__ = image.__class__
  260.         self.__dict__ = image.__dict__
  261.  
  262.     ##
  263.     # (Hook) Find actual image loader.
  264.  
  265.     def _load(self):
  266.         raise NotImplementedError(
  267.             "StubImageFile subclass must implement _load"
  268.             )
  269.  
  270. ##
  271. # (Internal) Support class for the <b>Parser</b> file.
  272.  
  273. class _ParserFile:
  274.     # parser support class.
  275.  
  276.     def __init__(self, data):
  277.         self.data = data
  278.         self.offset = 0
  279.  
  280.     def close(self):
  281.         self.data = self.offset = None
  282.  
  283.     def tell(self):
  284.         return self.offset
  285.  
  286.     def seek(self, offset, whence=0):
  287.         if whence == 0:
  288.             self.offset = offset
  289.         elif whence == 1:
  290.             self.offset = self.offset + offset
  291.         else:
  292.             # force error in Image.open
  293.             raise IOError("illegal argument to seek")
  294.  
  295.     def read(self, bytes=0):
  296.         pos = self.offset
  297.         if bytes:
  298.             data = self.data[pos:pos+bytes]
  299.         else:
  300.             data = self.data[pos:]
  301.         self.offset = pos + len(data)
  302.         return data
  303.  
  304.     def readline(self):
  305.         # FIXME: this is slow!
  306.         s = ""
  307.         while 1:
  308.             c = self.read(1)
  309.             if not c:
  310.                 break
  311.             s = s + c
  312.             if c == "\n":
  313.                 break
  314.         return s
  315.  
  316. ##
  317. # Incremental image parser.  This class implements the standard
  318. # feed/close consumer interface.
  319.  
  320. class Parser:
  321.  
  322.     incremental = None
  323.     image = None
  324.     data = None
  325.     decoder = None
  326.     finished = 0
  327.  
  328.     ##
  329.     # (Consumer) Reset the parser.  Note that you can only call this
  330.     # method immediately after you've created a parser; parser
  331.     # instances cannot be reused.
  332.  
  333.     def reset(self):
  334.         assert self.data is None, "cannot reuse parsers"
  335.  
  336.     ##
  337.     # (Consumer) Feed data to the parser.
  338.     #
  339.     # @param data A string buffer.
  340.     # @exception IOError If the parser failed to parse the image file.
  341.  
  342.     def feed(self, data):
  343.         # collect data
  344.  
  345.         if self.finished:
  346.             return
  347.  
  348.         if self.data is None:
  349.             self.data = data
  350.         else:
  351.             self.data = self.data + data
  352.  
  353.         # parse what we have
  354.         if self.decoder:
  355.  
  356.             if self.offset > 0:
  357.                 # skip header
  358.                 skip = min(len(self.data), self.offset)
  359.                 self.data = self.data[skip:]
  360.                 self.offset = self.offset - skip
  361.                 if self.offset > 0 or not self.data:
  362.                     return
  363.  
  364.             n, e = self.decoder.decode(self.data)
  365.  
  366.             if n < 0:
  367.                 # end of stream
  368.                 self.data = None
  369.                 self.finished = 1
  370.                 if e < 0:
  371.                     # decoding error
  372.                     self.image = None
  373.                     error = ERRORS.get(e, "decoder error %d" % e)
  374.                     raise IOError(error + " when reading image file")
  375.                 else:
  376.                     # end of image
  377.                     return
  378.             self.data = self.data[n:]
  379.  
  380.         elif self.image:
  381.  
  382.             # if we end up here with no decoder, this file cannot
  383.             # be incrementally parsed.  wait until we've gotten all
  384.             # available data
  385.             pass
  386.  
  387.         else:
  388.  
  389.             # attempt to open this file
  390.             try:
  391.                 try:
  392.                     fp = _ParserFile(self.data)
  393.                     im = Image.open(fp)
  394.                 finally:
  395.                     fp.close() # explicitly close the virtual file
  396.             except IOError:
  397.                 pass # not enough data
  398.             else:
  399.                 flag = hasattr(im, "load_seek") or hasattr(im, "load_read")
  400.                 if flag or len(im.tile) != 1:
  401.                     # custom load code, or multiple tiles
  402.                     self.decode = None
  403.                 else:
  404.                     # initialize decoder
  405.                     im.load_prepare()
  406.                     d, e, o, a = im.tile[0]
  407.                     im.tile = []
  408.                     self.decoder = Image._getdecoder(
  409.                         im.mode, d, a, im.decoderconfig
  410.                         )
  411.                     self.decoder.setimage(im.im, e)
  412.  
  413.                     # calculate decoder offset
  414.                     self.offset = o
  415.                     if self.offset <= len(self.data):
  416.                         self.data = self.data[self.offset:]
  417.                         self.offset = 0
  418.  
  419.                 self.image = im
  420.  
  421.     ##
  422.     # (Consumer) Close the stream.
  423.     #
  424.     # @return An image object.
  425.     # @exception IOError If the parser failed to parse the image file.
  426.  
  427.     def close(self):
  428.         # finish decoding
  429.         if self.decoder:
  430.             # get rid of what's left in the buffers
  431.             self.feed("")
  432.             self.data = self.decoder = None
  433.             if not self.finished:
  434.                 raise IOError("image was incomplete")
  435.         if not self.image:
  436.             raise IOError("cannot parse this image")
  437.         if self.data:
  438.             # incremental parsing not possible; reopen the file
  439.             # not that we have all data
  440.             try:
  441.                 fp = _ParserFile(self.data)
  442.                 self.image = Image.open(fp)
  443.             finally:
  444.                 fp.close() # explicitly close the virtual file
  445.         return self.image
  446.  
  447. # --------------------------------------------------------------------
  448.  
  449. ##
  450. # (Helper) Save image body to file.
  451. #
  452. # @param im Image object.
  453. # @param fp File object.
  454. # @param tile Tile list.
  455.  
  456. def _save(im, fp, tile):
  457.     "Helper to save image based on tile list"
  458.  
  459.     im.load()
  460.     if not hasattr(im, "encoderconfig"):
  461.         im.encoderconfig = ()
  462.     tile.sort(_tilesort)
  463.     # FIXME: make MAXBLOCK a configuration parameter
  464.     bufsize = max(MAXBLOCK, im.size[0] * 4) # see RawEncode.c
  465.     try:
  466.         fh = fp.fileno()
  467.         fp.flush()
  468.     except AttributeError:
  469.         # compress to Python file-compatible object
  470.         for e, b, o, a in tile:
  471.             e = Image._getencoder(im.mode, e, a, im.encoderconfig)
  472.             if o > 0:
  473.                 fp.seek(o, 0)
  474.             e.setimage(im.im, b)
  475.             while 1:
  476.                 l, s, d = e.encode(bufsize)
  477.                 fp.write(d)
  478.                 if s:
  479.                     break
  480.             if s < 0:
  481.                 raise IOError("encoder error %d when writing image file" % s)
  482.     else:
  483.         # slight speedup: compress to real file object
  484.         for e, b, o, a in tile:
  485.             e = Image._getencoder(im.mode, e, a, im.encoderconfig)
  486.             if o > 0:
  487.                 fp.seek(o, 0)
  488.             e.setimage(im.im, b)
  489.             s = e.encode_to_file(fh, bufsize)
  490.             if s < 0:
  491.                 raise IOError("encoder error %d when writing image file" % s)
  492.     try:
  493.         fp.flush()
  494.     except: pass
  495.  
  496.  
  497. ##
  498. # Reads large blocks in a safe way.  Unlike fp.read(n), this function
  499. # doesn't trust the user.  If the requested size is larger than
  500. # SAFEBLOCK, the file is read block by block.
  501. #
  502. # @param fp File handle.  Must implement a <b>read</b> method.
  503. # @param size Number of bytes to read.
  504. # @return A string containing up to <i>size</i> bytes of data.
  505.  
  506. def _safe_read(fp, size):
  507.     if size <= 0:
  508.         return ""
  509.     if size <= SAFEBLOCK:
  510.         return fp.read(size)
  511.     data = []
  512.     while size > 0:
  513.         block = fp.read(min(size, SAFEBLOCK))
  514.         if not block:
  515.             break
  516.         data.append(block)
  517.         size = size - len(block)
  518.     return string.join(data, "")
  519.