Changeset 1704 in josm


Ignore:
Timestamp:
2009-06-27T11:46:17+02:00 (13 years ago)
Author:
stoecker
Message:

fix #2674, #765 - patch by jttt - reworked GeoImage stuff

File:
1 edited

Legend:

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

    r1590 r1704  
    2525import java.awt.event.MouseEvent;
    2626import java.awt.image.BufferedImage;
     27import java.awt.image.ImageObserver;
    2728import java.io.File;
    2829import java.io.IOException;
     30import java.lang.ref.SoftReference;
    2931import java.text.ParseException;
    3032import java.text.SimpleDateFormat;
     
    3436import java.util.Date;
    3537import java.util.LinkedList;
     38import java.util.List;
     39import java.util.WeakHashMap;
    3640
    3741import javax.swing.BorderFactory;
     
    5256import javax.swing.JToggleButton;
    5357import javax.swing.JViewport;
     58import javax.swing.ScrollPaneConstants;
    5459import javax.swing.border.BevelBorder;
    5560import javax.swing.border.Border;
     
    6772import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
    6873import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
     74import org.openstreetmap.josm.gui.layer.GeoImageLayer.ImageLoader.ImageLoadedListener;
    6975import org.openstreetmap.josm.tools.DateParser;
    7076import org.openstreetmap.josm.tools.ExifReader;
     
    7985public class GeoImageLayer extends Layer {
    8086
    81     private static final class ImageEntry implements Comparable<ImageEntry> {
    82         File image;
     87    /**
     88     * Allows to load and scale images. Loaded images are kept in cache (using soft reference). Both
     89     * synchronous and asynchronous loading is supported
     90     *
     91     */
     92    public static class ImageLoader implements ImageObserver {
     93
     94        public static class Entry {
     95            final File file;
     96            final int width;
     97            final int height;
     98            final int maxSize;
     99            private final ImageLoadedListener listener;
     100
     101            volatile Image scaledImage;
     102
     103
     104            public Entry(File file, int width, int height, int maxSize, ImageLoadedListener listener) {
     105                this.file = file;
     106                this.height = height;
     107                this.width = width;
     108                this.maxSize = maxSize;
     109                this.listener = listener;
     110            }
     111        }
     112
     113        public interface ImageLoadedListener {
     114            void imageLoaded();
     115        }
     116
     117        private final List<ImageLoader.Entry> queue = new ArrayList<ImageLoader.Entry>();
     118        private final WeakHashMap<File, SoftReference<Image>> loadedImageCache = new WeakHashMap<File, SoftReference<Image>>();
     119        private ImageLoader.Entry currentEntry;
     120
     121        private Image getOrLoadImage(File file) {
     122            SoftReference<Image> cachedImageRef = loadedImageCache.get(file);
     123            if (cachedImageRef != null) {
     124                Image cachedImage = cachedImageRef.get();
     125                if (cachedImage != null) {
     126                    return cachedImage;
     127                }
     128            }
     129            return Toolkit.getDefaultToolkit().createImage(currentEntry.file.getAbsolutePath());
     130        }
     131
     132        private BufferedImage createResizedCopy(Image originalImage,
     133                int scaledWidth, int scaledHeight)
     134        {
     135            BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB);
     136            Graphics2D g = scaledBI.createGraphics();
     137            while (!g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null))
     138            {
     139                try {
     140                    Thread.sleep(10);
     141                } catch(InterruptedException ie) {}
     142            }
     143            g.dispose();
     144            return scaledBI;
     145        }
     146        private void loadImage() {
     147            if (currentEntry != null) {
     148                return;
     149            }
     150            while (!queue.isEmpty()) {
     151                currentEntry = queue.get(0);
     152                queue.remove(0);
     153
     154                Image newImage = getOrLoadImage(currentEntry.file);
     155                if (newImage.getWidth(this) == -1) {
     156                    break;
     157                } else {
     158                    finishImage(newImage, currentEntry);
     159                    currentEntry = null;
     160                }
     161            }
     162        }
     163
     164        private void finishImage(Image img, ImageLoader.Entry entry) {
     165            loadedImageCache.put(entry.file, new SoftReference<Image>(img));
     166            if (entry.maxSize != -1) {
     167                int w = img.getWidth(null);
     168                int h = img.getHeight(null);
     169                if (w>h) {
     170                    h = Math.round(entry.maxSize*((float)h/w));
     171                    w = entry.maxSize;
     172                } else {
     173                    w = Math.round(entry.maxSize*((float)w/h));
     174                    h = entry.maxSize;
     175                }
     176                entry.scaledImage = createResizedCopy(img, w, h);
     177            } else if (entry.width != -1 && entry.height != -1) {
     178                entry.scaledImage = createResizedCopy(img, entry.width, entry.height);
     179            } else {
     180                entry.scaledImage = img;
     181            }
     182            if (entry.listener != null) {
     183                entry.listener.imageLoaded();
     184            }
     185        }
     186
     187        public synchronized ImageLoader.Entry loadImage(File file, int width, int height, int maxSize, ImageLoadedListener listener) {
     188            ImageLoader.Entry e = new Entry(file, width, height, maxSize, listener);
     189            queue.add(e);
     190            loadImage();
     191            return e;
     192        }
     193
     194        public Image waitForImage(File file, int width, int height) {
     195            return waitForImage(file, width, height, -1);
     196        }
     197
     198        public Image waitForImage(File file, int maxSize) {
     199            return waitForImage(file, -1, -1, maxSize);
     200        }
     201
     202        public Image waitForImage(File file) {
     203            return waitForImage(file, -1, -1, -1);
     204        }
     205
     206        private synchronized Image waitForImage(File file, int width, int height, int maxSize) {
     207            ImageLoader.Entry entry;
     208            if (currentEntry != null && currentEntry.file.equals(file)) {
     209                entry = currentEntry;
     210            } else {
     211                entry = new Entry(file, width, height, maxSize, null);
     212                queue.add(0, entry);
     213            }
     214            loadImage();
     215
     216            while (true) {
     217                if (entry.scaledImage != null) {
     218                    return entry.scaledImage;
     219                }
     220                try {
     221                    wait();
     222                } catch (InterruptedException e) {}
     223            }
     224        }
     225
     226        public synchronized boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
     227            if ((infoflags & ImageObserver.ALLBITS) != 0) {
     228                finishImage(img, currentEntry);
     229                currentEntry = null;
     230                loadImage();
     231                notifyAll();
     232            }
     233            return true;
     234        }
     235    }
     236
     237    private static final int ICON_SIZE = 16;
     238    private static ImageLoader imageLoader = new ImageLoader();
     239
     240    private static final class ImageEntry implements Comparable<ImageEntry>, ImageLoadedListener {
     241
     242        private static final Image EMPTY_IMAGE = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY);
     243
     244        final File image;
     245        ImageLoader.Entry icon;
     246
    83247        Date time;
    84248        LatLon coor;
    85249        EastNorth pos;
    86         Icon icon;
     250
     251        public ImageEntry(File image) {
     252            this.image = image;
     253            icon = imageLoader.loadImage(image, ICON_SIZE, ICON_SIZE, -1, this);
     254        }
     255
    87256        public int compareTo(ImageEntry image) {
    88257            return time.compareTo(image.time);
     258        }
     259
     260        public Image getIcon() {
     261            if (icon.scaledImage == null) {
     262                return EMPTY_IMAGE;
     263            } else {
     264                return icon.scaledImage;
     265            }
     266        }
     267
     268        public void imageLoaded() {
     269            Main.map.mapView.repaint();
    89270        }
    90271    }
     
    109290                for (Collection<WayPoint> segment : trk.trackSegs) {
    110291                    for (WayPoint p : segment) {
    111                     if (!p.attr.containsKey("time"))
    112                         throw new IOException(tr("No time for point {0} x {1}",p.latlon.lat(),p.latlon.lon()));
    113                     Date d = null;
    114                     try {
    115                         d = DateParser.parse((String) p.attr.get("time"));
    116                     } catch (ParseException e) {
    117                         throw new IOException(tr("Cannot read time \"{0}\" from point {1} x {2}",p.attr.get("time"),p.latlon.lat(),p.latlon.lon()));
     292                        if (!p.attr.containsKey("time"))
     293                            throw new IOException(tr("No time for point {0} x {1}",p.latlon.lat(),p.latlon.lon()));
     294                        Date d = null;
     295                        try {
     296                            d = DateParser.parse((String) p.attr.get("time"));
     297                        } catch (ParseException e) {
     298                            throw new IOException(tr("Cannot read time \"{0}\" from point {1} x {2}",p.attr.get("time"),p.latlon.lat(),p.latlon.lon()));
     299                        }
     300                        gps.add(new TimedPoint(d, p.eastNorth));
    118301                    }
    119                     gps.add(new TimedPoint(d, p.eastNorth));
    120                 }
    121             }
     302                }
    122303            }
    123304
     
    137318                Main.pleaseWaitDlg.progress.setValue(i++);
    138319
    139                 ImageEntry e = new ImageEntry();
     320                ImageEntry e = new ImageEntry(f);
    140321                try {
    141322                    e.time = ExifReader.readTime(f);
     
    145326                if (e.time == null)
    146327                    continue;
    147                 e.image = f;
    148                 e.icon = loadScaledImage(f, 16);
    149328
    150329                data.add(e);
     
    172351    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
    173352    private MouseAdapter mouseAdapter;
    174     private int currentImage;
     353    private ImageViewerDialog imageViewerDialog;
    175354
    176355    public static final class GpsTimeIncorrect extends Exception {
     
    226405                        continue;
    227406                    Point p = Main.map.mapView.getPoint(e.pos);
    228                     Rectangle r = new Rectangle(p.x-e.icon.getIconWidth()/2, p.y-e.icon.getIconHeight()/2, e.icon.getIconWidth(), e.icon.getIconHeight());
     407                    Rectangle r = new Rectangle(p.x-ICON_SIZE/2, p.y-ICON_SIZE/2, ICON_SIZE, ICON_SIZE);
    229408                    if (r.contains(ev.getPoint())) {
    230409                        showImage(i-1);
     
    246425    }
    247426
     427    private class ImageViewerDialog {
     428
     429        private int currentImage;
     430        private ImageEntry currentImageEntry;
     431
     432        private final JDialog dlg;
     433        private final JButton nextButton;
     434        private final JButton prevButton;
     435        private final JToggleButton scaleToggle;
     436        private final JToggleButton centerToggle;
     437        private final JViewport imageViewport;
     438        private final JLabel imageLabel;
     439
     440        private class ImageAction implements ActionListener {
     441
     442            private final int offset;
     443
     444            public ImageAction(int offset) {
     445                this.offset = offset;
     446            }
     447
     448            public void actionPerformed(ActionEvent e) {
     449                showImage(currentImage + offset);
     450            }
     451
     452        }
     453
     454        public ImageViewerDialog(ImageEntry firstImage) {
     455            final JPanel p = new JPanel(new BorderLayout());
     456            imageLabel = new JLabel(new ImageIcon(imageLoader.waitForImage(firstImage.image, 580)));
     457            final JScrollPane scroll = new JScrollPane(imageLabel);
     458            scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
     459            scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
     460            imageViewport = scroll.getViewport();
     461            p.add(scroll, BorderLayout.CENTER);
     462
     463            scaleToggle = new JToggleButton(ImageProvider.get("dialogs", "zoom-best-fit"));
     464            nextButton  = new JButton(ImageProvider.get("dialogs", "next"));
     465            prevButton = new JButton(ImageProvider.get("dialogs", "previous"));
     466            centerToggle = new JToggleButton(ImageProvider.get("dialogs", "centreview"));
     467
     468            JPanel p2 = new JPanel();
     469            p2.add(prevButton);
     470            p2.add(scaleToggle);
     471            p2.add(centerToggle);
     472            p2.add(nextButton);
     473            p.add(p2, BorderLayout.SOUTH);
     474            final JOptionPane pane = new JOptionPane(p, JOptionPane.PLAIN_MESSAGE);
     475            dlg = pane.createDialog(Main.parent, "");
     476            scaleToggle.addActionListener(new ImageAction(0));
     477            scaleToggle.setSelected(true);
     478            centerToggle.addActionListener(new ImageAction(0));
     479
     480            nextButton.setActionCommand("Next");
     481            prevButton.setActionCommand("Previous");
     482            nextButton.setMnemonic(KeyEvent.VK_RIGHT);
     483            prevButton.setMnemonic(KeyEvent.VK_LEFT);
     484            scaleToggle.setMnemonic(KeyEvent.VK_F);
     485            centerToggle.setMnemonic(KeyEvent.VK_C);
     486            nextButton.setToolTipText("Show next image");
     487            prevButton.setToolTipText("Show previous image");
     488            centerToggle.setToolTipText("Centre image location in main display");
     489            scaleToggle.setToolTipText("Scale image to fit");
     490
     491            prevButton.addActionListener(new ImageAction(-1));
     492            nextButton.addActionListener(new ImageAction(1));
     493            centerToggle.setSelected(false);
     494
     495            dlg.addComponentListener(new ComponentListener() {
     496                boolean ignoreEvent = true;
     497                public void componentHidden(ComponentEvent e) {}
     498                public void componentMoved(ComponentEvent e) {}
     499                public void componentResized(ComponentEvent ev) {
     500                    // we ignore the first resize event, as the picture is scaled already on load:
     501                    if (scaleToggle.getModel().isSelected() && !ignoreEvent) {
     502                        imageLabel.setIcon(new ImageIcon(imageLoader.waitForImage(currentImageEntry.image,
     503                                Math.max(imageViewport.getWidth(), imageViewport.getHeight()))));
     504                    }
     505                    ignoreEvent = false;
     506                }
     507                public void componentShown(ComponentEvent e) {}
     508
     509            });
     510            dlg.setModal(false);
     511            dlg.setResizable(true);
     512            dlg.pack();
     513        }
     514
     515        public void showImage(int index) {
     516            dlg.setVisible(true);
     517            dlg.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
     518
     519            if (index < 0) {
     520                index = 0;
     521            } else if (index >= data.size() - 1) {
     522                index = data.size() - 1;
     523            }
     524
     525            currentImage = index;
     526            currentImageEntry = data.get(currentImage);
     527
     528            prevButton.setEnabled(currentImage > 0);
     529            nextButton.setEnabled(currentImage < data.size() - 1);
     530
     531            if (scaleToggle.getModel().isSelected())
     532                imageLabel.setIcon(new ImageIcon(imageLoader.waitForImage(currentImageEntry.image,
     533                        Math.max(imageViewport.getWidth(), imageViewport.getHeight()))));
     534            else
     535                imageLabel.setIcon(new ImageIcon(imageLoader.waitForImage(currentImageEntry.image)));
     536
     537            if (centerToggle.getModel().isSelected())
     538                Main.map.mapView.zoomTo(currentImageEntry.pos, Main.map.mapView.getScale());
     539
     540            dlg.setTitle(currentImageEntry.image +
     541                    " (" + currentImageEntry.coor.toDisplayString() + ")");
     542            dlg.setCursor(Cursor.getDefaultCursor());
     543        }
     544
     545    }
     546
    248547    private void showImage(int i) {
    249         currentImage = i;
    250         final JPanel p = new JPanel(new BorderLayout());
    251         final ImageEntry e = data.get(currentImage);
    252         if (!(e.image.exists() && e.image.canRead()))
    253         {
    254             JOptionPane.showMessageDialog(Main.parent,
    255             tr("Image with path {0} does not exist or is not readable.", e.image),
    256             tr("Warning"), JOptionPane.WARNING_MESSAGE);
    257             return;
    258         }
    259         final JScrollPane scroll = new JScrollPane(new JLabel(loadScaledImage(e.image, 580)));
    260         final JViewport vp = scroll.getViewport();
    261         p.add(scroll, BorderLayout.CENTER);
    262 
    263         final JToggleButton scale = new JToggleButton(ImageProvider.get("dialogs", "zoom-best-fit"));
    264         final JButton next  = new JButton(ImageProvider.get("dialogs", "next"));
    265         final JButton prev = new JButton(ImageProvider.get("dialogs", "previous"));
    266         final JToggleButton cent = new JToggleButton(ImageProvider.get("dialogs", "centreview"));
    267 
    268         JPanel p2 = new JPanel();
    269         p2.add(prev);
    270         p2.add(scale);
    271         p2.add(cent);
    272         p2.add(next);
    273         prev.setEnabled(currentImage>0?true:false);
    274         next.setEnabled(currentImage<data.size()-1?true:false);
    275         p.add(p2, BorderLayout.SOUTH);
    276         final JOptionPane pane = new JOptionPane(p, JOptionPane.PLAIN_MESSAGE);
    277         final JDialog dlg = pane.createDialog(Main.parent, e.image+" ("+e.coor.toDisplayString()+")");
    278         scale.addActionListener(new ActionListener(){
    279             public void actionPerformed(ActionEvent ev) {
    280                 p.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    281                 if (scale.getModel().isSelected())
    282                     ((JLabel)vp.getView()).setIcon(loadScaledImage(e.image, Math.max(vp.getWidth(), vp.getHeight())));
    283                 else
    284                     ((JLabel)vp.getView()).setIcon(new ImageIcon(e.image.getPath()));
    285                 p.setCursor(Cursor.getDefaultCursor());
    286             }
    287         });
    288         scale.setSelected(true);
    289         cent.addActionListener(new ActionListener(){
    290             public void actionPerformed(ActionEvent ev) {
    291                 final ImageEntry e = data.get(currentImage);
    292                 if (cent.getModel().isSelected())
    293                     Main.map.mapView.zoomTo(e.pos, Main.map.mapView.getScale());
    294             }
    295         });
    296 
    297         ActionListener nextprevAction = new ActionListener(){
    298             public void actionPerformed(ActionEvent ev) {
    299                 p.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    300                 if (ev.getActionCommand().equals("Next")) {
    301                     currentImage++;
    302                     if(currentImage>=data.size()-1) next.setEnabled(false);
    303                     prev.setEnabled(true);
    304                 } else {
    305                     currentImage--;
    306                     if(currentImage<=0) prev.setEnabled(false);
    307                     next.setEnabled(true);
    308                 }
    309 
    310                 final ImageEntry e = data.get(currentImage);
    311                 if (scale.getModel().isSelected())
    312                     ((JLabel)vp.getView()).setIcon(loadScaledImage(e.image, Math.max(vp.getWidth(), vp.getHeight())));
    313                 else
    314                     ((JLabel)vp.getView()).setIcon(new ImageIcon(e.image.getPath()));
    315                 dlg.setTitle(e.image+" ("+e.coor.toDisplayString()+")");
    316                 if (cent.getModel().isSelected())
    317                     Main.map.mapView.zoomTo(e.pos, Main.map.mapView.getScale());
    318                 p.setCursor(Cursor.getDefaultCursor());
    319             }
    320         };
    321         next.setActionCommand("Next");
    322         prev.setActionCommand("Previous");
    323         next.setMnemonic(KeyEvent.VK_RIGHT);
    324         prev.setMnemonic(KeyEvent.VK_LEFT);
    325         scale.setMnemonic(KeyEvent.VK_F);
    326         cent.setMnemonic(KeyEvent.VK_C);
    327         next.setToolTipText("Show next image");
    328         prev.setToolTipText("Show previous image");
    329         cent.setToolTipText("Centre image location in main display");
    330         scale.setToolTipText("Scale image to fit");
    331 
    332         prev.addActionListener(nextprevAction);
    333         next.addActionListener(nextprevAction);
    334         cent.setSelected(false);
    335 
    336         dlg.addComponentListener(new ComponentListener() {
    337             boolean ignoreEvent = true;
    338             public void componentHidden(ComponentEvent e) {}
    339             public void componentMoved(ComponentEvent e) {}
    340             public void componentResized(ComponentEvent ev) {
    341                 // we ignore the first resize event, as the picture is scaled already on load:
    342                 if (scale.getModel().isSelected() && !ignoreEvent) {
    343                     ((JLabel)vp.getView()).setIcon(loadScaledImage(e.image, Math.max(vp.getWidth(), vp.getHeight())));
    344                 }
    345                 ignoreEvent = false;
    346             }
    347             public void componentShown(ComponentEvent e) {}
    348 
    349         });
    350         dlg.setModal(false);
    351         dlg.setVisible(true);
    352         dlg.setResizable(true);
     548        if (imageViewerDialog == null) {
     549            imageViewerDialog = new ImageViewerDialog(data.get(i));
     550        }
     551        imageViewerDialog.showImage(i);
    353552    }
    354553
     
    372571                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    373572                ImageEntry e = (ImageEntry)value;
    374                 setIcon(e.icon);
     573                setIcon(new ImageIcon(e.getIcon()));
    375574                setText(e.image.getName()+" ("+dateFormat.format(new Date(e.time.getTime()+(delta+gpstimezone)))+")");
    376575                if (e.pos == null)
     
    402601
    403602    @Override public void paint(Graphics g, MapView mv) {
    404         boolean clickedFound = false;
    405         for (ImageEntry e : data) {
     603        int clickedIndex = -1;
     604
     605        // First select beveled icon (for cases where are more icons on the same spot)
     606        Point mousePosition = mv.getMousePosition();
     607        if (mousePosition != null  && mousePressed) {
     608            for (int i = data.size() - 1; i >= 0; i--) {
     609                ImageEntry e = data.get(i);
     610                if (e.pos == null) {
     611                    continue;
     612                }
     613
     614                Point p = mv.getPoint(e.pos);
     615                Rectangle r = new Rectangle(p.x-ICON_SIZE / 2, p.y-ICON_SIZE / 2, ICON_SIZE, ICON_SIZE);
     616                if (r.contains(mousePosition)) {
     617                    clickedIndex = i;
     618                    break;
     619                }
     620            }
     621        }
     622
     623        for (int i = 0; i < data.size(); i++) {
     624            ImageEntry e = data.get(i);
    406625            if (e.pos != null) {
    407626                Point p = mv.getPoint(e.pos);
    408                 Rectangle r = new Rectangle(p.x-e.icon.getIconWidth()/2, p.y-e.icon.getIconHeight()/2, e.icon.getIconWidth(), e.icon.getIconHeight());
    409                 e.icon.paintIcon(mv, g, r.x, r.y);
     627                Rectangle r = new Rectangle(p.x-ICON_SIZE / 2, p.y-ICON_SIZE / 2, ICON_SIZE, ICON_SIZE);
     628                g.drawImage(e.getIcon(), r.x, r.y, null);
    410629                Border b = null;
    411                 Point mousePosition = mv.getMousePosition();
    412                 if (mousePosition == null)
    413                     continue; // mouse outside the whole window
    414                 if (!clickedFound && mousePressed && r.contains(mousePosition)) {
     630                if (i == clickedIndex) {
    415631                    b = BorderFactory.createBevelBorder(BevelBorder.LOWERED);
    416                     clickedFound = true;
    417                 } else
     632                } else {
    418633                    b = BorderFactory.createBevelBorder(BevelBorder.RAISED);
     634                }
    419635                Insets inset = b.getBorderInsets(mv);
    420636                r.grow((inset.top+inset.bottom)/2, (inset.left+inset.right)/2);
     
    477693                lastTP = tp;
    478694            }
    479             if (e.pos != null)
    480                 e.coor = Main.proj.eastNorth2latlon(e.pos);
     695            if (e.pos == null) {
     696                e.pos = gps.getLast().pos;
     697            }
     698            e.coor = Main.proj.eastNorth2latlon(e.pos);
    481699        }
    482700    }
     
    496714        JPanel p = new JPanel(new GridBagLayout());
    497715        p.add(new JLabel(tr("Image")), GBC.eol());
    498         p.add(new JLabel(loadScaledImage(f, 300)), GBC.eop());
     716        p.add(new JLabel(new ImageIcon(imageLoader.waitForImage(f, 300))), GBC.eop());
    499717        p.add(new JLabel(tr("Enter shown date (mm/dd/yyyy HH:MM:SS)")), GBC.eol());
    500718        JTextField gpsText = new JTextField(dateFormat.format(new Date(exifDate.getTime()+delta)));
     
    531749    }
    532750
    533     private static Icon loadScaledImage(File f, int maxSize) {
    534         Image img = Toolkit.getDefaultToolkit().createImage(f.getPath());
    535         while (img.getWidth(null) < 0 || img.getHeight(null) < 0) {
    536           try {
    537             Thread.sleep(10);
    538           } catch(InterruptedException ie) {}
    539         }
    540         int w = img.getWidth(null);
    541         int h = img.getHeight(null);
    542         if (w>h) {
    543             h = Math.round(maxSize*((float)h/w));
    544             w = maxSize;
    545         } else {
    546             w = Math.round(maxSize*((float)w/h));
    547             h = maxSize;
    548         }
    549         return new ImageIcon(createResizedCopy(img, w, h));
    550     }
    551 
    552     private static BufferedImage createResizedCopy(Image originalImage,
    553     int scaledWidth, int scaledHeight)
    554     {
    555         BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB);
    556         Graphics2D g = scaledBI.createGraphics();
    557         while (!g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null))
    558         {
    559           try {
    560             Thread.sleep(10);
    561           } catch(InterruptedException ie) {}
    562         }
    563         g.dispose();
    564         return scaledBI;
    565     }
    566751}
Note: See TracChangeset for help on using the changeset viewer.