]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/tools/img2py.py
Docstring tweaks
[wxWidgets.git] / wxPython / wx / tools / img2py.py
CommitLineData
d14a1e28
RD
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#----------------------------------------------------------------------
d4b73b1b
RD
11# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
12#
13# o V2.5 compatability update
14#
1fded56b 15
1fded56b 16
d14a1e28
RD
17"""
18img2py.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
24Usage:
25
26 img2py.py [options] image_file python_file
27
28Options:
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#
d4b73b1b
RD
61# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
62#
63# o V2.5 compatability update
64#
65
66import cPickle
67import cStringIO
68import getopt
69import glob
70import os
71import sys
72import tempfile
73import zlib
d14a1e28 74
d4b73b1b 75import wx
d14a1e28 76
d4b73b1b 77import img2img
d14a1e28
RD
78
79
80def 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
128def 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...
d4b73b1b
RD
134 if wx.GetApp() is None:
135 app = wx.PySimpleApp()
d14a1e28
RD
136
137 append = 0
138 compressed = 1
139 maskClr = None
140 imgName = ""
141 icon = 0
142 catalog = 0
143
144 try:
145 opts, fileArgs = getopt.getopt(args, "auicn:m:")
146 except getopt.GetoptError:
147 print __doc__
148 return
149
150 for opt, val in opts:
151 if opt == "-a":
152 append = 1
153 elif opt == "-u":
154 compressed = 0
155 elif opt == "-n":
156 imgName = val
157 elif opt == "-m":
158 maskClr = val
159 elif opt == "-i":
160 icon = 1
161 elif opt == "-c":
162 catalog = 1
163
164 if len(fileArgs) != 2:
165 print __doc__
166 return
167
168 image_file, python_file = fileArgs
169
170 # convert the image file to a temporary file
171 tfname = tempfile.mktemp()
d4b73b1b 172 ok, msg = img2img.convert(image_file, maskClr, None, tfname, wx.BITMAP_TYPE_PNG, ".png")
d14a1e28
RD
173 if not ok:
174 print msg
175 return
176
177 data = open(tfname, "rb").read()
178 data = crunch_data(data, compressed)
179 os.unlink(tfname)
180
181 if append:
182 out = open(python_file, "a")
183 else:
184 out = open(python_file, "w")
185
186 if catalog:
187 pyPath, pyFile = os.path.split(python_file)
188 imgPath, imgFile = os.path.split(image_file)
189
190 if not imgName:
191 imgName = os.path.splitext(imgFile)[0]
192 print "\nWarning: -n not specified. Using filename (%s) for catalog entry." % imgName
193
194 old_index = []
195 if append:
196 # check to see if catalog exists already (file may have been created
197 # with an earlier version of img2py or without -c option)
198 oldSysPath = sys.path[:]
199 sys.path = [pyPath] # make sure we don't import something else by accident
200 mod = __import__(os.path.splitext(pyFile)[0])
201 if 'index' not in dir(mod):
202 print "\nWarning: %s was originally created without catalog." % python_file
203 print " Any images already in file will not be cataloged.\n"
204 out.write("\n# ***************** Catalog starts here *******************")
205 out.write("\n\ncatalog = {}\n")
206 out.write("index = []\n\n")
207 out.write("class ImageClass: pass\n\n")
208 else: # save a copy of the old index so we can warn about duplicate names
209 old_index[:] = mod.index[:]
210 del mod
211 sys.path = oldSysPath[:]
212
213 out.write("#" + "-" * 70 + "\n")
214 if not append:
215 out.write("# This file was generated by %s\n#\n" % sys.argv[0])
d4b73b1b 216 out.write("from wx import ImageFromStream, BitmapFromImage\n")
d14a1e28 217 if icon:
d4b73b1b 218 out.write("from wx import EmptyIcon\n")
d14a1e28
RD
219 if compressed:
220 out.write("import cStringIO, zlib\n\n\n")
221 else:
222 out.write("import cStringIO\n\n\n")
223
224 if catalog:
225 out.write("catalog = {}\n")
226 out.write("index = []\n\n")
227 out.write("class ImageClass: pass\n\n")
228
229 if compressed:
230 out.write("def get%sData():\n"
231 " return zlib.decompress(\n%s)\n\n"
232 % (imgName, data))
233 else:
234 out.write("def get%sData():\n"
235 " return \\\n%s\n\n"
236 % (imgName, data))
237
238
239 out.write("def get%sBitmap():\n"
d4b73b1b 240 " return BitmapFromImage(get%sImage())\n\n"
d14a1e28
RD
241 "def get%sImage():\n"
242 " stream = cStringIO.StringIO(get%sData())\n"
d4b73b1b 243 " return ImageFromStream(stream)\n\n"
d14a1e28
RD
244 % tuple([imgName] * 4))
245 if icon:
246 out.write("def get%sIcon():\n"
d4b73b1b 247 " icon = EmptyIcon()\n"
d14a1e28
RD
248 " icon.CopyFromBitmap(get%sBitmap())\n"
249 " return icon\n\n"
250 % tuple([imgName] * 2))
251
252 if catalog:
253 if imgName in old_index:
254 print "Warning: %s already in catalog." % imgName
255 print " Only the last entry will be accessible.\n"
256 old_index.append(imgName)
257 out.write("index.append('%s')\n" % imgName)
258 out.write("catalog['%s'] = ImageClass()\n" % imgName)
259 out.write("catalog['%s'].getData = get%sData\n" % tuple([imgName] * 2))
260 out.write("catalog['%s'].getImage = get%sImage\n" % tuple([imgName] * 2))
261 out.write("catalog['%s'].getBitmap = get%sBitmap\n" % tuple([imgName] * 2))
262 if icon:
263 out.write("catalog['%s'].getIcon = get%sIcon\n" % tuple([imgName] * 2))
264 out.write("\n\n")
265
266 if imgName:
267 n_msg = ' using "%s"' % imgName
268 else:
269 n_msg = ""
270 if maskClr:
271 m_msg = " with mask %s" % maskClr
272 else:
273 m_msg = ""
274 print "Embedded %s%s into %s%s" % (image_file, n_msg, python_file, m_msg)
275
276
277if __name__ == "__main__":
278 main(sys.argv[1:])
279