home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 April / enter-2004-04.iso / files / EVE_1424_100181.exe / IptcImagePlugin.py < prev    next >
Encoding:
Python Source  |  2004-04-20  |  4.9 KB  |  202 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id: //modules/pil/PIL/IptcImagePlugin.py#3 $
  4. #
  5. # IPTC/NAA file handling
  6. #
  7. # history:
  8. # 95-10-01 fl   Created
  9. # 98-03-09 fl   Cleaned up and added to PIL
  10. #
  11. # Copyright (c) Secret Labs AB 1997-2000.
  12. # Copyright (c) Fredrik Lundh 1995.
  13. #
  14. # See the README file for information on usage and redistribution.
  15. #
  16.  
  17.  
  18. __version__ = "0.2"
  19.  
  20.  
  21. import Image, ImageFile
  22. import os, tempfile
  23.  
  24.  
  25. COMPRESSION = {
  26.     1: "raw",
  27.     5: "jpeg"
  28. }
  29.  
  30. PAD = chr(0) * 4
  31.  
  32. #
  33. # Helpers
  34.  
  35. def i16(c):
  36.     return ord(c[1]) + (ord(c[0])<<8)
  37.  
  38. def i32(c):
  39.     return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
  40.  
  41. def i(c):
  42.     return i32((PAD + c)[-4:])
  43.  
  44. def dump(c):
  45.     for i in c:
  46.         print "%02x" % ord(i),
  47.     print
  48.  
  49.  
  50. #
  51. # Parser
  52.  
  53. class IptcImageFile(ImageFile.ImageFile):
  54.  
  55.     format = "IPTC"
  56.     format_description = "IPTC/NAA"
  57.  
  58.     def getint(self, key):
  59.         return i(self.info[key])
  60.  
  61.     def field(self):
  62.         #
  63.         # get a IPTC field header
  64.         s = self.fp.read(5)
  65.         if not len(s):
  66.             return None, 0
  67.  
  68.         tag = ord(s[1]), ord(s[2])
  69.  
  70.         # syntax
  71.         if ord(s[0]) != 0x1C or tag[0] < 1 or tag[0] > 9:
  72.             raise SyntaxError, "invalid IPTC/NAA file"
  73.  
  74.         # field size
  75.         size = ord(s[3])
  76.         if size > 132:
  77.             raise IOError, "illegal field length in IPTC/NAA file"
  78.         elif size == 128:
  79.             size = 0
  80.         elif size > 128:
  81.             size = i(self.fp.read(size-128))
  82.         else:
  83.             size = i16(s[3:])
  84.  
  85.         return tag, size
  86.  
  87.     def _is_raw(self, offset, size):
  88.         #
  89.         # check if the file can be mapped
  90.  
  91.         # DISABLED: the following only slows things down...
  92.         return 0
  93.  
  94.         self.fp.seek(offset)
  95.         t, sz = self.field()
  96.         if sz != size[0]:
  97.             return 0
  98.         y = 1
  99.         while 1:
  100.             self.fp.seek(sz, 1)
  101.             t, s = self.field()
  102.             if t != (8, 10):
  103.                 break
  104.             if s != sz:
  105.                 return 0
  106.             y = y + 1
  107.         return y == size[1]
  108.  
  109.     def _open(self):
  110.  
  111.         # load descriptive fields
  112.         while 1:
  113.             offset = self.fp.tell()
  114.             tag, size = self.field()
  115.             if not tag or tag == (8,10):
  116.                 break
  117.             if size:
  118.                 self.info[tag] = self.fp.read(size)
  119.             else:
  120.                 self.info[tag] = None
  121.             # print tag, self.info[tag]
  122.  
  123.         # mode
  124.         layers = ord(self.info[(3,60)][0])
  125.         component = ord(self.info[(3,60)][1])
  126.         if self.info.has_key((3,65)):
  127.             id = ord(self.info[(3,65)][0])-1
  128.         else:
  129.             id = 0
  130.         if layers == 1 and not component:
  131.             self.mode = "L"
  132.         elif layers == 3 and component:
  133.             self.mode = "RGB"[id]
  134.         elif layers == 4 and component:
  135.             self.mode = "CMYK"[id]
  136.  
  137.         # size
  138.         self.size = self.getint((3,20)), self.getint((3,30))
  139.  
  140.         # compression
  141.         try:
  142.             compression = COMPRESSION[self.getint((3,120))]
  143.         except KeyError:
  144.             raise IOError, "Unknown IPTC image compression"
  145.  
  146.         # tile
  147.         if tag == (8,10):
  148.             if compression == "raw" and self._is_raw(offset, self.size):
  149.                 self.tile = [(compression, (offset, size + 5, -1),
  150.                              (0, 0, self.size[0], self.size[1]))]
  151.             else:
  152.                 self.tile = [("iptc", (compression, offset),
  153.                              (0, 0, self.size[0], self.size[1]))]
  154.  
  155.     def load(self):
  156.  
  157.         if len(self.tile) != 1 or self.tile[0][0] != "iptc":
  158.             return ImageFile.ImageFile.load(self)
  159.  
  160.         type, tile, box = self.tile[0]
  161.  
  162.         encoding, offset = tile
  163.  
  164.         self.fp.seek(offset)
  165.  
  166.         # Copy image data to temporary file
  167.         outfile = tempfile.mktemp()
  168.         o = open(outfile, "wb")
  169.         if encoding == "raw":
  170.             # To simplify access to the extracted file,
  171.             # prepend a PPM header
  172.             o.write("P5\n%d %d\n255\n" % self.size)
  173.         while 1:
  174.             type, size = self.field()
  175.             if type != (8, 10):
  176.                 break
  177.             while size > 0:
  178.                 s = self.fp.read(min(size, 8192))
  179.                 if not s:
  180.                     break
  181.                 o.write(s)
  182.                 size = size - len(s)
  183.         o.close()
  184.  
  185.         try:
  186.             try:
  187.                 # fast
  188.                 self.im = Image.core.open_ppm(outfile)
  189.             except:
  190.                 # slightly slower
  191.                 im = Image.open(outfile)
  192.                 im.load()
  193.                 self.im = im.im
  194.         finally:
  195.             try: os.unlink(outfile)
  196.             except: pass
  197.  
  198.  
  199. Image.register_open("IPTC", IptcImageFile)
  200.  
  201. Image.register_extension("IPTC", ".iim")
  202.