Ignore:
Timestamp:
2018-02-10T00:13:49+01:00 (6 years ago)
Author:
michael2402
Message:

Fix #15878: Implement colorfullness filter for indexed images.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/imagery/ColorfulFilter.java

    r12620 r13397  
    1111import java.awt.image.DataBuffer;
    1212import java.awt.image.DataBufferByte;
     13import java.awt.image.IndexColorModel;
     14import java.util.Objects;
    1315import java.util.Optional;
     16import java.util.function.Consumer;
    1417
    1518import org.openstreetmap.josm.tools.Logging;
     
    2023 */
    2124public class ColorfulFilter implements BufferedImageOp {
     25    private static final double LUMINOSITY_RED = .21d;
     26    private static final double LUMINOSITY_GREEN = .72d;
     27    private static final double LUMINOSITY_BLUE = .07d;
    2228    private final double colorfulness;
    2329
     
    3743
    3844        BufferedImage dest = Optional.ofNullable(dst).orElseGet(() -> createCompatibleDestImage(src, null));
     45        int type = src.getType();
     46
     47        if (type == BufferedImage.TYPE_BYTE_INDEXED) {
     48            return filterIndexed(src, dest);
     49        }
     50
    3951        DataBuffer srcBuffer = src.getRaster().getDataBuffer();
    4052        DataBuffer destBuffer = dest.getRaster().getDataBuffer();
     
    4456        }
    4557
    46         int type = src.getType();
    4758        if (type != dest.getType()) {
    4859            Logging.trace("Cannot apply color filter: Src / Dest differ in type (" + type + '/' + dest.getType() + ')');
     
    8192    }
    8293
     94    /**
     95     * Fast alternative for indexed images: We can change the palette here.
     96     * @param src The source image
     97     * @param dest The image to copy the source to
     98     * @return The image.
     99     */
     100    private BufferedImage filterIndexed(BufferedImage src, BufferedImage dest) {
     101        Objects.requireNonNull(dest, "dst needs to be non null");
     102        if (src.getType() != BufferedImage.TYPE_BYTE_INDEXED) {
     103            throw new IllegalArgumentException("Source must be of type TYPE_BYTE_INDEXED");
     104        }
     105        if (dest.getType() != BufferedImage.TYPE_BYTE_INDEXED) {
     106            throw new IllegalArgumentException("Destination must be of type TYPE_BYTE_INDEXED");
     107        }
     108        if (!(src.getColorModel() instanceof IndexColorModel)) {
     109            throw new IllegalArgumentException("Expecting an IndexColorModel for a image of type TYPE_BYTE_INDEXED");
     110        }
     111        src.copyData(dest.getRaster());
     112
     113        IndexColorModel model = (IndexColorModel) src.getColorModel();
     114        int size = model.getMapSize();
     115        byte[] red = getIndexColorModelData(size, model::getReds);
     116        byte[] green = getIndexColorModelData(size, model::getGreens);
     117        byte[] blue = getIndexColorModelData(size, model::getBlues);
     118        byte[] alphas = getIndexColorModelData(size, model::getAlphas);
     119
     120        for (int i = 0; i < size; i++) {
     121            int r = red[i] & 0xff;
     122            int g = green[i] & 0xff;
     123            int b = blue[i] & 0xff;
     124            double luminosity = r * LUMINOSITY_RED + g * LUMINOSITY_GREEN + b * LUMINOSITY_BLUE;
     125            red[i] = mix(r, luminosity);
     126            green[i] = mix(g, luminosity);
     127            blue[i] = mix(b, luminosity);
     128        }
     129
     130        IndexColorModel dstModel = new IndexColorModel(model.getPixelSize(), model.getMapSize(), red, green, blue, alphas);
     131        return new BufferedImage(dstModel, dest.getRaster(), dest.isAlphaPremultiplied(), null);
     132    }
     133
     134    private static byte[] getIndexColorModelData(int size, Consumer<byte[]> consumer) {
     135        byte[] data = new byte[size];
     136        consumer.accept(data);
     137        return data;
     138    }
     139
    83140    private void doFilter(DataBufferByte src, DataBufferByte dest, int redOffset, int greenOffset, int blueOffset,
    84141            int alphaOffset, boolean hasAlpha) {
     
    94151            int g = srcPixels[i + greenOffset] & 0xff;
    95152            int b = srcPixels[i + blueOffset] & 0xff;
    96             double luminosity = r * .21d + g * .72d + b * .07d;
     153            double luminosity = r * LUMINOSITY_RED + g * LUMINOSITY_GREEN + b * LUMINOSITY_BLUE;
    97154            destPixels[i + redOffset] = mix(r, luminosity);
    98155            destPixels[i + greenOffset] = mix(g, luminosity);
Note: See TracChangeset for help on using the changeset viewer.