Ignore:
Timestamp:
2009-12-12T15:09:44+01:00 (14 years ago)
Author:
bastiK
Message:

geoimage: improved thumbnails (closes #4101)

Location:
trunk/src/org/openstreetmap/josm/gui/layer/geoimage
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • 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.