Index: /trunk/src/org/openstreetmap/josm/data/ImageData.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/ImageData.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/data/ImageData.java	(revision 19387)
@@ -367,4 +367,81 @@
 
     /**
+     * Update the GPS track direction of the image and trigger update.
+     * @param img the image to update
+     * @param trackDirection the new GPS track direction
+     * @since 19387
+     */
+    public void updateImageGpsTrack(ImageEntry img, double trackDirection) {
+        img.setExifGpsTrack(trackDirection);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image horizontal positioning error and trigger update.
+     * @param img the image to update
+     * @param hposerr the new horizontal positionning error
+     * @since 19387
+     */
+    public void updateImageHPosErr(ImageEntry img, double hposerr) {
+        img.setExifHPosErr(hposerr);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image GPS differential mode and trigger update.
+     * @param img the image to update
+     * @param gpsDiffMode the new GPS differential mode
+     * @since 19387
+     */
+    public void updateImageGpsDiffMode(ImageEntry img, Integer gpsDiffMode) {
+        img.setGpsDiffMode(gpsDiffMode);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image GPS 2d/3d mode value and trigger update.
+     * @param img the image to update
+     * @param gps2d3dMode the new 2d/3d GPS mode
+     * @since 19387
+     */
+    public void updateImageGps2d3dMode(ImageEntry img, Integer gps2d3dMode) {
+        img.setGps2d3dMode(gps2d3dMode);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image GPS DOP value and trigger update.
+     * @param img the image to update
+     * @param exifGpsDop the new GPS DOP value
+     * @since 19387
+     */
+    public void updateImageExifGpsDop(ImageEntry img, Double exifGpsDop) {
+        img.setExifGpsDop(exifGpsDop);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image GPS datum and trigger update.
+     * @param img the image to update
+     * @param exifGpsDatum the new datum string value
+     * @since 19387
+     */
+    public void updateImageExifGpsDatum(ImageEntry img, String exifGpsDatum) {
+        img.setExifGpsDatum(exifGpsDatum);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image GPS processing method and trigger update.
+     * @param img the image to update
+     * @param exifGpsProcMethod the new GPS processing method
+     * @since 19387
+     */
+    public void updateImageExifGpsProcMethod(ImageEntry img, String exifGpsProcMethod) {
+        img.setExifGpsProcMethod(exifGpsProcMethod);
+        afterImageUpdated(img);
+    }
+
+    /**
      * Manually trigger the {@link ImageDataUpdateListener#imageDataUpdated(ImageData)}
      */
Index: /trunk/src/org/openstreetmap/josm/data/gpx/GpxConstants.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/gpx/GpxConstants.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/data/gpx/GpxConstants.java	(revision 19387)
@@ -146,4 +146,9 @@
     String PT_TIME = "time";
 
+    /** True Course/Bearing angle over ground.
+     * @since 19387
+     */
+    String PT_COURSE = "course";
+
     /** Magnetic variation (in degrees) at the point. 0.0 &lt;= value &lt; 360.0 */
     String PT_MAGVAR = "magvar";
@@ -189,6 +194,6 @@
      */
     List<String> WPT_KEYS = Collections.unmodifiableList(Arrays.asList(PT_ELE, PT_TIME, PT_MAGVAR, PT_GEOIDHEIGHT,
-            GPX_NAME, GPX_CMT, GPX_DESC, GPX_SRC, META_LINKS, PT_SYM, PT_TYPE,
-            PT_FIX, PT_SAT, PT_HDOP, PT_VDOP, PT_PDOP, PT_AGEOFDGPSDATA, PT_DGPSID, PT_STD_HDEV, PT_STD_VDEV));
+            GPX_NAME, GPX_CMT, GPX_DESC, GPX_SRC, META_LINKS, PT_SYM, PT_TYPE, PT_FIX, PT_SAT, PT_COURSE,
+            PT_HDOP, PT_VDOP, PT_PDOP, PT_AGEOFDGPSDATA, PT_DGPSID, PT_STD_HDEV, PT_STD_VDEV));
 
     /**
Index: /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java	(revision 19387)
@@ -2,4 +2,5 @@
 package org.openstreetmap.josm.data.gpx;
 
+import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -73,4 +74,5 @@
 
         final GpxImageDirectionPositionSettings dirpos = settings.getDirectionPositionSettings();
+        final GpxImageDatumSettings datumSettings = settings.getDatumSettings();
         final long offset = settings.getOffset();
 
@@ -142,5 +144,6 @@
                     }
                     WayPoint nextWp = i < size - 1 ? wps.get(i + 1) : null;
-                    ret += matchPoints(images, prevWp, prevWpTime, curWp, curWpTime, offset, interpolate, tagTime, nextWp, dirpos);
+                    ret += matchPoints(images, prevWp, prevWpTime, curWp, curWpTime, offset,
+                                       interpolate, tagTime, nextWp, dirpos, datumSettings);
                     prevWp = curWp;
                     prevWpTime = curWpTime;
@@ -149,5 +152,6 @@
         }
         if (trkTag && prevWp != null) {
-            ret += matchPoints(images, prevWp, prevWpTime, prevWp, prevWpTime, offset, false, trkTagTime, null, dirpos);
+            ret += matchPoints(images, prevWp, prevWpTime, prevWp, prevWpTime, offset,
+                               false, trkTagTime, null, dirpos, datumSettings);
         }
         Logging.debug("Correlated {0} total points", ret);
@@ -210,6 +214,109 @@
     }
 
-    private static int matchPoints(List<? extends GpxImageEntry> images, WayPoint prevWp, long prevWpTime, WayPoint curWp, long curWpTime,
-            long offset, boolean interpolate, int tagTime, WayPoint nextWp, GpxImageDirectionPositionSettings dirpos) {
+    static Double getHPosErr(WayPoint wp) {
+        if (wp != null) {
+            if (wp.attr.get(GpxConstants.PT_STD_HDEV) instanceof Float) {
+                Float hposerr = (Float) wp.attr.get(GpxConstants.PT_STD_HDEV);
+                if (hposerr != null) {
+                    return hposerr.doubleValue();
+                }
+            } else if (wp.attr.get(GpxConstants.PT_STD_HDEV) instanceof Double) {               
+                Double hposerr = (Double) wp.attr.get(GpxConstants.PT_STD_HDEV);
+                if (hposerr != null) {
+                    return hposerr;
+                }
+            }
+        }
+        return null;
+    }
+
+    static Double getGpsDop(WayPoint wp) {
+        if (wp != null) {
+            if (wp.attr.get(GpxConstants.PT_PDOP) != null) {
+                if (wp.attr.get(GpxConstants.PT_PDOP) instanceof Float) {
+                    Float pdopvalue = (Float) wp.attr.get(GpxConstants.PT_PDOP);
+                    return pdopvalue.doubleValue();
+                } else if (wp.attr.get(GpxConstants.PT_PDOP) instanceof Double) {
+                    Double pdopvalue = (Double) wp.attr.get(GpxConstants.PT_PDOP);
+                    return pdopvalue.doubleValue();
+                }
+            } else if (wp.attr.get(GpxConstants.PT_HDOP) != null) {
+                if (wp.attr.get(GpxConstants.PT_HDOP) instanceof Float) {
+                    Float hdopvalue = (Float) wp.attr.get(GpxConstants.PT_HDOP);
+                    return hdopvalue.doubleValue();
+                } else if (wp.attr.get(GpxConstants.PT_HDOP) instanceof Double) {
+                    Double hdopvalue = (Double) wp.attr.get(GpxConstants.PT_HDOP);
+                    return hdopvalue.doubleValue();
+                }
+            }
+        }
+        return null;
+    }
+
+    static Double getGpsTrack(WayPoint wp) {
+        if (wp != null) {
+            String trackvalue = wp.getString(GpxConstants.PT_COURSE);
+            Logging.debug("track angle value: {0}", trackvalue);
+            if (!Utils.isEmpty(trackvalue)) {
+                try {
+                    return Double.valueOf(trackvalue);
+                } catch (NumberFormatException e) {
+                    Logging.warn(e);
+                }
+            }
+        }
+        return null;
+    }
+
+    static String getGpsProcMethod(String prevGpsFixMode, final String curGpsFixMode,
+                                    final List<String> positioningModes) {
+        String gpsProcMethod = null;
+        Integer lowestProcIndex = null;
+        int lowestGnssModeIdx = 3; // 2d or higher index in positioningModes list are Gnss methods
+        try {
+            lowestProcIndex = Math.min(positioningModes.indexOf(prevGpsFixMode), positioningModes.indexOf(curGpsFixMode));
+            if (lowestProcIndex < 0) {
+                return null;
+            }
+            gpsProcMethod = "GNSS" + " " + positioningModes.get(lowestProcIndex).toUpperCase() + " " + "CORRELATION";
+            if (lowestProcIndex < lowestGnssModeIdx) {
+                gpsProcMethod = positioningModes.get(lowestProcIndex).toUpperCase() + " " + "CORRELATION";
+            } else {
+                gpsProcMethod = "GNSS" + " " + positioningModes.get(lowestProcIndex).toUpperCase() + " " + "CORRELATION";
+            }
+            gpsProcMethod = gpsProcMethod.replace("FLOAT RTK", "RTK_FLOAT");
+            gpsProcMethod = gpsProcMethod.replace(" RTK ", " RTK_FIX ");
+        } catch (ArrayIndexOutOfBoundsException ex) {
+            Logging.warn(ex);
+        }
+        return gpsProcMethod;
+    }
+
+    static Integer getGps2d3dMode(String prevGpsFixMode, final String curGpsFixMode,
+                                final List<String> positioningModes) {
+        Integer lowestMode = null;
+        lowestMode = Math.min(positioningModes.indexOf(prevGpsFixMode), positioningModes.indexOf(curGpsFixMode));
+        if (lowestMode > 3) {
+            return 3;
+        }
+        if (lowestMode > 2) {
+            return 2;
+        }
+        return null;
+    }
+
+    // CHECKSTYLE.OFF: ParameterNumber
+    private static int matchPoints(List<? extends GpxImageEntry>
+                                        images,
+                                        WayPoint prevWp,
+                                        long prevWpTime,
+                                        WayPoint curWp,
+                                        long curWpTime,
+                                        long offset,
+                                        boolean interpolate,
+                                        int tagTime,
+                                        WayPoint nextWp,
+                                        GpxImageDirectionPositionSettings dirpos,
+                                        GpxImageDatumSettings datumSettings) {
 
         final boolean isLast = nextWp == null;
@@ -237,4 +344,13 @@
         Double speed = null;
         Double prevElevation = null;
+        Double prevHPosErr = null;
+        Double prevGpsDop = null;
+        Double prevGpsTrack = null;
+        String prevGpsFixMode = null;
+        //list of differential GPS mode
+        //TODO move these lists in Gpx.Constants?
+        final List<String> diffMode = Arrays.asList("dgps", "float rtk", "rtk");
+        final List<String> positioningModes = Arrays.asList("none", "manual", "estimated", "2d", "3d", "dgps", "float rtk", "rtk");
+
 
         if (prevWp != null && interpolate) {
@@ -245,7 +361,15 @@
             }
             prevElevation = getElevation(prevWp);
+            prevHPosErr = getHPosErr(prevWp);
+            prevGpsDop = getGpsDop(prevWp);
+            prevGpsTrack = getGpsTrack(prevWp);
+            prevGpsFixMode = prevWp.getString(GpxConstants.PT_FIX);
         }
 
         final Double curElevation = getElevation(curWp);
+        final Double curHPosErr = getHPosErr(curWp);
+        final Double curGpsDop = getGpsDop(curWp);
+        final Double curGpsTrack = getGpsTrack(curWp);
+        final String curGpsFixMode = curWp.getString(GpxConstants.PT_FIX);
 
         if (!interpolate || isLast) {
@@ -267,4 +391,5 @@
                         curTmp.setPos(curWp.getCoor());
                     }
+                    //TODO fix this, nextWp doesn't exist here
                     if (nextWp != null && dirpos.isSetImageDirection()) {
                         double direction = curWp.bearing(nextWp);
@@ -318,4 +443,60 @@
                         curTmp.setElevation(prevElevation + (curElevation - prevElevation) * timeDiff + dirpos.getElevationShift());
                     }
+
+                    // Add exif GpsHPositioningerror interpolated value
+                    if (curHPosErr != null && prevHPosErr != null) {
+                        Double interpolatedValue = prevHPosErr + (curHPosErr - prevHPosErr) * timeDiff;
+                        curTmp.setExifHPosErr(Math.round(interpolatedValue*10000)/10000.0);
+                    }
+
+                    // Add exif GpsDifferentialMode
+                    // Get previous and current waypoint differential. As no interpolation is possible,
+                    // set differential mode to 0 if any waypoint isn't in differential mode.
+                    if (prevGpsFixMode != null) {
+                        if (diffMode.contains(prevGpsFixMode) && diffMode.contains(curGpsFixMode)) {
+                            curTmp.setGpsDiffMode(1);
+                        } else {
+                            curTmp.setGpsDiffMode(0);
+                        }
+                    }
+
+                    // Add exif GpsMeasureMode
+                    if (prevGpsFixMode != null && curGpsFixMode != null) {
+                        Integer gps2d3dMode = getGps2d3dMode(prevGpsFixMode, curGpsFixMode, positioningModes);
+                        if (gps2d3dMode != null) {
+                            curTmp.setGps2d3dMode(gps2d3dMode);
+                        }
+                    }
+                    
+                    // Add exif GpsProcessingMethod. As no interpolation is possible,
+                    // set processing method to the "lowest" previous and current processing method value.
+                    if (prevGpsFixMode != null && curGpsFixMode != null) {
+                        String gpsProcMethod = getGpsProcMethod(prevGpsFixMode, curGpsFixMode, positioningModes);                       
+                        if (gpsProcMethod != null) {
+                            curTmp.setExifGpsProcMethod(gpsProcMethod);
+                        }
+                    }
+
+                    // Add Exif GpsDop with interpolated GPS DOP value
+                    if (curGpsDop != null && prevGpsDop != null) {
+                        Double interpolatedValue = prevGpsDop + (curGpsDop - prevGpsDop) * timeDiff;
+                        curTmp.setExifGpsDop(Math.round(interpolatedValue*100)/100.0);
+                    }
+
+                    // Add Exif GpsTrack tag
+                    if (dirpos.isSetGpxTrackDirection()) {
+                        if (curGpsTrack != null && prevGpsTrack != null) {
+                            curTmp.setExifGpsTrack(prevGpsTrack + (curGpsTrack - prevGpsTrack) * timeDiff);
+                        }
+                    }
+                    
+                    // Add GpsDatum tag
+                    if (datumSettings.isSetImageGpsDatum()) {
+                        if (diffMode.contains(prevGpsFixMode) && diffMode.contains(curGpsFixMode)) {
+                            curTmp.setExifGpsDatum(datumSettings.getImageGpsDatum());
+                        } else //without differential mode, datum is WGS-84
+                            curTmp.setExifGpsDatum("WGS-84");
+                    }
+
                     curTmp.setGpsTime(curImg.getExifInstant().minusMillis(offset));
                     curTmp.flagNewGpsData();
@@ -331,4 +512,5 @@
         return ret;
     }
+    // CHECKSTYLE.ON: ParameterNumber
 
     private static double computeDirection(double direction, double angleOffset) {
Index: /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelationSettings.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelationSettings.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelationSettings.java	(revision 19387)
@@ -13,4 +13,5 @@
     private final boolean forceTags;
     private final GpxImageDirectionPositionSettings directionPositionSettings;
+    private final GpxImageDatumSettings datumSettings;
 
     /**
@@ -20,5 +21,8 @@
      */
     public GpxImageCorrelationSettings(long offset, boolean forceTags) {
-        this(offset, forceTags, new GpxImageDirectionPositionSettings(false, 0, 0, 0, 0));
+        this(offset, forceTags,
+        new GpxImageDirectionPositionSettings(false, 0, false, 0, 0, 0),
+        new GpxImageDatumSettings(false, null)
+        );
     }
 
@@ -31,9 +35,25 @@
     public GpxImageCorrelationSettings(long offset, boolean forceTags,
             GpxImageDirectionPositionSettings directionPositionSettings) {
+        this(offset, forceTags, directionPositionSettings,
+        new GpxImageDatumSettings(false, null));
+    }
+
+    /**
+     * Constructs a new {@code GpxImageCorrelationSettings}.
+     * @param offset offset in milliseconds
+     * @param forceTags force tagging of all photos, otherwise prefs are used
+     * @param directionPositionSettings direction/position settings
+     * @param datumSettings GPS datum settings
+     * @since 19387 @datumSettings was added
+     */
+    public GpxImageCorrelationSettings(long offset, boolean forceTags,
+            GpxImageDirectionPositionSettings directionPositionSettings,
+            GpxImageDatumSettings datumSettings) {
         this.offset = offset;
         this.forceTags = forceTags;
         this.directionPositionSettings = Objects.requireNonNull(directionPositionSettings);
+        this.datumSettings = Objects.requireNonNull(datumSettings);
     }
-
+    
     /**
      * Returns the offset in milliseconds.
@@ -60,8 +80,18 @@
     }
 
+    /**
+     * Returns the EXIF metadata datum settings.
+     * @return the EXIF metadata datum settings
+     * @since 19387
+     */
+    public GpxImageDatumSettings getDatumSettings() {
+        return datumSettings;
+    }
+
     @Override
     public String toString() {
         return "[offset=" + offset + ", forceTags=" + forceTags
-                + ", directionPositionSettings=" + directionPositionSettings + ']';
+                + ", directionPositionSettings=" + directionPositionSettings
+                + ", datumSettings=" + datumSettings + ']';
     }
 }
Index: /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageDatumSettings.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageDatumSettings.java	(revision 19387)
+++ /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageDatumSettings.java	(revision 19387)
@@ -0,0 +1,39 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.gpx;
+
+/**
+ * Image extended exif metadata settings used by {@link GpxImageCorrelationSettings}.
+ * @since 19387
+ */
+public class GpxImageDatumSettings {
+
+    private final boolean setImageGpsDatum;
+    private final String imageGpsDatum;
+    
+    /**
+     * Construcs a new {@code GpxImageDatumSettings}.
+     * @param setImageGpsDatum determines if images GPS datum must be set
+     * @param imageGpsDatum determines the GPS coordinates datum value to be set
+     */
+    public GpxImageDatumSettings(
+        boolean setImageGpsDatum, String imageGpsDatum) {
+            this.setImageGpsDatum = setImageGpsDatum;
+            this.imageGpsDatum = imageGpsDatum;
+        }
+    
+    /**
+     * Determines if image GPS datum must be set
+     * @return if the GPS datum must be set
+     */
+    public boolean isSetImageGpsDatum() {
+        return setImageGpsDatum;
+    }
+    
+    /**
+     * Return the GPS coordinates datum code.
+     * @return the datum code
+     */
+    public String getImageGpsDatum() {
+        return imageGpsDatum;
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageDirectionPositionSettings.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageDirectionPositionSettings.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageDirectionPositionSettings.java	(revision 19387)
@@ -10,4 +10,5 @@
     private final boolean setImageDirection;
     private final double imageDirectionAngleOffset;
+    private final boolean setGpxTrackDirection;
     private final double shiftImageX;
     private final double shiftImageY;
@@ -18,12 +19,16 @@
      * @param setImageDirection determines if image direction must be set towards the next GPX waypoint
      * @param imageDirectionAngleOffset direction angle offset in degrees
+     * @param setGpxTrackDirection determines if image course direction must be set
      * @param shiftImageX image shift on X axis relative to the direction in meters
      * @param shiftImageY image shift on Y axis relative to the direction in meters
      * @param elevationShift image elevation shift in meters
+     * @since 19387 @setGpsTrackDirection was added
      */
     public GpxImageDirectionPositionSettings(
-            boolean setImageDirection, double imageDirectionAngleOffset, double shiftImageX, double shiftImageY, double elevationShift) {
+            boolean setImageDirection, double imageDirectionAngleOffset, boolean setGpxTrackDirection, 
+            double shiftImageX, double shiftImageY, double elevationShift) {
         this.setImageDirection = setImageDirection;
         this.imageDirectionAngleOffset = imageDirectionAngleOffset;
+        this.setGpxTrackDirection = setGpxTrackDirection;
         this.shiftImageX = shiftImageX;
         this.shiftImageY = shiftImageY;
@@ -45,4 +50,13 @@
     public double getImageDirectionAngleOffset() {
         return imageDirectionAngleOffset;
+    }
+
+    /**
+     * Determines if GPS course direction must be set. Angle value is from the gpx trace.
+     * @return {@code true} if image GPS course must be set
+     * @since 19387
+     */
+    public boolean isSetGpxTrackDirection() {
+        return setGpxTrackDirection;
     }
 
@@ -74,6 +88,9 @@
     public String toString() {
         return "[setImageDirection=" + setImageDirection
-                + ", imageDirectionAngleOffset=" + imageDirectionAngleOffset + ", shiftImageX=" + shiftImageX
-                + ", shiftImageY=" + shiftImageY + ", elevationShift=" + elevationShift + ']';
+                + ", imageDirectionAngleOffset=" + imageDirectionAngleOffset
+                + ", setImageGpxTrackDirection=" + setGpxTrackDirection
+                + ", shiftImageX=" + shiftImageX
+                + ", shiftImageY=" + shiftImageY
+                + ", elevationShift=" + elevationShift + ']';
     }
 }
Index: /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java	(revision 19387)
@@ -33,4 +33,7 @@
     private LatLon exifCoor;
     private Double exifImgDir;
+    private Double exifGpsTrack;
+    private Double exifHPosErr;
+    private Double exifGpsDop;
     private Instant exifTime;
     private Projections cameraProjection = Projections.UNKNOWN;
@@ -58,4 +61,12 @@
     /** Elevation (altitude) in meters */
     private Double elevation;
+    /** GPS Differential mode */
+    private Integer gpsDiffMode;
+    /** GPS Measure mode */
+    private Integer gps2d3dMode;
+    /** GPS Datum */
+    private String exifGpsDatum;
+    /** GPS processing method */
+    private String exifGpsProcMethod;
     /** The time after correlation with a gpx track */
     private Instant gpsTime;
@@ -89,4 +100,11 @@
         exifCoor = other.exifCoor;
         exifImgDir = other.exifImgDir;
+        exifGpsTrack = other.exifGpsTrack;
+        exifHPosErr = other.exifHPosErr;
+        gpsDiffMode = other.gpsDiffMode;
+        gps2d3dMode = other.gps2d3dMode;
+        exifGpsDop = other.exifGpsDop;
+        exifGpsDatum = other.exifGpsDatum;
+        exifGpsProcMethod = other.exifGpsProcMethod;
         exifTime = other.exifTime;
         isNewGpsData = other.isNewGpsData;
@@ -171,4 +189,67 @@
 
     /**
+     * Return the GPS Differential mode value. The GPS Differential mode value from the temporary
+     * copy is returned if that copy exists. 
+     * @return the differential mode value
+     * @since 19387
+     */
+    @Override
+    public Integer getGpsDiffMode() {
+        if (tmp != null)
+            return tmp.gpsDiffMode;
+        return gpsDiffMode;
+    }
+
+    /**
+     * Return the GPS 2d or 3d mode value. The GPS mode value form the temporary
+     * copy is returned if that copy exists. 
+     * @return the GPS 2d/3d mode value
+     * @since 19387
+     */
+    @Override
+    public Integer getGps2d3dMode() {
+        if (tmp != null)
+            return tmp.gps2d3dMode;
+        return gps2d3dMode;
+    }
+
+    /**
+     * Return the GPS DOP value. The GPS DOP value from the temporary
+     * copy is returned if that copy exists. 
+     * @return the DOP value
+     * @since 19387
+     */
+    @Override
+    public Double getExifGpsDop() {
+        if (tmp != null)
+            return tmp.exifGpsDop;
+        return exifGpsDop;
+    }
+
+    /**
+     * Return the exif GPS coordinates datum value.
+     * @return The datum value
+     * @since 19387
+     */
+    @Override
+    public String getExifGpsDatum() {
+        if (tmp != null)
+            return tmp.exifGpsDatum;
+        return exifGpsDatum;
+    }
+
+    /**
+     * Return the exif GPS processing method string
+     * @return the processing method string
+     * @since 19387
+     */
+    @Override
+    public String getExifGpsProcMethod() {
+        if (tmp != null)
+            return tmp.exifGpsProcMethod;
+        return exifGpsProcMethod;
+    }
+
+    /**
      * Returns the GPS time value. The GPS time value from the temporary copy
      * is returned if that copy exists.
@@ -272,4 +353,30 @@
             return tmp.exifImgDir;
         return exifImgDir;
+    }
+    
+    /**
+     * Convenient way to determine if this entry has a EXIF GPS track angle value,
+     * without the cost of building a defensive copy.
+     * @return {@code true} if this entry has a EXIF track angle value
+     * @since 19387
+     */
+    @Override
+    public Double getExifGpsTrack() {
+        if (tmp != null)
+            return tmp.exifGpsTrack;
+        return exifGpsTrack;
+    }
+
+    /**
+     * Convenient way to determine if this entry has a EXIF GPS horizontal positionning error value,
+     * without the cost of building a defensive copy.
+     * @return {@code true} if this entry has a EXIF GPS horizontal positionning error value
+     * @since 19387
+     */
+    @Override
+    public Double getExifHPosErr() {
+        if (tmp != null)
+            return tmp.exifHPosErr;
+        return exifHPosErr;
     }
 
@@ -347,4 +454,54 @@
 
     /**
+     * Sets GPS Differential mode.
+     * @param gpsDiffMode GPS Differential mode
+     * @since 19387
+     */
+    @Override
+    public void setGpsDiffMode(Integer gpsDiffMode) {
+        this.gpsDiffMode = gpsDiffMode;
+    }
+
+    /**
+     * Sets GPS 2d/3d mode.
+     * @param gps2d3dMode GPS 2d/3d mode value
+     * @since 19387
+     */
+    @Override
+    public void setGps2d3dMode(Integer gps2d3dMode) {
+        this.gps2d3dMode = gps2d3dMode;
+    }
+
+    /**
+     * Sets GPS DOP value.
+     * @param exifGpsDop GPS DOP value
+     * @since 19387
+     */
+    @Override
+    public void setExifGpsDop(Double exifGpsDop) {
+        this.exifGpsDop = exifGpsDop;
+    }
+
+    /**
+     * Sets the GPS Datum.
+     * @param exifGpsDatum GPS Datum
+     * @since 19387
+     */
+    @Override
+    public void setExifGpsDatum(String exifGpsDatum) {
+        this.exifGpsDatum = exifGpsDatum;
+    }
+
+    /**
+     * Sets the GPS Processing Method.
+     * @param exifGpsProcMethod GPS Processing Method
+     * @since 19387
+     */
+    @Override
+    public void setExifGpsProcMethod(String exifGpsProcMethod) {
+        this.exifGpsProcMethod = exifGpsProcMethod;
+    }
+
+    /**
      * Sets associated file.
      * @param file associated file
@@ -411,4 +568,24 @@
     public void setExifImgDir(Double exifDir) {
         this.exifImgDir = exifDir;
+    }
+
+    /**
+     * Sets the exif GPS track (move direction angle)
+     * @param exifGpsTrack the exif GPS track angle
+     * @since 19387
+     */
+    @Override
+    public void setExifGpsTrack(Double exifGpsTrack) {
+        this.exifGpsTrack = exifGpsTrack;
+    }
+
+    /**
+     * Sets the exif horizontal positioning error
+     * @param exifHposErr the Exif horizontal positionning error
+     * @since 19387
+     */
+    @Override
+    public void setExifHPosErr(Double exifHPosErr) {
+        this.exifHPosErr = exifHPosErr;
     }
 
@@ -508,7 +685,8 @@
     public int hashCode() {
         return Objects.hash(height, width, isNewGpsData,
-            elevation, exifCoor, exifGpsTime, exifImgDir, exifOrientation, exifTime,
-            iptcCaption, iptcHeadline, iptcKeywords, iptcObjectName,
-            file, gpsTime, pos, speed, tmp, cameraProjection);
+            elevation, exifCoor, exifGpsTime, exifImgDir, exifGpsTrack, exifHPosErr,
+            exifGpsDop, gpsDiffMode, gps2d3dMode, exifGpsDatum, exifGpsProcMethod,
+            exifOrientation, exifTime, iptcCaption, iptcHeadline, iptcKeywords,
+            iptcObjectName, file, gpsTime, pos, speed, tmp, cameraProjection);
     }
 
@@ -527,4 +705,11 @@
             && Objects.equals(exifGpsTime, other.exifGpsTime)
             && Objects.equals(exifImgDir, other.exifImgDir)
+            && Objects.equals(exifGpsTrack, other.exifGpsTrack)
+            && Objects.equals(exifHPosErr, other.exifHPosErr)
+            && Objects.equals(gpsDiffMode, other.gpsDiffMode)
+            && Objects.equals(gps2d3dMode, other.gps2d3dMode)
+            && Objects.equals(exifGpsDop, other.exifGpsDop)
+            && Objects.equals(exifGpsDatum, other.exifGpsDatum)
+            && Objects.equals(exifGpsProcMethod, other.exifGpsProcMethod)
             && Objects.equals(exifOrientation, other.exifOrientation)
             && Objects.equals(exifTime, other.exifTime)
@@ -571,4 +756,5 @@
      * temporary variable is deleted.
      * @see #discardTmp()
+     * @since 19387 exifGpsTrack, exifHPosErr, gpsDiffMode, gps2d3dMode, exifGpsDop, exifGpsDatum, exifGpsProcMethod added
      */
     public void applyTmp() {
@@ -579,4 +765,11 @@
             gpsTime = tmp.gpsTime;
             exifImgDir = tmp.exifImgDir;
+            exifGpsTrack = tmp.exifGpsTrack;
+            exifHPosErr = tmp.exifHPosErr;
+            gpsDiffMode = tmp.gpsDiffMode;
+            gps2d3dMode = tmp.gps2d3dMode;
+            exifGpsDop = tmp.exifGpsDop;
+            exifGpsDatum = tmp.exifGpsDatum;
+            exifGpsProcMethod = tmp.exifGpsProcMethod;
             isNewGpsData = isNewGpsData || tmp.isNewGpsData;
             tmp = null;
Index: /trunk/src/org/openstreetmap/josm/data/imagery/street_level/IImageEntry.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/imagery/street_level/IImageEntry.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/data/imagery/street_level/IImageEntry.java	(revision 19387)
@@ -220,4 +220,44 @@
 
     /**
+     * Return the GPS Differential mode value. The differential mode value from the temporary
+     * copy is returned if that copy exists. 
+     * @return the fix mode value
+     * @since 19387
+     */
+    Integer getGpsDiffMode();
+
+    /**
+     * Return the GPS 2d/3d mode value. The 2d/3d mode value from the temporary
+     * copy is returned if that copy exists.
+     * @return the 2d/3d mode value
+     * @since 19387
+     */
+    Integer getGps2d3dMode();
+
+    /**
+     * Return the GPS DOP value. The GPS DOP value from the temporary
+     * copy is return if that copy exists.
+     * @return the GPS DOP value
+     * @since 19387
+     */
+    Double getExifGpsDop();
+
+    /**
+     * Return the GPS datum value. The GPS datum value from the temporary
+     * copy is return if that copy exists. 
+     * @return the GPS datum value
+     * @since 19387
+     */
+    String getExifGpsDatum();
+
+    /**
+     * Return the GPS processing method. The processing method value from the temporary
+     * copy is return if that copy exists.
+     * @return the GPS processing method
+     * @since 19387
+     */
+    String getExifGpsProcMethod();
+
+    /**
      * Returns the image direction. The image direction from the temporary
      * copy is returned if that copy exists.
@@ -225,5 +265,21 @@
      */
     Double getExifImgDir();
-
+    
+    /**
+     * Returns the image GPS track direction. The GPS track direction from the temporary
+     * copy is returned if that copy exists.
+     * @return the image GPS track direction angle
+     * @since 19387
+     */
+    Double getExifGpsTrack();
+
+    /**
+     * Returns the image horizontal positionning error. The image positionning error
+     * from the temporary copy is returned if that copy exists.
+     * @return the image horizontal positionning error
+     * @since 19387
+     */
+    Double getExifHPosErr();
+    
     /**
      * Convenient way to determine if this entry has a EXIF time, without the cost of building a defensive copy.
@@ -253,4 +309,12 @@
 
     /**
+     * Returns the Exif GPS Time value. The Exif GPS time value from the temporary copy
+     * is returned if that copy exists.
+     * @return the Exif GPS time value
+     * @since 19387
+     */
+    Instant getExifGpsInstant();
+
+    /**
      * Returns the IPTC caption.
      * @return the IPTC caption
Index: /trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 19387)
@@ -979,4 +979,7 @@
         addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_TYPE, null, null);
 
+        // Angle info
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_COURSE, "gps:course");
+
         // Accuracy info
         addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_FIX, "gps:fix", null);
@@ -985,4 +988,6 @@
         addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_VDOP, "gps:vdop");
         addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_PDOP, "gps:pdop");
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_STD_HDEV, "gps:stdhdev");
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_STD_VDEV, "gps:stdvdev");
         addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_AGEOFDGPSDATA, "gps:ageofdgpsdata");
         addIntegerIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_DGPSID, "gps:dgpsid");
Index: /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java	(revision 19387)
@@ -54,4 +54,5 @@
 import org.openstreetmap.josm.data.gpx.GpxImageCorrelation;
 import org.openstreetmap.josm.data.gpx.GpxImageCorrelationSettings;
+import org.openstreetmap.josm.data.gpx.GpxImageDatumSettings;
 import org.openstreetmap.josm.data.gpx.GpxTimeOffset;
 import org.openstreetmap.josm.data.gpx.GpxTimezone;
@@ -169,4 +170,5 @@
                 Config.getPref().put("geoimage.delta", delta.formatOffset());
                 Config.getPref().putBoolean("geoimage.showThumbs", yLayer.useThumbs);
+                Config.getPref().put("geoimage.datum", tfDatum.getText());
 
                 yLayer.useThumbs = cbShowThumbs.isSelected();
@@ -247,4 +249,5 @@
     private ExtendedDialog syncDialog;
     private JPanel outerPanel;
+    private JPanel expertPanel;
     private JosmComboBox<GpxDataWrapper> cbGpx;
     private JButton buttonSupport;
@@ -254,7 +257,12 @@
     private JCheckBox cbTaggedImg;
     private JCheckBox cbShowThumbs;
+    private JSeparator sepExtendedTags;
+    private JLabel labelExtTags;
+    private JLabel labelDatum;
     private JLabel statusBarText;
     private JSeparator sepDirectionPosition;
     private ImageDirectionPositionPanel pDirectionPosition;
+    private JCheckBox cbAddGpsDatum;
+    private JosmTextField tfDatum;
 
     // remember the last number of matched photos
@@ -473,4 +481,9 @@
     }
 
+    static String loadGpsDatum() {
+        String gpsDatum = Config.getPref().get("geoimage.datum", "WGS-84");
+        return gpsDatum;
+    }
+
     @Override
     public void actionPerformed(ActionEvent ae) {
@@ -542,48 +555,28 @@
 
         int y = 0;
-        GBC gbc = GBC.eol();
-        gbc.gridx = 0;
-        gbc.gridy = y++;
-        panelTf.add(panelCb, gbc);
-
-        gbc = GBC.eol().fill(GridBagConstraints.HORIZONTAL).insets(0, 0, 0, 12);
-        gbc.gridx = 0;
-        gbc.gridy = y++;
+        panelTf.add(panelCb, GBC.eol().grid(0, y++));
+
+        GBC gbc = GBC.eol().grid(0, y++).fill(GridBagConstraints.HORIZONTAL).insets(0, 0, 0, 12);
         panelTf.add(new JSeparator(SwingConstants.HORIZONTAL), gbc);
 
-        gbc = GBC.std();
-        gbc.gridx = 0;
-        gbc.gridy = y;
-        panelTf.add(new JLabel(tr("Timezone: ")), gbc);
-
-        gbc = GBC.std().fill(GridBagConstraints.HORIZONTAL);
-        gbc.gridx = 1;
-        gbc.gridy = y++;
+        panelTf.add(new JLabel(tr("Timezone: ")), GBC.std(0, y));
+
+        gbc = GBC.std(1, y++).fill(GridBagConstraints.HORIZONTAL);
         gbc.weightx = 1.;
         panelTf.add(tfTimezone, gbc);
 
-        gbc = GBC.std();
-        gbc.gridx = 0;
-        gbc.gridy = y;
+        gbc = GBC.std(0, y);
         panelTf.add(new JLabel(tr("Offset:")), gbc);
 
-        gbc = GBC.std().fill(GridBagConstraints.HORIZONTAL);
-        gbc.gridx = 1;
-        gbc.gridy = y++;
+        gbc = GBC.std(1, y++).fill(GridBagConstraints.HORIZONTAL);
         gbc.weightx = 1.;
         panelTf.add(tfOffset, gbc);
 
-        gbc = GBC.std().insets(5, 5, 5, 5);
-        gbc.gridx = 2;
-        gbc.gridy = y-2;
-        gbc.gridheight = 2;
-        gbc.gridwidth = 2;
+        gbc = GBC.std(2, y-2).insets(5, 5, 5, 5).span(2, 2);
         gbc.fill = GridBagConstraints.BOTH;
         gbc.weightx = 0.5;
         panelTf.add(buttonViewGpsPhoto, gbc);
 
-        gbc = GBC.std().fill(GridBagConstraints.BOTH).insets(5, 5, 5, 5);
-        gbc.gridx = 1;
-        gbc.gridy = y++;
+        gbc = GBC.std(1, y++).fill(GridBagConstraints.BOTH).insets(5, 5, 5, 5);
         gbc.weightx = 0.5;
         panelTf.add(buttonAdvanced, gbc);
@@ -595,29 +588,12 @@
         panelTf.add(buttonAdjust, gbc);
 
-        gbc = GBC.eol().fill(GridBagConstraints.HORIZONTAL).insets(0, 12, 0, 0);
-        gbc.gridx = 0;
-        gbc.gridy = y++;
+        gbc = GBC.eol().grid(0, y++).fill(GridBagConstraints.HORIZONTAL).insets(0, 12, 0, 0);
         panelTf.add(new JSeparator(SwingConstants.HORIZONTAL), gbc);
-
-        gbc = GBC.eol();
-        gbc.gridx = 0;
-        gbc.gridy = y++;
-        panelTf.add(labelPosition, gbc);
-
-        gbc = GBC.eol();
-        gbc.gridx = 1;
-        gbc.gridy = y++;
-        panelTf.add(cbExifImg, gbc);
-
-        gbc = GBC.eol();
-        gbc.gridx = 1;
-        gbc.gridy = y++;
-        panelTf.add(cbTaggedImg, gbc);
-
-        gbc = GBC.eol();
-        gbc.gridx = 0;
-        gbc.gridy = y++;
-        panelTf.add(cbShowThumbs, gbc);
-
+        panelTf.add(labelPosition, GBC.eol().grid(0, y++));
+        panelTf.add(cbExifImg, GBC.eol().grid(1, y++));
+        panelTf.add(cbTaggedImg, GBC.eol().grid(1, y++));
+        panelTf.add(cbShowThumbs, GBC.eol().grid(0, y++));
+
+        //Image direction and position offset GUI
         gbc = GBC.eol().fill(GridBagConstraints.HORIZONTAL).insets(0, 12, 0, 0);
         sepDirectionPosition = new JSeparator(SwingConstants.HORIZONTAL);
@@ -631,4 +607,31 @@
         panelTf.add(pDirectionPosition, gbc);
 
+        //Extended tags GUI panel
+        expertPanel = new JPanel(new GridBagLayout());
+        gbc = GBC.eol().grid(0, 0).fill(GridBagConstraints.HORIZONTAL).insets(0, 12, 0, 0);
+        sepExtendedTags = new JSeparator(SwingConstants.HORIZONTAL);
+        expertPanel.add(sepExtendedTags, gbc);
+
+        labelExtTags = new JLabel(tr("Extended tags"));
+        cbAddGpsDatum = new JCheckBox(tr("Set datum for images coordinates"));
+        cbAddGpsDatum.addActionListener(e -> tfDatum.setEnabled(!tfDatum.isEnabled()));
+
+        labelDatum = new JLabel(tr("Datum: "));
+        //TODO An AutoCompComboBox would be nice to list the recent datum values. I don't have the skill to add it.
+        tfDatum = new JosmTextField(loadGpsDatum(), 8);
+        tfDatum.setToolTipText(tr("<html>Enter the datum for your images coordinates. Default value is WGS-84.<br>" + 
+                                "For RTK it could be your local CRS epsg code.<br>(e.g. EPSG:9782 for France mainland.)</html>"));
+        tfDatum.setEnabled(false);
+
+        expertPanel.add(labelExtTags, GBC.eol().grid(0, 1));
+        expertPanel.add(cbAddGpsDatum, GBC.eol().grid(0, 2));
+        expertPanel.add(labelDatum, GBC.std(1, 3));
+        expertPanel.add(tfDatum, GBC.eol().grid(2, 3));
+
+        //Add expertPanel to panelTf
+        gbc = GBC.eol().fill(GridBagConstraints.HORIZONTAL).insets(0, 12, 0, 0);
+        gbc.gridy = y++;
+        panelTf.add(expertPanel, gbc);
+        
         final JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
         statusPanel.setBorder(BorderFactory.createLoweredBevelBorder());
@@ -652,4 +655,6 @@
         cbExifImg.addItemListener(statusBarUpdaterWithRepaint);
         cbTaggedImg.addItemListener(statusBarUpdaterWithRepaint);
+        cbAddGpsDatum.addItemListener(statusBarUpdaterWithRepaint);
+        tfDatum.getDocument().addDocumentListener(statusBarUpdater);
         pDirectionPosition.addChangeListenerOnComponents(statusBarUpdaterWithRepaint);
         pDirectionPosition.addItemListenerOnComponents(statusBarUpdaterWithRepaint);
@@ -679,4 +684,10 @@
     }
 
+    public GpxImageDatumSettings getSettings() {
+        return new GpxImageDatumSettings(
+            cbAddGpsDatum.isSelected(),
+            tfDatum.getText());
+    }
+
     @Override
     public void expertChanged(boolean isExpert) {
@@ -689,4 +700,7 @@
         if (pDirectionPosition != null) {
             pDirectionPosition.setVisible(isExpert);
+        }
+        if (expertPanel != null) {
+            expertPanel.setVisible(isExpert);
         }
         if (syncDialog != null) {
@@ -787,5 +801,6 @@
             lastNumMatched = GpxImageCorrelation.matchGpxTrack(dateImgLst, selGpx.data,
                     pDirectionPosition.isVisible() ?
-                            new GpxImageCorrelationSettings(offsetMs, forceTags, pDirectionPosition.getSettings()) :
+                            new GpxImageCorrelationSettings(offsetMs, forceTags, pDirectionPosition.getSettings(),
+                                                            new GpxImageDatumSettings(cbAddGpsDatum.isSelected(), tfDatum.getText())) :
                             new GpxImageCorrelationSettings(offsetMs, forceTags));
 
Index: /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDirectionPositionPanel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDirectionPositionPanel.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDirectionPositionPanel.java	(revision 19387)
@@ -29,4 +29,5 @@
     private final JCheckBox cChangeImageDirection = new JCheckBox();
     private final JSpinner sOffsetDegrees = new JSpinner(new SpinnerNumberModel(0, -360, 360, 1));
+    private final JCheckBox cSetGpxTrackTag = new JCheckBox();
 
     private final JSpinner sX = new JSpinner(new SpinnerNumberModel(0.0, -50.0, 50.0, 0.1));
@@ -38,5 +39,5 @@
      * @param changeDirectionText the text displayed for the change image direction combobox
      */
-    protected ImageDirectionPositionPanel(String changeDirectionText) {
+    protected ImageDirectionPositionPanel(String changeDirectionText, boolean hideGpxTrack) {
         super(new GridBagLayout());
 
@@ -46,4 +47,10 @@
         addSetting(tr("Offset angle in degrees:"), sOffsetDegrees);
         sOffsetDegrees.setEnabled(false);
+        if (!hideGpxTrack) {
+            cChangeImageDirection.addActionListener(e -> cSetGpxTrackTag.setEnabled(!cSetGpxTrackTag.isEnabled()));
+            cSetGpxTrackTag.setText(tr("Set image course direction (from gpx track)"));
+            add(cSetGpxTrackTag, GBC.eol().insets(0, 0, 0, 5));
+            cSetGpxTrackTag.setEnabled(false);
+        }
 
         add(new JSeparator(SwingConstants.HORIZONTAL),
@@ -62,5 +69,5 @@
      */
     public static ImageDirectionPositionPanel forGpxTrace() {
-        return new ImageDirectionPositionPanel(tr("Set image direction towards the next GPX waypoint"));
+        return new ImageDirectionPositionPanel(tr("Set image direction towards the next GPX waypoint"), false);
     }
 
@@ -70,5 +77,5 @@
      */
     public static ImageDirectionPositionPanel forImageSequence() {
-        return new ImageDirectionPositionPanel(tr("Set image direction towards the next one"));
+        return new ImageDirectionPositionPanel(tr("Set image direction towards the next one"), true);
     }
 
@@ -87,4 +94,5 @@
                 cChangeImageDirection.isSelected(),
                 (Integer) sOffsetDegrees.getValue(),
+                cSetGpxTrackTag.isSelected(),
                 (Double) sX.getValue(),
                 (Double) sY.getValue(),
@@ -110,4 +118,5 @@
     public void addItemListenerOnComponents(ItemListener listener) {
         cChangeImageDirection.addItemListener(listener);
+        cSetGpxTrackTag.addItemListener(listener);
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageMetadata.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageMetadata.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageMetadata.java	(revision 19387)
@@ -117,5 +117,5 @@
 
     /**
-     * Get the exif coordinates
+     * Get the EXIF coordinates
      * @return The location of the image
      */
@@ -123,5 +123,5 @@
 
     /**
-     * Get the exif direction
+     * Get the EXIF direction
      * @return The image direction
      */
@@ -129,5 +129,54 @@
 
     /**
-     * Get the last time the source was modified
+     * Get the EXIF GPS track direction.
+     * @return The GPS track direction
+     * @since 19387
+     */
+    Double getExifGpsTrack();
+
+    /**
+     * Get the EXIF Horizontal positioning error.
+     * @return The image horizontal positioning error
+     * @since 19387
+     */
+    Double getExifHPosErr();
+
+    /**
+     * Get the GPS Differential mode.
+     * @return The image gnss fix mode
+     * @since 19387
+     */
+    Integer getGpsDiffMode();
+    
+    /**
+     * Get the GPS 2d/3d mode.
+     * @return The image gnss 2d/3d mode
+     * @since 19387
+     */
+    Integer getGps2d3dMode();
+
+    /**
+     * Get the EXIF GPS DOP value.
+     * @return The image GPS DOP value
+     * @since 19387
+     */
+    Double getExifGpsDop();
+
+    /**
+     * Get the GPS datum value.
+     * @return The image GPS datum value
+     * @since 19387
+     */
+    String getExifGpsDatum();
+
+    /**
+     * Get the EXIF GPS processing method.
+     * @return The image GPS processing method
+     * @since 19387
+     */
+    String getExifGpsProcMethod();
+
+    /**
+     * Get the last time the source was modified.
      * @return The last time the source was modified
      */
@@ -194,14 +243,63 @@
 
     /**
-     * Set the exif coordinates
-     * @param exifCoor The exif coordinates
+     * Sets the EXIF coordinates
+     * @param exifCoor The EXIF coordinates
      */
     void setExifCoor(ILatLon exifCoor);
 
     /**
-     * Set the exif direction
+     * Sets the EXIF direction
      * @param exifDir The direction
      */
     void setExifImgDir(Double exifDir);
+
+    /**
+     * Sets the EXIF GPS track direction.
+     * @param exifGpsTrack The GPS track direction
+     * @since 19387
+     */
+    void setExifGpsTrack(Double exifGpsTrack);
+
+    /**
+     * Sets the EXIF horizontal positioning error.
+     * @param exifHposErr the EXIF horizontal positionning error
+     * @since 19387
+     */
+    void setExifHPosErr(Double exifHPosErr);
+
+    /**
+     * Sets the EXIF GPS DOP value.
+     * @param exifGpsDop the EXIF GPS DOP value
+     * @since 19387
+     */
+    void setExifGpsDop(Double exifGpsDop);
+
+    /**
+     * Sets the GPS Differential mode.
+     * @param gpsDiffMode GPS Differential mode
+     * @since 19387
+     */
+    void setGpsDiffMode(Integer gpsDiffMode);
+
+    /**
+     * Sets the GPS 2d/3d mode.
+     * @param gps2d3dMode GPS 2d/3d mode
+     * @since 19387
+     */
+    void setGps2d3dMode(Integer gps2d3dMode);
+
+    /**
+     * Sets the GPS datum value.
+     * @param exifGpsDatum GPS datum
+     * @since 19387
+     */
+    void setExifGpsDatum(String exifGpsDatum);
+
+    /**
+     * Sets the GPS processing method.
+     * @param exifGpsProcMethod GPS processing method
+     * @since 19387
+     */
+    void setExifGpsProcMethod(String exifGpsProcMethod);
 
     /**
Index: /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageUtils.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageUtils.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageUtils.java	(revision 19387)
@@ -192,4 +192,46 @@
         }
 
+        try {
+            ifNotNull(ExifReader.readGpsTrackDirection(dirGps), image::setExifGpsTrack);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+
+        try {
+            ifNotNull(ExifReader.readHpositioningError(dirGps), image::setExifHPosErr);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+        
+        try {
+            ifNotNull(ExifReader.readGpsDiffMode(dirGps), image::setGpsDiffMode);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+        
+        try {
+            ifNotNull(ExifReader.readGpsMeasureMode(dirGps), image::setGps2d3dMode);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+
+        try {
+            ifNotNull(ExifReader.readGpsDop(dirGps), image::setExifGpsDop);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+
+        try {
+            ifNotNull(ExifReader.readGpsDatum(dirGps), image::setExifGpsDatum);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+
+        try {
+            ifNotNull(ExifReader.readGpsProcessingMethod(dirGps), image::setExifGpsProcMethod);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+        
         ifNotNull(dirGps.getGpsDate(), d -> image.setExifGpsTime(d.toInstant()));
     }
Index: /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java	(revision 19387)
@@ -89,4 +89,5 @@
     private final ImageZoomAction imageZoomAction = new ImageZoomAction();
     private final ImageCenterViewAction imageCenterViewAction = new ImageCenterViewAction();
+    private final ImageExtendedInfoAction imageExtendedInfoAction = new ImageExtendedInfoAction();
     private final ImageNextAction imageNextAction = new ImageNextAction();
     private final ImageRemoveAction imageRemoveAction = new ImageRemoveAction();
@@ -104,4 +105,5 @@
     private Future<?> imgLoadingFuture;
     private boolean centerView;
+    private boolean extendedImgInfo;
 
     // Only one instance of that class is present at one time
@@ -164,4 +166,5 @@
     private JButton btnDeleteFromDisk;
     private JToggleButton tbCentre;
+    private JToggleButton tbImgExtInfo;
     /** The layer tab (used to select images when multiple layers provide images, makes for easy switching) */
     private final HideableTabbedPane layers = new HideableTabbedPane();
@@ -235,4 +238,9 @@
         tbCentre.setPreferredSize(buttonDim);
 
+        extendedImgInfo = Config.getPref().getBoolean("geoimage.viewer.extendedinfo", false);
+        tbImgExtInfo = new JToggleButton(imageExtendedInfoAction);
+        tbImgExtInfo.setSelected(extendedImgInfo);
+        tbImgExtInfo.setPreferredSize(buttonDim);
+
         JButton btnZoomBestFit = new JButton(imageZoomAction);
         btnZoomBestFit.setPreferredSize(buttonDim);
@@ -243,5 +251,5 @@
         JPanel buttons = new JPanel();
         addButtonGroup(buttons, this.btnFirst, this.btnPrevious, this.btnNext, this.btnLast);
-        addButtonGroup(buttons, this.tbCentre, btnZoomBestFit);
+        addButtonGroup(buttons, this.tbCentre, btnZoomBestFit, this.tbImgExtInfo);
         addButtonGroup(buttons, this.btnDelete, this.btnDeleteFromDisk);
         addButtonGroup(buttons, this.btnCopyPath, this.btnOpenExternal);
@@ -584,4 +592,21 @@
     }
 
+    private class ImageExtendedInfoAction extends JosmAction {
+        ImageExtendedInfoAction() {
+            super(null, new ImageProvider("info"), tr("Display image extended metadata"), Shortcut.registerShortcut(
+                    "geoimage:extendedinfos", tr(GEOIMAGE_FILLER, tr("Toggle Osd extended informations")),
+                    KeyEvent.CHAR_UNDEFINED, Shortcut.NONE),
+            false, null, false);
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            final JToggleButton button = (JToggleButton) e.getSource();
+            extendedImgInfo = button.isEnabled() && button.isSelected();
+            Config.getPref().putBoolean("geoimage.viewer.extendedinfo", extendedImgInfo);
+            refresh(false);
+        }
+    }
+    
     private class ImageRemoveAction extends JosmAction {
         ImageRemoveAction() {
@@ -1000,18 +1025,47 @@
             osd.append(tr("\nSpeed: {0} km/h", Math.round(entry.getSpeed())));
         }
-        if (entry.getExifImgDir() != null) {
-            osd.append(tr("\nDirection {0}\u00b0", Math.round(entry.getExifImgDir())));
-        }
-
         DateTimeFormatter dtf = DateUtils.getDateTimeFormatter(FormatStyle.SHORT, FormatStyle.MEDIUM)
-                // Set timezone to UTC since UTC is assumed when parsing the EXIF timestamp,
-                // see see org.openstreetmap.josm.tools.ExifReader.readTime(com.drew.metadata.Metadata)
-                .withZone(ZoneOffset.UTC);
-
+                    // Set timezone to UTC since UTC is assumed when parsing the EXIF timestamp,
+                    // see see org.openstreetmap.josm.tools.ExifReader.readTime(com.drew.metadata.Metadata)
+                    .withZone(ZoneOffset.UTC);
         if (entry.hasExifTime()) {
-            osd.append(tr("\nEXIF time: {0}", dtf.format(entry.getExifInstant())));
-        }
-        if (entry.hasGpsTime()) {
-            osd.append(tr("\nGPS time: {0}", dtf.format(entry.getGpsInstant())));
+            if (Config.getPref().getBoolean("geoimage.viewer.extendedinfo", false)) {
+                osd.append(tr("\nEXIF DTO time: {0}", dtf.format(entry.getExifInstant())));
+            } else {
+                osd.append(tr("\nEXIF time: {0}", dtf.format(entry.getExifInstant())));        
+            }
+        }
+
+        if (Config.getPref().getBoolean("geoimage.viewer.extendedinfo", false)) {
+            if (entry.getExifGpsInstant() != null) {
+                osd.append(tr("\nEXIF GPS time: {0}", dtf.format(entry.getExifGpsInstant())));
+            }
+            if (entry.hasGpsTime()) {
+                osd.append(tr("\nCorr GPS time: {0}", dtf.format(entry.getGpsInstant())));
+            }            
+            if (entry.getExifImgDir() != null) {
+                osd.append(tr("\nDirection {0}\u00b0", Math.round(entry.getExifImgDir())));
+            }
+            if (entry.getExifGpsTrack() != null) {
+                osd.append(tr("\nGPS direction: {0}\u00b0", Math.round(entry.getExifGpsTrack())));
+            }
+            if (entry.getExifHPosErr() != null) {
+                osd.append(tr("\nHpos errror: {0}m", entry.getExifHPosErr()));
+            }
+            if (entry.getGps2d3dMode() != null) {
+                osd.append(tr("\n2d/3d mode: {0}d", entry.getGps2d3dMode()));
+            }
+            if (entry.getGpsDiffMode() != null) {
+                osd.append(tr("\nDifferential: {0}", entry.getGpsDiffMode()));
+            }
+            if (entry.getExifGpsDop() != null) {
+                osd.append(tr("\nDOP: {0}", entry.getExifGpsDop()));
+            }
+            if (entry.getExifGpsDatum() != null) {
+                osd.append(tr("\nDatum: {0}", entry.getExifGpsDatum().toString()));
+            }
+            if (entry.getExifGpsProcMethod() != null) {
+                osd.append(tr("\nProc. method: {0}", entry.getExifGpsProcMethod().toString()));
+            }
         }
         Optional.ofNullable(entry.getIptcCaption()).map(s -> tr("\nCaption: {0}", s)).ifPresent(osd::append);
@@ -1146,4 +1200,17 @@
     }
 
+    /**
+     * Reload the image or reload only the image info. Call this if want to update the OSD.
+     * @param imageChanged reload the image if true. Reload only the OSD if false.
+     * @since 19387
+     */
+    public void refresh(boolean imageChanged) {
+        if (SwingUtilities.isEventDispatchThread()) {
+            this.updateButtonsNonNullEntry(currentEntry, imageChanged);
+        } else {
+            GuiHelper.runInEDT(this::refresh);
+        }
+    }
+    
     private void registerOnLayer(Layer layer) {
         if (layer instanceof IGeoImageLayer) {
Index: /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/RemoteEntry.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/RemoteEntry.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/geoimage/RemoteEntry.java	(revision 19387)
@@ -38,6 +38,13 @@
     private Integer exifOrientation;
     private Double elevation;
+    private Integer gpsDiffMode;
+    private Integer gps2d3dMode;
+    private Double exifHPosErr;
+    private Double exifGpsDop;
+    private String exifGpsDatum;
+    private String exifGpsProcMethod;
     private Double speed;
     private Double exifImgDir;
+    private Double exifGpsTrack;
     private ILatLon exifCoor;
     private Instant exifTime;
@@ -118,4 +125,36 @@
     }
 
+    /**
+     * @since 19387
+     */
+    @Override
+    public void setGpsDiffMode(Integer gpsDiffMode) {
+        this.gpsDiffMode = gpsDiffMode;
+    }
+
+    /**
+     * @since 19387
+     */
+    @Override
+    public void setGps2d3dMode(Integer gps2d3dMode) {
+        this.gps2d3dMode = gps2d3dMode;
+    }
+
+    /**
+     * @since 19387
+     */
+    @Override
+    public void setExifGpsDatum(String exifGpsDatum) {
+        this.exifGpsDatum = exifGpsDatum;
+    }
+
+    /**
+     * @since 19387
+     */
+    @Override
+    public void setExifGpsProcMethod(String exifGpsProcMethod) {
+        this.exifGpsProcMethod = exifGpsProcMethod;
+    }
+
     @Override
     public void setElevation(Double elevation) {
@@ -153,4 +192,28 @@
     }
 
+    /**
+     * @since 19387
+     */
+    @Override
+    public void setExifGpsTrack(Double exifGpsTrack) {
+        this.exifGpsTrack = exifGpsTrack;
+    }
+
+    /**
+     * @since 19387
+     */
+    @Override
+    public void setExifHPosErr(Double exifHPosError) {
+        this.exifHPosErr = exifHPosError;
+    }
+
+    /**
+     * @since 19387
+     */
+    @Override
+    public void setExifGpsDop(Double exifGpsDop) {
+        this.exifGpsDop = exifGpsDop;
+    }
+
     @Override
     public void setIptcCaption(String iptcCaption) {
@@ -213,7 +276,66 @@
     }
 
+    /**
+     * @since 19387
+     */
+    @Override
+    public Integer getGpsDiffMode() {
+        return this.gpsDiffMode;
+    }
+    
+    /**
+     * @since 19387
+     */
+    @Override
+    public Integer getGps2d3dMode() {
+        return this.gps2d3dMode;
+    }
+
+    /**
+     * @since 19387
+     */
+    @Override
+    public String getExifGpsDatum() {
+        return this.exifGpsDatum;
+    }
+
+    /**
+     * @since 19387
+     */
+    @Override
+    public String getExifGpsProcMethod() {
+        return this.exifGpsProcMethod;
+    }
+
+    /**
+     * @since 19387
+     */
     @Override
     public Double getExifImgDir() {
         return this.exifImgDir;
+    }
+
+    /**
+     * @since 19387
+     */
+    @Override
+    public Double getExifGpsTrack() {
+        return this.exifGpsTrack;
+    }
+
+    /**
+     * @since 19387
+     */
+    @Override
+    public Double getExifHPosErr() {
+        return this.exifHPosErr;
+    }
+
+    /**
+     * @since 19387
+     */
+    @Override
+    public Double getExifGpsDop() {
+        return this.exifGpsDop;
     }
 
@@ -336,7 +458,9 @@
         return Objects.hash(this.uri, this.pos,
                 this.exifOrientation, this.elevation, this.speed, this.exifImgDir,
-                this.exifCoor, this.exifTime, this.exifGpsTime, this.gpsTime,
-                this.iptcObjectName, this.iptcCaption, this.iptcHeadline, this.iptcKeywords,
-                this.projection, this.title);
+                this.exifGpsTrack, this.exifCoor, this.exifTime, this.exifGpsTime,
+                this.gpsTime, this.exifHPosErr, this.exifGpsDop, this.gpsDiffMode,
+                this.gps2d3dMode, this.exifGpsDatum, this.exifGpsProcMethod,
+                this.iptcObjectName, this.iptcCaption, this.iptcHeadline,
+                this.iptcKeywords, this.projection, this.title);
     }
 
@@ -353,4 +477,7 @@
                     && Objects.equals(this.exifGpsTime, other.exifGpsTime)
                     && Objects.equals(this.exifImgDir, other.exifImgDir)
+                    && Objects.equals(this.exifGpsTrack, other.exifGpsTrack)
+                    && Objects.equals(this.exifHPosErr, other.exifHPosErr)
+                    && Objects.equals(this.exifGpsDop, other.exifGpsDop)
                     && Objects.equals(this.exifOrientation, other.exifOrientation)
                     && Objects.equals(this.exifTime, other.exifTime)
@@ -363,4 +490,8 @@
                     && Objects.equals(this.projection, other.projection)
                     && Objects.equals(this.speed, other.speed)
+                    && Objects.equals(this.gpsDiffMode, other.gpsDiffMode)
+                    && Objects.equals(this.gps2d3dMode, other.gps2d3dMode)
+                    && Objects.equals(this.exifGpsDatum, other.exifGpsDatum)
+                    && Objects.equals(this.exifGpsProcMethod, other.exifGpsProcMethod)
                     && Objects.equals(this.title, other.title);
         }
Index: /trunk/src/org/openstreetmap/josm/io/nmea/NmeaParser.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/nmea/NmeaParser.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/io/nmea/NmeaParser.java	(revision 19387)
@@ -467,5 +467,5 @@
                     if (!accu.isEmpty() && currentwp != null) {
                         Double.parseDouble(accu);
-                        currentwp.put("course", accu);
+                        currentwp.put(GpxConstants.PT_COURSE, accu);
                     }
                 }
@@ -543,5 +543,5 @@
                 if (!accu.isEmpty() && !currentwp.attr.containsKey("course")) {
                     Double.parseDouble(accu);
-                    currentwp.put("course", accu);
+                    currentwp.put(GpxConstants.PT_COURSE, accu);
                 }
 
Index: /trunk/src/org/openstreetmap/josm/io/session/GeoImageSessionExporter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/session/GeoImageSessionExporter.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/io/session/GeoImageSessionExporter.java	(revision 19387)
@@ -23,4 +23,5 @@
  * Session exporter for {@link GeoImageLayer}.
  * @since 5505
+ * @since 19387 exifGpsTrack, exifHPosErr, gpsDiffMode, gps2d3dMode, exifGpsDop, exifGpsDatum, exifGpsProcMethod exporter added
  */
 public class GeoImageSessionExporter extends AbstractSessionExporter<GeoImageLayer> {
@@ -106,4 +107,25 @@
                 addAttr("exif-image-direction", entry.getExifImgDir().toString(), imgElem, support);
             }
+            if (entry.getExifGpsTrack() != null) {
+                addAttr("exif-gps-track", entry.getExifGpsTrack().toString(), imgElem, support);
+            }
+            if (entry.getExifHPosErr() != null) {
+                addAttr("exif-gps-hposerr", entry.getExifHPosErr().toString(), imgElem, support);
+            }
+            if (entry.getGpsDiffMode() != null) {
+                addAttr("exif-gps-diffmode", entry.getGpsDiffMode().toString(), imgElem, support);
+            }
+            if (entry.getGps2d3dMode() != null) {
+                addAttr("exif-gps-2d3dmode", entry.getGps2d3dMode().toString(), imgElem, support);
+            }
+            if (entry.getExifGpsDop() != null) {
+                addAttr("exif-gps-dop", entry.getExifGpsDop().toString(), imgElem, support);
+            }
+            if (entry.getExifGpsDatum() != null) {
+                addAttr("exif-gps-datum", entry.getExifGpsDatum().toString(), imgElem, support);
+            }
+            if (entry.getExifGpsProcMethod() != null) {
+                addAttr("exif-gps-procmethod", entry.getExifGpsProcMethod().toString(), imgElem, support);
+            }
             if (entry.hasNewGpsData()) {
                 addAttr("is-new-gps-data", Boolean.toString(entry.hasNewGpsData()), imgElem, support);
Index: /trunk/src/org/openstreetmap/josm/io/session/GeoImageSessionImporter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/session/GeoImageSessionImporter.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/io/session/GeoImageSessionImporter.java	(revision 19387)
@@ -26,4 +26,5 @@
  * Session importer for {@link GeoImageLayer}.
  * @since 5505
+ * @since 19387 exifGpsTrack, exifHPosErr, gpsDiffMode, gps2d3dMode, exifGpsDop, exifGpsDatum, exifGpsProcMethod importer added
  */
 public class GeoImageSessionImporter implements SessionLayerImporter {
@@ -109,4 +110,25 @@
                 entry.setExifImgDir(Double.valueOf(attrElem.getTextContent()));
                 break;
+            case "exif-gps-track":
+                entry.setExifGpsTrack(Double.valueOf(attrElem.getTextContent()));
+                break;
+            case "exif-gps-hposerr":
+                entry.setExifHPosErr(Double.valueOf(attrElem.getTextContent()));
+                break;
+            case "exif-gps-diffmode":
+                entry.setGpsDiffMode(Integer.valueOf(attrElem.getTextContent()));
+                break;
+            case "exif-gps-2d3dmode":
+                entry.setGps2d3dMode(Integer.valueOf(attrElem.getTextContent()));
+                break;
+            case "exif-gps-dop":
+                entry.setExifGpsDop(Double.valueOf(attrElem.getTextContent()));
+                break;
+            case "exif-gps-datum":
+                entry.setExifGpsDatum(attrElem.getTextContent());
+                break;
+            case "exif-gps-procmethod":
+                entry.setExifGpsProcMethod(attrElem.getTextContent());
+                break;
             case "is-new-gps-data":
                 if (Boolean.parseBoolean(attrElem.getTextContent())) {
Index: /trunk/src/org/openstreetmap/josm/tools/ExifReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/ExifReader.java	(revision 19386)
+++ /trunk/src/org/openstreetmap/josm/tools/ExifReader.java	(revision 19387)
@@ -125,4 +125,39 @@
 
     /**
+     * Returns the GPS date/time from the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS date/time read in the EXIF section, or {@code null} if not found
+     * @since 19387
+     */
+    public static Instant readGpsInstant(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsInstant(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+ 
+    /**
+     * Returns the GPS date/time from the given JPEG file.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS date/time read in the EXIF section, or {@code null} if not found
+     * @since 19387
+     */
+    public static Instant readGpsInstant(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            try {
+                Instant dateTimeStamp = dirGps.getGpsDate().toInstant();
+                return dateTimeStamp;
+            } catch (UncheckedParseException | DateTimeException e) {
+                Logging.error(e);
+            }
+        }
+        return null;
+    }
+ 
+    /**
      * Returns the image orientation of the given JPEG file.
      * @param filename The JPEG file to read
@@ -219,4 +254,39 @@
     }
 
+    /**
+     * Returns the GPS track direction of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS track direction of the image when it was captures (in degrees between 0.0 and 359.99),
+     * or {@code null} if not found
+     * @since 19387
+     */
+    public static Double readGpsTrackDirection(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsTrackDirection(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+    
+    /**
+     * Returns the GPS track direction of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS track direction of the image when it was captured (in degrees between 0.0 and 359.99),
+     * or {@code null} if missing or if {@code dirGps} is null
+     * @since 19387
+     */
+    public static Double readGpsTrackDirection(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            Rational trackDirection = dirGps.getRational(GpsDirectory.TAG_TRACK);
+            if (trackDirection != null) {
+                return trackDirection.doubleValue();
+            }
+        }
+        return null;
+    }
+
     private static double readAxis(GpsDirectory dirGps, int gpsTag, int gpsTagRef, char cRef) throws MetadataException {
         double value;
@@ -319,4 +389,254 @@
                 }
                 return ele;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS horizontal positionning error of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS horizontal positionning error of the camera when the image was captured (in m),
+     *         or {@code null} if not found
+     * @since 19387
+     */
+    public static Double readHpositioningError(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readHpositioningError(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS horizontal positionning error of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS horizontal positionning error of the camera when the image was captured (in m),
+     *         or {@code null} if missing or if {@code dirGps} is null
+     * @since 19387
+     */
+    public static Double readHpositioningError(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            Double hposerr = dirGps.getDoubleObject(GpsDirectory.TAG_H_POSITIONING_ERROR);
+            if (hposerr != null) {
+                return hposerr.doubleValue();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS differential mode of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS differential mode of the camera when the image was captured,
+     * <ul>
+     *  <li>0 : no differential correction</li>
+     *  <li>1 : differential correction</li>
+     *  <li>or {@code null} if not found</li>
+     * </ul>
+     * @since 19387
+     */
+    public static Integer readGpsDiffMode(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsDiffMode(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS differential mode of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS differential mode of the camera when the image was captured,
+     * <ul>
+     *  <li>0 : no differential correction</li>
+     *  <li>1 : differential correction</li>
+     *  <li>or {@code null} if missing or if {@code dirGps} is null</li>
+     * </ul>
+     * @since 19387
+     */    
+    public static Integer readGpsDiffMode(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            Integer gpsDiffMode = dirGps.getInteger(GpsDirectory.TAG_DIFFERENTIAL);
+            if (gpsDiffMode != null) {
+                return gpsDiffMode.intValue();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS 2d/3d mode of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS 2d/3d mode of the camera when the image was captured,
+     * <ul>
+     *  <li>2 : 2d mode</li>
+     *  <li>2 : 3d mode</li>
+     *  <li>or {@code null} if not found</li>
+     * </ul>
+     * @since 19387
+     */
+    public static Integer readGpsMeasureMode(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsMeasureMode(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS 2d/3d mode of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The 2d/3d mode of the camera when the image was captured,
+     * <ul>
+     *  <li>2 : 2d mode</li>
+     *  <li>3 : 3d mode</li>
+     *  <li>or {@code null} if missing or if {@code dirGps} is null</li>
+     * </ul>
+     * @since 19387
+     */    
+    public static Integer readGpsMeasureMode(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            Integer gps2d3dMode = dirGps.getInteger(GpsDirectory.TAG_MEASURE_MODE);
+            if (gps2d3dMode != null) {
+                return gps2d3dMode.intValue();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS DOP value of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS DOP value of the camera when the image was captured,
+     *         or {@code null} if not found
+     * @since 19387
+     */
+    public static Double readGpsDop(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsDop(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS DOP value of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS DOP value of the camera when the image was captured,
+     *         or {@code null} if missing or if {@code dirGps} is null
+     * @since 19387
+     */
+    public static Double readGpsDop(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            Double gpsDop = dirGps.getDoubleObject(GpsDirectory.TAG_DOP);
+            if (gpsDop != null) {
+                return gpsDop.doubleValue();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS datum value of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS datum value of the camera when the image was captured,
+     *         or {@code null} if not found
+     * @since 19387
+     */
+    public static String readGpsDatum(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsDatum(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS datum value of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS datum value of the camera when the image was captured,
+     *         or {@code null} if missing or if {@code dirGps} is null
+     * @since 19387
+     */
+    public static String readGpsDatum(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            String gpsDatum = dirGps.getString(GpsDirectory.TAG_MAP_DATUM);
+            if (gpsDatum != null) {
+                return gpsDatum.toString();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return the GPS processing method of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS processing method. Possible values from the EXIF specs are:
+     * <ul>
+     * <li>GPS</li>
+     * <li>QZSS</li>
+     * <li>GALILEO</li>
+     * <li>GLONASS</li>
+     * <li>BEIDOU</li>
+     * <li>NAVIC</li>
+     * <li>CELLID</li>
+     * <li>WLAN</li>
+     * <li>MANUAL</li>
+     * </ul>
+     * Other values, and combined space separated values are possible too.
+     * or {@code null} if missing
+     * @since 19387
+     */
+    public static String readGpsProcessingMethod(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsProcessingMethod(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Return the GPS processing method of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS processing method. Possible values from the EXIF specs are:
+     * <ul>
+     * <li>GPS</li>
+     * <li>QZSS</li>
+     * <li>GALILEO</li>
+     * <li>GLONASS</li>
+     * <li>BEIDOU</li>
+     * <li>NAVIC</li>
+     * <li>CELLID</li>
+     * <li>WLAN</li>
+     * <li>MANUAL</li>
+     * </ul>
+     * Other values, and combined space separated values are possible too.
+     * or {@code null} if missing or if {@code dirGps} is null
+     * @since 19387
+     */
+    public static String readGpsProcessingMethod(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            String gpsProcessingMethod = dirGps.getDescription(GpsDirectory.TAG_PROCESSING_METHOD);
+            if (gpsProcessingMethod != null) {
+                return gpsProcessingMethod.toString();
             }
         }
Index: /trunk/test/unit/org/openstreetmap/josm/data/ImageDataTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/ImageDataTest.java	(revision 19386)
+++ /trunk/test/unit/org/openstreetmap/josm/data/ImageDataTest.java	(revision 19387)
@@ -446,4 +446,88 @@
 
     @Test
+    void testUpdateHPosErr() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setExifHPosErr(1.23);
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageHPosErr(list.get(0), 1.23);
+    }
+
+    @Test
+    void testUpdateGpsDatum() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setExifGpsDatum("WGS-84");
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageExifGpsDatum(list.get(0), "WGS-84");
+    }
+
+    @Test
+    void testUpdateGpsTrack() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setExifGpsTrack(180.5);
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageGpsTrack(list.get(0), 180.5);
+    }
+
+    @Test
+    void testUpdateGpsDop() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setExifGpsDop(1.9);
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageExifGpsDop(list.get(0), 1.9);
+    }
+
+    @Test
+    void testUpdateGpsProcMethod() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setExifGpsProcMethod("GNSS RTK CORRELATION");
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageExifGpsProcMethod(list.get(0), "GNSS RTK CORRELATION");
+    }
+
+    @Test
+    void testUpdateGpsDifferentialMode() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setGpsDiffMode(1);
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageGpsDiffMode(list.get(0), 1);
+    }
+
+    @Test
+    void testUpdateGps2d3dMode() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setGps2d3dMode(3);
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageGps2d3dMode(list.get(0), 3);
+    }
+
+    @Test
     void testTriggerListenerOnUpdate() {
         List<ImageEntry> list = getOneImage();
Index: /trunk/test/unit/org/openstreetmap/josm/data/gpx/GpxImageCorrelationTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/gpx/GpxImageCorrelationTest.java	(revision 19386)
+++ /trunk/test/unit/org/openstreetmap/josm/data/gpx/GpxImageCorrelationTest.java	(revision 19387)
@@ -351,3 +351,80 @@
         assertEquals(Double.valueOf(150.0d), GpxImageCorrelation.getElevation(wp));
     }
+
+    /**
+     * Unit test of {@link GpxImageCorrelation#getHPosErr}
+     */
+    @Test
+    void testGetHorizontalPosError() {
+        assertNull(GpxImageCorrelation.getHPosErr(null));
+        WayPoint wp = new WayPoint(LatLon.ZERO);
+        assertNull(GpxImageCorrelation.getHPosErr(wp));
+        wp.put(GpxConstants.PT_STD_HDEV, 1.5f);
+        assertEquals(1.5f, GpxImageCorrelation.getHPosErr(wp));
+    }
+
+    /**
+     * Unit test of {@link GpxImageCorrelation#getGpsDop}
+     */
+    @Test
+    void testGetGpsDop() {
+        assertNull(GpxImageCorrelation.getGpsDop(null));
+        WayPoint wp = new WayPoint(LatLon.ZERO);
+        assertNull(GpxImageCorrelation.getGpsDop(wp));
+        wp.put(GpxConstants.PT_HDOP, 2.1f);
+        assertEquals(2.1f, GpxImageCorrelation.getGpsDop(wp));
+        wp.put(GpxConstants.PT_PDOP, 0.9f);
+        assertEquals(0.9f, GpxImageCorrelation.getGpsDop(wp));
+        wp.put(GpxConstants.PT_PDOP, 1.2d);
+        assertEquals(1.2d, GpxImageCorrelation.getGpsDop(wp));
+    }
+
+    /**
+     * Unit test of {@link GpxImageCorrelation#getGpsTrack}
+     */
+    @Test
+    void testGetGpsTrack() {
+        assertNull(GpxImageCorrelation.getHPosErr(null));
+        WayPoint wp = new WayPoint(LatLon.ZERO);
+        assertNull(GpxImageCorrelation.getGpsTrack(wp));
+        wp.put(GpxConstants.PT_COURSE, "");
+        assertNull(GpxImageCorrelation.getGpsTrack(wp));
+        wp.put(GpxConstants.PT_COURSE, "not a number");
+        assertNull(GpxImageCorrelation.getGpsTrack(wp));
+        wp.put(GpxConstants.PT_COURSE, "167.0");
+        assertEquals(Double.valueOf(167.0d), GpxImageCorrelation.getGpsTrack(wp), 0.01d);
+    }
+
+    /**
+     * Unit test of {@link GpxImageCorrelation#getGpsProcMethod}
+     */
+    @Test
+    void testGetGpsProcMethod() {
+        final List<String> positionningModes = Arrays.asList("none", "manual", "estimated", "2d", "3d", "dgps", "float rtk", "rtk");
+        assertNull(GpxImageCorrelation.getGpsProcMethod(null, null, positionningModes));
+        assertNull(GpxImageCorrelation.getGpsProcMethod("", "", positionningModes));
+        assertNull(GpxImageCorrelation.getGpsProcMethod("3d", null, positionningModes));
+        assertNull(GpxImageCorrelation.getGpsProcMethod("", "dgps", positionningModes));
+        assertEquals("MANUAL CORRELATION", GpxImageCorrelation.getGpsProcMethod("manual", "rtk", positionningModes));
+        assertEquals("ESTIMATED CORRELATION", GpxImageCorrelation.getGpsProcMethod("estimated", "2d", positionningModes));
+        assertEquals("GNSS DGPS CORRELATION", GpxImageCorrelation.getGpsProcMethod("rtk", "dgps", positionningModes));
+        assertEquals("GNSS RTK_FLOAT CORRELATION", GpxImageCorrelation.getGpsProcMethod("float rtk", "rtk", positionningModes));
+        assertEquals("GNSS RTK_FIX CORRELATION", GpxImageCorrelation.getGpsProcMethod("rtk", "rtk", positionningModes));
+    }
+
+    /**
+     * Unit test of {@link GpxImageCorrelation#getGps2d3dMode}
+     */
+    @Test
+    void testGetGps2d3dMode() {
+        final List<String> positionningModes = Arrays.asList("none", "manual", "estimated", "2d", "3d", "dgps", "float rtk", "rtk");
+        assertNull(GpxImageCorrelation.getGps2d3dMode(null, null, positionningModes));
+        assertNull(GpxImageCorrelation.getGps2d3dMode("", "", positionningModes));
+        assertNull(GpxImageCorrelation.getGps2d3dMode("3d", null, positionningModes));
+        assertNull(GpxImageCorrelation.getGps2d3dMode("", "dgps", positionningModes));
+        assertNull(GpxImageCorrelation.getGps2d3dMode("estimated", "rtk", positionningModes));
+        assertEquals(2, GpxImageCorrelation.getGps2d3dMode("2d", "2d", positionningModes));
+        assertEquals(2, GpxImageCorrelation.getGps2d3dMode("2d", "3d", positionningModes));
+        assertEquals(3, GpxImageCorrelation.getGps2d3dMode("3d", "dgps", positionningModes));
+    }
 }
Index: /trunk/test/unit/org/openstreetmap/josm/tools/ExifReaderTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/tools/ExifReaderTest.java	(revision 19386)
+++ /trunk/test/unit/org/openstreetmap/josm/tools/ExifReaderTest.java	(revision 19387)
@@ -22,5 +22,5 @@
  */
 class ExifReaderTest {
-    private File orientationSampleFile, directionSampleFile;
+    private File orientationSampleFile, directionSampleFile, positionErrorSampleFile;
 
     /**
@@ -31,4 +31,5 @@
         directionSampleFile = new File("nodist/data/exif-example_direction.jpg");
         orientationSampleFile = new File("nodist/data/exif-example_orientation=6.jpg");
+        positionErrorSampleFile = new File("nodist/data/exif-position-error.jpg"); 
     }
 
@@ -56,4 +57,13 @@
     }
 
+    /**
+     * Test reading GPS date and time
+     */
+    @Test
+    void testReadGpsDateTime() {
+        Instant date = ExifReader.readGpsInstant(positionErrorSampleFile);
+        assertEquals(Instant.parse("2024-04-30T16:36:42Z"), date);
+    }
+ 
     /**
      * Test orientation extraction
@@ -102,4 +112,60 @@
 
     /**
+     * Test horizontal position error extraction
+     */
+    @Test
+    void testReadHorPosError() {
+        assertEquals(Double.valueOf(0.014), ExifReader.readHpositioningError(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS track course extraction
+     */
+    @Test
+    void testReadGpsTrack() {
+        assertEquals(Double.valueOf(298), ExifReader.readGpsTrackDirection(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS differential mode extraction
+     */
+    @Test
+    void testReadGpsDiffmode() {
+        assertEquals(Integer.valueOf(1), ExifReader.readGpsDiffMode(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS DOP value extraction
+     */
+    @Test
+    void testReadGpsDop() {
+        assertEquals(Double.valueOf(0.92), ExifReader.readGpsDop(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS measure mode (2D/3D) extraction
+     */
+    @Test
+    void testReadGps2d3dMode() {
+        assertEquals(Integer.valueOf(3), ExifReader.readGpsMeasureMode(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS datum extraction
+     */
+    @Test
+    void testReadGpsDatum() {
+        assertEquals(String.valueOf("EPSG:9782"), ExifReader.readGpsDatum(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS processing method extraction
+     */
+    @Test
+    void testReadGpsProcMethod() {
+        assertEquals(String.valueOf("GNSS RTK_FIX CORRELATION"), ExifReader.readGpsProcessingMethod(positionErrorSampleFile));
+    }
+
+    /**
      * Non-regression test for ticket <a href="https://josm.openstreetmap.de/ticket/11685">#11685</a>
      * @throws IOException if an error occurs during reading
