Index: applications/editors/josm/plugins/photo_geotagging/src/org/openstreetmap/josm/plugins/photo_geotagging/ExifGPSTagger.java
===================================================================
--- applications/editors/josm/plugins/photo_geotagging/src/org/openstreetmap/josm/plugins/photo_geotagging/ExifGPSTagger.java	(revision 30886)
+++ applications/editors/josm/plugins/photo_geotagging/src/org/openstreetmap/josm/plugins/photo_geotagging/ExifGPSTagger.java	(revision 30887)
@@ -10,4 +10,5 @@
 import java.text.DecimalFormat;
 import java.util.Calendar;
+import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.TimeZone;
@@ -34,10 +35,12 @@
      * @param lat latitude
      * @param lon longitude
-     * @param gpsTime time in milliseconds
+     * @param gpsTime time - can be null if not available
+     * @param speed speed in km/h - can be null if not available
      * @param ele elevation - can be null if not available
+     * @param imgDir image direction in degrees (0..360) - can be null if not available
      */
-    public static void setExifGPSTag(File jpegImageFile, File dst, double lat, double lon, long gpsTime, Double ele) throws IOException {
+    public static void setExifGPSTag(File jpegImageFile, File dst, double lat, double lon, Date gpsTime, Double speed, Double ele, Double imgDir) throws IOException {
         try {
-            setExifGPSTagWorker(jpegImageFile, dst, lat, lon, gpsTime, ele);
+            setExifGPSTagWorker(jpegImageFile, dst, lat, lon, gpsTime, speed, ele, imgDir);
         } catch (ImageReadException ire) {
             throw new IOException(tr("Read error: "+ire), ire);
@@ -47,5 +50,5 @@
     }
 
-    public static void setExifGPSTagWorker(File jpegImageFile, File dst, double lat, double lon, long gpsTime, Double ele)
+    public static void setExifGPSTagWorker(File jpegImageFile, File dst, double lat, double lon, Date gpsTime, Double speed, Double ele, Double imgDir)
             throws IOException, ImageReadException, ImageWriteException {
         TiffOutputSet outputSet = null;
@@ -69,38 +72,49 @@
         gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_VERSION_ID, (byte)2, (byte)3, (byte)0, (byte)0);
 
-        Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
-        calendar.setTimeInMillis(gpsTime);
+        if (gpsTime != null) {
+            Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+            calendar.setTime(gpsTime);
 
-        final int year =   calendar.get(Calendar.YEAR);
-        final int month =  calendar.get(Calendar.MONTH) + 1;
-        final int day =    calendar.get(Calendar.DAY_OF_MONTH);
-        final int hour =   calendar.get(Calendar.HOUR_OF_DAY);
-        final int minute = calendar.get(Calendar.MINUTE);
-        final int second = calendar.get(Calendar.SECOND);
+            final int year =   calendar.get(Calendar.YEAR);
+            final int month =  calendar.get(Calendar.MONTH) + 1;
+            final int day =    calendar.get(Calendar.DAY_OF_MONTH);
+            final int hour =   calendar.get(Calendar.HOUR_OF_DAY);
+            final int minute = calendar.get(Calendar.MINUTE);
+            final int second = calendar.get(Calendar.SECOND);
 
-        DecimalFormat yearFormatter = new DecimalFormat("0000");
-        DecimalFormat monthFormatter = new DecimalFormat("00");
-        DecimalFormat dayFormatter = new DecimalFormat("00");
+            DecimalFormat yearFormatter = new DecimalFormat("0000");
+            DecimalFormat monthFormatter = new DecimalFormat("00");
+            DecimalFormat dayFormatter = new DecimalFormat("00");
 
-        final String yearStr = yearFormatter.format(year);
-        final String monthStr = monthFormatter.format(month);
-        final String dayStr = dayFormatter.format(day);
-        final String dateStamp = yearStr+":"+monthStr+":"+dayStr;
-        //System.err.println("date: "+dateStamp+"  h/m/s: "+hour+"/"+minute+"/"+second);
+            final String yearStr = yearFormatter.format(year);
+            final String monthStr = monthFormatter.format(month);
+            final String dayStr = dayFormatter.format(day);
+            final String dateStamp = yearStr+":"+monthStr+":"+dayStr;
+            //System.err.println("date: "+dateStamp+"  h/m/s: "+hour+"/"+minute+"/"+second);
 
-        // make sure to remove old value if present (this method will
-        // not fail if the tag does not exist).
-        gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP);
-        gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP, 
-                RationalNumber.valueOf(hour),
-                RationalNumber.valueOf(minute),
-                RationalNumber.valueOf(second));
+            // make sure to remove old value if present (this method will
+            // not fail if the tag does not exist).
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP, 
+                    RationalNumber.valueOf(hour),
+                    RationalNumber.valueOf(minute),
+                    RationalNumber.valueOf(second));
 
-        // make sure to remove old value if present (this method will
-        // not fail if the tag does not exist).
-        gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP);
-        gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP, dateStamp);
+            // make sure to remove old value if present (this method will
+            // not fail if the tag does not exist).
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP, dateStamp);
+        }
 
         outputSet.setGPSInDegrees(lon, lat);
+
+        if (speed != null) {
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_SPEED_REF);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_SPEED_REF,
+                             GpsTagConstants.GPS_TAG_GPS_SPEED_REF_VALUE_KMPH);
+
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_SPEED);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_SPEED, RationalNumber.valueOf(speed));
+        }
 
         if (ele != null) {
@@ -112,4 +126,21 @@
             gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_ALTITUDE, RationalNumber.valueOf(Math.abs(ele)));
         }
+
+        if (imgDir != null) {
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF,
+                             GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF_VALUE_TRUE_NORTH);
+            // make sure the value is in the range 0.0...<360.0
+            if (imgDir < 0.0) {
+                imgDir %= 360.0; // >-360.0...-0.0
+                imgDir += 360.0; // >0.0...360.0
+            }
+            if (imgDir >= 360.0) {
+                imgDir %= 360.0;
+            }
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, RationalNumber.valueOf(imgDir));
+        }
+
         try (BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(dst))) {
             new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os, outputSet);
Index: applications/editors/josm/plugins/photo_geotagging/src/org/openstreetmap/josm/plugins/photo_geotagging/GeotaggingAction.java
===================================================================
--- applications/editors/josm/plugins/photo_geotagging/src/org/openstreetmap/josm/plugins/photo_geotagging/GeotaggingAction.java	(revision 30886)
+++ applications/editors/josm/plugins/photo_geotagging/src/org/openstreetmap/josm/plugins/photo_geotagging/GeotaggingAction.java	(revision 30887)
@@ -14,4 +14,5 @@
 import java.text.DecimalFormat;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.UUID;
@@ -66,6 +67,6 @@
         for (ImageEntry e : layer.getImages()) {
              /* Only write lat/lon to the file, if the position is known and
-                we have a time from the correlation to the gpx track. */
-            if (e.getPos() != null && e.hasGpsTime()) {
+                the GPS data changed. */
+            if (e.getPos() != null && (e.hasNewGpsData() || e.hasGpsTime())) {
                 images.add(e);
             }
@@ -205,5 +206,20 @@
 
                     Long mTime = null;
-                    if (mTimeMode == MTIME_MODE_PREVIOUS_VALUE) {
+                    if (mTimeMode == MTIME_MODE_GPS) {
+                        // check GPS time fields, do nothing if all fails
+                        Date time;
+                        if (e.hasGpsTime()) {
+                            time = e.getGpsTime();
+                        } else {
+                            time = e.getExifGpsTime();
+                        }
+                        if (time != null) {
+                            mTime = time.getTime();
+                        }
+                    }
+                    if ( mTimeMode == MTIME_MODE_PREVIOUS_VALUE
+                         // this is also the fallback if one of the other
+                         // modes failed to determine the modification time
+                         || (mTimeMode != 0 && mTime == null)) {
                         mTime = e.getFile().lastModified();
                         if (mTime.equals(0L))
@@ -213,9 +229,6 @@
                     chooseFiles(e.getFile());
                     if (canceled) return;
-                    ExifGPSTagger.setExifGPSTag(fileFrom, fileTo, e.getPos().lat(), e.getPos().lon(), e.getGpsTime().getTime(), e.getElevation());
-
-                    if (mTimeMode == MTIME_MODE_GPS) {
-                        mTime = e.getGpsTime().getTime();
-                    }
+                    ExifGPSTagger.setExifGPSTag(fileFrom, fileTo, e.getPos().lat(), e.getPos().lon(),
+                            e.getGpsTime(), e.getSpeed(), e.getElevation(), e.getExifImgDir());
 
                     if (mTime != null) {
@@ -378,5 +391,5 @@
     private boolean enabled(GeoImageLayer layer) {
         for (ImageEntry e : layer.getImages()) {
-            if (e.getPos() != null && e.hasGpsTime())
+            if (e.getPos() != null && (e.hasNewGpsData() || e.hasGpsTime()))
                 return true;
         }
