home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pypil112.zip / PIL-1.1.2.zip / Lib / site-packages / PIL / WmfImagePlugin.py < prev    next >
Text File  |  2001-05-03  |  7KB  |  280 lines

  1. #
  2. # THIS IS WORK IN PROGRESS.
  3. #
  4. # The Python Imaging Library.
  5. # $Id$
  6. #
  7. # WMF support for PIL
  8. #
  9. # history:
  10. #       96-12-14 fl     Created
  11. #
  12. # notes:
  13. #       This code currently supports placable metafiles only, and
  14. #       just a few graphics operations are implemented.
  15. #
  16. # Copyright (c) Secret Labs AB 1997.
  17. # Copyright (c) Fredrik Lundh 1996.
  18. #
  19. # See the README file for information on usage and redistribution.
  20. #
  21.  
  22. __version__ = "0.1"
  23.  
  24. import Image, ImageDraw, ImageFile
  25. import string
  26.  
  27. #
  28. # --------------------------------------------------------------------
  29.  
  30. def i16(c):
  31.     return ord(c[0]) + (ord(c[1])<<8)
  32.  
  33. def i32(c):
  34.     return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
  35.  
  36. # --------------------------------------------------------------------
  37. # The following codes are taken from the wingdi.h header file.
  38. # Copyright (c) 1985-1996, Microsoft Corp.  All rights reserved.
  39.  
  40. META_ANIMATEPALETTE = 0x0436
  41. META_ARC = 0x0817
  42. META_BITBLT = 0x0922
  43. META_CHORD = 0x0830
  44. META_CREATEBRUSHINDIRECT = 0x02FC
  45. META_CREATEFONTINDIRECT = 0x02FB
  46. META_CREATEPALETTE = 0x00f7
  47. META_CREATEPATTERNBRUSH = 0x01F9
  48. META_CREATEPENINDIRECT = 0x02FA
  49. META_CREATEREGION = 0x06FF
  50. META_DELETEOBJECT = 0x01f0
  51. META_DIBBITBLT = 0x0940
  52. META_DIBCREATEPATTERNBRUSH = 0x0142
  53. META_DIBSTRETCHBLT = 0x0b41
  54. META_ELLIPSE = 0x0418
  55. META_ESCAPE = 0x0626
  56. META_EXCLUDECLIPRECT = 0x0415
  57. META_EXTFLOODFILL = 0x0548
  58. META_EXTTEXTOUT = 0x0a32
  59. META_FILLREGION = 0x0228
  60. META_FLOODFILL = 0x0419
  61. META_FRAMEREGION = 0x0429
  62. META_INTERSECTCLIPRECT = 0x0416
  63. META_INVERTREGION = 0x012A
  64. META_LINETO = 0x0213
  65. META_MOVETO = 0x0214
  66. META_OFFSETCLIPRGN = 0x0220
  67. META_OFFSETVIEWPORTORG = 0x0211
  68. META_OFFSETWINDOWORG = 0x020F
  69. META_PAINTREGION = 0x012B
  70. META_PATBLT = 0x061D
  71. META_PIE = 0x081A
  72. META_POLYGON = 0x0324
  73. META_POLYLINE = 0x0325
  74. META_POLYPOLYGON = 0x0538
  75. META_REALIZEPALETTE = 0x0035
  76. META_RECTANGLE = 0x041B
  77. META_RESIZEPALETTE = 0x0139
  78. META_RESTOREDC = 0x0127
  79. META_ROUNDRECT = 0x061C
  80. META_SAVEDC = 0x001E
  81. META_SCALEVIEWPORTEXT = 0x0412
  82. META_SCALEWINDOWEXT = 0x0410
  83. META_SELECTCLIPREGION = 0x012C
  84. META_SELECTOBJECT = 0x012D
  85. META_SELECTPALETTE = 0x0234
  86. META_SETBKCOLOR = 0x0201
  87. META_SETBKMODE = 0x0102
  88. META_SETDIBTODEV = 0x0d33
  89. META_SETMAPMODE = 0x0103
  90. META_SETMAPPERFLAGS = 0x0231
  91. META_SETPALENTRIES = 0x0037
  92. META_SETPIXEL = 0x041F
  93. META_SETPOLYFILLMODE = 0x0106
  94. META_SETRELABS = 0x0105
  95. META_SETROP2 = 0x0104
  96. META_SETSTRETCHBLTMODE = 0x0107
  97. META_SETTEXTALIGN = 0x012E
  98. META_SETTEXTCHAREXTRA = 0x0108
  99. META_SETTEXTCOLOR = 0x0209
  100. META_SETTEXTJUSTIFICATION = 0x020A
  101. META_SETVIEWPORTEXT = 0x020E
  102. META_SETVIEWPORTORG = 0x020D
  103. META_SETWINDOWEXT = 0x020C
  104. META_SETWINDOWORG = 0x020B
  105. META_STRETCHBLT = 0x0B23
  106. META_STRETCHDIB = 0x0f43
  107. META_TEXTOUT = 0x0521
  108.  
  109. # create a code to name dictionary (for debugging)
  110. NAME = {}
  111. for k, v in vars().items():
  112.     if k[:5] == "META_":
  113.         NAME[v] = k[5:]
  114.  
  115. #
  116. # --------------------------------------------------------------------
  117. # Read WMF file
  118.  
  119. def _accept(prefix):
  120.     return prefix[:6] == "\327\315\306\232\000\000"
  121.  
  122. class WmfImageFile(ImageFile.ImageFile):
  123.  
  124.     format = "WMF"
  125.     format_description = "Windows Metafile"
  126.  
  127.     def _open(self):
  128.  
  129.         # check placable header
  130.         s = self.fp.read(22)
  131.         if s[:6] != "\327\315\306\232\000\000":
  132.             raise SyntaxError, "Not a placable WMF file"
  133.  
  134.         # position on output device
  135.         bbox = i16(s[6:8]), i16(s[8:10]), i16(s[10:12]), i16(s[12:14])
  136.  
  137.         # FIXME: should take the scale into account
  138.  
  139.         self.mode = "P"
  140.         self.size = (bbox[2]-bbox[0]) / 20, (bbox[3]-bbox[1]) / 20
  141.  
  142.         # FIXME: while hacking
  143.         self.size = (bbox[2] + bbox[0])/10, (bbox[3] + bbox[1])/10
  144.  
  145.         self.bbox = bbox
  146.  
  147.         # check standard header
  148.         s = self.fp.read(18)
  149.         if s[:6] != "\001\000\011\000\000\003":
  150.             raise SyntaxError, "Not a WMF file"
  151.  
  152.     def _ink(self, rgb):
  153.  
  154.         # lookup colour in current palette
  155.         try:
  156.             return self.palette[rgb]
  157.         except KeyError:
  158.             # hmm. what if the palette becomes full?
  159.             ink = len(self.palette)
  160.             self.palette[rgb] = ink
  161.             return ink
  162.  
  163.     def load(self):
  164.  
  165.         if self.im:
  166.             return
  167.  
  168.         #
  169.         # windows standard palette
  170.  
  171.         self.palette = {
  172.             '\000\000\000': 0,
  173.             '\200\000\000': 1,
  174.             '\000\200\000': 2,
  175.             '\200\200\000': 3,
  176.             '\000\000\200': 4,
  177.             '\200\000\200': 5,
  178.             '\000\200\200': 6,
  179.             '\300\300\300': 7,
  180.             '\300\334\300': 8,
  181.             '\246\312\360': 9,
  182.             '\377\373\360': 246,
  183.             '\240\240\244': 247,
  184.             '\200\200\200': 248,
  185.             '\377\000\000': 249,
  186.             '\000\377\000': 250,
  187.             '\377\377\000': 251,
  188.             '\000\000\377': 252,
  189.             '\377\000\377': 253,
  190.             '\000\377\377': 254,
  191.             '\377\377\377': 255,
  192.         }
  193.  
  194.         fill = 0
  195.  
  196.         pen = brush = self._ink("\000\000\000")
  197.         paper = self._ink("\377\377\377")
  198.  
  199.         self.im = Image.core.fill(self.mode, self.size, paper)
  200.  
  201.         #
  202.         # render metafile into image, using the standard palette
  203.  
  204.         id = ImageDraw.ImageDraw(self)
  205.  
  206.         while 1:
  207.  
  208.             s = self.fp.read(6)
  209.  
  210.             size = i32(s)*2
  211.             func = i16(s[4:])
  212.  
  213.             if not func:
  214.                 break
  215.  
  216.             s = self.fp.read(size-6)
  217.  
  218.             if func == META_SETPOLYFILLMODE:
  219.                 fill = i16(s)
  220.                 id.setfill(fill)
  221.  
  222.             elif func == META_CREATEBRUSHINDIRECT:
  223.                 brush = self._ink(s[2:5])
  224.  
  225.             elif func == META_CREATEPENINDIRECT:
  226.                 pen = self._ink(s[6:9])
  227.  
  228.             elif func == META_POLYGON:
  229.                 xy = map(lambda i,s=s: i16(s[i:i+2])/10, range(2, len(s), 2))
  230.                 if fill:
  231.                     id.setink(brush)
  232.                     id.polygon(xy)
  233.                     id.setink(pen)
  234.                     id.setfill(0)
  235.                     id.polygon(xy)
  236.                     id.setfill(1)
  237.                 else:
  238.                     id.setink(pen)
  239.                     id.polygon(xy)
  240.  
  241.             elif func == META_POLYLINE:
  242.                 xy = map(lambda i,s=s: i16(s[i:i+2])/10, range(2, len(s), 2))
  243.                 id.setink(pen)
  244.                 id.line(xy)
  245.  
  246.             elif func == META_RECTANGLE:
  247.                 xy = (i16(s[2:4])/10, i16(s[0:2])/10,
  248.                       i16(s[6:8])/10, i16(s[4:6])/10)
  249.                 if fill:
  250.                     id.setink(brush)
  251.                     id.rectangle(xy)
  252.                     id.setink(pen)
  253.                     id.setfill(0)
  254.                     id.rectangle(xy)
  255.                     id.setfill(1)
  256.                 else:
  257.                     id.setink(pen)
  258.                     id.rectangle(xy)
  259.             else:
  260.                 if Image.DEBUG:
  261.                     print size, hex(func), NAME[func]
  262.                 pass
  263.  
  264.         #
  265.         # attach palette to image
  266.  
  267.         palette = ["\0\0\0"] * 256
  268.         for rgb, i in self.palette.items():
  269.             if i < 256:
  270.                 palette[i] = rgb
  271.         self.im.putpalette("RGB", string.join(palette, ""))
  272.  
  273. #
  274. # --------------------------------------------------------------------
  275. # Registry stuff
  276.  
  277. Image.register_open("WMF", WmfImageFile, _accept)
  278.  
  279. Image.register_extension("WMF", ".wmf")
  280.