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