source: subversion/applications/rendering/osmarender/static-osmarender/generate-tiles.pl @ 13324

Last change on this file since 13324 was 1560, checked in by nickburch, 13 years ago

Add a -h option, that prints out the readme

  • Property svn:executable set to *
File size: 7.0 KB
Line 
1#!/usr/bin/perl
2# A script for rendering OSM data through osmarender, spitting out
3#  tiles at various scales for it
4#
5
6use strict;
7
8# Read in parameters
9my $initial_dpi;
10my @osmarender_scales;
11my $filename;
12
13while(my $arg = shift) {
14        if($arg eq "-initial-dpi" || $arg eq "--initial-dpi" || $arg eq "-dpi") {
15                $initial_dpi = shift;
16        }
17        elsif($arg eq "-osmarender-scales" || $arg eq "--osmarender-scales" || $arg eq "-scales") {
18                @osmarender_scales = split(/,/, shift);
19        }
20        elsif($arg = "-h") {
21                print `cat README.txt`;
22                exit;
23        } else {
24                $filename = $arg;
25        }
26}
27
28unless($initial_dpi && @osmarender_scales && $filename) {
29        &help;
30        exit;
31}
32
33
34sub help {
35        print "Use:\n";
36        print "   osmarender-tiles.pl -initial-dpi <dpi> -osmarender-scales <scale,scale,scale> <filename.osm>\n";
37        print "\n";
38        print "   initial-dpi        DPI setting of most zoomed out image\n";
39        print "                       Select so as to give a ~500x500 image\n";
40        print "   osmarender-scales  List of osmrender scales as we zoom in\n";
41        print "                       eg 0.3,0.3,0.5,0.8,1\n";
42        print "   filename.osm       The .osm file to render\n";
43        exit;
44}
45
46
47# Do we have a copy of osmarender to hand?
48my $osmarender_dir;
49if(-d "osmarender") {
50        $osmarender_dir = "osmarender";
51} elsif(-f "osm-map-features.xml") {
52        $osmarender_dir = "."; 
53} else {
54        # SVN checkout
55        print "Fetching osmarender\n";
56        `svn co http://svn.openstreetmap.org/utils/osmarender`;
57        $osmarender_dir = "osmarender";
58}
59
60
61# Where are we putting things?
62my ($dir) = ($filename =~ /^.*\/(.*?)\.osm$/);
63unless($dir) { 
64        if(!($filename =~ /\//) && $filename =~ /\.osm$/) {
65                ($dir) = ($filename =~ /^(.*?)\.osm$/);
66        } else {
67                $dir = "output"; 
68        }
69}
70unless(-d $dir) { mkdir $dir; }
71print "Outputting tiles to $dir\n";
72
73# What are we going to use to make svgs?
74my $xslt;
75my $xslt_out;
76if(-f "/usr/share/java/xalan2.jar") {
77        $xslt = "java -jar /usr/share/java/xalan2.jar -in";
78        $xslt_out = "-out";
79} elsif(-f "/usr/share/java/xalan-j2.jar") {
80        $xslt_out = "-out";
81        $xslt = "java -jar /usr/share/java/xalan-j2.jar -in";
82} elsif(-f "/usr/bin/xsltproc") {
83        $xslt = "/usr/bin/xsltproc";
84        $xslt_out = "-o";
85} else {
86        die("No supported xslt program found\n");
87}
88
89
90# Generate the svgs for each scale they wanted
91my %svgs;
92foreach my $scale (@osmarender_scales) {
93        if($svgs{$scale}) { next; }
94        my $ofn = "/tmp/output-$scale.svg";
95        print "Generating SVG at scale $scale\n";
96
97        # Copy stuff to tmp
98        `cp $filename /tmp/data.osm`;
99        `cp $osmarender_dir/*.xml /tmp/`;
100        `cp $osmarender_dir/*.xsl /tmp/`;
101        `cp $osmarender_dir/*.png /tmp/`;
102
103        # Tweak osm-map-features
104        tweakMapFeatures($scale);
105
106        # Turn into svg
107        `cd /tmp/ && $xslt osm-map-features.xml $xslt_out $ofn`;
108
109        # Save the filename
110        $svgs{$scale} = $ofn;
111}
112
113
114# For each scale, rasterize the image at the required DPI
115my $dpi_scale = 0.5;
116my @master_pngs;
117foreach my $scale (@osmarender_scales) {
118        # Move to the next DPI
119        $dpi_scale = $dpi_scale * 2;
120        my $output_dpi = int($initial_dpi * $dpi_scale);
121
122        # Do we need to tweak the DPI, to stop the tiles being too big?
123        # (Caused by osmarender scaling effects)
124        # (The 0.65 is an empirical scale factor, should give ~ same widths)
125        $output_dpi = $output_dpi / (($scale / $osmarender_scales[0]) ** 0.65);
126       
127        # Round the output dpi
128        $output_dpi = int($output_dpi);
129
130        # Rasterize the .svg, at the required DPI
131        my $png = "$dir/$output_dpi.png";
132        print "Generating PNG for scale $scale at $output_dpi dpi\n";
133        print `inkscape -D -z -d $output_dpi -e $png $svgs{$scale} 2>&1`;
134        print "Generated $png\n\n";
135        push @master_pngs, $png;
136}
137
138
139# Output some javascript to help the display program
140open(JS, "> $dir/information.js");
141print JS "var scales = ".scalar(@osmarender_scales).";\n";
142print JS "var tiles_in_dir = new Array();\n";
143print JS "var tile_widths = new Array();\n";
144print JS "var tile_heights = new Array();\n";
145
146
147# Now, generate tiles from the master PNGs
148#  (To zoom out, decrease the scale by 1, and halve the tile x+y)
149#  (To zoom in, increase the scale by 1, and double the tile x+y)
150# Start with 2x2 at the highest zoom
151my $oscale = 0;
152foreach my $scale (@osmarender_scales) {
153        $oscale++;
154        my $tscale = 2 ** ($oscale);
155
156        my $odir = "$dir/scale-$oscale";
157        unless(-d $odir) { mkdir $odir; }
158        my $png = $master_pngs[($oscale-1)];
159
160        # How many does the master png need to go into?
161        my $tiles = $tscale * $tscale;
162
163        # And how big is the image?
164        my $identify = `identify $png`;
165        my ($width,$height) = ($identify =~ /PNG (\d+)x(\d+) /);
166        my $tilewidth = int($width / $tscale);
167        my $tileheight = int($height / $tscale);
168        my $cropwidth = $tilewidth * $tscale;
169        my $cropheight = $tileheight * $tscale;
170        unless($width && $height) {
171                die("Couldn't make sense of identify output '$identify',\nso don't know how big things are\n");
172        }
173
174        print "\n";
175        print "Generating tile images in $odir for scale $scale from $png\n";
176
177        # Save the sizes for the javascript
178        print JS "\n";
179        print JS "tiles_in_dir[$oscale] = $tscale;\n";
180        print JS "tile_widths[$oscale] = $tilewidth;\n";
181        print JS "tile_heights[$oscale] = $tileheight;\n";
182
183        # Now, have it split into handy tiles
184        # Makes one call to vips per tile, which isn't ideal, but at least
185        #  it doesn't die / use lots of memory / break like "convert -crop" does
186        #       
187        # We want the tiles to be to be <updown>x<leftright>.png
188        print "Splitting into $tiles tiles of ${tilewidth}x${tileheight}:\n";
189        if($tscale == 1) {
190                `cp $png $odir/tile-1x1.png`;
191        } else {
192                for(my $i=0; $i<$tscale; $i++) {
193                        for(my $j=0; $j<$tscale; $j++) {
194                                my $tileid = ($i+1)."x".($j+1);
195                                my $otile = $odir."/tile-".$tileid.".png";
196
197                                my $toffset = $i * $tileheight;
198                                my $loffset = $j * $tilewidth;
199
200                                print "  Producing $tileid of ${tscale}x${tscale} - offset is ${loffset}x${toffset}\n";
201                                print `vips im_extract_area $png $otile $loffset $toffset $tilewidth $tileheight`;
202                        }
203                }
204        }
205
206        # Remove the large image, we no longer need it
207        unlink $png;
208
209        print "Finished generating $tiles tiles\n";
210}
211
212
213# Finish the javascript
214close JS;
215
216# Copy in the display html
217`cp display.html $dir/index.html`;
218
219print "\n\nTile generation complete\n";
220
221
222
223##########################################################################
224
225
226# To tweak map features to have the right settings
227sub tweakMapFeatures {
228        my $scale = shift;
229
230        open(OSM, "</tmp/osm-map-features.xml");
231        my $omf;
232        while(<OSM>) { $omf .= $_; }
233        close OSM;
234
235        $omf =~ s/^\s*scale=".*?"/scale="$scale"/m;
236
237        $omf =~ s/^\s*showScale=".*?"/showScale="no"/m;
238        $omf =~ s/^\s*showGrid=".*?"/showGrid="no"/m;
239        $omf =~ s/^\s*showBorder=".*?"/showBorder="no"/m;
240        $omf =~ s/^\s*showAttribution=".*?"/showAttribution="no"/m;
241        $omf =~ s/^\s*showLicense=".*?"/showLicense="no"/m;
242        $omf =~ s/^\s*showZoomControls=".*?"/showZoomControls="no"/m;
243        $omf =~ s/^\s*javaScript=".*?"/javaScript="no"/m;
244
245        open(OSM, ">/tmp/osm-map-features.xml");
246        print OSM $omf;
247        close OSM;
248}
249
250__END__
251
252=head1 NAME
253
254B<generate-tiles.pl>
255
256=head1 DESCRIPTION
257
258Please Fill in
259
260=head1 SYNOPSIS
261
262Please Fill in
263
264=head1 OPTIONS
265
266Please Fill in
267=head1 COPYRIGHT
268
269Please Fill in
270
271=head1 AUTHOR
272
273Please Fill in
274
275=head1 SEE ALSO
276
277http://www.openstreetmap.org/
278
279=cut
Note: See TracBrowser for help on using the repository browser.