Changeset 2617 in josm


Ignore:
Timestamp:
Dec 12, 2009 3:09:44 PM (4 years ago)
Author:
bastiK
Message:

geoimage: improved thumbnails (closes #4101)

Location:
trunk/src/org/openstreetmap/josm/gui
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MapView.java

    r2512 r2617  
    381381 
    382382        Graphics2D tempG = offscreenBuffer.createGraphics(); 
     383        tempG.setClip(g.getClip()); 
    383384        tempG.setColor(Main.pref.getColor("background", Color.BLACK)); 
    384385        tempG.fillRect(0, 0, getWidth(), getHeight()); 
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java

    r2606 r2617  
    564564        gc.fill = GridBagConstraints.NONE; 
    565565        gc.weightx = gc.weighty = 0.0; 
    566         yLayer.loadThumbs = Main.pref.getBoolean("geoimage.showThumbs", false); 
    567         JCheckBox cbShowThumbs = new JCheckBox(tr("Show Thumbnail images on the map"), yLayer.loadThumbs); 
     566        yLayer.useThumbs = Main.pref.getBoolean("geoimage.showThumbs", false); 
     567        JCheckBox cbShowThumbs = new JCheckBox(tr("Show Thumbnail images on the map"), yLayer.useThumbs); 
    568568        panelTf.add(cbShowThumbs, gc); 
    569569 
     
    635635            } 
    636636 
    637             yLayer.loadThumbs = cbShowThumbs.isSelected(); 
     637            yLayer.useThumbs = cbShowThumbs.isSelected(); 
    638638 
    639639            Main.pref.put("geoimage.doublegpstimezone", Double.toString(gpstimezone)); 
    640640            Main.pref.put("geoimage.gpstimezone", Long.toString(- ((long) gpstimezone))); 
    641641            Main.pref.put("geoimage.delta", Long.toString(delta * 1000)); 
    642             Main.pref.put("geoimage.showThumbs", yLayer.loadThumbs); 
     642            Main.pref.put("geoimage.showThumbs", yLayer.useThumbs); 
    643643            isOk = true; 
    644644 
    645             if (yLayer.loadThumbs) { 
    646                 yLayer.thumbsloader = new ThumbsLoader(yLayer.data); 
     645            if (yLayer.useThumbs) { 
     646                yLayer.thumbsloader = new ThumbsLoader(yLayer); 
    647647                Thread t = new Thread(yLayer.thumbsloader); 
    648648                t.setPriority(Thread.MIN_PRIORITY); 
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java

    r2606 r2617  
    99import static org.openstreetmap.josm.tools.I18n.trn; 
    1010 
     11import java.awt.AlphaComposite; 
     12import java.awt.Color; 
    1113import java.awt.Component; 
     14import java.awt.Composite; 
     15import java.awt.Dimension; 
    1216import java.awt.Graphics2D; 
    1317import java.awt.Image; 
     
    1923import java.awt.event.MouseEvent; 
    2024import java.awt.image.BufferedImage; 
     25import java.beans.PropertyChangeListener; 
     26import java.beans.PropertyChangeEvent; 
    2127import java.io.File; 
    2228import java.io.IOException; 
     
    5662import com.drew.metadata.exif.GpsDirectory; 
    5763 
    58 public class GeoImageLayer extends Layer { 
     64public class GeoImageLayer extends Layer implements PropertyChangeListener { 
    5965 
    6066    List<ImageEntry> data; 
     
    7177    public long timeoffset = 0; 
    7278 
    73     boolean loadThumbs; 
     79    boolean useThumbs = false; 
    7480    ThumbsLoader thumbsloader; 
     81    private BufferedImage offscreenBuffer; 
     82    boolean updateOffscreenBuffer = true; 
    7583 
    7684    /* 
     
    295303        Collections.sort(data); 
    296304        this.data = data; 
     305        Main.map.mapView.addPropertyChangeListener(this); 
    297306    } 
    298307 
     
    375384 
    376385        setName(l.getName()); 
    377  
     386    } 
     387 
     388    private Dimension scaledDimension(Image thumb) { 
     389        final double d = Main.map.mapView.getDist100Pixel(); 
     390        final double size = 40 /*meter*/;     /* size of the photo on the map */ 
     391        double s = size * 100 /*px*/ / d; 
     392 
     393        final double sMin = ThumbsLoader.minSize; 
     394        final double sMax = ThumbsLoader.maxSize; 
     395 
     396        if (s < sMin) { 
     397            s = sMin; 
     398        } 
     399        if (s > sMax) { 
     400            s = sMax; 
     401        } 
     402        final double f = s / sMax;  /* scale factor */ 
     403 
     404        if (thumb == null) 
     405            return null; 
     406 
     407        return new Dimension( 
     408            (int) Math.round(f * thumb.getWidth(null)), 
     409            (int) Math.round(f * thumb.getHeight(null))); 
    378410    } 
    379411 
    380412    @Override 
    381413    public void paint(Graphics2D g, MapView mv, Bounds bounds) { 
    382  
    383         for (ImageEntry e : data) { 
     414        int width = Main.map.mapView.getWidth(); 
     415        int height = Main.map.mapView.getHeight(); 
     416        Rectangle clip = g.getClipBounds(); 
     417        if (useThumbs) { 
     418            if (null == offscreenBuffer || offscreenBuffer.getWidth() != width  // reuse the old buffer if possible 
     419                    || offscreenBuffer.getHeight() != height) { 
     420                offscreenBuffer = new BufferedImage(width, height, 
     421                        BufferedImage.TYPE_INT_ARGB); 
     422                updateOffscreenBuffer = true; 
     423            } 
     424 
     425            if (updateOffscreenBuffer) { 
     426                Graphics2D tempG = offscreenBuffer.createGraphics(); 
     427                tempG.setColor(new Color(0,0,0,0)); 
     428                Composite saveComp = tempG.getComposite(); 
     429                tempG.setComposite(AlphaComposite.Clear);   // remove the old images 
     430                tempG.fillRect(0, 0, width, height); 
     431                tempG.setComposite(saveComp); 
     432 
     433                for (ImageEntry e : data) { 
     434                    if (e.pos == null) 
     435                        continue; 
     436                    Point p = mv.getPoint(e.pos); 
     437                    if (e.thumbnail != null) { 
     438                        Dimension d = scaledDimension(e.thumbnail); 
     439                        Rectangle target = new Rectangle(p.x - d.width / 2, p.y - d.height / 2, d.width, d.height); 
     440                        if (clip.intersects(target)) { 
     441                            tempG.drawImage(e.thumbnail, target.x, target.y, target.width, target.height, null); 
     442                        } 
     443                    } 
     444                    else { // thumbnail not loaded yet 
     445                        icon.paintIcon(mv, tempG, 
     446                                   p.x - icon.getIconWidth() / 2, 
     447                                   p.y - icon.getIconHeight() / 2); 
     448                    } 
     449                } 
     450                updateOffscreenBuffer = false; 
     451            } 
     452            g.drawImage(offscreenBuffer, 0, 0, null); 
     453        } 
     454        else { 
     455            for (ImageEntry e : data) { 
     456                if (e.pos == null) 
     457                    continue; 
     458                Point p = mv.getPoint(e.pos); 
     459                icon.paintIcon(mv, g, 
     460                           p.x - icon.getIconWidth() / 2, 
     461                           p.y - icon.getIconHeight() / 2); 
     462            } 
     463        } 
     464 
     465        if (currentPhoto >= 0 && currentPhoto < data.size()) { 
     466            ImageEntry e = data.get(currentPhoto); 
     467 
    384468            if (e.pos != null) { 
    385469                Point p = mv.getPoint(e.pos); 
    386                 if (e.thumbnail != null && e.thumbnail.getWidth(null) > 0 && e.thumbnail.getHeight(null) > 0) { 
    387                     g.drawImage(e.thumbnail, 
    388                                 p.x - e.thumbnail.getWidth(null) / 2, 
    389                                 p.y - e.thumbnail.getHeight(null) / 2, null); 
    390                 } 
    391                 else { 
    392                 icon.paintIcon(mv, g, 
    393                                p.x - icon.getIconWidth() / 2, 
    394                                p.y - icon.getIconHeight() / 2); 
    395                 } 
    396             } 
    397         } 
    398  
    399         // Draw the selection on top of the other pictures. 
    400         if (currentPhoto >= 0 && currentPhoto < data.size()) { 
    401             ImageEntry e = data.get(currentPhoto); 
    402  
    403             if (e.pos != null) { 
    404                 Point p = mv.getPoint(e.pos); 
    405  
    406                 Rectangle r = new Rectangle(p.x - selectedIcon.getIconWidth() / 2, 
    407                                             p.y - selectedIcon.getIconHeight() / 2, 
    408                                             selectedIcon.getIconWidth(), 
    409                                             selectedIcon.getIconHeight()); 
    410                 selectedIcon.paintIcon(mv, g, r.x, r.y); 
     470 
     471                if (e.thumbnail != null) { 
     472                    Dimension d = scaledDimension(e.thumbnail); 
     473                    g.setColor(new Color(128, 0, 0, 122)); 
     474                    g.fillRect(p.x - d.width / 2, p.y - d.height / 2, d.width, d.height); 
     475                } else { 
     476                    selectedIcon.paintIcon(mv, g, 
     477                                p.x - selectedIcon.getIconWidth() / 2, 
     478                                p.y - selectedIcon.getIconHeight() / 2); 
     479                } 
    411480            } 
    412481        } 
     
    500569 
    501570    public void checkPreviousNextButtons() { 
    502         System.err.println("check: " + currentPhoto); 
     571//        System.err.println("showing image " + currentPhoto); 
    503572        ImageViewerDialog.setNextEnabled(currentPhoto < data.size() - 1); 
    504573        ImageViewerDialog.setPreviousEnabled(currentPhoto > 0); 
     
    517586            } 
    518587        } 
     588        updateOffscreenBuffer = true; 
    519589        Main.main.map.repaint(); 
    520590    } 
     
    534604 
    535605            @Override public void mouseReleased(MouseEvent ev) { 
    536  
    537606                if (ev.getButton() != MouseEvent.BUTTON1) { 
    538607                    return; 
     
    541610                    return; 
    542611                } 
    543  
    544                 ImageViewerDialog d = ImageViewerDialog.getInstance(); 
    545612 
    546613                for (int i = data.size() - 1; i >= 0; --i) { 
     
    549616                        continue; 
    550617                    Point p = Main.map.mapView.getPoint(e.pos); 
    551                     Rectangle r = new Rectangle(p.x - icon.getIconWidth() / 2, 
    552                                                 p.y - icon.getIconHeight() / 2, 
    553                                                 icon.getIconWidth(), 
    554                                                 icon.getIconHeight()); 
     618                    Rectangle r; 
     619                    if (e.thumbnail != null) { 
     620                        Dimension d = scaledDimension(e.thumbnail); 
     621                        r = new Rectangle(p.x - d.width / 2, p.y - d.height / 2, d.width, d.height); 
     622                    } else { 
     623                        r = new Rectangle(p.x - icon.getIconWidth() / 2, 
     624                                            p.y - icon.getIconHeight() / 2, 
     625                                            icon.getIconWidth(), 
     626                                            icon.getIconHeight()); 
     627                    } 
    555628                    if (r.contains(ev.getPoint())) { 
    556629                        currentPhoto = i; 
     
    560633                    } 
    561634                } 
    562                 Main.map.mapView.repaint(); 
    563635            } 
    564636        }; 
     
    577649            public void layerRemoved(Layer oldLayer) { 
    578650                if (oldLayer == GeoImageLayer.this) { 
     651                    if (thumbsloader != null) { 
     652                        thumbsloader.stop = true; 
     653                    } 
    579654                    Main.map.mapView.removeMouseListener(mouseAdapter); 
    580655                    currentPhoto = -1; 
     
    585660        }); 
    586661    } 
    587      
    588     @Override 
    589     public void destroy() { 
    590         if (thumbsloader != null) { 
    591             thumbsloader.stop = true; 
     662 
     663    public void propertyChange(PropertyChangeEvent evt) { 
     664        if ("center".equals(evt.getPropertyName()) || "scale".equals(evt.getPropertyName())) { 
     665            updateOffscreenBuffer = true; 
    592666        } 
    593667    } 
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java

    r2602 r2617  
    201201    public void displayImage(GeoImageLayer layer, ImageEntry entry) { 
    202202        synchronized(this) { 
    203             if (currentLayer == layer && currentEntry == entry) { 
    204                 repaint(); 
    205                 return; 
    206             } 
     203//            if (currentLayer == layer && currentEntry == entry) { 
     204//                repaint(); 
     205//                return; 
     206//            }                     TODO: pop up image dialog but don't load image again 
    207207 
    208208            if (centerView && Main.map != null && entry != null && entry.pos != null) { 
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ThumbsLoader.java

    r2606 r2617  
    55import static org.openstreetmap.josm.tools.I18n.tr; 
    66 
    7 import java.awt.MediaTracker; 
    87import java.awt.Graphics2D; 
    98import java.awt.Image; 
     9import java.awt.MediaTracker; 
     10import java.awt.Rectangle; 
    1011import java.awt.Toolkit; 
    1112import java.awt.image.BufferedImage; 
     
    1920 
    2021public class ThumbsLoader implements Runnable { 
     22        public static final int maxSize = 120; 
     23        public static final int minSize = 22; 
    2124        volatile boolean stop = false; 
    2225        List<ImageEntry> data; 
     26        GeoImageLayer layer; 
    2327        MediaTracker tracker; 
    2428        CacheFiles cache; 
    2529        boolean cacheOff = Main.pref.getBoolean("geoimage.noThumbnailCache", false); 
    26          
    27         public ThumbsLoader(List<ImageEntry> data) { 
    28             this.data = new ArrayList<ImageEntry>(data); 
     30 
     31        public ThumbsLoader(GeoImageLayer layer) { 
     32            this.layer = layer; 
     33            this.data = new ArrayList<ImageEntry>(layer.data); 
    2934            if (!cacheOff) { 
    3035                cache = new CacheFiles("geoimage-thumbnails", false); 
     
    3944            for (int i = 0; i < data.size(); i++) { 
    4045                if (stop) return; 
     46 
    4147                System.err.print("fetching image "+i); 
     48 
    4249                data.get(i).thumbnail = loadThumb(data.get(i)); 
     50 
    4351                if (Main.map != null && Main.map.mapView != null) { 
     52                    try { 
     53                        layer.updateOffscreenBuffer = true; 
     54                    } catch (Exception e) {} 
    4455                    Main.map.mapView.repaint(); 
    4556                } 
    4657            } 
    47             (new Thread() { 
     58            try { 
     59                layer.updateOffscreenBuffer = true; 
     60            } catch (Exception e) {} 
     61            Main.map.mapView.repaint(); 
     62            (new Thread() {             // clean up the garbage - shouldn't hurt 
    4863                public void run() { 
    4964                    try { 
     
    5671 
    5772        } 
    58          
     73 
    5974        private BufferedImage loadThumb(ImageEntry entry) { 
    60             final int size = 16; 
    61             final String cacheIdent = entry.file.toString()+":"+size; 
    62              
     75            final String cacheIdent = entry.file.toString()+":"+maxSize; 
     76 
    6377            if (!cacheOff) { 
    6478                BufferedImage cached = cache.getImg(cacheIdent); 
    6579                if(cached != null) { 
    66                     System.err.println(" from cache");  
     80                    System.err.println(" from cache"); 
    6781                    return cached; 
    6882                } 
    6983            } 
    70              
     84 
    7185            Image img = Toolkit.getDefaultToolkit().createImage(entry.file.getPath()); 
    7286            tracker.addImage(img, 0); 
     
    7791                return null; 
    7892            } 
    79             BufferedImage scaledBI = new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB); 
     93            if (tracker.isErrorID(1) || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) { 
     94                System.err.println(" Invalid image"); 
     95                return null; 
     96            } 
     97            Rectangle targetSize = ImageDisplay.calculateDrawImageRectangle( 
     98                new Rectangle(0, 0, img.getWidth(null), img.getHeight(null)), 
     99                new Rectangle(0, 0, maxSize, maxSize)); 
     100            BufferedImage scaledBI = new BufferedImage(targetSize.width, targetSize.height, BufferedImage.TYPE_INT_RGB); 
    80101            Graphics2D g = scaledBI.createGraphics(); 
    81             while (!g.drawImage(img, 0, 0, 16, 16, null)) 
     102            while (!g.drawImage(img, 0, 0, targetSize.width, targetSize.height, null)) 
    82103            { 
    83104                try { 
    84105                    Thread.sleep(10); 
    85                 } catch(InterruptedException ie) {} //FIXME: timeout? 
     106                } catch(InterruptedException ie) {} 
    86107            } 
    87108            g.dispose(); 
    88109            tracker.removeImage(img); 
    89              
    90             if (!cacheOff && scaledBI != null && scaledBI.getWidth() > 0) { 
     110 
     111            if (scaledBI == null || scaledBI.getWidth() <= 0 || scaledBI.getHeight() <= 0) { 
     112                System.err.println(" Invalid image"); 
     113                return null; 
     114            } 
     115 
     116            if (!cacheOff) { 
    91117                cache.saveImg(cacheIdent, scaledBI); 
    92118            } 
    93              
     119 
    94120            System.err.println(""); 
    95121            return scaledBI; 
Note: See TracChangeset for help on using the changeset viewer.