Changeset 17880 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2021-05-10T21:44:33+02:00 (4 years ago)
Author:
simon04
Message:

see #8472 - Show geocoded images from Wikimedia Commons as GeoImageLayer

The icon wikimedia_commons.svg is taken from https://commons.wikimedia.org/wiki/File:Commons-logo.svg ("This image of simple geometry is ineligible for copyright and therefore in the public domain, because it consists entirely of information that is common property and contains no original authorship.")

Location:
trunk/src/org/openstreetmap/josm
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java

    r17878 r17880  
    207207    public File getFile() {
    208208        return file;
     209    }
     210
     211    /**
     212     * Returns a display name for this entry
     213     * @return a display name for this entry
     214     */
     215    public String getDisplayName() {
     216        return file == null ? "" : file.getName();
    209217    }
    210218
  • trunk/src/org/openstreetmap/josm/gui/MainMenu.java

    r17767 r17880  
    130130import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
    131131import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
     132import org.openstreetmap.josm.gui.layer.geoimage.WikimediaCommonsLoader;
    132133import org.openstreetmap.josm.gui.mappaint.MapPaintMenu;
    133134import org.openstreetmap.josm.gui.preferences.imagery.ImageryPreference;
     
    748749        add(fileMenu, searchNotes);
    749750        add(fileMenu, downloadNotesInView);
     751        add(fileMenu, new WikimediaCommonsLoader.Action());
    750752        add(fileMenu, downloadReferrers);
    751753        add(fileMenu, update);
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java

    r17878 r17880  
    702702                @Override
    703703                public String getElementAt(int i) {
    704                     return yLayer.getImageData().getImages().get(i).getFile().getName();
     704                    return yLayer.getImageData().getImages().get(i).getDisplayName();
    705705                }
    706706
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java

    r17872 r17880  
    703703            }
    704704            if (errorLoading) {
    705                 String loadingStr = tr("Error on file {0}", entry.getFile().getName());
     705                String loadingStr = tr("Error on file {0}", entry.getDisplayName());
    706706                Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(loadingStr, g);
    707707                g.drawString(loadingStr,
     
    749749            // we are probably still loading the image. (oldEntry gets set to entry when the image finishes loading).
    750750            if (!errorLoading) {
    751                 errorMessage = tr("Loading {0}", entry.getFile().getName());
     751                errorMessage = tr("Loading {0}", entry.getDisplayName());
    752752            } else {
    753                 errorMessage = tr("Error on file {0}", entry.getFile().getName());
     753                errorMessage = tr("Error on file {0}", entry.getDisplayName());
    754754            }
    755755        } else {
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageEntry.java

    r17872 r17880  
    1010import java.io.IOException;
    1111import java.io.UncheckedIOException;
     12import java.net.MalformedURLException;
     13import java.net.URL;
    1214import java.util.Collections;
    1315import java.util.Objects;
     
    2931 * @since 2662
    3032 */
    31 public final class ImageEntry extends GpxImageEntry {
     33public class ImageEntry extends GpxImageEntry {
    3234
    3335    private Image thumbnail;
     
    141143     */
    142144    public BufferedImage read(Dimension target) throws IOException {
    143         Logging.info(tr("Loading {0}", getFile().getPath()));
    144         BufferedImage image = ImageProvider.read(getFile(), false, false,
     145        URL imageUrl = getImageUrl();
     146        Logging.info(tr("Loading {0}", imageUrl));
     147        BufferedImage image = ImageProvider.read(imageUrl, false, false,
    145148                r -> target == null ? r.getDefaultReadParam() : withSubsampling(r, target));
    146149        Logging.debug("Loaded {0} with dimensions {1}x{2} memoryTaken={3}m exifOrientationSwitchedDimension={4}",
    147                 getFile().getPath(), image.getWidth(), image.getHeight(), image.getWidth() * image.getHeight() * 4 / 1024 / 1024,
     150                imageUrl, image.getWidth(), image.getHeight(), image.getWidth() * image.getHeight() * 4 / 1024 / 1024,
    148151                ExifReader.orientationSwitchesDimensions(getExifOrientation()));
    149152        return applyExifRotation(image);
     153    }
     154
     155    protected URL getImageUrl() throws MalformedURLException {
     156        return getFile().toURI().toURL();
    150157    }
    151158
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java

    r17740 r17880  
    372372        public void actionPerformed(ActionEvent e) {
    373373            if (currentData != null) {
    374                 ClipboardUtils.copyString(currentData.getSelectedImage().getFile().toString());
     374                ClipboardUtils.copyString(String.valueOf(currentData.getSelectedImage().getFile()));
    375375            }
    376376        }
     
    461461            setPreviousEnabled(data.hasPreviousImage());
    462462            btnDelete.setEnabled(true);
    463             btnDeleteFromDisk.setEnabled(true);
     463            btnDeleteFromDisk.setEnabled(entry.getFile() != null);
    464464            btnCopyPath.setEnabled(true);
    465465
     
    469469                imgDisplay.setImage(entry);
    470470            }
    471             setTitle(tr("Geotagged Images") + (entry.getFile() != null ? " - " + entry.getFile().getName() : ""));
    472             StringBuilder osd = new StringBuilder(entry.getFile() != null ? entry.getFile().getName() : "");
     471            setTitle(tr("Geotagged Images") + (!entry.getDisplayName().isEmpty() ? " - " + entry.getDisplayName() : ""));
     472            StringBuilder osd = new StringBuilder(entry.getDisplayName());
    473473            if (entry.getElevation() != null) {
    474474                osd.append(tr("\nAltitude: {0} m", Math.round(entry.getElevation())));
  • trunk/src/org/openstreetmap/josm/tools/ImageProvider.java

    r17871 r17880  
    15491549     */
    15501550    public static BufferedImage read(File input, boolean readMetadata, boolean enforceTransparency) throws IOException {
    1551         return read(input, readMetadata, enforceTransparency, ImageReader::getDefaultReadParam);
    1552     }
    1553 
    1554     /**
    1555      * Returns a <code>BufferedImage</code> as the result of decoding
    1556      * a supplied <code>File</code> with an <code>ImageReader</code>
    1557      * chosen automatically from among those currently registered.
    1558      * The <code>File</code> is wrapped in an
    1559      * <code>ImageInputStream</code>.  If no registered
    1560      * <code>ImageReader</code> claims to be able to read the
    1561      * resulting stream, <code>null</code> is returned.
    1562      *
    1563      * <p> The current cache settings from <code>getUseCache</code>and
    1564      * <code>getCacheDirectory</code> will be used to control caching in the
    1565      * <code>ImageInputStream</code> that is created.
    1566      *
    1567      * <p> Note that there is no <code>read</code> method that takes a
    1568      * filename as a <code>String</code>; use this method instead after
    1569      * creating a <code>File</code> from the filename.
    1570      *
    1571      * <p> This method does not attempt to locate
    1572      * <code>ImageReader</code>s that can read directly from a
    1573      * <code>File</code>; that may be accomplished using
    1574      * <code>IIORegistry</code> and <code>ImageReaderSpi</code>.
    1575      *
    1576      * @param input a <code>File</code> to read from.
    1577      * @param readMetadata if {@code true}, makes sure to read image metadata to detect transparency color, if any.
    1578      * In that case the color can be retrieved later through {@link #PROP_TRANSPARENCY_COLOR}.
    1579      * Always considered {@code true} if {@code enforceTransparency} is also {@code true}
    1580      * @param enforceTransparency if {@code true}, makes sure to read image metadata and, if the image does not
    1581      * provide an alpha channel but defines a {@code TransparentColor} metadata node, that the resulting image
    1582      * has a transparency set to {@code TRANSLUCENT} and uses the correct transparent color.
    1583      * @param readParamFunction a function to compute the read parameters from the image reader
    1584      *
    1585      * @return a <code>BufferedImage</code> containing the decoded contents of the input, or <code>null</code>.
    1586      *
    1587      * @throws IllegalArgumentException if <code>input</code> is <code>null</code>.
    1588      * @throws IOException if an error occurs during reading.
    1589      * @see BufferedImage#getProperty
    1590      * @since xxx
    1591      */
    1592     public static BufferedImage read(File input, boolean readMetadata, boolean enforceTransparency,
    1593                                      Function<ImageReader, ImageReadParam> readParamFunction) throws IOException {
    15941551        CheckParameterUtil.ensureParameterNotNull(input, "input");
    15951552        if (!input.canRead()) {
     
    16011558            throw new IIOException("Can't create an ImageInputStream!");
    16021559        }
    1603         BufferedImage bi = read(stream, readMetadata, enforceTransparency, readParamFunction);
     1560        BufferedImage bi = read(stream, readMetadata, enforceTransparency);
    16041561        if (bi == null) {
    16051562            stream.close();
     
    16881645     */
    16891646    public static BufferedImage read(URL input, boolean readMetadata, boolean enforceTransparency) throws IOException {
     1647        return read(input, readMetadata, enforceTransparency, ImageReader::getDefaultReadParam);
     1648    }
     1649
     1650    /**
     1651     * Returns a <code>BufferedImage</code> as the result of decoding
     1652     * a supplied <code>URL</code> with an <code>ImageReader</code>
     1653     * chosen automatically from among those currently registered.  An
     1654     * <code>InputStream</code> is obtained from the <code>URL</code>,
     1655     * which is wrapped in an <code>ImageInputStream</code>.  If no
     1656     * registered <code>ImageReader</code> claims to be able to read
     1657     * the resulting stream, <code>null</code> is returned.
     1658     *
     1659     * <p> The current cache settings from <code>getUseCache</code>and
     1660     * <code>getCacheDirectory</code> will be used to control caching in the
     1661     * <code>ImageInputStream</code> that is created.
     1662     *
     1663     * <p> This method does not attempt to locate
     1664     * <code>ImageReader</code>s that can read directly from a
     1665     * <code>URL</code>; that may be accomplished using
     1666     * <code>IIORegistry</code> and <code>ImageReaderSpi</code>.
     1667     *
     1668     * @param input a <code>URL</code> to read from.
     1669     * @param readMetadata if {@code true}, makes sure to read image metadata to detect transparency color for non translucent images, if any.
     1670     * In that case the color can be retrieved later through {@link #PROP_TRANSPARENCY_COLOR}.
     1671     * Always considered {@code true} if {@code enforceTransparency} is also {@code true}
     1672     * @param enforceTransparency if {@code true}, makes sure to read image metadata and, if the image does not
     1673     * provide an alpha channel but defines a {@code TransparentColor} metadata node, that the resulting image
     1674     * has a transparency set to {@code TRANSLUCENT} and uses the correct transparent color.
     1675     * @param readParamFunction a function to compute the read parameters from the image reader
     1676     *
     1677     * @return a <code>BufferedImage</code> containing the decoded contents of the input, or <code>null</code>.
     1678     *
     1679     * @throws IllegalArgumentException if <code>input</code> is <code>null</code>.
     1680     * @throws IOException if an error occurs during reading.
     1681     * @since 17880
     1682     */
     1683    public static BufferedImage read(URL input, boolean readMetadata, boolean enforceTransparency,
     1684                                     Function<ImageReader, ImageReadParam> readParamFunction) throws IOException {
    16901685        CheckParameterUtil.ensureParameterNotNull(input, "input");
    16911686
    16921687        try (InputStream istream = Utils.openStream(input)) {
    16931688            ImageInputStream stream = createImageInputStream(istream); // NOPMD
    1694             BufferedImage bi = read(stream, readMetadata, enforceTransparency);
     1689            BufferedImage bi = read(stream, readMetadata, enforceTransparency, readParamFunction);
    16951690            if (bi == null) {
    16961691                stream.close();
  • trunk/src/org/openstreetmap/josm/tools/Mediawiki.java

    r16988 r17880  
    77import java.util.List;
    88import java.util.Optional;
     9import java.util.function.BiConsumer;
    910import java.util.stream.Collectors;
    1011
     
    1516import javax.xml.xpath.XPathFactory;
    1617
     18import org.openstreetmap.josm.data.Bounds;
     19import org.openstreetmap.josm.data.coor.LatLon;
    1720import org.w3c.dom.Document;
     21import org.w3c.dom.NamedNodeMap;
    1822import org.w3c.dom.Node;
     23import org.w3c.dom.NodeList;
    1924import org.xml.sax.SAXException;
    2025
     
    5358                .collect(Collectors.joining(Utils.encodeUrl("|")))
    5459        );
    55         final HttpClient.Response conn = HttpClient.create(url).connect();
    56         final Document document;
    57         try (InputStream content = conn.getContent()) {
    58             document = XmlUtils.parseSafeDOM(content);
    59         }
    60         conn.disconnect();
     60        final Document document = getDocument(url);
    6161        final XPath xPath = XPathFactory.newInstance().newXPath();
    6262        for (String page : distinctPages) {
     
    7575    }
    7676
     77    private Document getDocument(URL url) throws IOException, ParserConfigurationException, SAXException {
     78        final HttpClient.Response conn = HttpClient.create(url).connect();
     79        try (InputStream content = conn.getContent()) {
     80            return XmlUtils.parseSafeDOM(content);
     81        } finally {
     82            conn.disconnect();
     83        }
     84    }
     85
     86    /**
     87     * Searches geocoded images from <a href="https://commons.wikimedia.org/">Wikimedia Commons</a> for the given bounding box.
     88     * @param bounds the bounds to load
     89     * @param imageConsumer a consumer to receive the file title and the coordinates for every geocoded image
     90     * @throws IOException if any I/O error occurs
     91     * @throws ParserConfigurationException if a parser cannot be created
     92     * @throws SAXException if any XML error occurs
     93     * @throws XPathExpressionException if any error in an XPath expression occurs
     94     */
     95    public void searchGeoImages(Bounds bounds, BiConsumer<String, LatLon> imageConsumer)
     96            throws IOException, ParserConfigurationException, SAXException, XPathExpressionException {
     97        final URL url = new URL(baseUrl +
     98                "?format=xml" +
     99                "&action=query" +
     100                "&list=geosearch" +
     101                "&gsnamespace=6" +
     102                "&gslimit=500" +
     103                "&gsprop=type|name" +
     104                "&gsbbox=" + bounds.getMaxLat() + "|" + bounds.getMinLon() + "|" + bounds.getMinLat() + "|" + bounds.getMaxLon());
     105        final Document document = getDocument(url);
     106        final XPath xPath = XPathFactory.newInstance().newXPath();
     107        NodeList nodes = (NodeList) xPath.evaluate("/api/query/geosearch/gs", document, XPathConstants.NODESET);
     108        for (int i = 0; i < nodes.getLength(); i++) {
     109            NamedNodeMap attributes = nodes.item(i).getAttributes();
     110            String title = attributes.getNamedItem("title").getNodeValue();
     111            double lat = Double.parseDouble(attributes.getNamedItem("lat").getNodeValue());
     112            double lon = Double.parseDouble(attributes.getNamedItem("lon").getNodeValue());
     113            imageConsumer.accept(title, new LatLon(lat, lon));
     114        }
     115    }
     116
    77117    /**
    78118     * Computes the URL for the given filename on the MediaWiki server
Note: See TracChangeset for help on using the changeset viewer.