Ticket #21016: 21016.patch

File 21016.patch, 9.9 KB (added by Bjoeni, 3 years ago)
  • src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java

    ### Eclipse Workspace Patch 1.0
    #P josm-2
     
    3131import org.openstreetmap.josm.gui.MainApplication;
    3232import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings;
    3333import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings.FilterChangeListener;
     34import org.openstreetmap.josm.gui.util.GuiHelper;
    3435import org.openstreetmap.josm.spi.preferences.Config;
    3536import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
    3637import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
     
    101102    /** Show a background for the error text (may be hard on eyes) */
    102103    private static final BooleanProperty ERROR_MESSAGE_BACKGROUND = new BooleanProperty("geoimage.message.error.background", false);
    103104
     105    private updateImageThread updateImageThreadInstance;
     106
     107    private class updateImageThread extends Thread {
     108        private boolean restart;
     109
     110        @Override
     111        public void run() {
     112            updateProcessedImage();
     113            if (restart) {
     114                restart = false;
     115                run();
     116            }
     117        }
     118
     119        public void restart() {
     120            restart = true;
     121            if (!isAlive()) {
     122                restart = false;
     123                updateImageThreadInstance = new updateImageThread();
     124                updateImageThreadInstance.start();
     125            }
     126        }
     127    }
     128
    104129    @Override
    105130    public void preferenceChanged(PreferenceChangeEvent e) {
    106131        if (e == null ||
     
    650675
    651676    @Override
    652677    public void filterChanged() {
    653         updateProcessedImage();
    654         repaint();
     678        if (updateImageThreadInstance != null) {
     679            updateImageThreadInstance.restart();
     680        } else {
     681            updateImageThreadInstance = new updateImageThread();
     682            updateImageThreadInstance.start();
     683        }
    655684    }
    656685
    657686    private void updateProcessedImage() {
    658687        processedImage = image == null ? null : imageProcessor.process(image);
     688        GuiHelper.runInEDT(() -> repaint());
    659689    }
    660690
    661691    @Override
  • src/org/openstreetmap/josm/gui/layer/imagery/ColorfulFilter.java

     
    3737
    3838    @Override
    3939    public BufferedImage filter(BufferedImage src, BufferedImage dst) {
    40         if (src.getWidth() == 0 || src.getHeight() == 0 || src.getType() == BufferedImage.TYPE_CUSTOM) {
     40        if (src.getWidth() == 0 || src.getHeight() == 0) {
    4141            return src;
    4242        }
    4343
    44         BufferedImage dest = Optional.ofNullable(dst).orElseGet(() -> createCompatibleDestImage(src, null));
    4544        int type = src.getType();
    4645
    47         if (type == BufferedImage.TYPE_BYTE_INDEXED) {
    48             return filterIndexed(src, dest);
    49         }
    50 
    51         DataBuffer srcBuffer = src.getRaster().getDataBuffer();
    52         DataBuffer destBuffer = dest.getRaster().getDataBuffer();
    53         if (!(srcBuffer instanceof DataBufferByte) || !(destBuffer instanceof DataBufferByte)) {
    54             Logging.trace("Cannot apply color filter: Images do not use DataBufferByte.");
    55             return src;
    56         }
    57 
    58         if (type != dest.getType()) {
    59             Logging.trace("Cannot apply color filter: Src / Dest differ in type (" + type + '/' + dest.getType() + ')');
    60             return src;
    61         }
    62         int redOffset;
    63         int greenOffset;
    64         int blueOffset;
    65         int alphaOffset = 0;
    6646        switch (type) {
     47        case BufferedImage.TYPE_BYTE_INDEXED:
    6748        case BufferedImage.TYPE_3BYTE_BGR:
    68             blueOffset = 0;
    69             greenOffset = 1;
    70             redOffset = 2;
    71             break;
    7249        case BufferedImage.TYPE_4BYTE_ABGR:
    7350        case BufferedImage.TYPE_4BYTE_ABGR_PRE:
    74             blueOffset = 1;
    75             greenOffset = 2;
    76             redOffset = 3;
    77             break;
    7851        case BufferedImage.TYPE_INT_ARGB:
    7952        case BufferedImage.TYPE_INT_ARGB_PRE:
    80             redOffset = 0;
    81             greenOffset = 1;
    82             blueOffset = 2;
    83             alphaOffset = 3;
    84             break;
    85         default:
    86             Logging.trace("Cannot apply color filter: Source image is of wrong type (" + type + ").");
    87             return src;
     53
     54            BufferedImage dest = Optional.ofNullable(dst).orElseGet(() -> createCompatibleDestImage(src, null));
     55
     56            if (type == BufferedImage.TYPE_BYTE_INDEXED) {
     57                try {
     58                    return filterIndexed(src, dest);
     59                } catch (IllegalArgumentException ex) {
     60                    Logging.warn(ex);
     61                    break;
     62                }
     63            }
     64
     65            DataBuffer srcBuffer = src.getRaster().getDataBuffer();
     66            DataBuffer destBuffer = dest.getRaster().getDataBuffer();
     67            if (!(srcBuffer instanceof DataBufferByte) || !(destBuffer instanceof DataBufferByte)) {
     68                Logging.trace("Images do not use DataBufferByte. Filtering RGB values instead.");
     69                break;
     70            }
     71
     72            if (type != dest.getType()) {
     73                Logging.trace("Src / Dest differ in type (" + type + '/' + dest.getType() + "). Filtering RGB values instead.");
     74                break;
     75            }
     76
     77            int redOffset;
     78            int greenOffset;
     79            int blueOffset;
     80            int alphaOffset = 0;
     81            switch (type) {
     82            case BufferedImage.TYPE_3BYTE_BGR:
     83                blueOffset = 0;
     84                greenOffset = 1;
     85                redOffset = 2;
     86                break;
     87            case BufferedImage.TYPE_4BYTE_ABGR:
     88            case BufferedImage.TYPE_4BYTE_ABGR_PRE:
     89                blueOffset = 1;
     90                greenOffset = 2;
     91                redOffset = 3;
     92                break;
     93            case BufferedImage.TYPE_INT_ARGB:
     94            case BufferedImage.TYPE_INT_ARGB_PRE:
     95                redOffset = 0;
     96                greenOffset = 1;
     97                blueOffset = 2;
     98                alphaOffset = 3;
     99                break;
     100            default:
     101                return doFilterRGB(src);
     102            }
     103
     104            doFilter((DataBufferByte) srcBuffer, (DataBufferByte) destBuffer, redOffset, greenOffset, blueOffset,
     105                    alphaOffset, src.getAlphaRaster() != null);
     106            return dest;
    88107        }
    89         doFilter((DataBufferByte) srcBuffer, (DataBufferByte) destBuffer, redOffset, greenOffset, blueOffset,
    90                 alphaOffset, src.getAlphaRaster() != null);
    91         return dest;
     108
     109        return doFilterRGB(src);
    92110    }
    93111
    94112    /**
     
    160178        }
    161179    }
    162180
    163     private byte mix(int color, double luminosity) {
     181    private BufferedImage doFilterRGB(BufferedImage src) {
     182        int w = src.getWidth();
     183        int h = src.getHeight();
     184
     185        int[] arr = src.getRGB(0, 0, w, h, null, 0, w);
     186        int argb, a, r, g, b;
     187        double luminosity;
     188
     189        for (int i = 0; i < arr.length; i++) {
     190            argb = arr[i];
     191            a = (argb >> 24) & 0xff;
     192            r = (argb >> 16) & 0xff;
     193            g = (argb >> 8) & 0xff;
     194            b = argb & 0xff;
     195            luminosity = r * LUMINOSITY_RED + g * LUMINOSITY_GREEN + b * LUMINOSITY_BLUE;
     196            r = mixInt(r, luminosity);
     197            g = mixInt(g, luminosity);
     198            b = mixInt(b, luminosity);
     199            argb = a;
     200            argb = (argb << 8) + r;
     201            argb = (argb << 8) + g;
     202            argb = (argb << 8) + b;
     203            arr[i] = argb;
     204        }
     205
     206        BufferedImage dest = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
     207        dest.setRGB(0, 0, w, h, arr, 0, w);
     208        return dest;
     209    }
     210
     211    private int mixInt(int color, double luminosity) {
    164212        int val = (int) (colorfulness * color + (1 - colorfulness) * luminosity);
    165213        if (val < 0) {
    166214            return 0;
    167215        } else if (val > 0xff) {
    168             return (byte) 0xff;
     216            return 0xff;
    169217        } else {
    170             return (byte) val;
     218            return val;
    171219        }
    172220    }
    173221
     222    private byte mix(int color, double luminosity) {
     223        return (byte) mixInt(color, luminosity);
     224    }
     225
    174226    @Override
    175227    public Rectangle2D getBounds2D(BufferedImage src) {
    176228        return new Rectangle(src.getWidth(), src.getHeight());
  • test/unit/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessorTest.java

     
    9797                    BufferedImage.TYPE_3BYTE_BGR,
    9898                    BufferedImage.TYPE_4BYTE_ABGR,
    9999                    BufferedImage.TYPE_4BYTE_ABGR_PRE,
    100                     BufferedImage.TYPE_BYTE_INDEXED }) {
     100                    BufferedImage.TYPE_BYTE_INDEXED,
     101                    BufferedImage.TYPE_BYTE_BINARY}) {
    101102                assertTrue(runProcessing(data, type));
    102103            }
    103104        }
     
    122123    }
    123124
    124125    private BufferedImage createImage(Color color, int type) {
    125         BufferedImage image = type == BufferedImage.TYPE_BYTE_INDEXED
     126        BufferedImage image = type == BufferedImage.TYPE_BYTE_INDEXED || type == BufferedImage.TYPE_BYTE_BINARY
    126127                ? new BufferedImage(TEST_IMAGE_SIZE, TEST_IMAGE_SIZE, type, COLOR_MODEL)
    127128                : new BufferedImage(TEST_IMAGE_SIZE, TEST_IMAGE_SIZE, type);
    128129        Graphics2D graphics = image.createGraphics();