source: subversion/applications/rendering/parking/mapnik/mapnik_to_bw.py @ 27686

Last change on this file since 27686 was 27545, checked in by kdrangmeister, 8 years ago

Removed CssParameters? for mapnik 2.0

File size: 11.4 KB
Line 
1# -*- coding: utf-8 -*-
2# by kay
3
4import sys,os,subprocess
5from optparse import OptionParser
6#from xml.dom.minidom import parse, parseString
7import pxdom
8#import colorsys
9
10simple_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
157def 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
170def 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
188def 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
192def 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
202def 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
236def 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
252def 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
259def 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
283def strip_doctype(f):
284    p = subprocess.Popen(['sed','-i','2,5 d',f]) # -i means 'in place'
285    p.wait()
286
287def 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
297def 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
305def 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
333if __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)
Note: See TracBrowser for help on using the repository browser.