Changeset 6392 in josm
- Timestamp:
- 2013-11-18T03:05:56+01:00 (11 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
r6318 r6392 1209 1209 curImg.tmp.setElevation(curElevation); 1210 1210 curImg.tmp.setGpsTime(new Date(curImg.getExifTime().getTime() - offset)); 1211 curImg.flagNewGpsData(); 1211 1212 ret++; 1212 1213 } … … 1238 1239 } 1239 1240 curImg.tmp.setGpsTime(new Date(curImg.getExifTime().getTime() - offset)); 1241 curImg.flagNewGpsData(); 1240 1242 1241 1243 ret++; -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
r6316 r6392 23 23 import java.util.ArrayList; 24 24 import java.util.Arrays; 25 import java.util.Calendar; 25 26 import java.util.Collection; 26 27 import java.util.Collections; 28 import java.util.Date; 29 import java.util.GregorianCalendar; 27 30 import java.util.HashSet; 28 31 import java.util.LinkedHashSet; … … 30 33 import java.util.List; 31 34 import java.util.Set; 35 import java.util.TimeZone; 32 36 33 37 import javax.swing.Action; … … 270 274 */ 271 275 public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer) { 272 super(tr("Geotagged Images")); 273 276 this(data, gpxLayer, null, false); 277 } 278 279 /** 280 * Constructs a new {@code GeoImageLayer}. 281 * @param data The list of images to display 282 * @param gpxLayer The associated GPX layer 283 * @param name Layer name 284 * @since 6392 285 */ 286 public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, final String name) { 287 this(data, gpxLayer, name, false); 288 } 289 290 /** 291 * Constructs a new {@code GeoImageLayer}. 292 * @param data The list of images to display 293 * @param gpxLayer The associated GPX layer 294 * @param useThumbs Thumbnail display flag 295 * @since 6392 296 */ 297 public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, boolean useThumbs) { 298 this(data, gpxLayer, null, useThumbs); 299 } 300 301 /** 302 * Constructs a new {@code GeoImageLayer}. 303 * @param data The list of images to display 304 * @param gpxLayer The associated GPX layer 305 * @param name Layer name 306 * @param useThumbs Thumbnail display flag 307 * @since 6392 308 */ 309 public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, final String name, boolean useThumbs) { 310 super(name != null ? name : tr("Geotagged Images")); 274 311 Collections.sort(data); 275 312 this.data = data; 276 313 this.gpxLayer = gpxLayer; 314 this.useThumbs = useThumbs; 277 315 } 278 316 … … 403 441 Rectangle clip = g.getClipBounds(); 404 442 if (useThumbs) { 443 if (!thumbsLoaded) { 444 loadThumbs(); 445 } 446 405 447 if (null == offscreenBuffer || offscreenBuffer.getWidth() != width // reuse the old buffer if possible 406 448 || offscreenBuffer.getHeight() != height) { … … 458 500 Point p = mv.getPoint(e.getPos()); 459 501 460 if (e.thumbnail != null) { 502 if (useThumbs && e.thumbnail != null) { 461 503 Dimension d = scaledDimension(e.thumbnail); 462 504 g.setColor(new Color(128, 0, 0, 122)); … … 572 614 // Do nothing 573 615 } 616 617 // Time and date. We can have these cases: 618 // 1) GPS_TIME_STAMP not set -> date/time will be null 619 // 2) GPS_DATE_STAMP not set -> use EXIF date or set to default 620 // 3) GPS_TIME_STAMP and GPS_DATE_STAMP are set 621 int[] timeStampComps = dirGps.getIntArray(GpsDirectory.TAG_GPS_TIME_STAMP); 622 if (timeStampComps != null) { 623 int gpsHour = timeStampComps[0]; 624 int gpsMin = timeStampComps[1]; 625 int gpsSec = timeStampComps[2]; 626 Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC")); 627 628 // We have the time. Next step is to check if the GPS date stamp is set. 629 // dirGps.getString() always succeeds, but the return value might be null. 630 String dateStampStr = dirGps.getString(GpsDirectory.TAG_GPS_DATE_STAMP); 631 if (dateStampStr != null && dateStampStr.matches("^\\d+:\\d+:\\d+$")) { 632 String[] dateStampComps = dateStampStr.split(":"); 633 cal.set(Calendar.YEAR, Integer.parseInt(dateStampComps[0])); 634 cal.set(Calendar.MONTH, Integer.parseInt(dateStampComps[1]) - 1); 635 cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStampComps[2])); 636 } 637 else { 638 // No GPS date stamp in EXIF data. Copy it from EXIF time. 639 // Date is not set if EXIF time is not available. 640 Date exifTime = e.getExifTime(); 641 if (exifTime != null) { 642 // Time not set yet, so we can copy everything, not just date. 643 cal.setTime(exifTime); 644 } 645 } 646 647 cal.set(Calendar.HOUR_OF_DAY, gpsHour); 648 cal.set(Calendar.MINUTE, gpsMin); 649 cal.set(Calendar.SECOND, gpsSec); 650 651 e.setExifGpsTime(cal.getTime()); 652 } 574 653 } 575 654 … … 668 747 } 669 748 749 /** 750 * Removes a photo from the list of images by index. 751 * @param idx Image index 752 * @since 6392 753 */ 754 public void removePhotoByIdx(int idx) { 755 if (idx >= 0 && data != null && idx < data.size()) { 756 data.remove(idx); 757 } 758 } 759 760 /** 761 * Returns the image that matches the position of the mouse event. 762 * @param evt Mouse event 763 * @return Image at mouse position, or {@code null} if there is no image at the mouse position 764 * @since 6392 765 */ 766 public ImageEntry getPhotoUnderMouse(MouseEvent evt) { 767 if (data != null) { 768 for (int idx = data.size() - 1; idx >= 0; --idx) { 769 ImageEntry img = data.get(idx); 770 if (img.getPos() == null) { 771 continue; 772 } 773 Point p = Main.map.mapView.getPoint(img.getPos()); 774 Rectangle r; 775 if (useThumbs && img.thumbnail != null) { 776 Dimension d = scaledDimension(img.thumbnail); 777 r = new Rectangle(p.x - d.width / 2, p.y - d.height / 2, d.width, d.height); 778 } else { 779 r = new Rectangle(p.x - icon.getIconWidth() / 2, 780 p.y - icon.getIconHeight() / 2, 781 icon.getIconWidth(), 782 icon.getIconHeight()); 783 } 784 if (r.contains(evt.getPoint())) { 785 return img; 786 } 787 } 788 } 789 return null; 790 } 791 792 /** 793 * Clears the currentPhoto, i.e. remove select marker, and optionally repaint. 794 * @param repaint Repaint flag 795 * @since 6392 796 */ 797 public void clearCurrentPhoto(boolean repaint) { 798 currentPhoto = -1; 799 if (repaint) { 800 updateBufferAndRepaint(); 801 } 802 } 803 804 /** 805 * Clears the currentPhoto of the other GeoImageLayer's. Otherwise there could be multiple selected photos. 806 */ 807 private void clearOtherCurrentPhotos() { 808 for (GeoImageLayer layer: 809 Main.map.mapView.getLayersOfType(GeoImageLayer.class)) { 810 if (layer != this) { 811 layer.clearCurrentPhoto(false); 812 } 813 } 814 } 815 816 private static List<MapMode> supportedMapModes = null; 817 818 /** 819 * Registers a map mode for which the functionality of this layer should be available. 820 * @param mapMode Map mode to be registered 821 * @since 6392 822 */ 823 public static void registerSupportedMapMode(MapMode mapMode) { 824 if (supportedMapModes == null) { 825 supportedMapModes = new ArrayList<MapMode>(); 826 } 827 supportedMapModes.add(mapMode); 828 } 829 830 /** 831 * Determines if the functionality of this layer is available in 832 * the specified map mode. SelectAction is supported by default, 833 * other map modes can be registered. 834 * @param mapMode Map mode to be checked 835 * @return {@code true} if the map mode is supported, 836 * {@code false} otherwise 837 */ 838 private static final boolean isSupportedMapMode(MapMode mapMode) { 839 if (mapMode instanceof SelectAction) return true; 840 if (supportedMapModes != null) { 841 for (MapMode supmmode: supportedMapModes) { 842 if (mapMode == supmmode) { 843 return true; 844 } 845 } 846 } 847 return false; 848 } 849 670 850 private MouseAdapter mouseAdapter = null; 671 851 private MapModeChangeListener mapModeListener = null; … … 675 855 mouseAdapter = new MouseAdapter() { 676 856 private final boolean isMapModeOk() { 677 return Main.map.mapMode == null || Main.map.mapMode instanceof SelectAction;857 return Main.map.mapMode == null || isSupportedMapMode(Main.map.mapMode); 678 858 } 679 859 @Override public void mousePressed(MouseEvent e) { … … 699 879 Point p = Main.map.mapView.getPoint(e.getPos()); 700 880 Rectangle r; 701 if (e.thumbnail != null) { 881 if (useThumbs && e.thumbnail != null) { 702 882 Dimension d = scaledDimension(e.thumbnail); 703 883 r = new Rectangle(p.x - d.width / 2, p.y - d.height / 2, d.width, d.height); … … 709 889 } 710 890 if (r.contains(ev.getPoint())) { 891 clearOtherCurrentPhotos(); 711 892 currentPhoto = i; 712 893 ImageViewerDialog.showImage(GeoImageLayer.this, e); … … 721 902 @Override 722 903 public void mapModeChange(MapMode oldMapMode, MapMode newMapMode) { 723 if (newMapMode == null || (newMapMode instanceof org.openstreetmap.josm.actions.mapmode.SelectAction)) {904 if (newMapMode == null || isSupportedMapMode(newMapMode)) { 724 905 Main.map.mapView.addMouseListener(mouseAdapter); 725 906 } else { … … 816 997 showPreviousPhoto(); 817 998 } 999 1000 /** 1001 * Returns the current thumbnail display status. 1002 * {@code true}: thumbnails are displayed, {@code false}: an icon is displayed instead of thumbnails. 1003 * @return Current thumbnail display status 1004 * @since 6392 1005 */ 1006 public boolean isUseThumbs() { 1007 return useThumbs; 1008 } 1009 1010 /** 1011 * Enables or disables the display of thumbnails. Does not update the display. 1012 * @param useThumbs New thumbnail display status 1013 * @since 6392 1014 */ 1015 public void setUseThumbs(boolean useThumbs) { 1016 this.useThumbs = useThumbs; 1017 if (useThumbs && !thumbsLoaded) { 1018 loadThumbs(); 1019 } 1020 } 818 1021 } -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageEntry.java
r6296 r6392 18 18 private Double exifImgDir; 19 19 private Date exifTime; 20 /** 21 * Flag isNewGpsData indicates that the GPS data of the image is new or has changed. 22 * GPS data includes the position, speed, elevation, time (e.g. as extracted from the GPS track). 23 * The flag can used to decide for which image file the EXIF GPS data is (re-)written. 24 */ 25 private boolean isNewGpsData = false; 26 /** Temporary source of GPS time if not correlated with GPX track. */ 27 private Date exifGpsTime = null; 20 28 Image thumbnail; 21 29 22 /** The following values are computed from the correlation with the gpx track */ 30 /** 31 * The following values are computed from the correlation with the gpx track 32 * or extracted from the image EXIF data. 33 */ 23 34 private CachedLatLon pos; 24 35 /** Speed in kilometer per second */ … … 75 86 return exifTime; 76 87 } 88 89 /** 90 * Returns the EXIF GPS time. 91 * @return the EXIF GPS time 92 * @since 6392 93 */ 94 public final Date getExifGpsTime() { 95 return exifGpsTime; 96 } 97 77 98 public LatLon getExifCoor() { 78 99 return exifCoor; … … 110 131 this.exifTime = exifTime; 111 132 } 133 134 /** 135 * Sets the EXIF GPS time. 136 * @param exifGpsTime the EXIF GPS time 137 * @since 6392 138 */ 139 public final void setExifGpsTime(Date exifGpsTime) { 140 this.exifGpsTime = exifGpsTime; 141 } 142 112 143 public void setGpsTime(Date gpsTime) { 113 144 this.gpsTime = gpsTime; … … 184 215 return result; 185 216 } 217 218 /** 219 * Indicates that the image has new GPS data. 220 * That flag is used e.g. by the photo_geotagging plugin to decide for which image 221 * file the EXIF GPS data needs to be (re-)written. 222 * @since 6392 223 */ 224 public void flagNewGpsData() { 225 isNewGpsData = true; 226 // We need to set the GPS time to tell the system (mainly the photo_geotagging plug-in) 227 // that the GPS data has changed. Check for existing GPS time and take EXIF time otherwise. 228 // This can be removed once isNewGpsData is used instead of the GPS time. 229 if (gpsTime == null) { 230 Date gpsTime = getExifGpsTime(); 231 if (gpsTime == null) { 232 gpsTime = getExifTime(); 233 if (gpsTime == null) { 234 // Time still not set, take the current time. 235 gpsTime = new Date(); 236 } 237 } 238 setGpsTime(gpsTime); 239 } 240 if (tmp != null && tmp.getGpsTime() == null) { 241 // tmp.gpsTime overrides gpsTime, so we set it too. 242 tmp.setGpsTime(getGpsTime()); 243 } 244 } 245 246 /** 247 * Queries whether the GPS data changed. 248 * @return {@code true} if GPS data changed, {@code false} otherwise 249 * @since 6392 250 */ 251 public boolean hasNewGpsData() { 252 return isNewGpsData; 253 } 186 254 } -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
r6362 r6392 214 214 215 215 public void displayImage(GeoImageLayer layer, ImageEntry entry) { 216 boolean imageChanged; 217 216 218 synchronized(this) { 217 219 // TODO: pop up image dialog but don't load image again 218 220 221 imageChanged = currentEntry != entry; 222 219 223 if (centerView && Main.isDisplayingMapView() && entry != null && entry.getPos() != null) { 220 224 Main.map.mapView.zoomTo(entry.getPos()); … … 226 230 227 231 if (entry != null) { 228 imgDisplay.setImage(entry.getFile(), entry.getExifOrientation()); 232 if (imageChanged) { 233 // Set only if the image is new to preserve zoom and position if the same image is redisplayed 234 // (e.g. to update the OSD). 235 imgDisplay.setImage(entry.getFile(), entry.getExifOrientation()); 236 } 229 237 setTitle("Geotagged Images" + (entry.getFile() != null ? " - " + entry.getFile().getName() : "")); 230 238 StringBuffer osd = new StringBuffer(entry.getFile() != null ? entry.getFile().getName() : ""); … … 302 310 return currentEntry != null; 303 311 } 312 313 /** 314 * Returns the currently displayed image. 315 * @return Currently displayed image or {@code null} 316 * @since 6392 317 */ 318 public static ImageEntry getCurrentImage() { 319 return getInstance().currentEntry; 320 } 321 322 /** 323 * Returns the layer associated with the image. 324 * @return Layer associated with the image 325 * @since 6392 326 */ 327 public static GeoImageLayer getCurrentLayer() { 328 return getInstance().currentLayer; 329 } 304 330 } -
trunk/src/org/openstreetmap/josm/io/session/GeoImageSessionExporter.java
r6070 r6392 66 66 layerElem.setAttribute("type", "geoimage"); 67 67 layerElem.setAttribute("version", "0.1"); 68 addAttr("show-thumbnails", Boolean.toString(layer.isUseThumbs()), layerElem, support); 68 69 69 70 for (ImageEntry entry : layer.getImages()) { … … 101 102 addAttr("exif-time", Long.toString(entry.getExifTime().getTime()), imgElem, support); 102 103 } 104 if (entry.getExifGpsTime() != null) { 105 addAttr("exif-gps-time", Long.toString(entry.getExifGpsTime().getTime()), imgElem, support); 106 } 103 107 if (entry.getExifCoor() != null) { 104 108 Element posElem = support.createElement("exif-coordinates"); … … 109 113 if (entry.getExifImgDir() != null) { 110 114 addAttr("exif-image-direction", entry.getExifImgDir().toString(), imgElem, support); 115 } 116 if (entry.hasNewGpsData()) { 117 addAttr("is-new-gps-data", Boolean.toString(entry.hasNewGpsData()), imgElem, support); 111 118 } 112 119 -
trunk/src/org/openstreetmap/josm/io/session/GeoImageSessionImporter.java
r6093 r6392 32 32 List<ImageEntry> entries = new ArrayList<ImageEntry>(); 33 33 NodeList imgNodes = elem.getChildNodes(); 34 boolean useThumbs = false; 34 35 for (int i=0; i<imgNodes.getLength(); ++i) { 35 36 Node imgNode = imgNodes.item(i); … … 56 57 } else if (attrElem.getTagName().equals("gps-time")) { 57 58 entry.setGpsTime(new Date(Long.parseLong(attrElem.getTextContent()))); 58 } else if (attrElem.getTagName().equals(" gps-orientation")) {59 } else if (attrElem.getTagName().equals("exif-orientation")) { 59 60 entry.setExifOrientation(Integer.parseInt(attrElem.getTextContent())); 60 61 } else if (attrElem.getTagName().equals("exif-time")) { 61 62 entry.setExifTime(new Date(Long.parseLong(attrElem.getTextContent()))); 63 } else if (attrElem.getTagName().equals("exif-gps-time")) { 64 entry.setExifGpsTime(new Date(Long.parseLong(attrElem.getTextContent()))); 62 65 } else if (attrElem.getTagName().equals("exif-coordinates")) { 63 66 double lat = Double.parseDouble(attrElem.getAttribute("lat")); … … 66 69 } else if (attrElem.getTagName().equals("exif-image-direction")) { 67 70 entry.setExifImgDir(Double.parseDouble(attrElem.getTextContent())); 71 } else if (attrElem.getTagName().equals("is-new-gps-data")) { 72 if (Boolean.parseBoolean(attrElem.getTextContent())) { 73 entry.flagNewGpsData(); 74 } 68 75 } 69 76 // TODO: handle thumbnail loading … … 74 81 } 75 82 entries.add(entry); 83 } else if (imgElem.getTagName().equals("show-thumbnails")) { 84 useThumbs = Boolean.parseBoolean(imgElem.getTextContent()); 76 85 } 77 86 } … … 87 96 } 88 97 89 return new GeoImageLayer(entries, gpxLayer); 98 return new GeoImageLayer(entries, gpxLayer, useThumbs); 90 99 } 91 100
Note:
See TracChangeset
for help on using the changeset viewer.