Index: trunk/src/org/openstreetmap/josm/data/gpx/GpxDataContainer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/gpx/GpxDataContainer.java	(revision 18078)
+++ trunk/src/org/openstreetmap/josm/data/gpx/GpxDataContainer.java	(revision 18078)
@@ -0,0 +1,15 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.gpx;
+
+/**
+ * Object containing a {@link GpxData} instance.
+ * @since 18078
+ */
+public interface GpxDataContainer {
+
+    /**
+     * Returns the GPX data.
+     * @return the GPX data
+     */
+    GpxData getGpxData();
+}
Index: trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 18077)
+++ trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 18078)
@@ -34,4 +34,5 @@
 import org.openstreetmap.josm.data.gpx.GpxConstants;
 import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.data.gpx.GpxDataContainer;
 import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeListener;
 import org.openstreetmap.josm.data.gpx.IGpxTrack;
@@ -67,5 +68,5 @@
  * A layer that displays data from a Gpx file / the OSM gpx downloads.
  */
-public class GpxLayer extends AbstractModifiableLayer implements ExpertModeChangeListener, JumpToMarkerLayer {
+public class GpxLayer extends AbstractModifiableLayer implements GpxDataContainer, ExpertModeChangeListener, JumpToMarkerLayer {
 
     /** GPX data */
@@ -575,4 +576,9 @@
     }
 
+    @Override
+    public GpxData getGpxData() {
+        return data;
+    }
+
     /**
      * Jump (move the viewport) to the next track segment.
Index: trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 18077)
+++ trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 18078)
@@ -762,4 +762,9 @@
     public static GpxData toGpxData(DataSet data, File file) {
         GpxData gpxData = new GpxData();
+        fillGpxData(gpxData, data, file, GpxConstants.GPX_PREFIX);
+        return gpxData;
+    }
+
+    protected static void fillGpxData(GpxData gpxData, DataSet data, File file, String gpxPrefix) {
         if (data.getGPXNamespaces() != null) {
             gpxData.getNamespaces().addAll(data.getGPXNamespaces());
@@ -767,10 +772,9 @@
         gpxData.storageFile = file;
         Set<Node> doneNodes = new HashSet<>();
-        waysToGpxData(data.getWays(), gpxData, doneNodes);
-        nodesToGpxData(data.getNodes(), gpxData, doneNodes);
-        return gpxData;
-    }
-
-    private static void waysToGpxData(Collection<Way> ways, GpxData gpxData, Set<Node> doneNodes) {
+        waysToGpxData(data.getWays(), gpxData, doneNodes, gpxPrefix);
+        nodesToGpxData(data.getNodes(), gpxData, doneNodes, gpxPrefix);
+    }
+
+    private static void waysToGpxData(Collection<Way> ways, GpxData gpxData, Set<Node> doneNodes, String gpxPrefix) {
         /* When the dataset has been obtained from a gpx layer and now is being converted back,
          * the ways have negative ids. The first created way corresponds to the first gpx segment,
@@ -791,5 +795,5 @@
             GpxExtensionCollection segExts = new GpxExtensionCollection();
             for (Entry<String, String> e : w.getKeys().entrySet()) {
-                String k = e.getKey().startsWith(GpxConstants.GPX_PREFIX) ? e.getKey().substring(GpxConstants.GPX_PREFIX.length()) : e.getKey();
+                String k = e.getKey().startsWith(gpxPrefix) ? e.getKey().substring(gpxPrefix.length()) : e.getKey();
                 String v = e.getValue();
                 if (GpxConstants.RTE_TRK_KEYS.contains(k)) {
@@ -799,5 +803,5 @@
                             .stream()
                             .filter(s -> s.getValue().equals(e.getKey()))
-                            .map(s -> s.getKey().substring(GpxConstants.GPX_PREFIX.length()))
+                            .map(s -> s.getKey().substring(gpxPrefix.length()))
                             .findAny()
                             .orElse(k);
@@ -822,8 +826,8 @@
                     continue;
                 }
-                if (!n.isTagged() || containsOnlyGpxTags(n)) {
+                if (!n.isTagged() || containsOnlyGpxTags(n, gpxPrefix)) {
                     doneNodes.add(n);
                 }
-                trkseg.add(nodeToWayPoint(n));
+                trkseg.add(nodeToWayPoint(n, Long.MIN_VALUE, gpxPrefix));
             }
             trk.add(new GpxTrackSegment(trkseg));
@@ -835,7 +839,7 @@
     }
 
-    private static boolean containsOnlyGpxTags(Tagged t) {
+    private static boolean containsOnlyGpxTags(Tagged t, String gpxPrefix) {
         return t.keys()
-                .allMatch(key -> GpxConstants.WPT_KEYS.contains(key) || key.startsWith(GpxConstants.GPX_PREFIX));
+                .allMatch(key -> GpxConstants.WPT_KEYS.contains(key) || key.startsWith(gpxPrefix));
     }
 
@@ -843,25 +847,15 @@
      * Reads the Gpx key from the given {@link OsmPrimitive}, with or without &quot;gpx:&quot; prefix
      * @param prim OSM primitive
+     * @param gpxPrefix the GPX prefix
      * @param key GPX key without prefix
      * @return the value or <code>null</code> if not present
-     * @since 15419
-     */
-    public static String gpxVal(OsmPrimitive prim, String key) {
-        String val = prim.get(GpxConstants.GPX_PREFIX + key);
+     */
+    private static String gpxVal(OsmPrimitive prim, String gpxPrefix, String key) {
+        String val = prim.get(gpxPrefix + key);
         return val != null ? val : prim.get(key);
     }
 
     /**
-     * Converts a node to a waypoint.
-     * @param n the {@code Node} to convert
-     * @return {@code WayPoint} object
-     * @since 13210
-     */
-    public static WayPoint nodeToWayPoint(Node n) {
-        return nodeToWayPoint(n, Long.MIN_VALUE);
-    }
-
-    /**
-     * Converts a node to a waypoint.
+     * Converts a node to a waypoint with default {@link GpxConstants#GPX_PREFIX} for tags.
      * @param n the {@code Node} to convert
      * @param time a timestamp value in milliseconds from the epoch.
@@ -870,9 +864,21 @@
      */
     public static WayPoint nodeToWayPoint(Node n, long time) {
+        return nodeToWayPoint(n, time, GpxConstants.GPX_PREFIX);
+    }
+
+    /**
+     * Converts a node to a waypoint with a configurable GPX prefix for tags.
+     * @param n the {@code Node} to convert
+     * @param time a timestamp value in milliseconds from the epoch.
+     * @param gpxPrefix the GPX prefix for tags
+     * @return {@code WayPoint} object
+     * @since 18078
+     */
+    public static WayPoint nodeToWayPoint(Node n, long time, String gpxPrefix) {
         WayPoint wpt = new WayPoint(n.getCoor());
 
         // Position info
 
-        addDoubleIfPresent(wpt, n, GpxConstants.PT_ELE, null);
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_ELE, null);
 
         try {
@@ -880,5 +886,5 @@
             if (time > Long.MIN_VALUE) {
                 wpt.setTimeInMillis(time);
-            } else if ((v = gpxVal(n, GpxConstants.PT_TIME)) != null) {
+            } else if ((v = gpxVal(n, gpxPrefix, GpxConstants.PT_TIME)) != null) {
                 wpt.setInstant(DateUtils.parseInstant(v));
             } else if (!n.isTimestampEmpty()) {
@@ -889,16 +895,16 @@
         }
 
-        addDoubleIfPresent(wpt, n, GpxConstants.PT_MAGVAR, null);
-        addDoubleIfPresent(wpt, n, GpxConstants.PT_GEOIDHEIGHT, null);
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_MAGVAR, null);
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_GEOIDHEIGHT, null);
 
         // Description info
 
-        addStringIfPresent(wpt, n, GpxConstants.GPX_NAME, null, null);
-        addStringIfPresent(wpt, n, GpxConstants.GPX_DESC, "description", null);
-        addStringIfPresent(wpt, n, GpxConstants.GPX_CMT, "comment", null);
-        addStringIfPresent(wpt, n, GpxConstants.GPX_SRC, "source", "source:position");
+        addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.GPX_NAME, null, null);
+        addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.GPX_DESC, "description", null);
+        addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.GPX_CMT, "comment", null);
+        addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.GPX_SRC, "source", "source:position");
 
         Collection<GpxLink> links = Stream.of("link", "url", "website", "contact:website")
-                .map(key -> gpxVal(n, key))
+                .map(key -> gpxVal(n, gpxPrefix, key))
                 .filter(Objects::nonNull)
                 .map(GpxLink::new)
@@ -906,20 +912,20 @@
         wpt.put(GpxConstants.META_LINKS, links);
 
-        addStringIfPresent(wpt, n, GpxConstants.PT_SYM, "wpt_symbol", null);
-        addStringIfPresent(wpt, n, GpxConstants.PT_TYPE, null, null);
+        addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_SYM, "wpt_symbol", null);
+        addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_TYPE, null, null);
 
         // Accuracy info
-        addStringIfPresent(wpt, n, GpxConstants.PT_FIX, "gps:fix", null);
-        addIntegerIfPresent(wpt, n, GpxConstants.PT_SAT, "gps:sat");
-        addDoubleIfPresent(wpt, n, GpxConstants.PT_HDOP, "gps:hdop");
-        addDoubleIfPresent(wpt, n, GpxConstants.PT_VDOP, "gps:vdop");
-        addDoubleIfPresent(wpt, n, GpxConstants.PT_PDOP, "gps:pdop");
-        addDoubleIfPresent(wpt, n, GpxConstants.PT_AGEOFDGPSDATA, "gps:ageofdgpsdata");
-        addIntegerIfPresent(wpt, n, GpxConstants.PT_DGPSID, "gps:dgpsid");
+        addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_FIX, "gps:fix", null);
+        addIntegerIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_SAT, "gps:sat");
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_HDOP, "gps:hdop");
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_VDOP, "gps:vdop");
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_PDOP, "gps:pdop");
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_AGEOFDGPSDATA, "gps:ageofdgpsdata");
+        addIntegerIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_DGPSID, "gps:dgpsid");
 
         return wpt;
     }
 
-    private static void nodesToGpxData(Collection<Node> nodes, GpxData gpxData, Set<Node> doneNodes) {
+    private static void nodesToGpxData(Collection<Node> nodes, GpxData gpxData, Set<Node> doneNodes, String gpxPrefix) {
         List<Node> sortedNodes = new ArrayList<>(nodes);
         sortedNodes.removeAll(doneNodes);
@@ -929,12 +935,12 @@
                 continue;
             }
-            gpxData.waypoints.add(nodeToWayPoint(n));
-        }
-    }
-
-    private static void addIntegerIfPresent(WayPoint wpt, OsmPrimitive p, String gpxKey, String osmKey) {
-        String value = gpxVal(p, gpxKey);
+            gpxData.waypoints.add(nodeToWayPoint(n, Long.MIN_VALUE, gpxPrefix));
+        }
+    }
+
+    private static void addIntegerIfPresent(WayPoint wpt, OsmPrimitive p, String gpxPrefix, String gpxKey, String osmKey) {
+        String value = gpxVal(p, gpxPrefix, gpxKey);
         if (value == null && osmKey != null) {
-            value = gpxVal(p, osmKey);
+            value = gpxVal(p, gpxPrefix, osmKey);
         }
         if (value != null) {
@@ -952,8 +958,8 @@
     }
 
-    private static void addDoubleIfPresent(WayPoint wpt, OsmPrimitive p, String gpxKey, String osmKey) {
-        String value = gpxVal(p, gpxKey);
+    private static void addDoubleIfPresent(WayPoint wpt, OsmPrimitive p, String gpxPrefix, String gpxKey, String osmKey) {
+        String value = gpxVal(p, gpxPrefix, gpxKey);
         if (value == null && osmKey != null) {
-            value = gpxVal(p, osmKey);
+            value = gpxVal(p, gpxPrefix, osmKey);
         }
         if (value != null) {
@@ -970,11 +976,11 @@
     }
 
-    private static void addStringIfPresent(WayPoint wpt, OsmPrimitive p, String gpxKey, String osmKey, String osmKey2) {
-        String value = gpxVal(p, gpxKey);
+    private static void addStringIfPresent(WayPoint wpt, OsmPrimitive p, String gpxPrefix, String gpxKey, String osmKey, String osmKey2) {
+        String value = gpxVal(p, gpxPrefix, gpxKey);
         if (value == null && osmKey != null) {
-            value = gpxVal(p, osmKey);
+            value = gpxVal(p, gpxPrefix, osmKey);
         }
         if (value == null && osmKey2 != null) {
-            value = gpxVal(p, osmKey2);
+            value = gpxVal(p, gpxPrefix, osmKey2);
         }
         // Sanity checks
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java	(revision 18077)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java	(revision 18078)
@@ -49,4 +49,7 @@
 import org.openstreetmap.josm.actions.ExpertToggleAction.ExpertModeChangeListener;
 import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeEvent;
+import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeListener;
+import org.openstreetmap.josm.data.gpx.GpxDataContainer;
 import org.openstreetmap.josm.data.gpx.GpxImageCorrelation;
 import org.openstreetmap.josm.data.gpx.GpxImageCorrelationSettings;
@@ -57,5 +60,5 @@
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.gui.layer.GpxLayer;
+import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
@@ -86,4 +89,5 @@
 
     private final transient GeoImageLayer yLayer;
+    private transient CorrelationSupportLayer supportLayer;
     private transient GpxTimezone timezone;
     private transient GpxTimeOffset delta;
@@ -153,4 +157,5 @@
                     yLayer.updateBufferAndRepaint();
                 }
+                removeSupportLayer();
                 break;
             case AGAIN:
@@ -186,4 +191,5 @@
                 yLayer.applyTmp();
                 yLayer.updateBufferAndRepaint();
+                removeSupportLayer();
 
                 break;
@@ -191,4 +197,11 @@
                 throw new IllegalStateException(Integer.toString(result));
             }
+        }
+    }
+
+    private void removeSupportLayer() {
+        if (supportLayer != null) {
+            MainApplication.getLayerManager().removeLayer(supportLayer);
+            supportLayer = null;
         }
     }
@@ -230,4 +243,5 @@
     private JPanel outerPanel;
     private JosmComboBox<GpxDataWrapper> cbGpx;
+    private JButton buttonSupport;
     private JosmTextField tfTimezone;
     private JosmTextField tfOffset;
@@ -269,4 +283,14 @@
     }
 
+    private class UseSupportLayerActionListener implements ActionListener {
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            supportLayer = new CorrelationSupportLayer(yLayer.getFauxGpxData());
+            supportLayer.getGpxData().addChangeListener(statusBarUpdaterWithRepaint);
+            MainApplication.getLayerManager().addLayer(supportLayer);
+        }
+    }
+
     private class AdvancedSettingsActionListener implements ActionListener {
 
@@ -331,12 +355,17 @@
         public void layerAdded(LayerAddEvent e) {
             Layer layer = e.getAddedLayer();
-            if (layer instanceof GpxLayer) {
-                GpxLayer gpx = (GpxLayer) layer;
-                File file = gpx.data.storageFile;
+            if (layer instanceof GpxDataContainer) {
+                GpxData gpx = ((GpxDataContainer) layer).getGpxData();
+                File file = gpx.storageFile;
                 removeDuplicates(file);
-                GpxDataWrapper gdw = new GpxDataWrapper(gpx.getName(), gpx.data, file);
-                gpx.addPropertyChangeListener(new GpxLayerRenamedListener(gdw));
+                GpxDataWrapper gdw = new GpxDataWrapper(layer.getName(), gpx, file);
+                layer.addPropertyChangeListener(new GpxLayerRenamedListener(gdw));
                 gpxModel.addElement(gdw);
-                forEachLayer(CorrelateGpxWithImages::repaintCombobox);
+                forEachLayer(correlateAction -> {
+                    correlateAction.repaintCombobox();
+                    if (layer.equals(correlateAction.supportLayer)) {
+                        correlateAction.buttonSupport.setEnabled(false);
+                    }
+                });
             }
         }
@@ -344,5 +373,23 @@
         @Override
         public void layerRemoving(LayerRemoveEvent e) {
-            // Not used
+            Layer layer = e.getRemovedLayer();
+            if (layer instanceof GpxDataContainer) {
+                GpxData removedGpxData = ((GpxDataContainer) layer).getGpxData();
+                for (int i = gpxModel.getSize() - 1; i >= 0; i--) {
+                    if (gpxModel.getElementAt(i).data.equals(removedGpxData)) {
+                        gpxModel.removeElementAt(i);
+                        forEachLayer(correlateAction -> {
+                            correlateAction.repaintCombobox();
+                            if (layer.equals(correlateAction.supportLayer)) {
+                                correlateAction.supportLayer.getGpxData()
+                                    .removeChangeListener(correlateAction.statusBarUpdaterWithRepaint);
+                                correlateAction.supportLayer = null;
+                                correlateAction.buttonSupport.setEnabled(true);
+                            }
+                        });
+                        break;
+                    }
+                }
+            }
         }
 
@@ -374,10 +421,13 @@
         gpxModel = new DefaultComboBoxModel<>();
         GpxDataWrapper defaultItem = null;
-        for (GpxLayer cur : MainApplication.getLayerManager().getLayersOfType(GpxLayer.class)) {
-            GpxDataWrapper gdw = new GpxDataWrapper(cur.getName(), cur.data, cur.data.storageFile);
-            cur.addPropertyChangeListener(new GpxLayerRenamedListener(gdw));
-            gpxModel.addElement(gdw);
-            if (cur == yLayer.gpxLayer || defaultItem == null) {
-                defaultItem = gdw;
+        for (AbstractModifiableLayer cur : MainApplication.getLayerManager().getLayersOfType(AbstractModifiableLayer.class)) {
+            if (cur instanceof GpxDataContainer) {
+                GpxData data = ((GpxDataContainer) cur).getGpxData();
+                GpxDataWrapper gdw = new GpxDataWrapper(cur.getName(), data, data.storageFile);
+                cur.addPropertyChangeListener(new GpxLayerRenamedListener(gdw));
+                gpxModel.addElement(gdw);
+                if (data.equals(yLayer.gpxData) || defaultItem == null) {
+                    defaultItem = gdw;
+                }
             }
         }
@@ -433,4 +483,8 @@
         buttonOpen.addActionListener(new LoadGpxDataActionListener());
         panelCb.add(buttonOpen);
+
+        buttonSupport = new JButton(tr("Use support layer"));
+        buttonSupport.addActionListener(new UseSupportLayerActionListener());
+        panelCb.add(buttonSupport);
 
         JPanel panelTf = new JPanel(new GridBagLayout());
@@ -584,4 +638,5 @@
         cbTaggedImg.addItemListener(statusBarUpdaterWithRepaint);
         pDirectionPosition.addChangeListenerOnComponents(statusBarUpdaterWithRepaint);
+        pDirectionPosition.addItemListenerOnComponents(statusBarUpdaterWithRepaint);
 
         statusBarUpdater.matchAndUpdateStatusBar();
@@ -612,4 +667,7 @@
     @Override
     public void expertChanged(boolean isExpert) {
+        if (buttonSupport != null) {
+            buttonSupport.setVisible(isExpert);
+        }
         if (sepDirectionPosition != null) {
             sepDirectionPosition.setVisible(isExpert);
@@ -640,5 +698,5 @@
     private final transient StatusBarUpdater statusBarUpdaterWithRepaint = new StatusBarUpdater(true);
 
-    private class StatusBarUpdater implements DocumentListener, ItemListener, ChangeListener, ActionListener {
+    private class StatusBarUpdater implements DocumentListener, ItemListener, ChangeListener, ActionListener, GpxDataChangeListener {
         private final boolean doRepaint;
 
@@ -674,4 +732,9 @@
         @Override
         public void actionPerformed(ActionEvent e) {
+            matchAndUpdateStatusBar();
+        }
+
+        @Override
+        public void gpxDataChanged(GpxDataChangeEvent e) {
             matchAndUpdateStatusBar();
         }
@@ -897,4 +960,6 @@
         }
 
+        closeDialog();
+
         outerPanel = null;
         tfTimezone = null;
@@ -906,6 +971,4 @@
         sepDirectionPosition = null;
         pDirectionPosition = null;
-
-        closeDialog();
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelationSupportLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelationSupportLayer.java	(revision 18078)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelationSupportLayer.java	(revision 18078)
@@ -0,0 +1,105 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.layer.geoimage;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.data.gpx.GpxDataContainer;
+import org.openstreetmap.josm.data.osm.DownloadPolicy;
+import org.openstreetmap.josm.data.osm.UploadPolicy;
+import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.layer.gpx.ConvertFromGpxLayerAction;
+
+/**
+ * A support layer meant to be modified by the user to provide real-time images correlation.
+ * @since 18078
+ */
+public final class CorrelationSupportLayer extends OsmDataLayer implements GpxDataContainer {
+
+    private static final String CORRELATION_PREFIX = "correlation:";
+
+    private final GpxData gpxData = new GpxData();
+
+    /**
+     * Constructs a new {@code CorrelationSupportLayer} with a default name
+     * @param fauxGpxData Faux GPX data to be modified using OSM editing tools
+     */
+    public CorrelationSupportLayer(GpxData fauxGpxData) {
+        this(fauxGpxData, tr("Correlation support layer"));
+    }
+
+    /**
+     * Constructs a new {@code CorrelationSupportLayer} with a given name
+     * @param fauxGpxData Faux GPX data to be modified using OSM editing tools
+     * @param name layer name
+     */
+    public CorrelationSupportLayer(GpxData fauxGpxData, String name) {
+        super(ConvertFromGpxLayerAction.convert(fauxGpxData, "list", CORRELATION_PREFIX), name, null);
+        data.setDownloadPolicy(DownloadPolicy.BLOCKED);
+        data.setUploadPolicy(UploadPolicy.BLOCKED);
+        rebuildGpxData();
+    }
+
+    private void rebuildGpxData() {
+        gpxData.beginUpdate();
+        try {
+            gpxData.clear();
+            fillGpxData(gpxData, data, null, CORRELATION_PREFIX);
+        } finally {
+            gpxData.endUpdate();
+        }
+    }
+
+    @Override
+    public GpxData getGpxData() {
+        return gpxData;
+    }
+
+    @Override
+    public void processDatasetEvent(AbstractDatasetChangedEvent event) {
+        invalidate();
+        rebuildGpxData();
+    }
+
+    @Override
+    protected void setRequiresSaveToFile(boolean newValue) {
+        // Do nothing
+    }
+
+    @Override
+    protected void setRequiresUploadToServer(boolean newValue) {
+        // Do nothing
+    }
+
+    @Override
+    public boolean isMergable(Layer other) {
+        return false;
+    }
+
+    @Override
+    public boolean isDownloadable() {
+        return false;
+    }
+
+    @Override
+    public boolean isUploadable() {
+        return false;
+    }
+
+    @Override
+    public boolean requiresUploadToServer() {
+        return false;
+    }
+
+    @Override
+    public boolean requiresSaveToFile() {
+        return false;
+    }
+
+    @Override
+    public boolean isSavable() {
+        return false;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/EditImagesSequenceAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/EditImagesSequenceAction.java	(revision 18077)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/EditImagesSequenceAction.java	(revision 18078)
@@ -5,4 +5,6 @@
 
 import java.awt.event.ActionEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
 import java.awt.event.KeyEvent;
 import java.util.List;
@@ -40,6 +42,8 @@
         this.pDirectionPosition = ImageDirectionPositionPanel.forImageSequence();
 
+        Updater updater = new Updater();
         pDirectionPosition.addFocusListenerOnComponent(new RepaintTheMapListener(yLayer));
-        pDirectionPosition.addChangeListenerOnComponents(new Updater());
+        pDirectionPosition.addChangeListenerOnComponents(updater);
+        pDirectionPosition.addItemListenerOnComponents(updater);
     }
 
@@ -58,8 +62,13 @@
     }
 
-    class Updater implements ChangeListener {
+    class Updater implements ChangeListener, ItemListener {
 
         @Override
         public void stateChanged(ChangeEvent e) {
+            matchAndUpdate();
+        }
+
+        @Override
+        public void itemStateChanged(ItemEvent e) {
             matchAndUpdate();
         }
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(revision 18077)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(revision 18078)
@@ -68,4 +68,5 @@
 /**
  * Layer displaying geotagged pictures.
+ * @since 99
  */
 public class GeoImageLayer extends AbstractModifiableLayer implements
@@ -77,5 +78,5 @@
 
     private final ImageData data;
-    GpxLayer gpxLayer;
+    GpxData gpxData;
     GpxLayer gpxFauxLayer;
     GpxData gpxFauxData;
@@ -153,7 +154,19 @@
      */
     public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, final String name, boolean useThumbs) {
+        this(data, gpxLayer != null ? gpxLayer.data : null, name, useThumbs);
+    }
+
+    /**
+     * Constructs a new {@code GeoImageLayer}.
+     * @param data The list of images to display
+     * @param gpxData The associated GPX data
+     * @param name Layer name
+     * @param useThumbs Thumbnail display flag
+     * @since 18078
+     */
+    public GeoImageLayer(final List<ImageEntry> data, GpxData gpxData, final String name, boolean useThumbs) {
         super(name != null ? name : tr("Geotagged Images"));
         this.data = new ImageData(data);
-        this.gpxLayer = gpxLayer;
+        this.gpxData = gpxData;
         this.useThumbs = useThumbs;
         this.data.addImageDataUpdateListener(this);
@@ -793,9 +806,20 @@
 
     /**
-     * Returns the associated GPX layer.
-     * @return The associated GPX layer
+     * Returns the associated GPX data if any.
+     * @return The associated GPX data or {@code null}
+     * @since 18078
+     */
+    public GpxData getGpxData() {
+        return gpxData;
+    }
+
+    /**
+     * Returns the associated GPX layer if any.
+     * @return The associated GPX layer or {@code null}
      */
     public GpxLayer getGpxLayer() {
-        return gpxLayer;
+        return gpxData != null ? MainApplication.getLayerManager().getLayersOfType(GpxLayer.class)
+                .stream().filter(l -> gpxData.equals(l.getGpxData()))
+                .findFirst().orElseThrow(() -> new IllegalStateException()) : null;
     }
 
@@ -817,5 +841,6 @@
      */
     public synchronized GpxLayer getFauxGpxLayer() {
-        if (gpxLayer != null) return getGpxLayer();
+        GpxLayer gpxLayer = getGpxLayer();
+        if (gpxLayer != null) return gpxLayer;
         if (gpxFauxLayer == null) {
             gpxFauxLayer = new GpxLayer(getFauxGpxData());
@@ -830,5 +855,6 @@
      */
     public synchronized GpxData getFauxGpxData() {
-        if (gpxLayer != null) return getGpxLayer().data;
+        GpxLayer gpxLayer = getGpxLayer();
+        if (gpxLayer != null) return gpxLayer.data;
         if (gpxFauxData == null) {
             gpxFauxData = new GpxData();
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDirectionPositionPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDirectionPositionPanel.java	(revision 18077)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDirectionPositionPanel.java	(revision 18078)
@@ -6,4 +6,5 @@
 import java.awt.GridBagLayout;
 import java.awt.event.FocusListener;
+import java.awt.event.ItemListener;
 
 import javax.swing.JCheckBox;
@@ -103,9 +104,17 @@
 
     /**
-     * Adds a change listener on all checkboxes and spinners of this panel.
+     * Adds a change listener on all checkboxes of this panel.
+     * @param listener change listener to add
+     * @since 18078
+     */
+    public void addItemListenerOnComponents(ItemListener listener) {
+        cChangeImageDirection.addItemListener(listener);
+    }
+
+    /**
+     * Adds a change listener on all spinners of this panel.
      * @param listener change listener to add
      */
     public void addChangeListenerOnComponents(ChangeListener listener) {
-        cChangeImageDirection.addChangeListener(listener);
         sOffsetDegrees.addChangeListener(listener);
         sX.addChangeListener(listener);
Index: trunk/src/org/openstreetmap/josm/gui/layer/gpx/ConvertFromGpxLayerAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/gpx/ConvertFromGpxLayerAction.java	(revision 18077)
+++ trunk/src/org/openstreetmap/josm/gui/layer/gpx/ConvertFromGpxLayerAction.java	(revision 18078)
@@ -21,4 +21,5 @@
 
 import org.openstreetmap.josm.data.gpx.GpxConstants;
+import org.openstreetmap.josm.data.gpx.GpxData;
 import org.openstreetmap.josm.data.gpx.GpxExtension;
 import org.openstreetmap.josm.data.gpx.GpxExtensionCollection;
@@ -55,20 +56,31 @@
     @Override
     public DataSet convert() {
+        return convert(layer.data, Config.getPref().get(GPX_SETTING, "ask"), GpxConstants.GPX_PREFIX);
+    }
+
+    /**
+     * Converts the given {@link GpxData} to a {@link DataSet}
+     * @param data GPX data to convert
+     * @param convertTags "list", "ask" or "no"
+     * @param gpxPrefix GPX prefix for tags
+     * @return the converted dataset
+     * @since 18078
+     */
+    public static DataSet convert(GpxData data, String convertTags, String gpxPrefix) {
         final DataSet ds = new DataSet();
-        ds.setGPXNamespaces(layer.data.getNamespaces());
+        ds.setGPXNamespaces(data.getNamespaces());
 
         List<String> keys = new ArrayList<>(); // note that items in this list don't have the GPX_PREFIX
-        String convertTags = Config.getPref().get(GPX_SETTING, "ask");
         boolean check = "list".equals(convertTags) || "ask".equals(convertTags);
         boolean none = "no".equals(convertTags); // no need to convert tags when no dialog will be shown anyways
 
-        for (IGpxTrack trk : layer.data.getTracks()) {
+        for (IGpxTrack trk : data.getTracks()) {
             for (IGpxTrackSegment segment : trk.getSegments()) {
                 List<Node> nodes = new ArrayList<>();
                 for (WayPoint p : segment.getWayPoints()) {
                     Node n = new Node(p.getCoor());
-                    addAttributes(p.getAttributes(), n, keys, check, none);
+                    addAttributes(p.getAttributes(), n, keys, check, none, gpxPrefix);
                     if (!none) {
-                        addExtensions(p.getExtensions(), n, false, keys, check);
+                        addExtensions(p.getExtensions(), n, false, keys, check, gpxPrefix);
                     }
                     ds.addPrimitive(n);
@@ -77,9 +89,9 @@
                 Way w = new Way();
                 w.setNodes(nodes);
-                addAttributes(trk.getAttributes(), w, keys, check, none);
-                addAttributes(segment.getAttributes(), w, keys, check, none);
+                addAttributes(trk.getAttributes(), w, keys, check, none, gpxPrefix);
+                addAttributes(segment.getAttributes(), w, keys, check, none, gpxPrefix);
                 if (!none) {
-                    addExtensions(trk.getExtensions(), w, false, keys, check);
-                    addExtensions(segment.getExtensions(), w, true, keys, check);
+                    addExtensions(trk.getExtensions(), w, false, keys, check, gpxPrefix);
+                    addExtensions(segment.getExtensions(), w, true, keys, check, gpxPrefix);
                 }
                 ds.addPrimitive(w);
@@ -106,5 +118,5 @@
                 if ("no".equals(res.sel)) {
                     // User just chose not to convert any tags, but that was unknown before the initial conversion
-                    return filterDataSet(ds, null);
+                    return filterDataSet(ds, null, gpxPrefix);
                 } else if ("all".equals(res.sel)) {
                     return ds;
@@ -112,5 +124,5 @@
             }
             if (!listPos.containsAll(keys)) {
-                return filterDataSet(ds, listPos);
+                return filterDataSet(ds, listPos, gpxPrefix);
             }
         }
@@ -118,5 +130,6 @@
     }
 
-    private static void addAttributes(Map<String, Object> attr, OsmPrimitive p, List<String> keys, boolean check, boolean none) {
+    private static void addAttributes(
+            Map<String, Object> attr, OsmPrimitive p, List<String> keys, boolean check, boolean none, String gpxPrefix) {
         for (Entry<String, Object> entry : attr.entrySet()) {
             String key = entry.getKey();
@@ -127,10 +140,10 @@
             if (!none && (obj instanceof String || obj instanceof Number)) {
                 // only convert when required
-                p.put(GpxConstants.GPX_PREFIX + key, obj.toString());
+                p.put(gpxPrefix + key, obj.toString());
             } else if (obj instanceof Instant && GpxConstants.PT_TIME.equals(key)) {
                 // timestamps should always be converted
                 Instant date = (Instant) obj;
                 if (!none) { //... but the tag will only be set when required
-                    p.put(GpxConstants.GPX_PREFIX + key, String.valueOf(date));
+                    p.put(gpxPrefix + key, String.valueOf(date));
                 }
                 p.setInstant(date);
@@ -139,5 +152,6 @@
     }
 
-    private static void addExtensions(GpxExtensionCollection exts, OsmPrimitive p, boolean seg, List<String> keys, boolean check) {
+    private static void addExtensions(
+            GpxExtensionCollection exts, OsmPrimitive p, boolean seg, List<String> keys, boolean check, String gpxPrefix) {
         for (GpxExtension ext : exts) {
             String value = ext.getValue();
@@ -151,5 +165,5 @@
                 String segpre = seg ? "segment:" : "";
                 String key = ext.getFlatKey();
-                String fullkey = GpxConstants.GPX_PREFIX + extpre + pre + ":" + segpre + key;
+                String fullkey = gpxPrefix + extpre + pre + ":" + segpre + key;
                 if (GpxConstants.EXTENSION_ABBREVIATIONS.containsKey(fullkey)) {
                     fullkey = GpxConstants.EXTENSION_ABBREVIATIONS.get(fullkey);
@@ -160,5 +174,5 @@
                 p.put(fullkey, value);
             }
-            addExtensions(ext.getExtensions(), p, seg, keys, check);
+            addExtensions(ext.getExtensions(), p, seg, keys, check, gpxPrefix);
         }
     }
@@ -168,13 +182,14 @@
      * @param ds The {@link DataSet}
      * @param listPos A {@code List<String>} containing the tags (without prefix) to be kept, can be {@code null} if all tags are to be removed
+     * @param gpxPrefix The GPX prefix
      * @return The {@link DataSet}
-     * @since 14103
+     * @since 18078
      */
-    public DataSet filterDataSet(DataSet ds, List<String> listPos) {
+    public static DataSet filterDataSet(DataSet ds, List<String> listPos, String gpxPrefix) {
         for (OsmPrimitive p : ds.getPrimitives(p -> p instanceof Node || p instanceof Way)) {
             p.visitKeys((primitive, key, value) -> {
                 String listkey;
-                if (listPos != null && key.startsWith(GpxConstants.GPX_PREFIX)) {
-                    listkey = key.substring(GpxConstants.GPX_PREFIX.length());
+                if (listPos != null && key.startsWith(gpxPrefix)) {
+                    listkey = key.substring(gpxPrefix.length());
                 } else {
                     listkey = key;
