1 | # -*- coding: utf-8 -*- |
---|
2 | # by kay |
---|
3 | |
---|
4 | import sys,os,subprocess |
---|
5 | from optparse import OptionParser |
---|
6 | #from xml.dom.minidom import parse, parseString |
---|
7 | import pxdom |
---|
8 | #import colorsys |
---|
9 | |
---|
10 | simple_colors = { |
---|
11 | 'aliceblue': 'f0f8ff', |
---|
12 | 'antiquewhite': 'faebd7', |
---|
13 | 'aqua': '00ffff', |
---|
14 | 'aquamarine': '7fffd4', |
---|
15 | 'azure': 'f0ffff', |
---|
16 | 'beige': 'f5f5dc', |
---|
17 | 'bisque': 'ffe4c4', |
---|
18 | 'black': '000000', |
---|
19 | 'blanchedalmond': 'ffebcd', |
---|
20 | 'blue': '0000ff', |
---|
21 | 'blueviolet': '8a2be2', |
---|
22 | 'brown': 'a52a2a', |
---|
23 | 'burlywood': 'deb887', |
---|
24 | 'cadetblue': '5f9ea0', |
---|
25 | 'chartreuse': '7fff00', |
---|
26 | 'chocolate': 'd2691e', |
---|
27 | 'coral': 'ff7f50', |
---|
28 | 'cornflowerblue': '6495ed', |
---|
29 | 'cornsilk': 'fff8dc', |
---|
30 | 'crimson': 'dc143c', |
---|
31 | 'cyan': '00ffff', |
---|
32 | 'darkblue': '00008b', |
---|
33 | 'darkcyan': '008b8b', |
---|
34 | 'darkgoldenrod': 'b8860b', |
---|
35 | 'darkgray': 'a9a9a9', |
---|
36 | 'darkgreen': '006400', |
---|
37 | 'darkkhaki': 'bdb76b', |
---|
38 | 'darkmagenta': '8b008b', |
---|
39 | 'darkolivegreen': '556b2f', |
---|
40 | 'darkorange': 'ff8c00', |
---|
41 | 'darkorchid': '9932cc', |
---|
42 | 'darkred': '8b0000', |
---|
43 | 'darksalmon': 'e9967a', |
---|
44 | 'darkseagreen': '8fbc8f', |
---|
45 | 'darkslateblue': '483d8b', |
---|
46 | 'darkslategray': '2f4f4f', |
---|
47 | 'darkturquoise': '00ced1', |
---|
48 | 'darkviolet': '9400d3', |
---|
49 | 'deeppink': 'ff1493', |
---|
50 | 'deepskyblue': '00bfff', |
---|
51 | 'dimgray': '696969', |
---|
52 | 'dodgerblue': '1e90ff', |
---|
53 | 'feldspar': 'd19275', |
---|
54 | 'firebrick': 'b22222', |
---|
55 | 'floralwhite': 'fffaf0', |
---|
56 | 'forestgreen': '228b22', |
---|
57 | 'fuchsia': 'ff00ff', |
---|
58 | 'gainsboro': 'dcdcdc', |
---|
59 | 'ghostwhite': 'f8f8ff', |
---|
60 | 'gold': 'ffd700', |
---|
61 | 'goldenrod': 'daa520', |
---|
62 | 'gray': '808080', |
---|
63 | 'green': '008000', |
---|
64 | 'greenyellow': 'adff2f', |
---|
65 | 'grey': '808080', |
---|
66 | 'honeydew': 'f0fff0', |
---|
67 | 'hotpink': 'ff69b4', |
---|
68 | 'indianred ': 'cd5c5c', |
---|
69 | 'indigo ': '4b0082', |
---|
70 | 'ivory': 'fffff0', |
---|
71 | 'khaki': 'f0e68c', |
---|
72 | 'lavender': 'e6e6fa', |
---|
73 | 'lavenderblush': 'fff0f5', |
---|
74 | 'lawngreen': '7cfc00', |
---|
75 | 'lemonchiffon': 'fffacd', |
---|
76 | 'lightblue': 'add8e6', |
---|
77 | 'lightcoral': 'f08080', |
---|
78 | 'lightcyan': 'e0ffff', |
---|
79 | 'lightgoldenrodyellow': 'fafad2', |
---|
80 | 'lightgrey': 'd3d3d3', |
---|
81 | 'lightgreen': '90ee90', |
---|
82 | 'lightpink': 'ffb6c1', |
---|
83 | 'lightsalmon': 'ffa07a', |
---|
84 | 'lightseagreen': '20b2aa', |
---|
85 | 'lightskyblue': '87cefa', |
---|
86 | 'lightslateblue': '8470ff', |
---|
87 | 'lightslategray': '778899', |
---|
88 | 'lightsteelblue': 'b0c4de', |
---|
89 | 'lightyellow': 'ffffe0', |
---|
90 | 'lime': '00ff00', |
---|
91 | 'limegreen': '32cd32', |
---|
92 | 'linen': 'faf0e6', |
---|
93 | 'magenta': 'ff00ff', |
---|
94 | 'maroon': '800000', |
---|
95 | 'mediumaquamarine': '66cdaa', |
---|
96 | 'mediumblue': '0000cd', |
---|
97 | 'mediumorchid': 'ba55d3', |
---|
98 | 'mediumpurple': '9370d8', |
---|
99 | 'mediumseagreen': '3cb371', |
---|
100 | 'mediumslateblue': '7b68ee', |
---|
101 | 'mediumspringgreen': '00fa9a', |
---|
102 | 'mediumturquoise': '48d1cc', |
---|
103 | 'mediumvioletred': 'c71585', |
---|
104 | 'midnightblue': '191970', |
---|
105 | 'mintcream': 'f5fffa', |
---|
106 | 'mistyrose': 'ffe4e1', |
---|
107 | 'moccasin': 'ffe4b5', |
---|
108 | 'navajowhite': 'ffdead', |
---|
109 | 'navy': '000080', |
---|
110 | 'oldlace': 'fdf5e6', |
---|
111 | 'olive': '808000', |
---|
112 | 'olivedrab': '6b8e23', |
---|
113 | 'orange': 'ffa500', |
---|
114 | 'orangered': 'ff4500', |
---|
115 | 'orchid': 'da70d6', |
---|
116 | 'palegoldenrod': 'eee8aa', |
---|
117 | 'palegreen': '98fb98', |
---|
118 | 'paleturquoise': 'afeeee', |
---|
119 | 'palevioletred': 'd87093', |
---|
120 | 'papayawhip': 'ffefd5', |
---|
121 | 'peachpuff': 'ffdab9', |
---|
122 | 'peru': 'cd853f', |
---|
123 | 'pink': 'ffc0cb', |
---|
124 | 'plum': 'dda0dd', |
---|
125 | 'powderblue': 'b0e0e6', |
---|
126 | 'purple': '800080', |
---|
127 | 'red': 'ff0000', |
---|
128 | 'rosybrown': 'bc8f8f', |
---|
129 | 'royalblue': '4169e1', |
---|
130 | 'saddlebrown': '8b4513', |
---|
131 | 'salmon': 'fa8072', |
---|
132 | 'sandybrown': 'f4a460', |
---|
133 | 'seagreen': '2e8b57', |
---|
134 | 'seashell': 'fff5ee', |
---|
135 | 'sienna': 'a0522d', |
---|
136 | 'silver': 'c0c0c0', |
---|
137 | 'skyblue': '87ceeb', |
---|
138 | 'slateblue': '6a5acd', |
---|
139 | 'slategray': '708090', |
---|
140 | 'snow': 'fffafa', |
---|
141 | 'springgreen': '00ff7f', |
---|
142 | 'steelblue': '4682b4', |
---|
143 | 'tan': 'd2b48c', |
---|
144 | 'teal': '008080', |
---|
145 | 'thistle': 'd8bfd8', |
---|
146 | 'tomato': 'ff6347', |
---|
147 | 'turquoise': '40e0d0', |
---|
148 | 'violet': 'ee82ee', |
---|
149 | 'violetred': 'd02090', |
---|
150 | 'wheat': 'f5deb3', |
---|
151 | 'white': 'ffffff', |
---|
152 | 'whitesmoke': 'f5f5f5', |
---|
153 | 'yellow': 'ffff00', |
---|
154 | 'yellowgreen': '9acd32' |
---|
155 | } |
---|
156 | |
---|
157 | def color_to_bw(rgb): |
---|
158 | r,g,b=rgb |
---|
159 | #method 1: |
---|
160 | #y = 0.229*r + 0.587*g + 0.114*b |
---|
161 | y = 0.25*r + 0.62*g + 0.13*b |
---|
162 | return (y,y,y) |
---|
163 | """ |
---|
164 | #method 2: |
---|
165 | h,l,s = colorsys.rgb_to_hls(r, g, b) |
---|
166 | s *= 0 # desaturate |
---|
167 | return colorsys.hls_to_rgb(h,l,s) |
---|
168 | """ |
---|
169 | |
---|
170 | def parse_color(s): |
---|
171 | """ Parses color string in format #ABC or #AABBCC to RGB tuple. """ |
---|
172 | s = s.lower() |
---|
173 | if simple_colors.has_key(s): # translate color names to rgb |
---|
174 | s = '#'+simple_colors.get(s) |
---|
175 | l = len(s) |
---|
176 | assert(l in (4,7)) |
---|
177 | # print "s=",s |
---|
178 | if l==4: |
---|
179 | return tuple(int(ch * 2, 16)/255.0 for ch in s[1:]) |
---|
180 | else: |
---|
181 | return tuple(int(ch1 + ch2, 16)/255.0 for ch1, ch2 in \ |
---|
182 | zip( |
---|
183 | (ch1 for ch1 in s[1::2]), |
---|
184 | (ch2 for ch2 in s[2::2]) |
---|
185 | ) |
---|
186 | ) |
---|
187 | |
---|
188 | def rgb_to_css(rgb): |
---|
189 | r,g,b=rgb |
---|
190 | return "#{r:02x}{g:02x}{b:02x}".format(r=int(r*255.0),g=int(g*255.0),b=int(b*255.0)) |
---|
191 | |
---|
192 | def element_convert_attibute_to_grey(document,elementName,attributeName): |
---|
193 | els = document.getElementsByTagName(elementName) |
---|
194 | for el in els: |
---|
195 | col = el.getAttribute(attributeName) |
---|
196 | assert(col!='') |
---|
197 | assert(col!=None) |
---|
198 | bw=rgb_to_css(color_to_bw(parse_color(col))) |
---|
199 | #print "converted {ele}:{att} from {a} to {bw}." .format(ele=elementName,att=attributeName,a=col,bw=bw) |
---|
200 | el.setAttribute(attributeName,bw) |
---|
201 | |
---|
202 | def dom_convert_to_grey(document): |
---|
203 | element_convert_attibute_to_grey(document,"Map","background-color") |
---|
204 | """ vorher: CssParameter fuer die Farben bei LineSymbolizer und PolygonSymbolizer |
---|
205 | els = document.getElementsByTagName("CssParameter") |
---|
206 | #print "els=",els |
---|
207 | for el in els: |
---|
208 | at = el.getAttribute("name") |
---|
209 | if at=="stroke" or at=="fill": |
---|
210 | col=el.firstChild.nodeValue |
---|
211 | bw=rgb_to_css(color_to_bw(parse_color(col))) |
---|
212 | #print "converted {typ} from {a} to {bw}." .format(typ=at,a=col,bw=bw) |
---|
213 | el.firstChild.nodeValue=bw |
---|
214 | """ |
---|
215 | element_convert_attibute_to_grey(document,"LineSymbolizer","stroke") |
---|
216 | element_convert_attibute_to_grey(document,"PolygonSymbolizer","fill") |
---|
217 | |
---|
218 | #<TextSymbolizer ... fill="#6699cc"/> |
---|
219 | els = document.getElementsByTagName("TextSymbolizer") |
---|
220 | for el in els: |
---|
221 | col = el.getAttribute("fill") |
---|
222 | assert(col!='') |
---|
223 | assert(col!=None) |
---|
224 | bw=rgb_to_css(color_to_bw(parse_color(col))) |
---|
225 | #print "converted {typ} from {a} to {bw}." .format(typ='TS-fill',a=col,bw=bw) |
---|
226 | el.setAttribute("fill",bw) |
---|
227 | #<TextSymbolizer halo-fill="#fed7a5"/> (optional) |
---|
228 | col = el.getAttribute("halo-fill") |
---|
229 | assert(col!=None) |
---|
230 | if col!='': |
---|
231 | bw=rgb_to_css(color_to_bw(parse_color(col))) |
---|
232 | #print "converted {typ} from {a} to {bw}." .format(typ='TS-halo-fill',a=col,bw=bw) |
---|
233 | el.setAttribute("halo-fill",bw) |
---|
234 | |
---|
235 | |
---|
236 | def dom_strip_style_and_layer(document,stylename,layername): |
---|
237 | removeElements=[] |
---|
238 | # remove <Style name="points"> and <Layer name="amenity-points"> |
---|
239 | els = document.getElementsByTagName("Style") |
---|
240 | for el in els: |
---|
241 | if el.getAttribute("name")==stylename: |
---|
242 | removeElements.append(el) |
---|
243 | els = document.getElementsByTagName("Layer") |
---|
244 | for el in els: |
---|
245 | if el.getAttribute("name")==layername: |
---|
246 | removeElements.append(el) |
---|
247 | print removeElements |
---|
248 | for el in removeElements: |
---|
249 | parent = el.parentNode |
---|
250 | parent.removeChild(el) |
---|
251 | |
---|
252 | def dom_strip_icons(document): |
---|
253 | dom_strip_style_and_layer(document,"points","amenity-points") |
---|
254 | dom_strip_style_and_layer(document,"power_line","power_line") |
---|
255 | dom_strip_style_and_layer(document,"power_minorline","power_minorline") |
---|
256 | dom_strip_style_and_layer(document,"power_towers","power_towers") |
---|
257 | dom_strip_style_and_layer(document,"power_poles","power_poles") |
---|
258 | |
---|
259 | def transmogrify_file(sf,dfgrey,dfnoicons): |
---|
260 | dom= pxdom.getDOMImplementation('') |
---|
261 | parser= dom.createLSParser(dom.MODE_SYNCHRONOUS, None) |
---|
262 | parser.domConfig.setParameter('entities', 0) # 1 -> exception if attribute values is set |
---|
263 | #parser.domConfig.setParameter('disallow-doctype', 1) |
---|
264 | parser.domConfig.setParameter('pxdom-resolve-resources', 1) # 1 -> replace &xyz; with text |
---|
265 | document = parser.parseURI(sf) |
---|
266 | |
---|
267 | dom_convert_to_grey(document) |
---|
268 | |
---|
269 | output= document.implementation.createLSOutput() |
---|
270 | output.systemId= dfgrey |
---|
271 | output.encoding= 'utf-8' |
---|
272 | serialiser= document.implementation.createLSSerializer() |
---|
273 | serialiser.write(document, output) |
---|
274 | |
---|
275 | dom_strip_icons(document) |
---|
276 | |
---|
277 | output= document.implementation.createLSOutput() |
---|
278 | output.systemId= dfnoicons |
---|
279 | output.encoding= 'utf-8' |
---|
280 | serialiser= document.implementation.createLSSerializer() |
---|
281 | serialiser.write(document, output) |
---|
282 | |
---|
283 | def strip_doctype(f): |
---|
284 | p = subprocess.Popen(['sed','-i','2,5 d',f]) # -i means 'in place' |
---|
285 | p.wait() |
---|
286 | |
---|
287 | def convert_icons_to_bw(source_symbols_dir,dest_symbols_dir): |
---|
288 | image_files = os.listdir(source_symbols_dir) |
---|
289 | image_files = [f for f in image_files if f.endswith('png')] |
---|
290 | for f in image_files: |
---|
291 | # convert ./original-mapnik/symbols/*.png -fx '0.25*r + 0.62*g + 0.13*b' ./bw-mapnik/symbols/*.png |
---|
292 | sf = os.path.join(source_symbols_dir,f) |
---|
293 | df = os.path.join(dest_symbols_dir,f) |
---|
294 | p = subprocess.Popen(['convert',sf,'-fx','0.25*r + 0.62*g + 0.13*b',df]) |
---|
295 | p.wait() |
---|
296 | |
---|
297 | def add_license_files(dirname): |
---|
298 | f = open(os.path.join(dirname,"CONTACT"), 'w') |
---|
299 | f.write("This style is created by kayd@toolserver.org") |
---|
300 | f.close |
---|
301 | f = open(os.path.join(dirname,"LICENSE"), 'w') |
---|
302 | f.write("This derived work is published by the author, Kay Drangmeister, under the same license as the original OSM mapnik style sheet (found here: http://svn.openstreetmap.org/applications/rendering/mapnik)") |
---|
303 | f.close |
---|
304 | |
---|
305 | def main(options): |
---|
306 | source_dir = options['sourcedir'] |
---|
307 | source_file = options['sourcefile'] |
---|
308 | source_symbols_dir = os.path.join(source_dir,"symbols") |
---|
309 | dest_dir = options['destdir'] |
---|
310 | |
---|
311 | dest_dir_bw = os.path.join(dest_dir,"bw-mapnik") |
---|
312 | dest_dir_bw_symbols = os.path.join(dest_dir_bw,"symbols") |
---|
313 | dest_file_bw = 'osm-bw.xml' |
---|
314 | bw_file = os.path.join(dest_dir_bw,dest_file_bw) |
---|
315 | if not os.path.exists(dest_dir_bw_symbols): |
---|
316 | os.makedirs(dest_dir_bw_symbols) |
---|
317 | |
---|
318 | dest_dir_bw_noicons = os.path.join(dest_dir,"bw-noicons") |
---|
319 | dest_dir_bw_noicons_symbols = os.path.join(dest_dir_bw_noicons,"symbols") |
---|
320 | dest_file_bw_noicons = 'osm-bw-noicons.xml' |
---|
321 | bw_noicons_file = os.path.join(dest_dir_bw_noicons,dest_file_bw_noicons) |
---|
322 | if not os.path.exists(dest_dir_bw_noicons_symbols): |
---|
323 | os.makedirs(dest_dir_bw_noicons_symbols) |
---|
324 | |
---|
325 | convert_icons_to_bw(source_symbols_dir,dest_dir_bw_symbols) |
---|
326 | convert_icons_to_bw(source_symbols_dir,dest_dir_bw_noicons_symbols) |
---|
327 | transmogrify_file(os.path.join(source_dir,source_file),bw_file,bw_noicons_file) |
---|
328 | strip_doctype(bw_file) |
---|
329 | strip_doctype(bw_noicons_file) |
---|
330 | add_license_files(dest_dir_bw) |
---|
331 | add_license_files(dest_dir_bw_noicons) |
---|
332 | |
---|
333 | if __name__ == '__main__': |
---|
334 | parser = OptionParser() |
---|
335 | parser.add_option("-s", "--sourcedir", dest="sourcedir", help="path to the source directory", default=".") |
---|
336 | parser.add_option("-f", "--sourcefile", dest="sourcefile", help="source filename, default is 'osm.xml')", default="osm.xml") |
---|
337 | parser.add_option("-d", "--destdir", dest="destdir", help="path to the destination directory, further dirs are created within. default is '/tmp'", default="/tmp") |
---|
338 | (options, args) = parser.parse_args() |
---|
339 | print options |
---|
340 | main(options.__dict__) |
---|
341 | sys.exit(0) |
---|