Index: trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 12593)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 12594)
@@ -18,5 +18,4 @@
 import java.util.LinkedList;
 import java.util.Optional;
-import java.util.Set;
 
 import javax.swing.JOptionPane;
Index: trunk/src/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessor.java	(revision 12593)
+++ trunk/src/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessor.java	(revision 12594)
@@ -3,6 +3,10 @@
 
 import java.awt.image.BufferedImage;
+import java.util.Collections;
+import java.util.Map;
 
 import org.openstreetmap.josm.gui.layer.ImageProcessor;
+import org.openstreetmap.josm.io.session.SessionAwareReadApply;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -12,7 +16,7 @@
  * @since 10547
  */
-public class ColorfulImageProcessor implements ImageProcessor {
+public class ColorfulImageProcessor implements ImageProcessor, SessionAwareReadApply {
     private ColorfulFilter op;
-    private double colorfulness = 1;
+    private double colorfulness = 1.0;
 
     /**
@@ -52,4 +56,24 @@
 
     @Override
+    public void applyFromPropertiesMap(Map<String, String> properties) {
+        String cStr = properties.get("colorfulness");
+        if (cStr != null) {
+            try {
+                setColorfulness(Double.parseDouble(cStr));
+            } catch (NumberFormatException e) {
+                // nothing
+            }
+        }
+    }
+
+    @Override
+    public Map<String, String> toPropertiesMap() {
+        if (Utils.equalsEpsilon(colorfulness, 1.0))
+            return Collections.emptyMap();
+        else
+            return Collections.singletonMap("colorfulness", Double.toString(colorfulness));
+    }
+
+    @Override
     public String toString() {
         return "ColorfulImageProcessor [colorfulness=" + colorfulness + ']';
Index: trunk/src/org/openstreetmap/josm/gui/layer/imagery/GammaImageProcessor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/imagery/GammaImageProcessor.java	(revision 12593)
+++ trunk/src/org/openstreetmap/josm/gui/layer/imagery/GammaImageProcessor.java	(revision 12594)
@@ -6,7 +6,11 @@
 import java.awt.image.LookupOp;
 import java.awt.image.ShortLookupTable;
+import java.util.Collections;
+import java.util.Map;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.layer.ImageProcessor;
+import org.openstreetmap.josm.io.session.SessionAwareReadApply;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -14,6 +18,6 @@
  * @since 10547
  */
-public class GammaImageProcessor implements ImageProcessor {
-    private double gamma = 1;
+public class GammaImageProcessor implements ImageProcessor, SessionAwareReadApply {
+    private double gamma = 1.0;
     final short[] gammaChange = new short[256];
     private final LookupOp op3 = new LookupOp(
@@ -43,5 +47,5 @@
     @Override
     public BufferedImage process(BufferedImage image) {
-        if (gamma == 1) {
+        if (gamma == 1.0) {
             return image;
         }
@@ -63,4 +67,24 @@
 
     @Override
+    public void applyFromPropertiesMap(Map<String, String> properties) {
+        String cStr = properties.get("gamma");
+        if (cStr != null) {
+            try {
+                setGamma(Double.parseDouble(cStr));
+            } catch (NumberFormatException e) {
+                // nothing
+            }
+        }
+    }
+
+    @Override
+    public Map<String, String> toPropertiesMap() {
+        if (Utils.equalsEpsilon(gamma, 1.0))
+            return Collections.emptyMap();
+        else
+            return Collections.singletonMap("gamma", Double.toString(gamma));
+    }
+
+    @Override
     public String toString() {
         return "GammaImageProcessor [gamma=" + gamma + ']';
Index: trunk/src/org/openstreetmap/josm/gui/layer/imagery/SharpenImageProcessor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/imagery/SharpenImageProcessor.java	(revision 12593)
+++ trunk/src/org/openstreetmap/josm/gui/layer/imagery/SharpenImageProcessor.java	(revision 12594)
@@ -5,6 +5,10 @@
 import java.awt.image.ConvolveOp;
 import java.awt.image.Kernel;
+import java.util.Collections;
+import java.util.Map;
 
 import org.openstreetmap.josm.gui.layer.ImageProcessor;
+import org.openstreetmap.josm.io.session.SessionAwareReadApply;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -18,6 +22,6 @@
  * @since 10547
  */
-public class SharpenImageProcessor implements ImageProcessor {
-    private float sharpenLevel = 1;
+public class SharpenImageProcessor implements ImageProcessor, SessionAwareReadApply {
+    private float sharpenLevel = 1.0f;
     private ConvolveOp op;
 
@@ -89,4 +93,24 @@
 
     @Override
+    public void applyFromPropertiesMap(Map<String, String> properties) {
+        String vStr = properties.get("sharpenlevel");
+        if (vStr != null) {
+            try {
+                setSharpenLevel(Float.parseFloat(vStr));
+            } catch (NumberFormatException e) {
+                // nothing
+            }
+        }
+    }
+
+    @Override
+    public Map<String, String> toPropertiesMap() {
+        if (Utils.equalsEpsilon(sharpenLevel, 1.0))
+            return Collections.emptyMap();
+        else
+            return Collections.singletonMap("sharpenlevel", Float.toString(sharpenLevel));
+    }
+
+    @Override
     public String toString() {
         return "SharpenImageProcessor [sharpenLevel=" + sharpenLevel + ']';
Index: trunk/src/org/openstreetmap/josm/io/session/ImagerySessionExporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/ImagerySessionExporter.java	(revision 12593)
+++ trunk/src/org/openstreetmap/josm/io/session/ImagerySessionExporter.java	(revision 12594)
@@ -5,4 +5,5 @@
 import java.awt.GridBagLayout;
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -20,6 +21,8 @@
 import org.openstreetmap.josm.gui.layer.WMSLayer;
 import org.openstreetmap.josm.gui.layer.WMTSLayer;
+import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings;
 import org.openstreetmap.josm.io.session.SessionWriter.ExportSupport;
 import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.Utils;
 import org.w3c.dom.Element;
 
@@ -95,4 +98,16 @@
             }
         }
+        ImageryFilterSettings filters = layer.getFilterSettings();
+        if (filters != null) {
+            Map<String, String> filterProps = new HashMap<>();
+            filters.getProcessors().stream()
+                    .flatMap(Utils.castToStream(SessionAwareReadApply.class))
+                    .forEach(proc -> filterProps.putAll(proc.toPropertiesMap()));
+            if (!filterProps.isEmpty()) {
+                Element filterEl = support.createElement("filters");
+                layerElem.appendChild(filterEl);
+                addAttributes(filterEl, filterProps, support);
+            }
+        }
         return layerElem;
     }
Index: trunk/src/org/openstreetmap/josm/io/session/ImagerySessionImporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/ImagerySessionImporter.java	(revision 12593)
+++ trunk/src/org/openstreetmap/josm/io/session/ImagerySessionImporter.java	(revision 12594)
@@ -18,7 +18,9 @@
 import org.openstreetmap.josm.gui.layer.WMSLayer;
 import org.openstreetmap.josm.gui.layer.WMTSLayer;
+import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.IllegalDataException;
 import org.openstreetmap.josm.io.session.SessionReader.ImportSupport;
+import org.openstreetmap.josm.tools.Utils;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -45,16 +47,29 @@
             AbstractTileSourceLayer<?> tsLayer = (AbstractTileSourceLayer<?>) layer;
             tsLayer.getDisplaySettings().loadFrom(attributes);
-            NodeList nodes = elem.getChildNodes();
-            for (int i = 0; i < nodes.getLength(); ++i) {
-                Node node = nodes.item(i);
-                if (node.getNodeType() == Node.ELEMENT_NODE && "offset".equals(node.getLocalName())) {
-                    Map<String, String> offsetAttributes = readProperties((Element) node);
-                    OffsetBookmark offset = OffsetBookmark.fromPropertiesMap(offsetAttributes);
-                    tsLayer.getDisplaySettings().setOffsetBookmark(offset);
-                    break;
-                }
+            Element offsetEl = getFirstElementByTagName(elem, "offset");
+            if (offsetEl != null) {
+                Map<String, String> offsetAttributes = readProperties(offsetEl);
+                OffsetBookmark offset = OffsetBookmark.fromPropertiesMap(offsetAttributes);
+                tsLayer.getDisplaySettings().setOffsetBookmark(offset);
+            }
+        }
+        Element filtersEl = getFirstElementByTagName(elem, "filters");
+        if (filtersEl != null) {
+            ImageryFilterSettings filterSettings = layer.getFilterSettings();
+            if (filterSettings != null) {
+                Map<String, String> filtersProps = readProperties(filtersEl);
+                filterSettings.getProcessors().stream()
+                        .flatMap(Utils.castToStream(SessionAwareReadApply.class))
+                        .forEach(proc -> proc.applyFromPropertiesMap(filtersProps));
             }
         }
         return layer;
+    }
+
+    private static Element getFirstElementByTagName(Element el, String name) {
+        NodeList nl = el.getElementsByTagName(name);
+        if (nl.getLength() == 0)
+            return null;
+        return (Element) nl.item(0);
     }
 
Index: trunk/src/org/openstreetmap/josm/io/session/SessionAwareReadApply.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/SessionAwareReadApply.java	(revision 12594)
+++ trunk/src/org/openstreetmap/josm/io/session/SessionAwareReadApply.java	(revision 12594)
@@ -0,0 +1,25 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.session;
+
+import java.util.Map;
+
+/**
+ * Interface to support export to session file (and import back) for a class that
+ * stores customizable user settings.
+ *
+ * @since 12594
+ */
+public interface SessionAwareReadApply {
+
+    /**
+     * Export settings to a map of properties.
+     * @return map of properties
+     */
+    Map<String, String> toPropertiesMap();
+
+    /**
+     * Import settings from a map of properties.
+     * @param properties properties map
+     */
+    void applyFromPropertiesMap(Map<String, String> properties);
+}
Index: trunk/src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 12593)
+++ trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 12594)
@@ -55,4 +55,5 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Stream;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.ZipEntry;
@@ -1690,3 +1691,18 @@
         return null;
     }
+
+    /**
+     * Get a function that converts an object to a singleton stream of a certain
+     * class (or null if the object cannot be cast to that class).
+     *
+     * Can be useful in relation with streams, but be aware of the performance
+     * implications of creating a stream for each element.
+     * @param <T> type of the objects to convert
+     * @param <U> type of the elements in the resulting stream
+     * @param klass the class U
+     * @return function converting an object to a singleton stream or null
+     */
+    public static <T, U> Function<T, Stream<U>> castToStream(Class<U> klass) {
+        return x -> klass.isInstance(x) ? Stream.of(klass.cast(x)) : null;
+    }
 }
