home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 April / enter-2004-04.iso / files / EVE_1424_100181.exe / PsdImagePlugin.py < prev    next >
Encoding:
Text File  |  2004-04-20  |  6.7 KB  |  269 lines

  1. #
  2. # The Python Imaging Library
  3. # $Id: //modules/pil/PIL/PsdImagePlugin.py#5 $
  4. #
  5. # Adobe PSD 2.5/3.0 file handling
  6. #
  7. # History:
  8. # 1995-09-01 fl   Created
  9. # 1997-01-03 fl   Read most PSD images
  10. # 1997-01-18 fl   Fixed P and CMYK support
  11. # 2001-10-21 fl   Added seek/tell support (for layers)
  12. #
  13. # Copyright (c) 1997-2001 by Secret Labs AB.
  14. # Copyright (c) 1995-2001 by Fredrik Lundh
  15. #
  16. # See the README file for information on usage and redistribution.
  17. #
  18.  
  19. __version__ = "0.4"
  20.  
  21. import string
  22. import Image, ImageFile, ImagePalette
  23.  
  24. MODES = {
  25.     # (photoshop mode, bits) -> (pil mode, required channels)
  26.     (0, 1): ("1", 1),
  27.     (0, 8): ("L", 1),
  28.     (1, 8): ("L", 1),
  29.     (2, 8): ("P", 1),
  30.     (3, 8): ("RGB", 3),
  31.     (4, 8): ("CMYK", 4),
  32.     (7, 8): ("L", 1), # FIXME: multilayer
  33.     (8, 8): ("L", 1), # duotone
  34.     (9, 8): ("LAB", 3)
  35. }
  36.  
  37. #
  38. # helpers
  39.  
  40. def i16(c):
  41.     return ord(c[1]) + (ord(c[0])<<8)
  42.  
  43. def i32(c):
  44.     return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
  45.  
  46. # --------------------------------------------------------------------.
  47. # read PSD images
  48.  
  49. def _accept(prefix):
  50.     return prefix[:4] == "8BPS"
  51.  
  52. class PsdImageFile(ImageFile.ImageFile):
  53.  
  54.     format = "PSD"
  55.     format_description = "Adobe Photoshop"
  56.  
  57.     def _open(self):
  58.  
  59.         read = self.fp.read
  60.  
  61.         #
  62.         # header
  63.  
  64.         s = read(26)
  65.         if s[:4] != "8BPS" or i16(s[4:]) != 1:
  66.             raise SyntaxError, "not a PSD file"
  67.  
  68.         psd_bits = i16(s[22:])
  69.         psd_channels = i16(s[12:])
  70.         psd_mode = i16(s[24:])
  71.  
  72.         mode, channels = MODES[(psd_mode, psd_bits)]
  73.  
  74.         if channels > psd_channels:
  75.             raise IOError, "not enough channels"
  76.  
  77.         self.mode = mode
  78.         self.size = i32(s[18:]), i32(s[14:])
  79.  
  80.         #
  81.         # color mode data
  82.  
  83.         size = i32(read(4))
  84.         if size:
  85.             data = read(size)
  86.             if mode == "P" and size == 768:
  87.                 self.palette = ImagePalette.raw("RGB;L", data)
  88.  
  89.         #
  90.         # image resources
  91.  
  92.         self.resources = []
  93.  
  94.         size = i32(read(4))
  95.         if size:
  96.             # load resources
  97.             end = self.fp.tell() + size
  98.             while self.fp.tell() < end:
  99.                 signature = read(4)
  100.                 id = i16(read(2))
  101.                 name = read(ord(read(1)))
  102.                 if not (len(name) & 1):
  103.                     read(1) # padding
  104.                 data = read(i32(read(4)))
  105.                 if (len(data) & 1):
  106.                     read(1) # padding
  107.                 self.resources.append((id, name, data))
  108.  
  109.         #
  110.         # layer and mask information
  111.  
  112.         self.layers = []
  113.  
  114.         size = i32(read(4))
  115.         if size:
  116.             end = self.fp.tell() + size
  117.             size = i32(read(4))
  118.             if size:
  119.                 self.layers = _layerinfo(self.fp)
  120.             self.fp.seek(end)
  121.  
  122.         #
  123.         # image descriptor
  124.  
  125.         self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)
  126.  
  127.         # keep the file open
  128.         self._fp = self.fp
  129.         self.frame = 0
  130.  
  131.     def seek(self, layer):
  132.         # seek to given layer (1..max)
  133.         if layer == self.frame:
  134.             return
  135.         try:
  136.             if layer <= 0:
  137.                 raise IndexError
  138.             name, mode, bbox, tile = self.layers[layer-1]
  139.             self.mode = mode
  140.             self.tile = tile
  141.             self.frame = layer
  142.             self.fp = self._fp
  143.             return name, bbox
  144.         except IndexError:
  145.             raise EOFError, "no such layer"
  146.  
  147.     def tell(self):
  148.         # return layer number (0=image, 1..max=layers)
  149.         return self.frame
  150.  
  151.     def load_prepare(self):
  152.         # create image memory if necessary
  153.         if not self.im or\
  154.            self.im.mode != self.mode or self.im.size != self.size:
  155.             self.im = Image.core.fill(self.mode, self.size, 0)
  156.         # create palette (optional)
  157.         if self.mode == "P":
  158.             Image.Image.load(self)
  159.  
  160. def _layerinfo(file):
  161.     # read layerinfo block
  162.     layers = []
  163.     read = file.read
  164.  
  165.     for i in range(abs(i16(read(2)))):
  166.  
  167.         # bounding box
  168.         y0 = i32(read(4)); x0 = i32(read(4))
  169.         y1 = i32(read(4)); x1 = i32(read(4))
  170.  
  171.         # image info
  172.         info = []
  173.         mode = []
  174.         for i in range(i16(read(2))):
  175.             type = i16(read(2))
  176.             if type == 65535:
  177.                 m = "A"
  178.             else:
  179.                 m = "RGB"[type]
  180.             mode.append(m)
  181.             size = i32(read(4))
  182.             info.append((m, size))
  183.  
  184.         # figure out the image mode
  185.         mode.sort()
  186.         if mode == ["R"]:
  187.             mode = "L"
  188.         elif mode == ["B", "G", "R"]:
  189.             mode = "RGB"
  190.         elif mode == ["A", "B", "G", "R"]:
  191.             mode = "RGBA"
  192.         else:
  193.             mode = None # unknown
  194.  
  195.         # skip over blend flags and extra information
  196.         filler = read(12)
  197.         name = None # FIXME
  198.         file.seek(i32(read(4)), 1)
  199.  
  200.         layers.append((name, mode, (x0, y0, x1, y1)))
  201.  
  202.     # get tiles
  203.     i = 0
  204.     for name, mode, bbox in layers:
  205.         tile = []
  206.         for m in mode:
  207.             t = _maketile(file, m, bbox, 1)
  208.             if t:
  209.                 tile.extend(t)
  210.         layers[i] = name, mode, bbox, tile
  211.         i = i + 1
  212.  
  213.     return layers
  214.  
  215. def _maketile(file, mode, bbox, channels):
  216.  
  217.     tile = None
  218.     read = file.read
  219.  
  220.     compression = i16(read(2))
  221.  
  222.     xsize = bbox[2] - bbox[0]
  223.     ysize = bbox[3] - bbox[1]
  224.  
  225.     offset = file.tell()
  226.  
  227.     if compression == 0:
  228.         #
  229.         # raw compression
  230.         tile = []
  231.         for channel in range(channels):
  232.             layer = mode[channel]
  233.             if mode == "CMYK":
  234.                 layer = layer + ";I"
  235.             tile.append(("raw", bbox, offset, layer))
  236.             offset = offset + xsize*ysize
  237.  
  238.     elif compression == 1:
  239.         #
  240.         # packbits compression
  241.         i = 0
  242.         tile = []
  243.         bytecount = read(channels * ysize * 2)
  244.         offset = file.tell()
  245.         for channel in range(channels):
  246.             layer = mode[channel]
  247.             if mode == "CMYK":
  248.                 layer = layer + ";I"
  249.             tile.append(
  250.                 ("packbits", bbox, offset, layer)
  251.                 )
  252.             for y in range(ysize):
  253.                 offset = offset + i16(bytecount[i:i+2])
  254.                 i = i + 2
  255.  
  256.     file.seek(offset)
  257.  
  258.     if offset & 1:
  259.         read(1) # padding
  260.  
  261.     return tile
  262.  
  263. # --------------------------------------------------------------------
  264. # registry
  265.  
  266. Image.register_open("PSD", PsdImageFile, _accept)
  267.  
  268. Image.register_extension("PSD", ".psd")
  269.