Ignore:
Timestamp:
2017-12-18T00:46:58+01:00 (6 years ago)
Author:
Don-vip
Message:

see #15574:

  • additionally refactors ImageDisplay to use ImageEntry instead; stores width and height info while metadata of images are read; might break plugin code (patch by cmuelle8, minor changes)
  • remove double semicolon causing https://github.com/pmd/pmd/issues/785
  • enable PMD rule DoNotCallGarbageCollectionExplicitly
  • disable SpotBugs rule ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java

    r13191 r13220  
    4646
    4747    /** The file that is currently displayed */
    48     private File file;
     48    private ImageEntry entry;
    4949
    5050    /** The image currently displayed */
     
    215215    private class LoadImageRunnable implements Runnable, ImageObserver {
    216216
     217        private final ImageEntry entry;
    217218        private final File file;
    218         private final int orientation;
    219         private int width;
    220         private int height;
    221 
    222         LoadImageRunnable(File file, Integer orientation) {
    223             this.file = file;
    224             this.orientation = orientation == null ? -1 : orientation;
     219
     220        LoadImageRunnable(ImageEntry entry) {
     221            this.entry = entry;
     222            this.file = entry.getFile();
    225223        }
    226224
     
    229227            if (((infoflags & ImageObserver.WIDTH) == ImageObserver.WIDTH) &&
    230228                ((infoflags & ImageObserver.HEIGHT) == ImageObserver.HEIGHT)) {
    231                 this.width = width;
    232                 this.height = height;
    233                 synchronized (this) {
    234                     this.notify();
     229                synchronized (entry) {
     230                    entry.setWidth(width);
     231                    entry.setHeight(height);
     232                    entry.notifyAll();
    235233                    return false;
    236234                }
    237235            }
    238236            return true;
     237        }
     238
     239        private boolean updateImageEntry(Image img) {
     240            if (!(entry.getWidth() > 0 && entry.getHeight() > 0)) {
     241                synchronized (entry) {
     242                    img.getWidth(this);
     243                    img.getHeight(this);
     244
     245                    long now = System.currentTimeMillis();
     246                    while (!(entry.getWidth() > 0 && entry.getHeight() > 0)) {
     247                        try {
     248                            entry.wait(1000);
     249                            if (this.entry != ImageDisplay.this.entry)
     250                                return false;
     251                            if (System.currentTimeMillis() - now > 10000)
     252                                synchronized (ImageDisplay.this) {
     253                                    errorLoading = true;
     254                                    ImageDisplay.this.repaint();
     255                                    return false;
     256                                }
     257                        } catch (InterruptedException e) {
     258                            Logging.trace(e);
     259                            Logging.warn("InterruptedException in {0} while getting properties of image {1}",
     260                                    getClass().getSimpleName(), file.getPath());
     261                            Thread.currentThread().interrupt();
     262                        }
     263                    }
     264                }
     265            }
     266            return true;
     267        }
     268
     269        private boolean mayFitMemory(long amountWanted) {
     270            return amountWanted < (
     271                   Runtime.getRuntime().maxMemory() -
     272                   Runtime.getRuntime().totalMemory() +
     273                   Runtime.getRuntime().freeMemory());
    239274        }
    240275
     
    242277        public void run() {
    243278            Image img = Toolkit.getDefaultToolkit().createImage(file.getPath());
    244 
    245             synchronized (this) {
    246                 width = -1;
    247                 img.getWidth(this);
    248                 img.getHeight(this);
    249 
    250                 while (width < 0) {
    251                     try {
    252                         this.wait();
    253                         if (width < 0) {
    254                             errorLoading = true;
    255                             return;
    256                         }
    257                     } catch (InterruptedException e) {
    258                         e.printStackTrace();
    259                     }
    260                 }
    261             }
    262 
    263             long allocatedMem = Runtime.getRuntime().totalMemory() -
    264                     Runtime.getRuntime().freeMemory();
    265             long mem = Runtime.getRuntime().maxMemory()-allocatedMem;
    266 
    267             if (mem > ((long) width*height*4)*2) {
     279            if (!updateImageEntry(img))
     280                return;
     281
     282            int width = entry.getWidth();
     283            int height = entry.getHeight();
     284
     285            if (mayFitMemory(((long) width)*height*4*2)) {
    268286                Logging.info("Loading {0} using default toolkit", file.getPath());
    269287                tracker.addImage(img, 1);
     
    271289                // Wait for the end of loading
    272290                while (!tracker.checkID(1, true)) {
    273                     if (this.file != ImageDisplay.this.file) {
     291                    if (this.entry != ImageDisplay.this.entry) {
    274292                        // The file has changed
    275293                        tracker.removeImage(img);
     
    280298                    } catch (InterruptedException e) {
    281299                        Logging.trace(e);
    282                         Logging.warn("InterruptedException in "+getClass().getSimpleName()+
    283                                 " while loading image "+file.getPath());
     300                        Logging.warn("InterruptedException in {0} while loading image {1}",
     301                                getClass().getSimpleName(), file.getPath());
    284302                        Thread.currentThread().interrupt();
    285303                    }
    286304                }
    287305                if (tracker.isErrorID(1)) {
     306                    // the tracker catches OutOfMemory conditions
    288307                    img = null;
    289                     System.gc();
    290308                }
    291309            } else {
     
    293311            }
    294312
    295             if (img == null || width <= 0 || height <= 0) {
    296                 tracker.removeImage(img);
    297                 img = null;
    298             }
    299 
    300313            synchronized (ImageDisplay.this) {
    301                 if (this.file != ImageDisplay.this.file) {
     314                if (this.entry != ImageDisplay.this.entry) {
    302315                    // The file has changed
    303316                    tracker.removeImage(img);
     
    307320                if (img != null) {
    308321                    boolean switchedDim = false;
    309                     if (ExifReader.orientationNeedsCorrection(orientation)) {
    310                         if (ExifReader.orientationSwitchesDimensions(orientation)) {
     322                    if (ExifReader.orientationNeedsCorrection(entry.getExifOrientation())) {
     323                        if (ExifReader.orientationSwitchesDimensions(entry.getExifOrientation())) {
    311324                            width = img.getHeight(null);
    312325                            height = img.getWidth(null);
     
    314327                        }
    315328                        final BufferedImage rot = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    316                         final AffineTransform xform = ExifReader.getRestoreOrientationTransform(orientation,
    317                                 img.getWidth(null), img.getHeight(null));
     329                        final AffineTransform xform = ExifReader.getRestoreOrientationTransform(
     330                                entry.getExifOrientation(),
     331                                img.getWidth(null),
     332                                img.getHeight(null));
    318333                        final Graphics2D g = rot.createGraphics();
    319334                        g.drawImage(img, xform, null);
     
    326341                    visibleRect = new VisRect(0, 0, width, height);
    327342
    328                     Logging.info("Loaded {0} with dimensions {1}x{2} mem(prev-avail={3}m,taken={4}m) exifOrientationSwitchedDimension={5}",
    329                             file.getPath(), width, height, mem/1024/1024, width*height*4/1024/1024, switchedDim);
     343                    Logging.info("Loaded {0} with dimensions {1}x{2} memoryTaken={3}m exifOrientationSwitchedDimension={4}",
     344                            file.getPath(), width, height, width*height*4/1024/1024, switchedDim);
    330345                }
    331346
     
    361376
    362377        private void mouseWheelMovedImpl(int x, int y, int rotation, boolean refreshMousePointInImg) {
    363             File file;
     378            ImageEntry entry;
    364379            Image image;
    365380            VisRect visibleRect;
    366381
    367382            synchronized (ImageDisplay.this) {
    368                 file = ImageDisplay.this.file;
     383                entry = ImageDisplay.this.entry;
    369384                image = ImageDisplay.this.image;
    370385                visibleRect = ImageDisplay.this.visibleRect;
     
    418433
    419434            synchronized (ImageDisplay.this) {
    420                 if (ImageDisplay.this.file == file) {
     435                if (ImageDisplay.this.entry == entry) {
    421436                    ImageDisplay.this.visibleRect = visibleRect;
    422437                }
     
    447462        public void mouseClicked(MouseEvent e) {
    448463            // Move the center to the clicked point.
    449             File file;
     464            ImageEntry entry;
    450465            Image image;
    451466            VisRect visibleRect;
    452467
    453468            synchronized (ImageDisplay.this) {
    454                 file = ImageDisplay.this.file;
     469                entry = ImageDisplay.this.entry;
    455470                image = ImageDisplay.this.image;
    456471                visibleRect = ImageDisplay.this.visibleRect;
     
    486501
    487502            synchronized (ImageDisplay.this) {
    488                 if (ImageDisplay.this.file == file) {
     503                if (ImageDisplay.this.entry == entry) {
    489504                    ImageDisplay.this.visibleRect = visibleRect;
    490505                }
     
    519534                return;
    520535
    521             File file;
     536            ImageEntry entry;
    522537            Image image;
    523538            VisRect visibleRect;
    524539
    525540            synchronized (ImageDisplay.this) {
    526                 file = ImageDisplay.this.file;
     541                entry = ImageDisplay.this.entry;
    527542                image = ImageDisplay.this.image;
    528543                visibleRect = ImageDisplay.this.visibleRect;
     
    539554                visibleRect.checkRectPos();
    540555                synchronized (ImageDisplay.this) {
    541                     if (ImageDisplay.this.file == file) {
     556                    if (ImageDisplay.this.entry == entry) {
    542557                        ImageDisplay.this.visibleRect = visibleRect;
    543558                    }
     
    565580        @Override
    566581        public void mouseReleased(MouseEvent e) {
    567             File file;
     582            ImageEntry entry;
    568583            Image image;
     584            VisRect visibleRect;
    569585
    570586            synchronized (ImageDisplay.this) {
    571                 file = ImageDisplay.this.file;
     587                entry = ImageDisplay.this.entry;
    572588                image = ImageDisplay.this.image;
     589                visibleRect = ImageDisplay.this.visibleRect;
    573590            }
    574591
     
    614631
    615632            synchronized (ImageDisplay.this) {
    616                 if (file == ImageDisplay.this.file) {
     633                if (entry == ImageDisplay.this.entry) {
    617634                    if (selectedRect == null) {
    618635                        ImageDisplay.this.visibleRect = visibleRect;
     
    656673    /**
    657674     * Sets a new source image to be displayed by this {@code ImageDisplay}.
    658      * @param file new source image
    659      * @param orientation orientation of new source (landscape, portrait, upside-down, etc.)
     675     * @param entry new source image
     676     * @since 13220
    660677     */
    661     public void setImage(File file, Integer orientation) {
     678    public void setImage(ImageEntry entry) {
    662679        synchronized (this) {
    663             this.file = file;
     680            this.entry = entry;
    664681            image = null;
    665682            errorLoading = false;
    666683        }
    667684        repaint();
    668         if (file != null) {
    669             new Thread(new LoadImageRunnable(file, orientation), LoadImageRunnable.class.getName()).start();
     685        if (entry != null) {
     686            new Thread(new LoadImageRunnable(entry), LoadImageRunnable.class.getName()).start();
    670687        }
    671688    }
     
    682699    @Override
    683700    public void paintComponent(Graphics g) {
     701        ImageEntry entry;
    684702        Image image;
    685         File file;
    686703        VisRect visibleRect;
    687704        boolean errorLoading;
     
    689706        synchronized (this) {
    690707            image = this.image;
    691             file = this.file;
     708            entry = this.entry;
    692709            visibleRect = this.visibleRect;
    693710            errorLoading = this.errorLoading;
     
    699716
    700717        Dimension size = getSize();
    701         if (file == null) {
     718        if (entry == null) {
    702719            g.setColor(Color.black);
    703720            String noImageStr = tr("No image");
     
    710727            String loadingStr;
    711728            if (!errorLoading) {
    712                 loadingStr = tr("Loading {0}", file.getName());
     729                loadingStr = tr("Loading {0}", entry.getFile().getName());
    713730            } else {
    714                 loadingStr = tr("Error on file {0}", file.getName());
     731                loadingStr = tr("Error on file {0}", entry.getFile().getName());
    715732            }
    716733            Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(loadingStr, g);
     
    742759                    r.x = visibleRect.x;
    743760                    r.y = visibleRect.y;
    744                     System.gc();
    745761                }
    746762            } else {
     
    772788            }
    773789            if (errorLoading) {
    774                 String loadingStr = tr("Error on file {0}", file.getName());
     790                String loadingStr = tr("Error on file {0}", entry.getFile().getName());
    775791                Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(loadingStr, g);
    776792                g.drawString(loadingStr,
     
    885901     */
    886902    public void zoomBestFitOrOne() {
    887         File file;
     903        ImageEntry entry;
    888904        Image image;
    889905        VisRect visibleRect;
    890906
    891907        synchronized (this) {
    892             file = this.file;
     908            entry = this.entry;
    893909            image = this.image;
    894910            visibleRect = this.visibleRect;
     
    911927
    912928        synchronized (this) {
    913             if (file == this.file) {
     929            if (this.entry == entry) {
    914930                this.visibleRect = visibleRect;
    915931            }
Note: See TracChangeset for help on using the changeset viewer.