Ticket #20813: 20813-alpha.patch
| File 20813-alpha.patch, 8.6 KB (added by , 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; 9 9 import java.awt.Graphics; 10 10 import java.awt.Graphics2D; 11 11 import java.awt.Image; 12 import java.awt.MediaTracker;13 12 import java.awt.Point; 14 13 import java.awt.Rectangle; 15 14 import java.awt.RenderingHints; … … import java.awt.event.MouseWheelListener; 21 20 import java.awt.geom.AffineTransform; 22 21 import java.awt.geom.Rectangle2D; 23 22 import java.awt.image.BufferedImage; 24 import java.awt.image.ImageObserver;25 23 import java.io.File; 26 24 import java.io.IOException; 27 25 import java.util.Objects; … … import javax.swing.SwingUtilities; 32 30 33 31 import org.openstreetmap.josm.data.preferences.BooleanProperty; 34 32 import org.openstreetmap.josm.data.preferences.DoubleProperty; 33 import org.openstreetmap.josm.gui.MainApplication; 35 34 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings; 36 35 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings.FilterChangeListener; 37 36 import org.openstreetmap.josm.spi.preferences.Config; … … public class ImageDisplay extends JComponent implements Destroyable, PreferenceC 78 77 /** When a selection is done, the rectangle of the selection (in image coordinates) */ 79 78 private VisRect selectedRect; 80 79 81 /** The tracker to load the images */82 private final MediaTracker tracker = new MediaTracker(this);83 84 80 private final ImgDisplayMouseListener imgMouseListener = new ImgDisplayMouseListener(); 85 81 86 82 private String emptyText; … … public class ImageDisplay extends JComponent implements Destroyable, PreferenceC 236 232 } 237 233 238 234 /** The thread that reads the images. */ 239 private class LoadImageRunnable implements Runnable , ImageObserver{235 private class LoadImageRunnable implements Runnable { 240 236 241 237 private final ImageEntry entry; 242 238 private final File file; … … public class ImageDisplay extends JComponent implements Destroyable, PreferenceC 247 243 } 248 244 249 245 @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); 264 249 if (img == null) { 265 250 synchronized (ImageDisplay.this) { 266 251 errorLoading = true; 267 252 ImageDisplay.this.repaint(); 268 return false;253 return; 269 254 } 270 255 } 271 if (!(entry.getWidth() > 0 && entry.getHeight() > 0)) {272 synchronized (entry) {273 int width = img.getWidth(this);274 int height = img.getHeight(this);275 256 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 called257 int width = img.getWidth(); 258 int height = img.getHeight(); 278 259 entry.setWidth(width); 279 260 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 @Override315 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 loading331 while (!tracker.checkID(1, true)) {332 if (this.entry != ImageDisplay.this.entry) {333 // The file has changed334 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 conditions349 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 }358 261 359 262 synchronized (ImageDisplay.this) { 360 263 if (this.entry != ImageDisplay.this.entry) { … … public class ImageDisplay extends JComponent implements Destroyable, PreferenceC 362 265 return; 363 266 } 364 267 365 if (img != null) {366 268 boolean switchedDim = false; 367 269 if (ExifReader.orientationNeedsCorrection(entry.getExifOrientation())) { 368 270 if (ExifReader.orientationSwitchesDimensions(entry.getExifOrientation())) { … … public class ImageDisplay extends JComponent implements Destroyable, PreferenceC 389 291 390 292 Logging.debug("Loaded {0} with dimensions {1}x{2} memoryTaken={3}m exifOrientationSwitchedDimension={4}", 391 293 file.getPath(), width, height, width*height*4/1024/1024, switchedDim); 392 }393 294 394 295 selectedRect = null; 395 errorLoading = (img == null);296 errorLoading = false; 396 297 } 397 298 ImageDisplay.this.repaint(); 398 299 } catch (IOException ex) { … … public class ImageDisplay extends JComponent implements Destroyable, PreferenceC 755 656 } 756 657 repaint(); 757 658 if (entry != null) { 758 new Thread(new LoadImageRunnable(entry), LoadImageRunnable.class.getName()).start();659 MainApplication.worker.execute(new LoadImageRunnable(entry)); 759 660 } 760 661 } 761 662
