]> git.saurik.com Git - wxWidgets.git/blame_incremental - wxPython/wx/tools/img2py.py
use wxString in wxFileSystem::FindFileInPath()
[wxWidgets.git] / wxPython / wx / tools / img2py.py
... / ...
CommitLineData
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#
14# 2/25/2007 - Gianluca Costa (archimede86@katamail.com)
15#
16#
17# o V2.5 compatibility update
18#
19
20"""
21img2py.py -- Convert an image to PNG format and embed it in a Python
22 module with appropriate code so it can be loaded into
23 a program at runtime. The benefit is that since it is
24 Python source code it can be delivered as a .pyc or
25 'compiled' into the program using freeze, py2exe, etc.
26
27Usage:
28
29 img2py.py [options] image_file python_file
30
31Options:
32
33 -m <#rrggbb> If the original image has a mask or transparency defined
34 it will be used by default. You can use this option to
35 override the default or provide a new mask by specifying
36 a colour in the image to mark as transparent.
37
38 -n <name> Normally generic names (getBitmap, etc.) are used for the
39 image access functions. If you use this option you can
40 specify a name that should be used to customize the access
41 fucntions, (getNameBitmap, etc.)
42
43 -c Maintain a catalog of names that can be used to reference
44 images. Catalog can be accessed via catalog and
45 index attributes of the module.
46 If the -n <name> option is specified then <name>
47 is used for the catalog key and index value, otherwise
48 the filename without any path or extension is used
49 as the key.
50
51 -a This flag specifies that the python_file should be appended
52 to instead of overwritten. This in combination with -n will
53 allow you to put multiple images in one Python source file.
54
55 -u Don't use compression. Leaves the data uncompressed.
56
57 -i Also output a function to return the image as a wxIcon.
58
59
60You can also import this module from your Python scripts, and use its img2py()
61function. See its docstring for more info.
62"""
63
64#
65# Changes:
66# - Cliff Wells <LogiplexSoftware@earthlink.net>
67# 20021206: Added catalog (-c) option.
68#
69# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
70#
71#
72# 2/25/2007 - Gianluca Costa (archimede86@katamail.com)
73# -Refactorization of the script-creation code in a specific "img2py()" function
74# -Added regex parsing instead of module importing
75# -Added some "try/finally" statements
76# -Added default values as named constants
77# -Made some parts of code a bit easier to read
78# -Updated the module docstring
79# -Corrected a bug with EmptyIcon
80#
81# o V2.5 compatibility update
82#
83import cPickle
84import cStringIO
85import getopt
86import glob
87import os
88import os.path
89import sys
90import tempfile
91import zlib
92import re
93
94import wx
95import img2img
96
97
98def crunch_data(data, compressed):
99 # compress it?
100 if compressed:
101 data = zlib.compress(data, 9)
102
103 # convert to a printable format, so it can be in a Python source file
104 data = repr(data)
105
106 # This next bit is borrowed from PIL. It is used to wrap the text intelligently.
107 fp = cStringIO.StringIO()
108 data += " " # buffer for the +1 test
109 c = i = 0
110 word = ""
111 octdigits = "01234567"
112 hexdigits = "0123456789abcdef"
113 while i < len(data):
114 if data[i] != "\\":
115 word = data[i]
116 i += 1
117 else:
118 if data[i+1] in octdigits:
119 for n in xrange(2, 5):
120 if data[i+n] not in octdigits:
121 break
122 word = data[i:i+n]
123 i += n
124 elif data[i+1] == 'x':
125 for n in xrange(2, 5):
126 if data[i+n] not in hexdigits:
127 break
128 word = data[i:i+n]
129 i += n
130 else:
131 word = data[i:i+2]
132 i += 2
133
134 l = len(word)
135 if c + l >= 78-1:
136 fp.write("\\\n")
137 c = 0
138 fp.write(word)
139 c += l
140
141 # return the formatted compressed data
142 return fp.getvalue()
143
144
145app = None
146DEFAULT_APPEND = False
147DEFAULT_COMPRESSED = True
148DEFAULT_MASKCLR = None
149DEFAULT_IMGNAME = ""
150DEFAULT_ICON = False
151DEFAULT_CATALOG = False
152
153#THIS IS USED TO IDENTIFY, IN THE GENERATED SCRIPT, LINES IN THE FORM "index.append('Image name')"
154indexPattern = re.compile(r"\s*index.append\('(.+)'\)\s*")
155
156def img2py(image_file, python_file, append=DEFAULT_APPEND, compressed=DEFAULT_COMPRESSED, maskClr=DEFAULT_MASKCLR, imgName=DEFAULT_IMGNAME, icon=DEFAULT_ICON, catalog=DEFAULT_CATALOG):
157 """
158 Converts an image file to a data structure written in a Python file
159 --image_file: string; the path of the source image file
160 --python_file: string; the path of the destination python file
161 --other arguments: they are equivalent to the command-line arguments
162 """
163 global app
164 if not wx.GetApp():
165 app = wx.PySimpleApp()
166
167 # convert the image file to a temporary file
168 tfname = tempfile.mktemp()
169 try:
170 ok, msg = img2img.convert(image_file, maskClr, None, tfname, wx.BITMAP_TYPE_PNG, ".png")
171 if not ok:
172 print msg
173 return
174
175 data = open(tfname, "rb").read()
176 data = crunch_data(data, compressed)
177 finally:
178 if os.path.exists(tfname):
179 os.remove(tfname)
180
181
182 old_index = []
183 if catalog and append:
184 # check to see if catalog exists already (file may have been created
185 # with an earlier version of img2py or without -c option)
186 pyPath, pyFile = os.path.split(python_file)
187
188 append_catalog = True
189
190 sourcePy = open(python_file, "r")
191 try:
192 for line in sourcePy:
193
194 if line == "catalog = {}\n":
195 append_catalog = False
196 else:
197 lineMatcher = indexPattern.match(line)
198 if lineMatcher:
199 old_index.append(lineMatcher.groups()[0])
200 finally:
201 sourcePy.close()
202
203
204 if append_catalog:
205 out = open(python_file, "a")
206 try:
207 out.write("\n# ***************** Catalog starts here *******************")
208 out.write("\n\ncatalog = {}\n")
209 out.write("index = []\n\n")
210 out.write("class ImageClass: pass\n\n")
211 finally:
212 out.close()
213
214
215
216 if append:
217 out = open(python_file, "a")
218 else:
219 out = open(python_file, "w")
220
221 try:
222 if catalog:
223 imgPath, imgFile = os.path.split(image_file)
224
225 if not imgName:
226 imgName = os.path.splitext(imgFile)[0]
227 print "\nWarning: -n not specified. Using filename (%s) for catalog entry." % imgName
228
229 out.write("#" + "-" * 70 + "\n")
230 if not append:
231 out.write("# This file was generated by %s\n#\n" % sys.argv[0])
232 out.write("from wx import ImageFromStream, BitmapFromImage, EmptyIcon\n")
233 if compressed:
234 out.write("import cStringIO, zlib\n\n\n")
235 else:
236 out.write("import cStringIO\n\n\n")
237
238 if catalog:
239 out.write("catalog = {}\n")
240 out.write("index = []\n\n")
241 out.write("class ImageClass: pass\n\n")
242
243 if compressed:
244 out.write("def get%sData():\n"
245 " return zlib.decompress(\n%s)\n\n"
246 % (imgName, data))
247 else:
248 out.write("def get%sData():\n"
249 " return \\\n%s\n\n"
250 % (imgName, data))
251
252
253 out.write("def get%sBitmap():\n"
254 " return BitmapFromImage(get%sImage())\n\n"
255 "def get%sImage():\n"
256 " stream = cStringIO.StringIO(get%sData())\n"
257 " return ImageFromStream(stream)\n\n"
258 % tuple([imgName] * 4))
259 if icon:
260 out.write("def get%sIcon():\n"
261 " icon = EmptyIcon()\n"
262 " icon.CopyFromBitmap(get%sBitmap())\n"
263 " return icon\n\n"
264 % tuple([imgName] * 2))
265
266 if catalog:
267 if imgName in old_index:
268 print "Warning: %s already in catalog." % imgName
269 print " Only the last entry will be accessible.\n"
270 old_index.append(imgName)
271 out.write("index.append('%s')\n" % imgName)
272 out.write("catalog['%s'] = ImageClass()\n" % imgName)
273 out.write("catalog['%s'].getData = get%sData\n" % tuple([imgName] * 2))
274 out.write("catalog['%s'].getImage = get%sImage\n" % tuple([imgName] * 2))
275 out.write("catalog['%s'].getBitmap = get%sBitmap\n" % tuple([imgName] * 2))
276 if icon:
277 out.write("catalog['%s'].getIcon = get%sIcon\n" % tuple([imgName] * 2))
278 out.write("\n\n")
279
280
281 if imgName:
282 n_msg = ' using "%s"' % imgName
283 else:
284 n_msg = ""
285
286 if maskClr:
287 m_msg = " with mask %s" % maskClr
288 else:
289 m_msg = ""
290
291 print "Embedded %s%s into %s%s" % (image_file, n_msg, python_file, m_msg)
292 finally:
293 out.close()
294
295
296
297def main(args):
298 if not args or ("-h" in args):
299 print __doc__
300 return
301
302 append = DEFAULT_APPEND
303 compressed = DEFAULT_COMPRESSED
304 maskClr = DEFAULT_MASKCLR
305 imgName = DEFAULT_IMGNAME
306 icon = DEFAULT_ICON
307 catalog = DEFAULT_CATALOG
308
309 try:
310 opts, fileArgs = getopt.getopt(args, "auicn:m:")
311 except getopt.GetoptError:
312 print __doc__
313 return
314
315 for opt, val in opts:
316 if opt == "-a":
317 append = True
318 elif opt == "-u":
319 compressed = False
320 elif opt == "-n":
321 imgName = val
322 elif opt == "-m":
323 maskClr = val
324 elif opt == "-i":
325 icon = True
326 elif opt == "-c":
327 catalog = True
328
329 if len(fileArgs) != 2:
330 print __doc__
331 return
332
333 image_file, python_file = fileArgs
334 img2py(image_file, python_file, append, compressed, maskClr, imgName, icon, catalog)
335
336
337
338if __name__ == "__main__":
339 main(sys.argv[1:])