source: josm/trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java@ 9983

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

remove unused code

  • Property svn:eol-style set to native
File size: 12.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.layer;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trc;
7
8import java.awt.Color;
9import java.awt.Component;
10import java.awt.GridBagLayout;
11import java.awt.Transparency;
12import java.awt.event.ActionEvent;
13import java.awt.image.BufferedImage;
14import java.awt.image.BufferedImageOp;
15import java.awt.image.ConvolveOp;
16import java.awt.image.Kernel;
17import java.awt.image.LookupOp;
18import java.awt.image.ShortLookupTable;
19import java.util.ArrayList;
20import java.util.List;
21
22import javax.swing.AbstractAction;
23import javax.swing.Icon;
24import javax.swing.JCheckBoxMenuItem;
25import javax.swing.JComponent;
26import javax.swing.JLabel;
27import javax.swing.JMenu;
28import javax.swing.JMenuItem;
29import javax.swing.JPanel;
30import javax.swing.JPopupMenu;
31import javax.swing.JSeparator;
32
33import org.openstreetmap.josm.Main;
34import org.openstreetmap.josm.actions.ImageryAdjustAction;
35import org.openstreetmap.josm.data.ProjectionBounds;
36import org.openstreetmap.josm.data.imagery.ImageryInfo;
37import org.openstreetmap.josm.data.imagery.OffsetBookmark;
38import org.openstreetmap.josm.data.preferences.ColorProperty;
39import org.openstreetmap.josm.data.preferences.IntegerProperty;
40import org.openstreetmap.josm.gui.MenuScroller;
41import org.openstreetmap.josm.gui.widgets.UrlLabel;
42import org.openstreetmap.josm.tools.GBC;
43import org.openstreetmap.josm.tools.ImageProvider;
44import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
45import org.openstreetmap.josm.tools.Utils;
46
47public abstract class ImageryLayer extends Layer {
48
49 public static final ColorProperty PROP_FADE_COLOR = new ColorProperty(marktr("Imagery fade"), Color.white);
50 public static final IntegerProperty PROP_FADE_AMOUNT = new IntegerProperty("imagery.fade_amount", 0);
51 public static final IntegerProperty PROP_SHARPEN_LEVEL = new IntegerProperty("imagery.sharpen_level", 0);
52
53 private final List<ImageProcessor> imageProcessors = new ArrayList<>();
54
55 public static Color getFadeColor() {
56 return PROP_FADE_COLOR.get();
57 }
58
59 public static Color getFadeColorWithAlpha() {
60 Color c = PROP_FADE_COLOR.get();
61 return new Color(c.getRed(), c.getGreen(), c.getBlue(), PROP_FADE_AMOUNT.get()*255/100);
62 }
63
64 protected final ImageryInfo info;
65
66 protected Icon icon;
67
68 protected double dx;
69 protected double dy;
70
71 protected GammaImageProcessor gammaImageProcessor = new GammaImageProcessor();
72
73 private final ImageryAdjustAction adjustAction = new ImageryAdjustAction(this);
74
75 /**
76 * Constructs a new {@code ImageryLayer}.
77 * @param info imagery info
78 */
79 public ImageryLayer(ImageryInfo info) {
80 super(info.getName());
81 this.info = info;
82 if (info.getIcon() != null) {
83 icon = new ImageProvider(info.getIcon()).setOptional(true).
84 setMaxSize(ImageSizes.LAYER).get();
85 }
86 if (icon == null) {
87 icon = ImageProvider.get("imagery_small");
88 }
89 addImageProcessor(createSharpener(PROP_SHARPEN_LEVEL.get()));
90 addImageProcessor(gammaImageProcessor);
91 }
92
93 public double getPPD() {
94 if (!Main.isDisplayingMapView()) return Main.getProjection().getDefaultZoomInPPD();
95 ProjectionBounds bounds = Main.map.mapView.getProjectionBounds();
96 return Main.map.mapView.getWidth() / (bounds.maxEast - bounds.minEast);
97 }
98
99 public double getDx() {
100 return dx;
101 }
102
103 public double getDy() {
104 return dy;
105 }
106
107 public void setOffset(double dx, double dy) {
108 this.dx = dx;
109 this.dy = dy;
110 }
111
112 public void displace(double dx, double dy) {
113 setOffset(this.dx += dx, this.dy += dy);
114 }
115
116 public ImageryInfo getInfo() {
117 return info;
118 }
119
120 @Override
121 public Icon getIcon() {
122 return icon;
123 }
124
125 @Override
126 public boolean isMergable(Layer other) {
127 return false;
128 }
129
130 @Override
131 public void mergeFrom(Layer from) {
132 }
133
134 @Override
135 public Object getInfoComponent() {
136 JPanel panel = new JPanel(new GridBagLayout());
137 panel.add(new JLabel(getToolTipText()), GBC.eol());
138 if (info != null) {
139 String url = info.getUrl();
140 if (url != null) {
141 panel.add(new JLabel(tr("URL: ")), GBC.std().insets(0, 5, 2, 0));
142 panel.add(new UrlLabel(url), GBC.eol().insets(2, 5, 10, 0));
143 }
144 if (dx != 0 || dy != 0) {
145 panel.add(new JLabel(tr("Offset: ") + dx + ';' + dy), GBC.eol().insets(0, 5, 10, 0));
146 }
147 }
148 return panel;
149 }
150
151 public static ImageryLayer create(ImageryInfo info) {
152 switch(info.getImageryType()) {
153 case WMS:
154 case HTML:
155 return new WMSLayer(info);
156 case WMTS:
157 return new WMTSLayer(info);
158 case TMS:
159 case BING:
160 case SCANEX:
161 return new TMSLayer(info);
162 default:
163 throw new AssertionError(tr("Unsupported imagery type: {0}", info.getImageryType()));
164 }
165 }
166
167 class ApplyOffsetAction extends AbstractAction {
168 private final transient OffsetBookmark b;
169
170 ApplyOffsetAction(OffsetBookmark b) {
171 super(b.name);
172 this.b = b;
173 }
174
175 @Override
176 public void actionPerformed(ActionEvent ev) {
177 setOffset(b.dx, b.dy);
178 Main.main.menu.imageryMenu.refreshOffsetMenu();
179 Main.map.repaint();
180 }
181 }
182
183 public class OffsetAction extends AbstractAction implements LayerAction {
184 @Override
185 public void actionPerformed(ActionEvent e) {
186 }
187
188 @Override
189 public Component createMenuComponent() {
190 return getOffsetMenuItem();
191 }
192
193 @Override
194 public boolean supportLayers(List<Layer> layers) {
195 return false;
196 }
197 }
198
199 public JMenuItem getOffsetMenuItem() {
200 JMenu subMenu = new JMenu(trc("layer", "Offset"));
201 subMenu.setIcon(ImageProvider.get("mapmode", "adjustimg"));
202 return (JMenuItem) getOffsetMenuItem(subMenu);
203 }
204
205 public JComponent getOffsetMenuItem(JComponent subMenu) {
206 JMenuItem adjustMenuItem = new JMenuItem(adjustAction);
207 if (OffsetBookmark.allBookmarks.isEmpty()) return adjustMenuItem;
208
209 subMenu.add(adjustMenuItem);
210 subMenu.add(new JSeparator());
211 boolean hasBookmarks = false;
212 int menuItemHeight = 0;
213 for (OffsetBookmark b : OffsetBookmark.allBookmarks) {
214 if (!b.isUsable(this)) {
215 continue;
216 }
217 JCheckBoxMenuItem item = new JCheckBoxMenuItem(new ApplyOffsetAction(b));
218 if (Utils.equalsEpsilon(b.dx, dx) && Utils.equalsEpsilon(b.dy, dy)) {
219 item.setSelected(true);
220 }
221 subMenu.add(item);
222 menuItemHeight = item.getPreferredSize().height;
223 hasBookmarks = true;
224 }
225 if (menuItemHeight > 0) {
226 if (subMenu instanceof JMenu) {
227 MenuScroller.setScrollerFor((JMenu) subMenu);
228 } else if (subMenu instanceof JPopupMenu) {
229 MenuScroller.setScrollerFor((JPopupMenu) subMenu);
230 }
231 }
232 return hasBookmarks ? subMenu : adjustMenuItem;
233 }
234
235 public ImageProcessor createSharpener(int sharpenLevel) {
236 final Kernel kernel;
237 if (sharpenLevel == 1) {
238 kernel = new Kernel(3, 3, new float[]{-0.25f, -0.5f, -0.25f, -0.5f, 4, -0.5f, -0.25f, -0.5f, -0.25f});
239 } else if (sharpenLevel == 2) {
240 kernel = new Kernel(3, 3, new float[]{-0.5f, -1, -0.5f, -1, 7, -1, -0.5f, -1, -0.5f});
241 } else {
242 return null;
243 }
244 BufferedImageOp op = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
245 return createImageProcessor(op, false);
246 }
247
248 /**
249 * An image processor which adjusts the gamma value of an image.
250 */
251 public static class GammaImageProcessor implements ImageProcessor {
252 private double gamma = 1;
253 final short[] gammaChange = new short[256];
254 private final LookupOp op3 = new LookupOp(
255 new ShortLookupTable(0, new short[][]{gammaChange, gammaChange, gammaChange}), null);
256 private final LookupOp op4 = new LookupOp(
257 new ShortLookupTable(0, new short[][]{gammaChange, gammaChange, gammaChange, gammaChange}), null);
258
259 /**
260 * Returns the currently set gamma value.
261 * @return the currently set gamma value
262 */
263 public double getGamma() {
264 return gamma;
265 }
266
267 /**
268 * Sets a new gamma value, {@code 1} stands for no correction.
269 * @param gamma new gamma value
270 */
271 public void setGamma(double gamma) {
272 this.gamma = gamma;
273 for (int i = 0; i < 256; i++) {
274 gammaChange[i] = (short) (255 * Math.pow(i / 255., gamma));
275 }
276 }
277
278 @Override
279 public BufferedImage process(BufferedImage image) {
280 if (gamma == 1) {
281 return image;
282 }
283 try {
284 final int bands = image.getRaster().getNumBands();
285 if (image.getType() != BufferedImage.TYPE_CUSTOM && bands == 3) {
286 return op3.filter(image, null);
287 } else if (image.getType() != BufferedImage.TYPE_CUSTOM && bands == 4) {
288 return op4.filter(image, null);
289 }
290 } catch (IllegalArgumentException ignore) {
291 if (Main.isTraceEnabled()) {
292 Main.trace(ignore.getMessage());
293 }
294 }
295 final int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
296 final BufferedImage to = new BufferedImage(image.getWidth(), image.getHeight(), type);
297 to.getGraphics().drawImage(image, 0, 0, null);
298 return process(to);
299 }
300 }
301
302 /**
303 * Returns the currently set gamma value.
304 * @return the currently set gamma value
305 */
306 public double getGamma() {
307 return gammaImageProcessor.getGamma();
308 }
309
310 /**
311 * Sets a new gamma value, {@code 1} stands for no correction.
312 * @param gamma new gamma value
313 */
314 public void setGamma(double gamma) {
315 gammaImageProcessor.setGamma(gamma);
316 }
317
318 /**
319 * This method adds the {@link ImageProcessor} to this Layer if it is not {@code null}.
320 *
321 * @param processor that processes the image
322 *
323 * @return true if processor was added, false otherwise
324 */
325 public boolean addImageProcessor(ImageProcessor processor) {
326 return processor != null && imageProcessors.add(processor);
327 }
328
329 /**
330 * This method removes given {@link ImageProcessor} from this layer
331 *
332 * @param processor which is needed to be removed
333 *
334 * @return true if processor was removed
335 */
336 public boolean removeImageProcessor(ImageProcessor processor) {
337 return imageProcessors.remove(processor);
338 }
339
340 /**
341 * Wraps a {@link BufferedImageOp} to be used as {@link ImageProcessor}.
342 * @param op the {@link BufferedImageOp}
343 * @param inPlace true to apply filter in place, i.e., not create a new {@link BufferedImage} for the result
344 * (the {@code op} needs to support this!)
345 * @return the {@link ImageProcessor} wrapper
346 */
347 public static ImageProcessor createImageProcessor(final BufferedImageOp op, final boolean inPlace) {
348 return new ImageProcessor() {
349 @Override
350 public BufferedImage process(BufferedImage image) {
351 return op.filter(image, inPlace ? image : null);
352 }
353 };
354 }
355
356 /**
357 * This method gets all {@link ImageProcessor}s of the layer
358 *
359 * @return list of image processors without removed one
360 */
361 public List<ImageProcessor> getImageProcessors() {
362 return imageProcessors;
363 }
364
365 /**
366 * Applies all the chosen {@link ImageProcessor}s to the image
367 *
368 * @param img - image which should be changed
369 *
370 * @return the new changed image
371 */
372 public BufferedImage applyImageProcessors(BufferedImage img) {
373 for (ImageProcessor processor : imageProcessors) {
374 img = processor.process(img);
375 }
376 return img;
377 }
378
379 @Override
380 public void destroy() {
381 super.destroy();
382 adjustAction.destroy();
383 }
384}
Note: See TracBrowser for help on using the repository browser.