]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/tools/img2py.py
another fix for undo/redo
[wxWidgets.git] / wxPython / wx / tools / img2py.py
1 #----------------------------------------------------------------------
2 # Name: wxPython.tools.img2py
3 # Purpose: Convert an image to Python code.
4 #
5 # Author: Robin Dunn
6 #
7 # RCS-ID: $Id$
8 # Copyright: (c) 2002 by Total Control Software
9 # Licence: wxWindows license
10 #----------------------------------------------------------------------
11 # 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
12 #
13 # o V2.5 compatability update
14 #
15
16
17 """
18 img2py.py -- Convert an image to PNG format and embed it in a Python
19 module with appropriate code so it can be loaded into
20 a program at runtime. The benefit is that since it is
21 Python source code it can be delivered as a .pyc or
22 'compiled' into the program using freeze, py2exe, etc.
23
24 Usage:
25
26 img2py.py [options] image_file python_file
27
28 Options:
29
30 -m <#rrggbb> If the original image has a mask or transparency defined
31 it will be used by default. You can use this option to
32 override the default or provide a new mask by specifying
33 a colour in the image to mark as transparent.
34
35 -n <name> Normally generic names (getBitmap, etc.) are used for the
36 image access functions. If you use this option you can
37 specify a name that should be used to customize the access
38 fucntions, (getNameBitmap, etc.)
39
40 -c Maintain a catalog of names that can be used to reference
41 images. Catalog can be accessed via catalog and index attributes
42 of the module. If the -n <name> option is specified then <name>
43 is used for the catalog key and index value, otherwise
44 the filename without any path or extension is used as the key.
45
46 -a This flag specifies that the python_file should be appended
47 to instead of overwritten. This in combination with -n will
48 allow you to put multiple images in one Python source file.
49
50 -u Don't use compression. Leaves the data uncompressed.
51
52 -i Also output a function to return the image as a wxIcon.
53
54 """
55
56 #
57 # Changes:
58 # - Cliff Wells <LogiplexSoftware@earthlink.net>
59 # 20021206: Added catalog (-c) option.
60 #
61 # 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
62 #
63 # o V2.5 compatability update
64 #
65
66 import cPickle
67 import cStringIO
68 import getopt
69 import glob
70 import os
71 import sys
72 import tempfile
73 import zlib
74
75 import wx
76
77 import img2img
78
79
80 def crunch_data(data, compressed):
81 # compress it?
82 if compressed:
83 data = zlib.compress(data, 9)
84
85 # convert to a printable format, so it can be in a Python source file
86 data = repr(data)
87
88 # This next bit is borrowed from PIL. It is used to wrap the text intelligently.
89 fp = cStringIO.StringIO()
90 data = data + " " # buffer for the +1 test
91 c = i = 0
92 word = ""
93 octdigits = "01234567"
94 hexdigits = "0123456789abcdef"
95 while i < len(data):
96 if data[i] != "\\":
97 word = data[i]
98 i = i + 1
99 else:
100 if data[i+1] in octdigits:
101 for n in range(2, 5):
102 if data[i+n] not in octdigits:
103 break
104 word = data[i:i+n]
105 i = i + n
106 elif data[i+1] == 'x':
107 for n in range(2, 5):
108 if data[i+n] not in hexdigits:
109 break
110 word = data[i:i+n]
111 i = i + n
112 else:
113 word = data[i:i+2]
114 i = i + 2
115
116 l = len(word)
117 if c + l >= 78-1:
118 fp.write("\\\n")
119 c = 0
120 fp.write(word)
121 c = c + l
122
123 # return the formatted compressed data
124 return fp.getvalue()
125
126
127 app = None
128 def main(args):
129 if not args or ("-h" in args):
130 print __doc__
131 return
132
133 # some bitmap related things need to have a wxApp initialized...
134 if wx.GetApp() is None:
135 global app
136 app = wx.PySimpleApp()
137
138 append = 0
139 compressed = 1
140 maskClr = None
141 imgName = ""
142 icon = 0
143 catalog = 0
144
145 try:
146 opts, fileArgs = getopt.getopt(args, "auicn:m:")
147 except getopt.GetoptError:
148 print __doc__
149 return
150
151 for opt, val in opts:
152 if opt == "-a":
153 append = 1
154 elif opt == "-u":
155 compressed = 0
156 elif opt == "-n":
157 imgName = val
158 elif opt == "-m":
159 maskClr = val
160 elif opt == "-i":
161 icon = 1
162 elif opt == "-c":
163 catalog = 1
164
165 if len(fileArgs) != 2:
166 print __doc__
167 return
168
169 image_file, python_file = fileArgs
170
171 # convert the image file to a temporary file
172 tfname = tempfile.mktemp()
173 ok, msg = img2img.convert(image_file, maskClr, None, tfname, wx.BITMAP_TYPE_PNG, ".png")
174 if not ok:
175 print msg
176 return
177
178 data = open(tfname, "rb").read()
179 data = crunch_data(data, compressed)
180 os.unlink(tfname)
181
182 if append:
183 out = open(python_file, "a")
184 else:
185 out = open(python_file, "w")
186
187 if catalog:
188 pyPath, pyFile = os.path.split(python_file)
189 imgPath, imgFile = os.path.split(image_file)
190
191 if not imgName:
192 imgName = os.path.splitext(imgFile)[0]
193 print "\nWarning: -n not specified. Using filename (%s) for catalog entry." % imgName
194
195 old_index = []
196 if append:
197 # check to see if catalog exists already (file may have been created
198 # with an earlier version of img2py or without -c option)
199 oldSysPath = sys.path[:]
200 sys.path = [pyPath] # make sure we don't import something else by accident
201 mod = __import__(os.path.splitext(pyFile)[0])
202 if 'index' not in dir(mod):
203 print "\nWarning: %s was originally created without catalog." % python_file
204 print " Any images already in file will not be cataloged.\n"
205 out.write("\n# ***************** Catalog starts here *******************")
206 out.write("\n\ncatalog = {}\n")
207 out.write("index = []\n\n")
208 out.write("class ImageClass: pass\n\n")
209 else: # save a copy of the old index so we can warn about duplicate names
210 old_index[:] = mod.index[:]
211 del mod
212 sys.path = oldSysPath[:]
213
214 out.write("#" + "-" * 70 + "\n")
215 if not append:
216 out.write("# This file was generated by %s\n#\n" % sys.argv[0])
217 out.write("from wx import ImageFromStream, BitmapFromImage\n")
218 if icon:
219 out.write("from wx import EmptyIcon\n")
220 if compressed:
221 out.write("import cStringIO, zlib\n\n\n")
222 else:
223 out.write("import cStringIO\n\n\n")
224
225 if catalog:
226 out.write("catalog = {}\n")
227 out.write("index = []\n\n")
228 out.write("class ImageClass: pass\n\n")
229
230 if compressed:
231 out.write("def get%sData():\n"
232 " return zlib.decompress(\n%s)\n\n"
233 % (imgName, data))
234 else:
235 out.write("def get%sData():\n"
236 " return \\\n%s\n\n"
237 % (imgName, data))
238
239
240 out.write("def get%sBitmap():\n"
241 " return BitmapFromImage(get%sImage())\n\n"
242 "def get%sImage():\n"
243 " stream = cStringIO.StringIO(get%sData())\n"
244 " return ImageFromStream(stream)\n\n"
245 % tuple([imgName] * 4))
246 if icon:
247 out.write("def get%sIcon():\n"
248 " icon = EmptyIcon()\n"
249 " icon.CopyFromBitmap(get%sBitmap())\n"
250 " return icon\n\n"
251 % tuple([imgName] * 2))
252
253 if catalog:
254 if imgName in old_index:
255 print "Warning: %s already in catalog." % imgName
256 print " Only the last entry will be accessible.\n"
257 old_index.append(imgName)
258 out.write("index.append('%s')\n" % imgName)
259 out.write("catalog['%s'] = ImageClass()\n" % imgName)
260 out.write("catalog['%s'].getData = get%sData\n" % tuple([imgName] * 2))
261 out.write("catalog['%s'].getImage = get%sImage\n" % tuple([imgName] * 2))
262 out.write("catalog['%s'].getBitmap = get%sBitmap\n" % tuple([imgName] * 2))
263 if icon:
264 out.write("catalog['%s'].getIcon = get%sIcon\n" % tuple([imgName] * 2))
265 out.write("\n\n")
266
267 if imgName:
268 n_msg = ' using "%s"' % imgName
269 else:
270 n_msg = ""
271 if maskClr:
272 m_msg = " with mask %s" % maskClr
273 else:
274 m_msg = ""
275 print "Embedded %s%s into %s%s" % (image_file, n_msg, python_file, m_msg)
276
277
278 if __name__ == "__main__":
279 main(sys.argv[1:])
280