source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/RenderingHelper.java@ 12963

Last change on this file since 12963 was 12963, checked in by bastiK, 7 years ago

see #15273 - extract rendering code to new class

File size: 6.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Dimension;
7import java.awt.Graphics2D;
8import java.awt.Point;
9import java.awt.image.BufferedImage;
10import java.io.File;
11import java.io.IOException;
12import java.util.Collection;
13import java.util.HashMap;
14import java.util.Map;
15import java.util.Optional;
16
17import javax.imageio.ImageIO;
18
19import org.openstreetmap.josm.Main;
20import org.openstreetmap.josm.data.Bounds;
21import org.openstreetmap.josm.data.ProjectionBounds;
22import org.openstreetmap.josm.data.osm.DataSet;
23import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
24import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
25import org.openstreetmap.josm.data.preferences.sources.SourceEntry;
26import org.openstreetmap.josm.data.preferences.sources.SourceType;
27import org.openstreetmap.josm.data.projection.Projection;
28import org.openstreetmap.josm.gui.NavigatableComponent;
29import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
30import org.openstreetmap.josm.io.IllegalDataException;
31import org.openstreetmap.josm.tools.CheckParameterUtil;
32import org.openstreetmap.josm.tools.Logging;
33
34/**
35 * Class to render osm data to a file.
36 * @since 12963
37 */
38public class RenderingHelper {
39
40 private final DataSet ds;
41 private final Bounds bounds;
42 private final ProjectionBounds projBounds;
43 private final double scale;
44 private final Collection<StyleData> styles;
45 private String outputFile;
46
47 /**
48 * Data class to save style settings along with the corresponding style URL.
49 */
50 public static class StyleData {
51 public String styleUrl;
52 public Map<String, String> settings = new HashMap<>();
53 }
54
55 /**
56 * Construct a new {@code RenderingHelper}.
57 * @param ds the dataset to render
58 * @param bounds the bounds of the are to render
59 * @param scale the scale to render at (east/north units per pixel)
60 * @param styles the styles to use for rendering
61 */
62 public RenderingHelper(DataSet ds, Bounds bounds, double scale, Collection<StyleData> styles) {
63 CheckParameterUtil.ensureParameterNotNull(ds, "ds");
64 CheckParameterUtil.ensureParameterNotNull(bounds, "bounds");
65 CheckParameterUtil.ensureParameterNotNull(styles, "styles");
66 this.ds = ds;
67 this.bounds = bounds;
68 this.scale = scale;
69 this.styles = styles;
70 Projection proj = Main.getProjection();
71 projBounds = new ProjectionBounds();
72 projBounds.extend(proj.latlon2eastNorth(bounds.getMin()));
73 projBounds.extend(proj.latlon2eastNorth(bounds.getMax()));
74 }
75
76 /**
77 * Set the output file for rendering.
78 *
79 * Default is {@code out.png}.
80 * @param outputFile the output file for rendering
81 */
82 public void setOutputFile(String outputFile) {
83 this.outputFile = outputFile;
84 }
85
86 Dimension getImageSize() {
87 double widthEn = projBounds.maxEast - projBounds.minEast;
88 double heightEn = projBounds.maxNorth - projBounds.minNorth;
89 int widthPx = (int) Math.round(widthEn / scale);
90 int heightPx = (int) Math.round(heightEn / scale);
91 return new Dimension(widthPx, heightPx);
92 }
93
94 /**
95 * Invoke the renderer.
96 *
97 * @throws IOException in case of an IOException
98 * @throws IllegalDataException when illegal data is encountered (style has errors, etc.)
99 */
100 public void render() throws IOException, IllegalDataException {
101 // load the styles
102 MapCSSStyleSource.STYLE_SOURCE_LOCK.writeLock().lock();
103 try {
104 MapPaintStyles.getStyles().clear();
105 for (StyleData sd : styles) {
106 SourceEntry se = new SourceEntry(SourceType.MAP_PAINT_STYLE, sd.styleUrl,
107 "cliRenderingStyle", "cli rendering style '" + sd.styleUrl + "'", true /* active */);
108 StyleSource source = MapPaintStyles.addStyle(se);
109 if (!source.getErrors().isEmpty()) {
110 throw new IllegalDataException("Failed to load style file. Errors: " + source.getErrors());
111 }
112 for (String key : sd.settings.keySet()) {
113 StyleSetting.BooleanStyleSetting match = source.settings.stream()
114 .filter(s -> s instanceof StyleSetting.BooleanStyleSetting)
115 .map(s -> (StyleSetting.BooleanStyleSetting) s)
116 .filter(bs -> bs.prefKey.endsWith(":" + key))
117 .findFirst().orElse(null);
118 if (match == null) {
119 Logging.warn(tr("Style setting not found: ''{0}''", key));
120 } else {
121 boolean value = Boolean.parseBoolean(sd.settings.get(key));
122 Logging.trace("setting applied: ''{0}:{1}''", key, value);
123 match.setValue(value);
124 }
125 }
126 if (!sd.settings.isEmpty()) {
127 source.loadStyleSource(); // reload to apply settings
128 }
129 }
130 } finally {
131 MapCSSStyleSource.STYLE_SOURCE_LOCK.writeLock().unlock();
132 }
133
134 Dimension imgDimPx = getImageSize();
135 NavigatableComponent nc = new NavigatableComponent() {
136 {
137 setBounds(0, 0, imgDimPx.width, imgDimPx.height);
138 updateLocationState();
139 }
140
141 @Override
142 protected boolean isVisibleOnScreen() {
143 return true;
144 }
145
146 @Override
147 public Point getLocationOnScreen() {
148 return new Point(0, 0);
149 }
150 };
151 nc.zoomTo(projBounds.getCenter(), scale);
152
153 // render the data
154 BufferedImage image = new BufferedImage(imgDimPx.width, imgDimPx.height, BufferedImage.TYPE_INT_ARGB);
155 Graphics2D g = image.createGraphics();
156 g.setColor(PaintColors.getBackgroundColor());
157 g.fillRect(0, 0, imgDimPx.width, imgDimPx.height);
158 new StyledMapRenderer(g, nc, false).render(ds, false, bounds);
159
160 // write to file
161 String output = Optional.ofNullable(outputFile).orElse("out.png");
162 ImageIO.write(image, "png", new File(output));
163 }
164
165}
Note: See TracBrowser for help on using the repository browser.