Ticket #20813: 20813-alpha.patch

File 20813-alpha.patch, 8.6 KB (added by simon04, 5 years ago)
  • src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java
    index 66938b131..9f857d4b9 100644
    a b import java.awt.FontMetrics;  
    99import java.awt.Graphics;
    1010import java.awt.Graphics2D;
    1111import java.awt.Image;
    12 import java.awt.MediaTracker;
    1312import java.awt.Point;
    1413import java.awt.Rectangle;
    1514import java.awt.RenderingHints;
    import java.awt.event.MouseWheelListener;  
    2120import java.awt.geom.AffineTransform;
    2221import java.awt.geom.Rectangle2D;
    2322import java.awt.image.BufferedImage;
    24 import java.awt.image.ImageObserver;
    2523import java.io.File;
    2624import java.io.IOException;
    2725import java.util.Objects;
    import javax.swing.SwingUtilities;  
    3230
    3331import org.openstreetmap.josm.data.preferences.BooleanProperty;
    3432import org.openstreetmap.josm.data.preferences.DoubleProperty;
     33import org.openstreetmap.josm.gui.MainApplication;
    3534import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings;
    3635import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings.FilterChangeListener;
    3736import org.openstreetmap.josm.spi.preferences.Config;
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    7877    /** When a selection is done, the rectangle of the selection (in image coordinates) */
    7978    private VisRect selectedRect;
    8079
    81     /** The tracker to load the images */
    82     private final MediaTracker tracker = new MediaTracker(this);
    83 
    8480    private final ImgDisplayMouseListener imgMouseListener = new ImgDisplayMouseListener();
    8581
    8682    private String emptyText;
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    236232    }
    237233
    238234    /** The thread that reads the images. */
    239     private class LoadImageRunnable implements Runnable, ImageObserver {
     235    private class LoadImageRunnable implements Runnable {
    240236
    241237        private final ImageEntry entry;
    242238        private final File file;
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    247243        }
    248244
    249245        @Override
    250         public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
    251             if (((infoflags & ImageObserver.WIDTH) == ImageObserver.WIDTH) &&
    252                 ((infoflags & ImageObserver.HEIGHT) == ImageObserver.HEIGHT)) {
    253                 synchronized (entry) {
    254                     entry.setWidth(width);
    255                     entry.setHeight(height);
    256                     entry.notifyAll();
    257                     return false;
    258                 }
    259             }
    260             return true;
    261         }
    262 
    263         private boolean updateImageEntry(Image img) {
     246        public void run() {
     247            try {
     248                BufferedImage img = ImageIO.read(file);
    264249                if (img == null) {
    265250                    synchronized (ImageDisplay.this) {
    266251                        errorLoading = true;
    267252                        ImageDisplay.this.repaint();
    268                     return false;
     253                        return;
    269254                    }
    270255                }
    271             if (!(entry.getWidth() > 0 && entry.getHeight() > 0)) {
    272                 synchronized (entry) {
    273                     int width = img.getWidth(this);
    274                     int height = img.getHeight(this);
    275256
    276                     if (!(entry.getWidth() > 0 && entry.getHeight() > 0) && width > 0 && height > 0) {
    277                         // dimensions not in metadata but already present in image, so observer won't be called
     257                int width = img.getWidth();
     258                int height = img.getHeight();
    278259                entry.setWidth(width);
    279260                entry.setHeight(height);
    280                         entry.notifyAll();
    281                     }
    282 
    283                     long now = System.currentTimeMillis();
    284                     while (!(entry.getWidth() > 0 && entry.getHeight() > 0)) {
    285                         try {
    286                             entry.wait(1000);
    287                             if (this.entry != ImageDisplay.this.entry)
    288                                 return false;
    289                             if (System.currentTimeMillis() - now > 10000)
    290                                 synchronized (ImageDisplay.this) {
    291                                     errorLoading = true;
    292                                     ImageDisplay.this.repaint();
    293                                     return false;
    294                                 }
    295                         } catch (InterruptedException e) {
    296                             Logging.trace(e);
    297                             Logging.warn("InterruptedException in {0} while getting properties of image {1}",
    298                                     getClass().getSimpleName(), file.getPath());
    299                             Thread.currentThread().interrupt();
    300                         }
    301                     }
    302                 }
    303             }
    304             return true;
    305         }
    306 
    307         private boolean mayFitMemory(long amountWanted) {
    308             return amountWanted < (
    309                    Runtime.getRuntime().maxMemory() -
    310                    Runtime.getRuntime().totalMemory() +
    311                    Runtime.getRuntime().freeMemory());
    312         }
    313 
    314         @Override
    315         public void run() {
    316             BufferedImage img;
    317             try {
    318                 img = ImageIO.read(file);
    319 
    320                 if (!updateImageEntry(img))
    321                     return;
    322 
    323                 int width = entry.getWidth();
    324                 int height = entry.getHeight();
    325 
    326                 if (mayFitMemory(((long) width)*height*4*2)) {
    327                     Logging.info(tr("Loading {0}", file.getPath()));
    328                     tracker.addImage(img, 1);
    329 
    330                     // Wait for the end of loading
    331                     while (!tracker.checkID(1, true)) {
    332                         if (this.entry != ImageDisplay.this.entry) {
    333                             // The file has changed
    334                             tracker.removeImage(img);
    335                             return;
    336                         }
    337                         try {
    338                             Thread.sleep(5);
    339                         } catch (InterruptedException e) {
    340                             Logging.trace(e);
    341                             Logging.warn("InterruptedException in {0} while loading image {1}",
    342                                     getClass().getSimpleName(), file.getPath());
    343                             Thread.currentThread().interrupt();
    344                         }
    345                     }
    346                     if (tracker.isErrorID(1)) {
    347                         Logging.warn("Abort loading of {0} since tracker errored with 1", file);
    348                         // the tracker catches OutOfMemory conditions
    349                         tracker.removeImage(img);
    350                         img = null;
    351                     } else {
    352                         tracker.removeImage(img);
    353                     }
    354                 } else {
    355                     Logging.warn("Abort loading of {0} since it might not fit into memory", file);
    356                     img = null;
    357                 }
    358261
    359262                synchronized (ImageDisplay.this) {
    360263                    if (this.entry != ImageDisplay.this.entry) {
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    362265                        return;
    363266                    }
    364267
    365                     if (img != null) {
    366268                    boolean switchedDim = false;
    367269                    if (ExifReader.orientationNeedsCorrection(entry.getExifOrientation())) {
    368270                        if (ExifReader.orientationSwitchesDimensions(entry.getExifOrientation())) {
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    389291
    390292                    Logging.debug("Loaded {0} with dimensions {1}x{2} memoryTaken={3}m exifOrientationSwitchedDimension={4}",
    391293                            file.getPath(), width, height, width*height*4/1024/1024, switchedDim);
    392                     }
    393294
    394295                    selectedRect = null;
    395                     errorLoading = (img == null);
     296                    errorLoading = false;
    396297                }
    397298                ImageDisplay.this.repaint();
    398299            } catch (IOException ex) {
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    755656        }
    756657        repaint();
    757658        if (entry != null) {
    758             new Thread(new LoadImageRunnable(entry), LoadImageRunnable.class.getName()).start();
     659            MainApplication.worker.execute(new LoadImageRunnable(entry));
    759660        }
    760661    }
    761662