001// License: GPL. See LICENSE file for details.
002package org.openstreetmap.josm.gui.layer.geoimage;
003
004import java.awt.Graphics2D;
005import java.awt.Image;
006import java.awt.MediaTracker;
007import java.awt.Rectangle;
008import java.awt.Toolkit;
009import java.awt.image.BufferedImage;
010import java.util.ArrayList;
011import java.util.List;
012
013import org.openstreetmap.josm.Main;
014import org.openstreetmap.josm.io.CacheFiles;
015
016public class ThumbsLoader implements Runnable {
017    public static final int maxSize = 120;
018    public static final int minSize = 22;
019    volatile boolean stop = false;
020    List<ImageEntry> data;
021    GeoImageLayer layer;
022    MediaTracker tracker;
023    CacheFiles cache;
024    boolean cacheOff = Main.pref.getBoolean("geoimage.noThumbnailCache", false);
025
026    public ThumbsLoader(GeoImageLayer layer) {
027        this.layer = layer;
028        this.data = new ArrayList<>(layer.data);
029        if (!cacheOff) {
030            cache = new CacheFiles("geoimage-thumbnails", false);
031            cache.setExpire(CacheFiles.EXPIRE_NEVER, false);
032            cache.setMaxSize(120, false);
033        }
034    }
035
036    @Override
037    public void run() {
038        Main.debug("Load Thumbnails");
039        tracker = new MediaTracker(Main.map.mapView);
040        for (int i = 0; i < data.size(); i++) {
041            if (stop) return;
042
043            // Do not load thumbnails that were loaded before.
044            if (data.get(i).thumbnail == null) {
045                data.get(i).thumbnail = loadThumb(data.get(i));
046
047                if (Main.isDisplayingMapView()) {
048                    layer.updateOffscreenBuffer = true;
049                    Main.map.mapView.repaint();
050                }
051            }
052        }
053        layer.updateOffscreenBuffer = true;
054        Main.map.mapView.repaint();
055    }
056
057    private BufferedImage loadThumb(ImageEntry entry) {
058        final String cacheIdent = entry.getFile().toString()+":"+maxSize;
059
060        if (!cacheOff) {
061            BufferedImage cached = cache.getImg(cacheIdent);
062            if (cached != null) {
063                Main.debug(" from cache");
064                return cached;
065            }
066        }
067
068        Image img = Toolkit.getDefaultToolkit().createImage(entry.getFile().getPath());
069        tracker.addImage(img, 0);
070        try {
071            tracker.waitForID(0);
072        } catch (InterruptedException e) {
073            Main.error(" InterruptedException while loading thumb");
074            return null;
075        }
076        if (tracker.isErrorID(1) || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) {
077            Main.error(" Invalid image");
078            return null;
079        }
080        Rectangle targetSize = ImageDisplay.calculateDrawImageRectangle(
081                new Rectangle(0, 0, img.getWidth(null), img.getHeight(null)),
082                new Rectangle(0, 0, maxSize, maxSize));
083        BufferedImage scaledBI = new BufferedImage(targetSize.width, targetSize.height, BufferedImage.TYPE_INT_RGB);
084        Graphics2D g = scaledBI.createGraphics();
085        while (!g.drawImage(img, 0, 0, targetSize.width, targetSize.height, null)) {
086            try {
087                Thread.sleep(10);
088            } catch(InterruptedException ie) {
089                Main.warn("InterruptedException while drawing thumb");
090            }
091        }
092        g.dispose();
093        tracker.removeImage(img);
094
095        if (scaledBI.getWidth() <= 0 || scaledBI.getHeight() <= 0) {
096            Main.error(" Invalid image");
097            return null;
098        }
099
100        if (!cacheOff) {
101            cache.saveImg(cacheIdent, scaledBI);
102        }
103
104        return scaledBI;
105    }
106
107}