source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/RenderingCLI.java@ 14120

Last change on this file since 14120 was 14120, checked in by Don-vip, 6 years ago

see #15229 - deprecate all Main methods related to projections. New ProjectionRegistry class

File size: 26.7 KB
RevLine 
[12906]1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
[12963]6import java.awt.Dimension;
[12966]7import java.awt.image.BufferedImage;
8import java.io.File;
[12906]9import java.io.FileNotFoundException;
10import java.io.IOException;
[13204]11import java.nio.file.Files;
12import java.nio.file.Paths;
[12906]13import java.util.ArrayList;
14import java.util.List;
15import java.util.Locale;
16import java.util.Optional;
[13849]17import java.util.function.DoubleSupplier;
[12906]18import java.util.logging.Level;
19
[12966]20import javax.imageio.ImageIO;
21
[12906]22import org.openstreetmap.gui.jmapviewer.OsmMercator;
[14118]23import org.openstreetmap.josm.cli.CLIModule;
[12906]24import org.openstreetmap.josm.data.Bounds;
25import org.openstreetmap.josm.data.ProjectionBounds;
26import org.openstreetmap.josm.data.coor.EastNorth;
27import org.openstreetmap.josm.data.coor.LatLon;
28import org.openstreetmap.josm.data.coor.conversion.LatLonParser;
29import org.openstreetmap.josm.data.osm.DataSet;
[13021]30import org.openstreetmap.josm.data.preferences.JosmBaseDirectories;
[14119]31import org.openstreetmap.josm.data.preferences.JosmUrls;
[12906]32import org.openstreetmap.josm.data.projection.Projection;
[14120]33import org.openstreetmap.josm.data.projection.ProjectionRegistry;
[12906]34import org.openstreetmap.josm.data.projection.Projections;
[12963]35import org.openstreetmap.josm.gui.mappaint.RenderingHelper.StyleData;
[12906]36import org.openstreetmap.josm.io.IllegalDataException;
37import org.openstreetmap.josm.io.OsmReader;
38import org.openstreetmap.josm.spi.preferences.Config;
39import org.openstreetmap.josm.spi.preferences.MemoryPreferences;
[13050]40import org.openstreetmap.josm.tools.I18n;
41import org.openstreetmap.josm.tools.JosmDecimalFormatSymbolsProvider;
[12906]42import org.openstreetmap.josm.tools.Logging;
43import org.openstreetmap.josm.tools.RightAndLefthandTraffic;
44
45import gnu.getopt.Getopt;
46import gnu.getopt.LongOpt;
47
48/**
49 * Command line interface for rendering osm data to an image file.
50 *
51 * @since 12906
52 */
53public class RenderingCLI implements CLIModule {
54
55 /**
56 * The singleton instance of this class.
57 */
58 public static final RenderingCLI INSTANCE = new RenderingCLI();
59
60 private static final double PIXEL_PER_METER = 96 / 2.54 * 100; // standard value of 96 dpi display resolution
61 private static final int DEFAULT_MAX_IMAGE_SIZE = 20000;
62
63 private boolean argDebug;
64 private boolean argTrace;
65 private String argInput;
66 private String argOutput;
67 private List<StyleData> argStyles;
68 private Integer argZoom;
69 private Double argScale;
70 private Bounds argBounds;
71 private LatLon argAnchor;
72 private Double argWidthM;
73 private Double argHeightM;
74 private Integer argWidthPx;
75 private Integer argHeightPx;
76 private String argProjection;
77 private Integer argMaxImageSize;
78
79 private enum Option {
80 HELP(false, 'h'),
81 DEBUG(false, '*'),
82 TRACE(false, '*'),
83 INPUT(true, 'i'),
84 STYLE(true, 's'),
85 SETTING(true, '*'),
86 OUTPUT(true, 'o'),
87 ZOOM(true, 'z'),
88 SCALE(true, '*'),
89 BOUNDS(true, 'b'),
90 ANCHOR(true, '*'),
91 WIDTH_M(true, '*'),
92 HEIGHT_M(true, '*'),
93 WIDTH_PX(true, '*'),
94 HEIGHT_PX(true, '*'),
95 PROJECTION(true, '*'),
96 MAX_IMAGE_SIZE(true, '*');
97
98 private final String name;
99 private final boolean requiresArg;
100 private final char shortOption;
101
102 Option(boolean requiresArgument, char shortOption) {
103 this.name = name().toLowerCase(Locale.US).replace('_', '-');
104 this.requiresArg = requiresArgument;
105 this.shortOption = shortOption;
106 }
107
108 /**
109 * Replies the option name
110 * @return The option name, in lowercase
111 */
112 public String getName() {
113 return name;
114 }
115
116 /**
117 * Determines if this option requires an argument.
118 * @return {@code true} if this option requires an argument, {@code false} otherwise
119 */
120 public boolean requiresArgument() {
121 return requiresArg;
122 }
123
124 /**
125 * Replies the short option (single letter) associated with this option.
126 * @return the short option or '*' if there is no short option
127 */
128 public char getShortOption() {
129 return shortOption;
130 }
131
132 LongOpt toLongOpt() {
133 return new LongOpt(getName(), requiresArgument() ? LongOpt.REQUIRED_ARGUMENT : LongOpt.NO_ARGUMENT, null, getShortOption());
134 }
135 }
136
137 /**
138 * Data class to hold return values for {@link #determineRenderingArea(DataSet)}.
139 *
140 * Package private access for unit tests.
141 */
142 static class RenderingArea {
143 public Bounds bounds;
144 public double scale; // in east-north units per pixel (unlike the --scale option, which is in meter per meter)
145 }
146
147 RenderingCLI() {
148 // hide constructor (package private access for unit tests)
149 }
150
151 @Override
152 public String getActionKeyword() {
153 return "render";
154 }
155
156 @Override
157 public void processArguments(String[] argArray) {
158 try {
159 parseArguments(argArray);
160 initialize();
[12963]161 DataSet ds = loadDataset();
162 RenderingArea area = determineRenderingArea(ds);
163 RenderingHelper rh = new RenderingHelper(ds, area.bounds, area.scale, argStyles);
164 checkPreconditions(rh);
[12966]165 BufferedImage image = rh.render();
166 writeImageToFile(image);
[12906]167 } catch (FileNotFoundException e) {
168 if (Logging.isDebugEnabled()) {
169 e.printStackTrace();
170 }
171 System.err.println(tr("Error - file not found: ''{0}''", e.getMessage()));
172 System.exit(1);
173 } catch (IllegalArgumentException | IllegalDataException | IOException e) {
174 if (Logging.isDebugEnabled()) {
175 e.printStackTrace();
176 }
177 if (e.getMessage() != null) {
178 System.err.println(tr("Error: {0}", e.getMessage()));
179 }
180 System.exit(1);
181 }
182 System.exit(0);
183 }
184
185 /**
186 * Parse command line arguments and do some low-level error checking.
187 * @param argArray the arguments array
188 */
189 void parseArguments(String[] argArray) {
190 Getopt.setI18nHandler(I18n::tr);
191 Logging.setLogLevel(Level.INFO);
192
193 LongOpt[] opts = new LongOpt[Option.values().length];
194 StringBuilder optString = new StringBuilder();
195 for (Option o : Option.values()) {
196 opts[o.ordinal()] = o.toLongOpt();
197 if (o.getShortOption() != '*') {
198 optString.append(o.getShortOption());
199 if (o.requiresArgument()) {
200 optString.append(':');
201 }
202 }
203 }
204
205 Getopt getopt = new Getopt("JOSM rendering", argArray, optString.toString(), opts);
206
207 StyleData currentStyle = new StyleData();
208 argStyles = new ArrayList<>();
209
210 int c;
211 while ((c = getopt.getopt()) != -1) {
212 switch (c) {
213 case 'h':
214 showHelp();
215 System.exit(0);
216 case 'i':
217 argInput = getopt.getOptarg();
218 break;
219 case 's':
220 if (currentStyle.styleUrl != null) {
221 argStyles.add(currentStyle);
222 currentStyle = new StyleData();
223 }
224 currentStyle.styleUrl = getopt.getOptarg();
225 break;
226 case 'o':
227 argOutput = getopt.getOptarg();
228 break;
229 case 'z':
230 try {
[13399]231 argZoom = Integer.valueOf(getopt.getOptarg());
[12906]232 } catch (NumberFormatException nfe) {
233 throw new IllegalArgumentException(
[13207]234 tr("Expected integer number for option {0}, but got ''{1}''", "--zoom", getopt.getOptarg()), nfe);
[12906]235 }
236 if (argZoom < 0)
237 throw new IllegalArgumentException(
238 tr("Expected integer number >= 0 for option {0}, but got ''{1}''", "--zoom", getopt.getOptarg()));
239 break;
240 case 'b':
[13849]241 if (!"auto".equals(getopt.getOptarg())) {
[12906]242 try {
243 argBounds = new Bounds(getopt.getOptarg(), ",", Bounds.ParseMethod.LEFT_BOTTOM_RIGHT_TOP, false);
[12907]244 } catch (IllegalArgumentException iae) { // NOPMD
[13207]245 throw new IllegalArgumentException(tr("Unable to parse {0} parameter: {1}", "--bounds", iae.getMessage()), iae);
[12906]246 }
247 }
248 break;
249 case '*':
250 switch (Option.values()[getopt.getLongind()]) {
251 case DEBUG:
252 argDebug = true;
253 break;
254 case TRACE:
255 argTrace = true;
256 break;
257 case SETTING:
258 String keyval = getopt.getOptarg();
259 String[] comp = keyval.split(":");
260 if (comp.length != 2)
261 throw new IllegalArgumentException(
262 tr("Expected key and value, separated by '':'' character for option {0}, but got ''{1}''",
263 "--setting", getopt.getOptarg()));
264 currentStyle.settings.put(comp[0].trim(), comp[1].trim());
265 break;
266 case SCALE:
267 try {
[13050]268 argScale = JosmDecimalFormatSymbolsProvider.parseDouble(getopt.getOptarg());
[12906]269 } catch (NumberFormatException nfe) {
270 throw new IllegalArgumentException(
[13207]271 tr("Expected floating point number for option {0}, but got ''{1}''", "--scale", getopt.getOptarg()), nfe);
[12906]272 }
273 break;
274 case ANCHOR:
275 String[] parts = getopt.getOptarg().split(",");
276 if (parts.length != 2)
277 throw new IllegalArgumentException(
278 tr("Expected two coordinates, separated by comma, for option {0}, but got ''{1}''",
279 "--anchor", getopt.getOptarg()));
280 try {
281 double lon = LatLonParser.parseCoordinate(parts[0]);
282 double lat = LatLonParser.parseCoordinate(parts[1]);
283 argAnchor = new LatLon(lat, lon);
[12907]284 } catch (IllegalArgumentException iae) { // NOPMD
[13207]285 throw new IllegalArgumentException(tr("In option {0}: {1}", "--anchor", iae.getMessage()), iae);
[12906]286 }
287 break;
288 case WIDTH_M:
289 try {
[13050]290 argWidthM = JosmDecimalFormatSymbolsProvider.parseDouble(getopt.getOptarg());
[12906]291 } catch (NumberFormatException nfe) {
292 throw new IllegalArgumentException(
[13207]293 tr("Expected floating point number for option {0}, but got ''{1}''", "--width-m", getopt.getOptarg()), nfe);
[12906]294 }
295 if (argWidthM <= 0) throw new IllegalArgumentException(
296 tr("Expected floating point number > 0 for option {0}, but got ''{1}''", "--width-m", getopt.getOptarg()));
297 break;
298 case HEIGHT_M:
299 try {
[13050]300 argHeightM = JosmDecimalFormatSymbolsProvider.parseDouble(getopt.getOptarg());
[12906]301 } catch (NumberFormatException nfe) {
302 throw new IllegalArgumentException(
[13207]303 tr("Expected floating point number for option {0}, but got ''{1}''", "--height-m", getopt.getOptarg()), nfe);
[12906]304 }
305 if (argHeightM <= 0) throw new IllegalArgumentException(
306 tr("Expected floating point number > 0 for option {0}, but got ''{1}''", "--width-m", getopt.getOptarg()));
307 break;
308 case WIDTH_PX:
309 try {
[13399]310 argWidthPx = Integer.valueOf(getopt.getOptarg());
[12906]311 } catch (NumberFormatException nfe) {
312 throw new IllegalArgumentException(
[13207]313 tr("Expected integer number for option {0}, but got ''{1}''", "--width-px", getopt.getOptarg()), nfe);
[12906]314 }
315 if (argWidthPx <= 0) throw new IllegalArgumentException(
316 tr("Expected integer number > 0 for option {0}, but got ''{1}''", "--width-px", getopt.getOptarg()));
317 break;
318 case HEIGHT_PX:
319 try {
[13399]320 argHeightPx = Integer.valueOf(getopt.getOptarg());
[12906]321 } catch (NumberFormatException nfe) {
322 throw new IllegalArgumentException(
[13207]323 tr("Expected integer number for option {0}, but got ''{1}''", "--height-px", getopt.getOptarg()), nfe);
[12906]324 }
325 if (argHeightPx <= 0) throw new IllegalArgumentException(
326 tr("Expected integer number > 0 for option {0}, but got ''{1}''", "--height-px", getopt.getOptarg()));
327 break;
328 case PROJECTION:
329 argProjection = getopt.getOptarg();
330 break;
331 case MAX_IMAGE_SIZE:
332 try {
[13399]333 argMaxImageSize = Integer.valueOf(getopt.getOptarg());
[12906]334 } catch (NumberFormatException nfe) {
335 throw new IllegalArgumentException(
[13207]336 tr("Expected integer number for option {0}, but got ''{1}''", "--max-image-size", getopt.getOptarg()), nfe);
[12906]337 }
338 if (argMaxImageSize < 0) throw new IllegalArgumentException(
[12936]339 tr("Expected integer number >= 0 for option {0}, but got ''{1}''", "--max-image-size", getopt.getOptarg()));
[12906]340 break;
341 default:
342 throw new AssertionError("Unexpected option index: " + getopt.getLongind());
343 }
344 break;
345 case '?':
346 throw new IllegalArgumentException(); // getopt error
347 default:
348 throw new AssertionError("Unrecognized option: " + c);
349 }
350 }
351 if (currentStyle.styleUrl != null) {
352 argStyles.add(currentStyle);
353 }
354 }
355
356 /**
357 * Displays help on the console
358 */
359 public static void showHelp() {
360 System.out.println(getHelp());
361 }
362
363 private static String getHelp() {
364 return tr("JOSM rendering command line interface")+"\n\n"+
365 tr("Usage")+":\n"+
366 "\tjava -jar josm.jar render <options>\n\n"+
367 tr("Description")+":\n"+
368 tr("Renders data and saves the result to an image file.")+"\n\n"+
369 tr("Options")+":\n"+
370 "\t--help|-h "+tr("Show this help")+"\n"+
371 "\t--input|-i <file> "+tr("Input data file name (.osm)")+"\n"+
372 "\t--output|-o <file> "+tr("Output image file name (.png); defaults to ''{0}''", "out.png")+"\n"+
373 "\t--style|-s <file> "+tr("Style file to use for rendering (.mapcss or .zip)")+"\n"+
374 "\t "+tr("This option can be repeated to load multiple styles.")+"\n"+
375 "\t--setting <key>:<value> "+tr("Style setting (in JOSM accessible in the style list dialog right click menu)")+"\n"+
376 "\t "+tr("Applies to the last style loaded with the {0} option.", "--style")+"\n"+
377 "\t--zoom|-z <lvl> "+tr("Select zoom level to render. (integer value, 0=entire earth, 18=street level)")+"\n"+
378 "\t--scale <scale> "+tr("Select the map scale")+"\n"+
379 "\t "+tr("A value of 10000 denotes a scale of 1:10000 (1 cm on the map equals 100 m on the ground; "
380 + "display resolution: 96 dpi)")+"\n"+
381 "\t "+tr("Options {0} and {1} are mutually exclusive.", "--zoom", "--scale")+"\n"+
382 "\t--bounds|-b auto|<min_lon>,<min_lat>,<max_lon>,<max_lat>\n"+
383 "\t "+tr("Area to render, default value is ''{0}''", "auto")+"\n"+
384 "\t "+tr("With keyword ''{0}'', the downloaded area in the .osm input file will be used (if recorded).",
385 "auto")+"\n"+
386 "\t--anchor <lon>,<lat> "+tr("Specify bottom left corner of the rendering area")+"\n"+
387 "\t "+tr("Used in combination with width and height options to determine the area to render.")+"\n"+
388 "\t--width-m <number> "+tr("Width of the rendered area, in meter")+"\n"+
389 "\t--height-m <number> "+tr("Height of the rendered area, in meter")+"\n"+
390 "\t--width-px <number> "+tr("Width of the target image, in pixel")+"\n"+
391 "\t--height-px <number> "+tr("Height of the target image, in pixel")+"\n"+
392 "\t--projection <code> "+tr("Projection to use, default value ''{0}'' (web-Mercator)", "epsg:3857")+"\n"+
393 "\t--max-image-size <number> "+tr("Maximum image width/height in pixel (''{0}'' means no limit), default value: {1}",
394 0, Integer.toString(DEFAULT_MAX_IMAGE_SIZE))+"\n"+
395 "\n"+
396 tr("To specify the rendered area and scale, the options can be combined in various ways")+":\n"+
397 " * --bounds (--zoom|--scale|--width-px|--height-px)\n"+
398 " * --anchor (--width-m|--width-px) (--height-m|--height-px) (--zoom|--scale)\n"+
399 " * --anchor --width-m --height-m (--width-px|--height-px)\n"+
400 " * --anchor --width-px --height-px (--width-m|--height-m)\n"+
401 tr("If neither ''{0}'' nor ''{1}'' is given, the default value {2} takes effect "
402 + "and the bounds of the download area in the .osm input file are used.",
403 "bounds", "anchor", "--bounds=auto")+"\n\n"+
404 tr("Examples")+":\n"+
405 " java -jar josm.jar render -i data.osm -s style.mapcss -z 16\n"+
406 " josm render -i data.osm -s style.mapcss --scale 5000\n"+
407 " josm render -i data.osm -s style.mapcss -z 16 -o image.png\n"+
408 " josm render -i data.osm -s elemstyles.mapcss --setting hide_icons:false -z 16\n"+
409 " josm render -i data.osm -s style.mapcss -s another_style.mapcss -z 16 -o image.png\n"+
410 " josm render -i data.osm -s style.mapcss --bounds 21.151,51.401,21.152,51.402 -z 16\n"+
411 " josm render -i data.osm -s style.mapcss --anchor 21.151,51.401 --width-m 500 --height-m 300 -z 16\n"+
412 " josm render -i data.osm -s style.mapcss --anchor 21.151,51.401 --width-m 500 --height-m 300 --width-px 1800\n"+
413 " josm render -i data.osm -s style.mapcss --scale 5000 --projection epsg:4326\n";
414 }
415
416 /**
417 * Initialization.
418 *
419 * Requires arguments to be parsed already ({@link #parseArguments(java.lang.String[])}).
420 */
421 void initialize() {
422 Logging.setLogLevel(getLogLevel());
423
[13021]424 Config.setBaseDirectoriesProvider(JosmBaseDirectories.getInstance()); // for right-left-hand traffic cache file
[12906]425 Config.setPreferencesInstance(new MemoryPreferences());
[14119]426 Config.setUrlsProvider(JosmUrls.getInstance());
[12906]427 Config.getPref().putBoolean("mappaint.auto_reload_local_styles", false); // unnecessary to listen for external changes
428 String projCode = Optional.ofNullable(argProjection).orElse("epsg:3857");
[14120]429 ProjectionRegistry.setProjection(Projections.getProjectionByCode(projCode.toUpperCase(Locale.US)));
[12906]430
431 RightAndLefthandTraffic.initialize();
432 }
433
434 private Level getLogLevel() {
435 if (argTrace) {
436 return Logging.LEVEL_TRACE;
437 } else if (argDebug) {
438 return Logging.LEVEL_DEBUG;
439 } else {
440 return Logging.LEVEL_INFO;
441 }
442 }
443
444 /**
445 * Find the area to render and the scale, given certain command line options and the dataset.
446 * @param ds the dataset
447 * @return area to render and the scale
448 */
449 RenderingArea determineRenderingArea(DataSet ds) {
450
[14120]451 Projection proj = ProjectionRegistry.getProjection();
[12906]452 Double scale = null; // scale in east-north units per pixel
453 if (argZoom != null) {
454 scale = OsmMercator.EARTH_RADIUS * Math.PI * 2 / Math.pow(2, argZoom) / OsmMercator.DEFAUL_TILE_SIZE / proj.getMetersPerUnit();
455 }
456 Bounds bounds = argBounds;
457 ProjectionBounds pb = null;
458
459 if (bounds == null) {
460 if (argAnchor != null) {
461 EastNorth projAnchor = proj.latlon2eastNorth(argAnchor);
462
[13849]463 double enPerMeter = Double.NaN;
464 DoubleSupplier getEnPerMeter = () -> {
[12906]465 double shiftMeter = 10;
466 EastNorth projAnchorShifted = projAnchor.add(
467 shiftMeter / proj.getMetersPerUnit(), shiftMeter / proj.getMetersPerUnit());
468 LatLon anchorShifted = proj.eastNorth2latlon(projAnchorShifted);
469 return projAnchor.distance(projAnchorShifted) / argAnchor.greatCircleDistance(anchorShifted);
470 };
471
472 if (scale == null) {
473 if (argScale != null) {
[13849]474 enPerMeter = getEnPerMeter.getAsDouble();
[12906]475 scale = argScale * enPerMeter / PIXEL_PER_METER;
476 } else if (argWidthM != null && argWidthPx != null) {
[13849]477 enPerMeter = getEnPerMeter.getAsDouble();
[12906]478 scale = argWidthM / argWidthPx * enPerMeter;
479 } else if (argHeightM != null && argHeightPx != null) {
[13849]480 enPerMeter = getEnPerMeter.getAsDouble();
[12906]481 scale = argHeightM / argHeightPx * enPerMeter;
482 } else {
483 throw new IllegalArgumentException(
484 tr("Argument {0} given, but scale cannot be determined from remaining arguments", "--anchor"));
485 }
486 }
487
488 double widthEn;
489 if (argWidthM != null) {
[13850]490 if (Double.isNaN(enPerMeter)) {
[13849]491 enPerMeter = getEnPerMeter.getAsDouble();
492 }
[12906]493 widthEn = argWidthM * enPerMeter;
494 } else if (argWidthPx != null) {
495 widthEn = argWidthPx * scale;
496 } else {
497 throw new IllegalArgumentException(
498 tr("Argument {0} given, expected {1} or {2}", "--anchor", "--width-m", "--width-px"));
499 }
500
501 double heightEn;
502 if (argHeightM != null) {
[13850]503 if (Double.isNaN(enPerMeter)) {
[13849]504 enPerMeter = getEnPerMeter.getAsDouble();
505 }
[12906]506 heightEn = argHeightM * enPerMeter;
507 } else if (argHeightPx != null) {
508 heightEn = argHeightPx * scale;
509 } else {
510 throw new IllegalArgumentException(
511 tr("Argument {0} given, expected {1} or {2}", "--anchor", "--height-m", "--height-px"));
512 }
513 pb = new ProjectionBounds(projAnchor);
514 pb.extend(new EastNorth(projAnchor.east() + widthEn, projAnchor.north() + heightEn));
515 bounds = new Bounds(proj.eastNorth2latlon(pb.getMin()), false);
516 bounds.extend(proj.eastNorth2latlon(pb.getMax()));
517 } else {
518 if (ds.getDataSourceBounds().isEmpty()) {
519 throw new IllegalArgumentException(tr("{0} mode, but no bounds found in osm data input file", "--bounds=auto"));
520 }
521 bounds = ds.getDataSourceBounds().get(0);
522 }
523 }
524
525 if (pb == null) {
526 pb = new ProjectionBounds();
527 pb.extend(proj.latlon2eastNorth(bounds.getMin()));
528 pb.extend(proj.latlon2eastNorth(bounds.getMax()));
529 }
530
531 if (scale == null) {
532 if (argScale != null) {
533 double enPerMeter = pb.getMin().distance(pb.getMax()) / bounds.getMin().greatCircleDistance(bounds.getMax());
534 scale = argScale * enPerMeter / PIXEL_PER_METER;
535 } else if (argWidthPx != null) {
536 scale = (pb.maxEast - pb.minEast) / argWidthPx;
537 } else if (argHeightPx != null) {
538 scale = (pb.maxNorth - pb.minNorth) / argHeightPx;
539 } else {
540 throw new IllegalArgumentException(
541 tr("Unable to determine scale, one of the options {0}, {1}, {2} or {3} expected",
542 "--zoom", "--scale", "--width-px", "--height-px"));
543 }
544 }
545
546 RenderingArea ra = new RenderingArea();
547 ra.bounds = bounds;
548 ra.scale = scale;
549 return ra;
550 }
551
[13204]552 private DataSet loadDataset() throws IOException, IllegalDataException {
[12906]553 if (argInput == null) {
554 throw new IllegalArgumentException(tr("Missing argument - input data file ({0})", "--input|-i"));
555 }
556 try {
[13204]557 return OsmReader.parseDataSet(Files.newInputStream(Paths.get(argInput)), null);
[12906]558 } catch (IllegalDataException e) {
[13207]559 throw new IllegalDataException(tr("In .osm data file ''{0}'' - ", argInput) + e.getMessage(), e);
[12906]560 }
[12963]561 }
[12906]562
[12963]563 private void checkPreconditions(RenderingHelper rh) {
564 if (argStyles.isEmpty())
565 throw new IllegalArgumentException(tr("Missing argument - at least one style expected ({0})", "--style"));
[12906]566
[12963]567 Dimension imgSize = rh.getImageSize();
568 Logging.debug("image size (px): {0}x{1}", imgSize.width, imgSize.height);
[12906]569 int maxSize = Optional.ofNullable(argMaxImageSize).orElse(DEFAULT_MAX_IMAGE_SIZE);
[12963]570 if (maxSize != 0 && (imgSize.width > maxSize || imgSize.height > maxSize)) {
[12906]571 throw new IllegalArgumentException(
572 tr("Image dimensions ({0}x{1}) exceeds maximum image size {2} (use option {3} to change limit)",
[12963]573 imgSize.width, imgSize.height, maxSize, "--max-image-size"));
[12906]574 }
575 }
[12966]576
577 private void writeImageToFile(BufferedImage image) throws IOException {
578 String output = Optional.ofNullable(argOutput).orElse("out.png");
579 ImageIO.write(image, "png", new File(output));
580 }
[12906]581}
Note: See TracBrowser for help on using the repository browser.