Index: src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapView.java	(revision 8614)
+++ src/org/openstreetmap/josm/gui/MapView.java	(working copy)
@@ -1158,6 +1158,12 @@
                 changedLayer = l;
                 repaint();
             }
+        } else if (evt.getPropertyName().equals(Layer.FILTER_STATE_PROP)){
+            Layer l = (Layer) evt.getSource();
+            if (l.isVisible()) {
+                changedLayer = l;
+                repaint();
+            }
         } else if (evt.getPropertyName().equals(OsmDataLayer.REQUIRES_SAVE_TO_DISK_PROP)
                 || evt.getPropertyName().equals(OsmDataLayer.REQUIRES_UPLOAD_TO_SERVER_PROP)) {
             OsmDataLayer layer = (OsmDataLayer) evt.getSource();
Index: src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 8614)
+++ src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(working copy)
@@ -16,6 +16,7 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
+import java.awt.image.BufferedImage;
 import java.awt.image.ImageObserver;
 import java.io.File;
 import java.io.IOException;
@@ -985,6 +986,10 @@
                 missedTiles.add(tile);
                 continue;
             }
+
+            // applying all filters to this layer
+            img = applyImageProcessors((BufferedImage) img);
+
             Rectangle sourceRect = tileToRect(tile);
             if (borderRect != null && !sourceRect.intersects(borderRect)) {
                 continue;
Index: src/org/openstreetmap/josm/gui/layer/ImageProcessor.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/ImageProcessor.java	(revision 0)
+++ src/org/openstreetmap/josm/gui/layer/ImageProcessor.java	(working copy)
@@ -0,0 +1,27 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.layer;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * This interface was created for processing {@link ImageryLayer}s
+ * following the rules of created image processors
+ *
+ * @author Nipel-Crumple
+ *
+ * @since 8614
+ *
+ */
+public interface ImageProcessor {
+
+    /**
+     * This method should process given image according to image processors
+     * which is contained in the {@link Layer}
+     *
+     * @param image that should be processed
+     *
+     * @return processed image
+     */
+    public BufferedImage process(BufferedImage image);
+
+}
Index: src/org/openstreetmap/josm/gui/layer/ImageryLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/ImageryLayer.java	(revision 8614)
+++ src/org/openstreetmap/josm/gui/layer/ImageryLayer.java	(working copy)
@@ -21,6 +21,7 @@
 import java.awt.image.Kernel;
 import java.text.AttributedCharacterIterator;
 import java.text.AttributedString;
+import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
@@ -55,6 +56,8 @@
     public static final IntegerProperty PROP_FADE_AMOUNT = new IntegerProperty("imagery.fade_amount", 0);
     public static final IntegerProperty PROP_SHARPEN_LEVEL = new IntegerProperty("imagery.sharpen_level", 0);
 
+    private final List<ImageProcessor> imageProcessors = new ArrayList<>();
+
     public static Color getFadeColor() {
         return PROP_FADE_COLOR.get();
     }
@@ -251,6 +254,59 @@
     }
 
     /**
+     * This method adds the {@link ImageProcessor} to this Layer
+     *
+     * @param processor that processes the image
+     *
+     * @return true if processor was added, false otherwise
+     *
+     * @since 8614
+     */
+    public boolean addImageProcessor(ImageProcessor processor) {
+        return imageProcessors.add(processor);
+    }
+
+    /**
+     * This method removes given {@link ImageProcessor} from this layer
+     *
+     * @param processor which is needed to be removed
+     *
+     * @return true if processor was removed
+     *
+     * @since 8614
+     */
+    public boolean removeImageProcessor(ImageProcessor processor) {
+        return imageProcessors.remove(processor);
+    }
+
+    /**
+     * This method gets all {@link ImageProcessor}s of the layer
+     *
+     * @return list of image processors without removed one
+     *
+     * @since 8614
+     */
+    public List<ImageProcessor> getImageProcessors() {
+        return imageProcessors;
+    }
+
+    /**
+     * Applies all the chosen {@link ImageProcessor}s to the image
+     *
+     * @param img - image which should be changed
+     *
+     * @return the new changed image
+     *
+     * @since 8614
+     */
+    public BufferedImage applyImageProcessors(BufferedImage img) {
+        for (ImageProcessor processor : imageProcessors) {
+            img = processor.process(img);
+        }
+        return img;
+    }
+
+    /**
      * Draws a red error tile when imagery tile cannot be fetched.
      * @param img The buffered image
      * @param message Additional error message to display
Index: src/org/openstreetmap/josm/gui/layer/Layer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 8614)
+++ src/org/openstreetmap/josm/gui/layer/Layer.java	(working copy)
@@ -85,6 +85,7 @@
     public static final String VISIBLE_PROP = Layer.class.getName() + ".visible";
     public static final String OPACITY_PROP = Layer.class.getName() + ".opacity";
     public static final String NAME_PROP = Layer.class.getName() + ".name";
+    public static final String FILTER_STATE_PROP = Layer.class.getName() + ".filterstate";
 
     public static final int ICON_SIZE = 16;
 
@@ -313,6 +314,15 @@
     }
 
     /**
+     * Sets new state to the layer after applying {@link ImageProcessor}
+     *
+     * @since 8614
+     */
+    public void setFilterStateChanged() {
+        fireFilterStateChanged();
+    }
+
+    /**
      * Toggles the visibility state of this layer.
      */
     public void toggleVisible() {
@@ -358,6 +368,14 @@
     }
 
     /**
+     * fires a property change for the property {@link #FILTER_STATE_PROP}
+     *
+     */
+    protected void fireFilterStateChanged() {
+        propertyChangeSupport.firePropertyChange(FILTER_STATE_PROP, null, null);
+    }
+
+    /**
      * Check changed status of layer
      *
      * @return True if layer was changed since last paint
