Index: /trunk/src/org/openstreetmap/josm/gui/layer/imagery/ColorfulFilter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/imagery/ColorfulFilter.java	(revision 13396)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/imagery/ColorfulFilter.java	(revision 13397)
@@ -11,5 +11,8 @@
 import java.awt.image.DataBuffer;
 import java.awt.image.DataBufferByte;
+import java.awt.image.IndexColorModel;
+import java.util.Objects;
 import java.util.Optional;
+import java.util.function.Consumer;
 
 import org.openstreetmap.josm.tools.Logging;
@@ -20,4 +23,7 @@
  */
 public class ColorfulFilter implements BufferedImageOp {
+    private static final double LUMINOSITY_RED = .21d;
+    private static final double LUMINOSITY_GREEN = .72d;
+    private static final double LUMINOSITY_BLUE = .07d;
     private final double colorfulness;
 
@@ -37,4 +43,10 @@
 
         BufferedImage dest = Optional.ofNullable(dst).orElseGet(() -> createCompatibleDestImage(src, null));
+        int type = src.getType();
+
+        if (type == BufferedImage.TYPE_BYTE_INDEXED) {
+            return filterIndexed(src, dest);
+        }
+
         DataBuffer srcBuffer = src.getRaster().getDataBuffer();
         DataBuffer destBuffer = dest.getRaster().getDataBuffer();
@@ -44,5 +56,4 @@
         }
 
-        int type = src.getType();
         if (type != dest.getType()) {
             Logging.trace("Cannot apply color filter: Src / Dest differ in type (" + type + '/' + dest.getType() + ')');
@@ -81,4 +92,50 @@
     }
 
+    /**
+     * Fast alternative for indexed images: We can change the palette here.
+     * @param src The source image
+     * @param dest The image to copy the source to
+     * @return The image.
+     */
+    private BufferedImage filterIndexed(BufferedImage src, BufferedImage dest) {
+        Objects.requireNonNull(dest, "dst needs to be non null");
+        if (src.getType() != BufferedImage.TYPE_BYTE_INDEXED) {
+            throw new IllegalArgumentException("Source must be of type TYPE_BYTE_INDEXED");
+        }
+        if (dest.getType() != BufferedImage.TYPE_BYTE_INDEXED) {
+            throw new IllegalArgumentException("Destination must be of type TYPE_BYTE_INDEXED");
+        }
+        if (!(src.getColorModel() instanceof IndexColorModel)) {
+            throw new IllegalArgumentException("Expecting an IndexColorModel for a image of type TYPE_BYTE_INDEXED");
+        }
+        src.copyData(dest.getRaster());
+
+        IndexColorModel model = (IndexColorModel) src.getColorModel();
+        int size = model.getMapSize();
+        byte[] red = getIndexColorModelData(size, model::getReds);
+        byte[] green = getIndexColorModelData(size, model::getGreens);
+        byte[] blue = getIndexColorModelData(size, model::getBlues);
+        byte[] alphas = getIndexColorModelData(size, model::getAlphas);
+
+        for (int i = 0; i < size; i++) {
+            int r = red[i] & 0xff;
+            int g = green[i] & 0xff;
+            int b = blue[i] & 0xff;
+            double luminosity = r * LUMINOSITY_RED + g * LUMINOSITY_GREEN + b * LUMINOSITY_BLUE;
+            red[i] = mix(r, luminosity);
+            green[i] = mix(g, luminosity);
+            blue[i] = mix(b, luminosity);
+        }
+
+        IndexColorModel dstModel = new IndexColorModel(model.getPixelSize(), model.getMapSize(), red, green, blue, alphas);
+        return new BufferedImage(dstModel, dest.getRaster(), dest.isAlphaPremultiplied(), null);
+    }
+
+    private static byte[] getIndexColorModelData(int size, Consumer<byte[]> consumer) {
+        byte[] data = new byte[size];
+        consumer.accept(data);
+        return data;
+    }
+
     private void doFilter(DataBufferByte src, DataBufferByte dest, int redOffset, int greenOffset, int blueOffset,
             int alphaOffset, boolean hasAlpha) {
@@ -94,5 +151,5 @@
             int g = srcPixels[i + greenOffset] & 0xff;
             int b = srcPixels[i + blueOffset] & 0xff;
-            double luminosity = r * .21d + g * .72d + b * .07d;
+            double luminosity = r * LUMINOSITY_RED + g * LUMINOSITY_GREEN + b * LUMINOSITY_BLUE;
             destPixels[i + redOffset] = mix(r, luminosity);
             destPixels[i + greenOffset] = mix(g, luminosity);
Index: /trunk/test/unit/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessorTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessorTest.java	(revision 13396)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessorTest.java	(revision 13397)
@@ -8,4 +8,6 @@
 import java.awt.Graphics2D;
 import java.awt.image.BufferedImage;
+import java.awt.image.DataBuffer;
+import java.awt.image.IndexColorModel;
 
 import org.junit.Rule;
@@ -22,4 +24,20 @@
 
     private static final int TEST_IMAGE_SIZE = 5;
+
+    private static final int[] PALETTE = {
+            Color.BLACK.getRGB(),
+            Color.WHITE.getRGB(),
+            Color.GRAY.getRGB(),
+            Color.GREEN.getRGB(),
+            Color.RED.getRGB(),
+            Color.BLUE.getRGB(),
+            0xff908050,
+            0xff908070,
+            0xff908070,
+            0xff908070,
+            0xfff02080,
+    };
+
+    private static final IndexColorModel COLOR_MODEL = new IndexColorModel(8, PALETTE.length, PALETTE, 0, true, 255, DataBuffer.TYPE_BYTE);
 
     /**
@@ -79,5 +97,6 @@
                     BufferedImage.TYPE_3BYTE_BGR,
                     BufferedImage.TYPE_4BYTE_ABGR,
-                    BufferedImage.TYPE_4BYTE_ABGR_PRE }) {
+                    BufferedImage.TYPE_4BYTE_ABGR_PRE,
+                    BufferedImage.TYPE_BYTE_INDEXED }) {
                 assertTrue(runProcessing(data, type));
             }
@@ -104,8 +123,11 @@
 
     private BufferedImage createImage(Color color, int type) {
-        BufferedImage image = new BufferedImage(TEST_IMAGE_SIZE, TEST_IMAGE_SIZE, type);
+        BufferedImage image = type == BufferedImage.TYPE_BYTE_INDEXED
+                ? new BufferedImage(TEST_IMAGE_SIZE, TEST_IMAGE_SIZE, type, COLOR_MODEL)
+                : new BufferedImage(TEST_IMAGE_SIZE, TEST_IMAGE_SIZE, type);
         Graphics2D graphics = image.createGraphics();
         graphics.setColor(color);
         graphics.fillRect(0, 0, TEST_IMAGE_SIZE, TEST_IMAGE_SIZE);
+        assertEquals(color.getRGB(), image.getRGB(1, 1));
         return image;
     }
