Changeset 13397 in josm


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

Fix #15878: Implement colorfullness filter for indexed images.

Location:
trunk
Files:
2 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);
  • trunk/test/unit/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessorTest.java

    r10547 r13397  
    88import java.awt.Graphics2D;
    99import java.awt.image.BufferedImage;
     10import java.awt.image.DataBuffer;
     11import java.awt.image.IndexColorModel;
    1012
    1113import org.junit.Rule;
     
    2224
    2325    private static final int TEST_IMAGE_SIZE = 5;
     26
     27    private static final int[] PALETTE = {
     28            Color.BLACK.getRGB(),
     29            Color.WHITE.getRGB(),
     30            Color.GRAY.getRGB(),
     31            Color.GREEN.getRGB(),
     32            Color.RED.getRGB(),
     33            Color.BLUE.getRGB(),
     34            0xff908050,
     35            0xff908070,
     36            0xff908070,
     37            0xff908070,
     38            0xfff02080,
     39    };
     40
     41    private static final IndexColorModel COLOR_MODEL = new IndexColorModel(8, PALETTE.length, PALETTE, 0, true, 255, DataBuffer.TYPE_BYTE);
    2442
    2543    /**
     
    7997                    BufferedImage.TYPE_3BYTE_BGR,
    8098                    BufferedImage.TYPE_4BYTE_ABGR,
    81                     BufferedImage.TYPE_4BYTE_ABGR_PRE }) {
     99                    BufferedImage.TYPE_4BYTE_ABGR_PRE,
     100                    BufferedImage.TYPE_BYTE_INDEXED }) {
    82101                assertTrue(runProcessing(data, type));
    83102            }
     
    104123
    105124    private BufferedImage createImage(Color color, int type) {
    106         BufferedImage image = new BufferedImage(TEST_IMAGE_SIZE, TEST_IMAGE_SIZE, type);
     125        BufferedImage image = type == BufferedImage.TYPE_BYTE_INDEXED
     126                ? new BufferedImage(TEST_IMAGE_SIZE, TEST_IMAGE_SIZE, type, COLOR_MODEL)
     127                : new BufferedImage(TEST_IMAGE_SIZE, TEST_IMAGE_SIZE, type);
    107128        Graphics2D graphics = image.createGraphics();
    108129        graphics.setColor(color);
    109130        graphics.fillRect(0, 0, TEST_IMAGE_SIZE, TEST_IMAGE_SIZE);
     131        assertEquals(color.getRGB(), image.getRGB(1, 1));
    110132        return image;
    111133    }
Note: See TracChangeset for help on using the changeset viewer.