]>
Commit | Line | Data |
---|---|---|
96bfd053 RD |
1 | #!/usr/bin/env python |
2 | """ | |
3 | img2py.py -- Convert an image to XPM format and embed it in a Python | |
4 | module with appropriate code so it can be loaded into | |
5 | a program at runtime. The benefit is that since it is | |
6 | Python source code it can be delivered as a .pyc or | |
7 | 'compiled' into the program using freeze, py2exe, etc. | |
8 | ||
9 | Usage: | |
10 | ||
11 | img2py.py [options] image_file python_file | |
12 | ||
13 | Options: | |
14 | ||
15 | -m <#rrggbb> If the original image has a mask or transparency defined | |
16 | it will be used by default. You can use this option to | |
17 | override the default or provide a new mask by specifying | |
18 | a colour in the image to mark as transparent. | |
19 | ||
20 | -n <name> Normally generic names (getBitmap, etc.) are used for the | |
21 | image access functions. If you use this option you can | |
22 | specify a name that should be used to customize the access | |
23 | fucntions, (getNameBitmap, etc.) | |
24 | ||
25 | -a This flag specifies that the python_file should be appended | |
26 | to instead of overwritten. This in combination with -n will | |
27 | allow you to put multiple images in one Python source file. | |
28 | ||
29 | -u Don't use compression. Leaves the data uncompressed. | |
30 | ||
7fa0effc RD |
31 | -i Also output a function to return the image as a wxIcon. |
32 | ||
96bfd053 RD |
33 | """ |
34 | ||
35 | ||
36 | ||
7905ec55 | 37 | import sys, os, glob, getopt, tempfile, string |
96bfd053 RD |
38 | import cPickle, cStringIO, zlib |
39 | import img2xpm | |
40 | ||
41 | ||
42 | def crunch_data(data, compressed): | |
bae17009 | 43 | # convert the lines to a Python list, pickle it and optionally compress the result. |
96bfd053 | 44 | lines = [] |
7905ec55 RD |
45 | for line in data: |
46 | if line[0] == "\"": | |
47 | # the line is typically (but not always): | |
48 | # [quote] <data> [quote][comma][newline] | |
49 | ||
50 | # chop one char from the front | |
51 | line = line[1:] | |
52 | ||
53 | # now find the final quote and truncate there | |
54 | quote = string.rfind(line, "\"") | |
55 | ||
56 | # and append the remaining data to our list | |
57 | lines.append(line[:quote]) | |
96bfd053 | 58 | |
96bfd053 RD |
59 | |
60 | # pickle, crunch and convert it to a form suitable for embedding in code | |
61 | data = cPickle.dumps(lines) | |
62 | if compressed: | |
63 | data = zlib.compress(data, 9) | |
64 | data = repr(data) | |
65 | ||
66 | ||
67 | # This next bit is borrowed from PIL. It is used to wrap the text intelligently. | |
68 | fp = cStringIO.StringIO() | |
69 | data = data + " " # buffer for the +1 test | |
70 | c = i = 0 | |
71 | word = "" | |
72 | octdigits = "01234567" | |
286e2db6 | 73 | hexdigits = "0123456789abcdef" |
96bfd053 RD |
74 | while i < len(data): |
75 | if data[i] != "\\": | |
76 | word = data[i] | |
77 | i = i + 1 | |
78 | else: | |
79 | if data[i+1] in octdigits: | |
80 | for n in range(2, 5): | |
81 | if data[i+n] not in octdigits: | |
82 | break | |
83 | word = data[i:i+n] | |
84 | i = i + n | |
286e2db6 RD |
85 | elif data[i+1] == 'x': |
86 | for n in range(2, 5): | |
87 | if data[i+n] not in hexdigits: | |
88 | break | |
89 | word = data[i:i+n] | |
90 | i = i + n | |
96bfd053 RD |
91 | else: |
92 | word = data[i:i+2] | |
93 | i = i + 2 | |
286e2db6 | 94 | |
96bfd053 RD |
95 | l = len(word) |
96 | if c + l >= 78-1: | |
97 | fp.write("\\\n") | |
98 | c = 0 | |
99 | fp.write(word) | |
100 | c = c + l | |
101 | ||
102 | # return the formatted compressed data | |
103 | return fp.getvalue() | |
104 | ||
105 | ||
106 | ||
107 | def main(args): | |
108 | if not args or ("-h" in args): | |
109 | print __doc__ | |
110 | return | |
111 | ||
112 | append = 0 | |
113 | compressed = 1 | |
114 | maskClr = None | |
115 | imgName = "" | |
7fa0effc | 116 | icon = 0 |
96bfd053 RD |
117 | |
118 | try: | |
7fa0effc | 119 | opts, fileArgs = getopt.getopt(args, "auin:m:") |
96bfd053 RD |
120 | except getopt.GetoptError: |
121 | print __doc__ | |
122 | return | |
123 | ||
124 | for opt, val in opts: | |
125 | if opt == "-a": | |
126 | append = 1 | |
127 | elif opt == "-u": | |
128 | compressed = 0 | |
129 | elif opt == "-n": | |
130 | imgName = val | |
131 | elif opt == "-m": | |
132 | maskClr = val | |
7fa0effc RD |
133 | elif opt == "-i": |
134 | icon = 1 | |
96bfd053 RD |
135 | |
136 | if len(fileArgs) != 2: | |
137 | print __doc__ | |
138 | return | |
139 | ||
140 | image_file, python_file = fileArgs | |
141 | ||
142 | # convert the image file to a temporary file | |
143 | tfname = tempfile.mktemp() | |
144 | ok, msg = img2xpm.convert(image_file, maskClr, None, tfname) | |
145 | if not ok: | |
146 | print msg | |
147 | return | |
148 | ||
149 | data = open(tfname, "r").readlines() | |
150 | data = crunch_data(data, compressed) | |
151 | os.unlink(tfname) | |
152 | ||
153 | if append: | |
154 | out = open(python_file, "a") | |
155 | else: | |
156 | out = open(python_file, "w") | |
157 | ||
158 | out.write("#" + "-" * 70 + "\n") | |
159 | if not append: | |
160 | out.write("# This file was generated by %s\n#\n" % sys.argv[0]) | |
161 | out.write("from wxPython.wx import wxBitmapFromXPMData, wxImageFromBitmap\n") | |
7fa0effc RD |
162 | if icon: |
163 | out.write("from wxPython.wx import wxIconFromXPMData\n") | |
96bfd053 RD |
164 | if compressed: |
165 | out.write("import cPickle, zlib\n\n\n") | |
166 | else: | |
167 | out.write("import cPickle\n\n\n") | |
168 | ||
169 | if compressed: | |
170 | out.write("def get%sData():\n" | |
171 | " return cPickle.loads(zlib.decompress(\n%s))\n\n" | |
172 | % (imgName, data)) | |
173 | else: | |
174 | out.write("def get%sData():\n" | |
175 | " return cPickle.loads(\n%s)\n\n" | |
176 | % (imgName, data)) | |
177 | ||
178 | ||
179 | out.write("def get%sBitmap():\n" | |
180 | " return wxBitmapFromXPMData(get%sData())\n\n" | |
181 | "def get%sImage():\n" | |
182 | " return wxImageFromBitmap(get%sBitmap())\n\n" | |
183 | % tuple([imgName] * 4)) | |
7fa0effc RD |
184 | if icon: |
185 | out.write("def get%sIcon():\n" | |
186 | " return wxIconFromXPMData(get%sData())\n\n" | |
187 | % tuple([imgName] * 2)) | |
188 | ||
96bfd053 RD |
189 | |
190 | if imgName: | |
191 | n_msg = ' using "%s"' % imgName | |
192 | else: | |
193 | n_msg = "" | |
194 | if maskClr: | |
195 | m_msg = " with mask %s" % maskClr | |
196 | else: | |
197 | m_msg = "" | |
198 | print "Embedded %s%s into %s%s" % (image_file, n_msg, python_file, m_msg) | |
199 | ||
200 | ||
201 | if __name__ == "__main__": | |
202 | main(sys.argv[1:]) | |
203 | ||
204 | ||
205 | ||
206 | ||
207 |