Ticket #20341: 20341-core-V2.diff

File 20341-core-V2.diff, 35.2 KB (added by Bjoeni, 5 years ago)
  • build.xml

     
    10481048                <exclude name="com/drew/imaging/mp3/**"/>
    10491049                <exclude name="com/drew/imaging/mp4/**"/>
    10501050                <exclude name="com/drew/imaging/pcx/**"/>
    1051                 <exclude name="com/drew/imaging/png/**"/>
    10521051                <exclude name="com/drew/imaging/psd/**"/>
    10531052                <exclude name="com/drew/imaging/quicktime/**"/>
    10541053                <exclude name="com/drew/imaging/raf/**"/>
     
    10651064                <exclude name="com/drew/metadata/mp3/**"/>
    10661065                <exclude name="com/drew/metadata/mp4/**"/>
    10671066                <exclude name="com/drew/metadata/pcx/**"/>
    1068                 <exclude name="com/drew/metadata/png/**"/>
    10691067                <exclude name="com/drew/metadata/wav/**"/>
    10701068                <exclude name="com/drew/metadata/webp/**"/>
    10711069                <exclude name="com/drew/tools/**"/>
  • src/org/openstreetmap/josm/actions/ExtensionFileFilter.java

     
    2222import org.openstreetmap.josm.gui.io.importexport.FileImporter;
    2323import org.openstreetmap.josm.gui.io.importexport.GeoJSONImporter;
    2424import org.openstreetmap.josm.gui.io.importexport.GpxImporter;
    25 import org.openstreetmap.josm.gui.io.importexport.JpgImporter;
     25import org.openstreetmap.josm.gui.io.importexport.ImageImporter;
    2626import org.openstreetmap.josm.gui.io.importexport.NMEAImporter;
    2727import org.openstreetmap.josm.gui.io.importexport.NoteImporter;
    2828import org.openstreetmap.josm.gui.io.importexport.OsmChangeImporter;
     
    6969                NMEAImporter.class,
    7070                RtkLibImporter.class,
    7171                NoteImporter.class,
    72                 JpgImporter.class,
     72                ImageImporter.class,
    7373                WMSLayerImporter.class,
    7474                AllFormatsImporter.class,
    7575                SessionImporter.class
  • src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.gpx;
    33
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.io.File;
    5 import java.io.IOException;
    67import java.util.Date;
    78import java.util.List;
    89import java.util.Objects;
     
    1516import org.openstreetmap.josm.tools.Logging;
    1617
    1718import com.drew.imaging.jpeg.JpegMetadataReader;
    18 import com.drew.lang.CompoundException;
     19import com.drew.imaging.png.PngMetadataReader;
     20import com.drew.imaging.tiff.TiffMetadataReader;
    1921import com.drew.metadata.Directory;
    2022import com.drew.metadata.Metadata;
    2123import com.drew.metadata.MetadataException;
     
    573575            return;
    574576        }
    575577
     578        String fn = file.getName();
     579
    576580        try {
    577             metadata = JpegMetadataReader.readMetadata(file);
    578         } catch (CompoundException | IOException ex) {
    579             Logging.error(ex);
    580             setExifTime(null);
    581             setExifCoor(null);
    582             setPos(null);
    583             return;
     581            //try to parse metadata according to extension
     582            String ext = fn.substring(fn.lastIndexOf(".") + 1).toLowerCase();
     583            switch (ext) {
     584            case "jpg":
     585            case "jpeg":
     586                metadata = JpegMetadataReader.readMetadata(file);
     587                break;
     588            case "tif":
     589            case "tiff":
     590                metadata = TiffMetadataReader.readMetadata(file);
     591                break;
     592            case "png":
     593                metadata = PngMetadataReader.readMetadata(file);
     594                break;
     595            default:
     596                throw new NoMetadataReaderWarning(ext);
     597            }
     598        } catch (Exception topException) {
     599            //try other formats (e.g. JPEG file with .png extension)
     600            try {
     601                metadata = JpegMetadataReader.readMetadata(file);
     602            } catch (Exception ex1) {
     603                try {
     604                    metadata = TiffMetadataReader.readMetadata(file);
     605                } catch (Exception ex2) {
     606                    try {
     607                        metadata = PngMetadataReader.readMetadata(file);
     608                    } catch (Exception ex3) {
     609
     610                        Logging.warn(topException);
     611                        Logging.info(tr("Can''t parse metadata for file \"{0}\". Using last modified date as timestamp.", fn));
     612                        setExifTime(new Date(file.lastModified()));
     613                        setExifCoor(null);
     614                        setPos(null);
     615                        return;
     616                    }
     617                }
     618            }
    584619        }
    585620
    586621        // Changed to silently cope with no time info in exif. One case
    587622        // of person having time that couldn't be parsed, but valid GPS info
     623        Date time = null;
    588624        try {
    589             setExifTime(ExifReader.readTime(metadata));
     625            time = ExifReader.readTime(metadata);
    590626        } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException ex) {
    591627            Logging.warn(ex);
    592             setExifTime(null);
    593628        }
    594629
     630        if (time == null) {
     631            Logging.info(tr("No EXIF time in file \"{0}\". Using last modified date as timestamp.", fn));
     632            time = new Date(file.lastModified()); //use lastModified time if no EXIF time present
     633        }
     634        setExifTime(time);
     635
     636
    595637        final Directory dir = metadata.getFirstDirectoryOfType(JpegDirectory.class);
    596638        final Directory dirExif = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
    597639        final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
     
    614656            Logging.debug(ex);
    615657        }
    616658
    617         if (dirGps == null) {
     659        if (dirGps == null || dirGps.getTagCount() <= 1) {
    618660            setExifCoor(null);
    619661            setPos(null);
    620662            return;
     
    649691        }
    650692    }
    651693
     694    private static class NoMetadataReaderWarning extends Exception {
     695        NoMetadataReaderWarning(String ext) {
     696            super("No metadata reader for format *." + ext);
     697        }
     698    }
     699
    652700    private static <T> void ifNotNull(T value, Consumer<T> setter) {
    653701        if (value != null) {
    654702            setter.accept(value);
  • src/org/openstreetmap/josm/gui/io/importexport/ImageImporter.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.io.importexport;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
     6import java.io.File;
     7import java.io.IOException;
     8import java.util.ArrayList;
     9import java.util.Arrays;
     10import java.util.HashSet;
     11import java.util.List;
     12import java.util.Set;
     13
     14import javax.imageio.ImageIO;
     15
     16import org.openstreetmap.josm.actions.ExtensionFileFilter;
     17import org.openstreetmap.josm.gui.layer.GpxLayer;
     18import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
     19import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     20import org.openstreetmap.josm.io.IllegalDataException;
     21
     22/**
     23 * File importer allowing to import geotagged images
     24 * @since xxx
     25 */
     26public class ImageImporter extends FileImporter {
     27    private GpxLayer gpx;
     28
     29    /**
     30     * The supported image file types on the current system
     31     */
     32    public static final String[] SUPPORTED_FILE_TYPES = ImageIO.getReaderFileSuffixes();
     33
     34    /**
     35     * The default file filter
     36     */
     37    public static final ExtensionFileFilter FILE_FILTER = getFileFilters(false);
     38
     39    /**
     40     * An alternate file filter that also includes folders.
     41     */
     42    public static final ExtensionFileFilter FILE_FILTER_WITH_FOLDERS = getFileFilters(true);
     43
     44    private static ExtensionFileFilter getFileFilters(boolean folder) {
     45        String typeStr = String.join(",", SUPPORTED_FILE_TYPES);
     46        String humanStr = tr("Image Files") + " (*." + String.join(", *.", SUPPORTED_FILE_TYPES);
     47        if (folder) {
     48            humanStr += ", " + tr("folder");
     49        }
     50        humanStr += ")";
     51
     52        return new ExtensionFileFilter(typeStr, "jpg", humanStr);
     53    }
     54
     55    /**
     56     * Constructs a new {@code ImageImporter}.
     57     */
     58    public ImageImporter() {
     59        this(false);
     60    }
     61
     62    /**
     63     * Constructs a new {@code ImageImporter} with folders selection, if wanted.
     64     * @param includeFolders If true, includes folders in the file filter
     65     */
     66    public ImageImporter(boolean includeFolders) {
     67        super(includeFolders ? FILE_FILTER_WITH_FOLDERS : FILE_FILTER);
     68    }
     69
     70    /**
     71     * Constructs a new {@code ImageImporter} for the given GPX layer. Folders selection is allowed.
     72     * @param gpx The GPX layer
     73     */
     74    public ImageImporter(GpxLayer gpx) {
     75        this(true);
     76        this.gpx = gpx;
     77    }
     78
     79    @Override
     80    public boolean acceptFile(File pathname) {
     81        return super.acceptFile(pathname) || pathname.isDirectory();
     82    }
     83
     84    @Override
     85    public void importData(List<File> sel, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
     86        progressMonitor.beginTask(tr("Looking for image files"), 1);
     87        try {
     88            List<File> files = new ArrayList<>();
     89            Set<String> visitedDirs = new HashSet<>();
     90            addRecursiveFiles(files, visitedDirs, sel, progressMonitor.createSubTaskMonitor(1, true));
     91
     92            if (progressMonitor.isCanceled())
     93                return;
     94
     95            if (files.isEmpty())
     96                throw new IOException(tr("No image files found."));
     97
     98            GeoImageLayer.create(files, gpx);
     99        } finally {
     100            progressMonitor.finishTask();
     101        }
     102    }
     103
     104    static void addRecursiveFiles(List<File> files, Set<String> visitedDirs, List<File> sel, ProgressMonitor progressMonitor)
     105            throws IOException {
     106
     107        if (progressMonitor.isCanceled())
     108            return;
     109
     110        progressMonitor.beginTask(null, sel.size());
     111        try {
     112            for (File f : sel) {
     113                if (f.isDirectory()) {
     114                    if (visitedDirs.add(f.getCanonicalPath())) { // Do not loop over symlinks
     115                        File[] dirFiles = f.listFiles(); // Can be null for some strange directories (like lost+found)
     116                        if (dirFiles != null) {
     117                            addRecursiveFiles(files, visitedDirs, Arrays.asList(dirFiles), progressMonitor.createSubTaskMonitor(1, true));
     118                        }
     119                    } else {
     120                        progressMonitor.worked(1);
     121                    }
     122                } else {
     123                    if (FILE_FILTER.accept(f)) {
     124                        files.add(f);
     125                    }
     126                    progressMonitor.worked(1);
     127                }
     128            }
     129        } finally {
     130            progressMonitor.finishTask();
     131        }
     132    }
     133
     134    @Override
     135    public boolean isBatchImporter() {
     136        return true;
     137    }
     138
     139    /**
     140     * Needs to be the last, to avoid problems.
     141     */
     142    @Override
     143    public double getPriority() {
     144        return -1000;
     145    }
     146}
  • src/org/openstreetmap/josm/gui/io/importexport/JpgImporter.java

    Property changes on: src/org/openstreetmap/josm/gui/io/importexport/ImageImporter.java
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.io.importexport;
    3 
    4 import static org.openstreetmap.josm.tools.I18n.tr;
    5 
    6 import java.io.File;
    7 import java.io.IOException;
    8 import java.util.ArrayList;
    9 import java.util.Arrays;
    10 import java.util.HashSet;
    11 import java.util.List;
    12 import java.util.Set;
    13 
    14 import org.openstreetmap.josm.actions.ExtensionFileFilter;
    15 import org.openstreetmap.josm.gui.layer.GpxLayer;
    16 import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
    17 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    18 import org.openstreetmap.josm.io.IllegalDataException;
    19 
    20 /**
    21  * File importer allowing to import geotagged images (*.jpg files).
    22  *
    23  */
    24 public class JpgImporter extends FileImporter {
    25     private GpxLayer gpx;
    26 
    27     /**
    28      * The default file filter (only *.jpg files).
    29      */
    30     public static final ExtensionFileFilter FILE_FILTER = new ExtensionFileFilter(
    31             "jpg,jpeg", "jpg", tr("Image Files") + " (*.jpg)");
    32 
    33     /**
    34      * An alternate file filter that also includes folders.
    35      * @since 5438
    36      */
    37     public static final ExtensionFileFilter FILE_FILTER_WITH_FOLDERS = new ExtensionFileFilter(
    38             "jpg,jpeg", "jpg", tr("Image Files") + " (*.jpg, "+ tr("folder")+')');
    39 
    40     /**
    41      * Constructs a new {@code JpgImporter}.
    42      */
    43     public JpgImporter() {
    44         this(false);
    45     }
    46 
    47     /**
    48      * Constructs a new {@code JpgImporter} with folders selection, if wanted.
    49      * @param includeFolders If true, includes folders in the file filter
    50      * @since 5438
    51      */
    52     public JpgImporter(boolean includeFolders) {
    53         super(includeFolders ? FILE_FILTER_WITH_FOLDERS : FILE_FILTER);
    54     }
    55 
    56     /**
    57      * Constructs a new {@code JpgImporter} for the given GPX layer. Folders selection is allowed.
    58      * @param gpx The GPX layer
    59      */
    60     public JpgImporter(GpxLayer gpx) {
    61         this(true);
    62         this.gpx = gpx;
    63     }
    64 
    65     @Override
    66     public boolean acceptFile(File pathname) {
    67         return super.acceptFile(pathname) || pathname.isDirectory();
    68     }
    69 
    70     @Override
    71     public void importData(List<File> sel, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
    72         progressMonitor.beginTask(tr("Looking for image files"), 1);
    73         try {
    74             List<File> files = new ArrayList<>();
    75             Set<String> visitedDirs = new HashSet<>();
    76             addRecursiveFiles(files, visitedDirs, sel, progressMonitor.createSubTaskMonitor(1, true));
    77 
    78             if (progressMonitor.isCanceled())
    79                 return;
    80 
    81             if (files.isEmpty())
    82                 throw new IOException(tr("No image files found."));
    83 
    84             GeoImageLayer.create(files, gpx);
    85         } finally {
    86             progressMonitor.finishTask();
    87         }
    88     }
    89 
    90     static void addRecursiveFiles(List<File> files, Set<String> visitedDirs, List<File> sel, ProgressMonitor progressMonitor)
    91             throws IOException {
    92 
    93         if (progressMonitor.isCanceled())
    94             return;
    95 
    96         progressMonitor.beginTask(null, sel.size());
    97         try {
    98             for (File f : sel) {
    99                 if (f.isDirectory()) {
    100                     if (visitedDirs.add(f.getCanonicalPath())) { // Do not loop over symlinks
    101                         File[] dirFiles = f.listFiles(); // Can be null for some strange directories (like lost+found)
    102                         if (dirFiles != null) {
    103                             addRecursiveFiles(files, visitedDirs, Arrays.asList(dirFiles), progressMonitor.createSubTaskMonitor(1, true));
    104                         }
    105                     } else {
    106                         progressMonitor.worked(1);
    107                     }
    108                 } else {
    109                     if (FILE_FILTER.accept(f)) {
    110                         files.add(f);
    111                     }
    112                     progressMonitor.worked(1);
    113                 }
    114             }
    115         } finally {
    116             progressMonitor.finishTask();
    117         }
    118     }
    119 
    120     @Override
    121     public boolean isBatchImporter() {
    122         return true;
    123     }
    124 
    125     /**
    126      * Needs to be the last, to avoid problems.
    127      */
    128     @Override
    129     public double getPriority() {
    130         return -1000;
    131     }
    132 }
  • src/org/openstreetmap/josm/gui/io/importexport/JpgImporter.java

    Property changes on: src/org/openstreetmap/josm/gui/io/importexport/JpgImporter.java
    ___________________________________________________________________
    Deleted: svn:eol-style
    ## -1 +0,0 ##
    -native
    \ No newline at end of property
     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.io.importexport;
     3
     4/**
     5 *  File importer allowing to import geotagged images
     6 *  @deprecated use {@link ImageImporter} instead
     7 */
     8@Deprecated
     9public class JpgImporter extends ImageImporter {
     10
     11    /**
     12     * Constructs a new {@code JpgImporter}.
     13     */
     14    public JpgImporter() {
     15        super(false);
     16    }
     17
     18    /**
     19     * Constructs a new {@code JpgImporter} with folders selection, if wanted.
     20     * @param includeFolders If true, includes folders in the file filter
     21     * @since 5438
     22     */
     23    public JpgImporter(boolean includeFolders) {
     24        super(includeFolders);
     25    }
     26
     27}
  • src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java

     
    7878import org.openstreetmap.josm.gui.ExtendedDialog;
    7979import org.openstreetmap.josm.gui.MainApplication;
    8080import org.openstreetmap.josm.gui.io.importexport.GpxImporter;
    81 import org.openstreetmap.josm.gui.io.importexport.JpgImporter;
     81import org.openstreetmap.josm.gui.io.importexport.ImageImporter;
    8282import org.openstreetmap.josm.gui.io.importexport.NMEAImporter;
    8383import org.openstreetmap.josm.gui.io.importexport.RtkLibImporter;
    8484import org.openstreetmap.josm.gui.layer.GpxLayer;
     
    717717            JButton openButton = new JButton(tr("Open another photo"));
    718718            openButton.addActionListener(ae -> {
    719719                AbstractFileChooser fc = DiskAccessAction.createAndOpenFileChooser(true, false, null,
    720                         JpgImporter.FILE_FILTER_WITH_FOLDERS, JFileChooser.FILES_ONLY, "geoimage.lastdirectory");
     720                        ImageImporter.FILE_FILTER_WITH_FOLDERS, JFileChooser.FILES_ONLY, "geoimage.lastdirectory");
    721721                if (fc == null)
    722722                    return;
    723723                ImageEntry entry = new ImageEntry(fc.getSelectedFile());
  • src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java

     
    5555import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    5656import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
    5757import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
    58 import org.openstreetmap.josm.gui.io.importexport.JpgImporter;
     58import org.openstreetmap.josm.gui.io.importexport.ImageImporter;
    5959import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;
    6060import org.openstreetmap.josm.gui.layer.GpxLayer;
    6161import org.openstreetmap.josm.gui.layer.JumpToMarkerActions.JumpToMarkerLayer;
     
    312312                        loadedDirectories.add(canonical);
    313313                    }
    314314
    315                     File[] children = f.listFiles(JpgImporter.FILE_FILTER_WITH_FOLDERS);
     315                    File[] children = f.listFiles(ImageImporter.FILE_FILTER_WITH_FOLDERS);
    316316                    if (children != null) {
    317317                        progressMonitor.subTask(tr("Scanning directory {0}", f.getPath()));
    318318                        addRecursiveFiles(files, Arrays.asList(children));
  • src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java

     
    1313import java.awt.Point;
    1414import java.awt.Rectangle;
    1515import java.awt.RenderingHints;
    16 import java.awt.Toolkit;
    1716import java.awt.event.MouseEvent;
    1817import java.awt.event.MouseListener;
    1918import java.awt.event.MouseMotionListener;
     
    2423import java.awt.image.BufferedImage;
    2524import java.awt.image.ImageObserver;
    2625import java.io.File;
     26import java.io.IOException;
    2727
     28import javax.imageio.ImageIO;
    2829import javax.swing.JComponent;
    2930import javax.swing.SwingUtilities;
    3031
     
    243244        private boolean updateImageEntry(Image img) {
    244245            if (!(entry.getWidth() > 0 && entry.getHeight() > 0)) {
    245246                synchronized (entry) {
    246                     img.getWidth(this);
    247                     img.getHeight(this);
     247                    int width = img.getWidth(this);
     248                    int height = img.getHeight(this);
    248249
     250                    if (!(entry.getWidth() > 0 && entry.getHeight() > 0) && width > 0 && height > 0) {
     251                        // dimensions not in metadata but already present in image, so observer won't be called
     252                        entry.setWidth(width);
     253                        entry.setHeight(height);
     254                        entry.notifyAll();
     255                    }
     256
    249257                    long now = System.currentTimeMillis();
    250258                    while (!(entry.getWidth() > 0 && entry.getHeight() > 0)) {
    251259                        try {
     
    279287
    280288        @Override
    281289        public void run() {
    282             Image img = Toolkit.getDefaultToolkit().createImage(file.getPath());
    283             if (!updateImageEntry(img))
    284                 return;
     290            Image img;
     291            try {
     292                img = ImageIO.read(file);
    285293
    286             int width = entry.getWidth();
    287             int height = entry.getHeight();
     294                if (!updateImageEntry(img))
     295                    return;
    288296
    289             if (mayFitMemory(((long) width)*height*4*2)) {
    290                 Logging.info(tr("Loading {0}", file.getPath()));
    291                 tracker.addImage(img, 1);
     297                int width = entry.getWidth();
     298                int height = entry.getHeight();
    292299
    293                 // Wait for the end of loading
    294                 while (!tracker.checkID(1, true)) {
    295                     if (this.entry != ImageDisplay.this.entry) {
    296                         // The file has changed
     300                if (mayFitMemory(((long) width)*height*4*2)) {
     301                    Logging.info(tr("Loading {0}", file.getPath()));
     302                    tracker.addImage(img, 1);
     303
     304                    // Wait for the end of loading
     305                    while (!tracker.checkID(1, true)) {
     306                        if (this.entry != ImageDisplay.this.entry) {
     307                            // The file has changed
     308                            tracker.removeImage(img);
     309                            return;
     310                        }
     311                        try {
     312                            Thread.sleep(5);
     313                        } catch (InterruptedException e) {
     314                            Logging.trace(e);
     315                            Logging.warn("InterruptedException in {0} while loading image {1}",
     316                                    getClass().getSimpleName(), file.getPath());
     317                            Thread.currentThread().interrupt();
     318                        }
     319                    }
     320                    if (tracker.isErrorID(1)) {
     321                        Logging.warn("Abort loading of {0} since tracker errored with 1", file);
     322                        // the tracker catches OutOfMemory conditions
    297323                        tracker.removeImage(img);
    298                         return;
     324                        img = null;
     325                    } else {
     326                        tracker.removeImage(img);
    299327                    }
    300                     try {
    301                         Thread.sleep(5);
    302                     } catch (InterruptedException e) {
    303                         Logging.trace(e);
    304                         Logging.warn("InterruptedException in {0} while loading image {1}",
    305                                 getClass().getSimpleName(), file.getPath());
    306                         Thread.currentThread().interrupt();
    307                     }
    308                 }
    309                 if (tracker.isErrorID(1)) {
    310                     Logging.warn("Abort loading of {0} since tracker errored with 1", file);
    311                     // the tracker catches OutOfMemory conditions
    312                     tracker.removeImage(img);
     328                } else {
     329                    Logging.warn("Abort loading of {0} since it might not fit into memory", file);
    313330                    img = null;
    314                 } else {
    315                     tracker.removeImage(img);
    316331                }
    317             } else {
    318                 Logging.warn("Abort loading of {0} since it might not fit into memory", file);
    319                 img = null;
    320             }
    321332
    322             synchronized (ImageDisplay.this) {
    323                 if (this.entry != ImageDisplay.this.entry) {
    324                     // The file has changed
    325                     return;
    326                 }
     333                synchronized (ImageDisplay.this) {
     334                    if (this.entry != ImageDisplay.this.entry) {
     335                        // The file has changed
     336                        return;
     337                    }
    327338
    328                 if (img != null) {
    329                     boolean switchedDim = false;
    330                     if (ExifReader.orientationNeedsCorrection(entry.getExifOrientation())) {
    331                         if (ExifReader.orientationSwitchesDimensions(entry.getExifOrientation())) {
    332                             width = img.getHeight(null);
    333                             height = img.getWidth(null);
    334                             switchedDim = true;
     339                    if (img != null) {
     340                        boolean switchedDim = false;
     341                        if (ExifReader.orientationNeedsCorrection(entry.getExifOrientation())) {
     342                            if (ExifReader.orientationSwitchesDimensions(entry.getExifOrientation())) {
     343                                width = img.getHeight(null);
     344                                height = img.getWidth(null);
     345                                switchedDim = true;
     346                            }
     347                            final BufferedImage rot = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
     348                            final AffineTransform xform = ExifReader.getRestoreOrientationTransform(
     349                                    entry.getExifOrientation(),
     350                                    img.getWidth(null),
     351                                    img.getHeight(null));
     352                            final Graphics2D g = rot.createGraphics();
     353                            g.drawImage(img, xform, null);
     354                            g.dispose();
     355                            img = rot;
    335356                        }
    336                         final BufferedImage rot = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    337                         final AffineTransform xform = ExifReader.getRestoreOrientationTransform(
    338                                 entry.getExifOrientation(),
    339                                 img.getWidth(null),
    340                                 img.getHeight(null));
    341                         final Graphics2D g = rot.createGraphics();
    342                         g.drawImage(img, xform, null);
    343                         g.dispose();
    344                         img = rot;
     357
     358                        ImageDisplay.this.image = img;
     359                        visibleRect = new VisRect(0, 0, width, height);
     360
     361                        Logging.debug("Loaded {0} with dimensions {1}x{2} memoryTaken={3}m exifOrientationSwitchedDimension={4}",
     362                                file.getPath(), width, height, width*height*4/1024/1024, switchedDim);
    345363                    }
    346364
    347                     ImageDisplay.this.image = img;
    348                     visibleRect = new VisRect(0, 0, width, height);
    349 
    350                     Logging.debug("Loaded {0} with dimensions {1}x{2} memoryTaken={3}m exifOrientationSwitchedDimension={4}",
    351                             file.getPath(), width, height, width*height*4/1024/1024, switchedDim);
     365                    selectedRect = null;
     366                    errorLoading = (img == null);
    352367                }
    353 
    354                 selectedRect = null;
    355                 errorLoading = (img == null);
     368                ImageDisplay.this.repaint();
     369            } catch (IOException ex) {
     370                Logging.error(ex);
    356371            }
    357             ImageDisplay.this.repaint();
    358372        }
    359373    }
    360374
  • src/org/openstreetmap/josm/gui/layer/gpx/ImportImagesAction.java

     
    1515
    1616import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    1717import org.openstreetmap.josm.gui.MainApplication;
    18 import org.openstreetmap.josm.gui.io.importexport.JpgImporter;
     18import org.openstreetmap.josm.gui.io.importexport.ImageImporter;
    1919import org.openstreetmap.josm.gui.layer.GpxLayer;
    2020import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    2121import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
     
    6868            warnCantImportIntoServerLayer(layer);
    6969            return;
    7070        }
    71         JpgImporter importer = new JpgImporter(layer);
     71        ImageImporter importer = new ImageImporter(layer);
    7272        AbstractFileChooser fc = new FileChooserManager(true, "geoimage.lastdirectory", Config.getPref().get("lastDirectory")).
    7373                createFileChooser(true, null, importer.filter, JFileChooser.FILES_AND_DIRECTORIES).openFileChooser();
    7474        if (fc != null) {
  • src/org/openstreetmap/josm/tools/ExifReader.java

     
    177177     * @since 6209
    178178     */
    179179    public static LatLon readLatLon(GpsDirectory dirGps) throws MetadataException {
    180         if (dirGps != null) {
     180        if (dirGps != null && dirGps.getTagCount() > 1) {
    181181            double lat = readAxis(dirGps, GpsDirectory.TAG_LATITUDE, GpsDirectory.TAG_LATITUDE_REF, 'S');
    182182            double lon = readAxis(dirGps, GpsDirectory.TAG_LONGITUDE, GpsDirectory.TAG_LONGITUDE_REF, 'W');
    183183            return new LatLon(lat, lon);
  • test/unit/org/openstreetmap/josm/gui/io/importexport/ImageImporterTest.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.io.importexport;
     3
     4import static org.junit.jupiter.api.Assertions.assertEquals;
     5
     6import java.io.File;
     7import java.io.IOException;
     8import java.util.ArrayList;
     9import java.util.Arrays;
     10import java.util.HashSet;
     11import java.util.List;
     12
     13import org.junit.jupiter.api.extension.RegisterExtension;
     14import org.junit.jupiter.api.Test;
     15import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
     16import org.openstreetmap.josm.testutils.JOSMTestRules;
     17
     18import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     19
     20/**
     21 * Unit tests of {@link ImageImporter} class.
     22 */
     23class ImageImporterTest {
     24
     25    /**
     26     * Setup test
     27     */
     28    @RegisterExtension
     29    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
     30    public JOSMTestRules test = new JOSMTestRules();
     31
     32    /**
     33     * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/14868">Bug #14868</a>.
     34     * @throws IOException if an error occurs
     35     */
     36    @Test
     37    void testTicket14868() throws IOException {
     38        List<File> files = new ArrayList<>();
     39        ImageImporter.addRecursiveFiles(files, new HashSet<>(), Arrays.asList(
     40                new File("foo.jpg"), new File("foo.jpeg")
     41                ), NullProgressMonitor.INSTANCE);
     42        assertEquals(2, files.size());
     43        assertEquals("foo.jpg", files.get(0).getName());
     44        assertEquals("foo.jpeg", files.get(1).getName());
     45    }
     46}
  • test/unit/org/openstreetmap/josm/gui/io/importexport/JpgImporterTest.java

    Property changes on: test/unit/org/openstreetmap/josm/gui/io/importexport/ImageImporterTest.java
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.io.importexport;
    3 
    4 import static org.junit.jupiter.api.Assertions.assertEquals;
    5 
    6 import java.io.File;
    7 import java.io.IOException;
    8 import java.util.ArrayList;
    9 import java.util.Arrays;
    10 import java.util.HashSet;
    11 import java.util.List;
    12 
    13 import org.junit.jupiter.api.extension.RegisterExtension;
    14 import org.junit.jupiter.api.Test;
    15 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    16 import org.openstreetmap.josm.testutils.JOSMTestRules;
    17 
    18 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    19 
    20 /**
    21  * Unit tests of {@link JpgImporter} class.
    22  */
    23 class JpgImporterTest {
    24 
    25     /**
    26      * Setup test
    27      */
    28     @RegisterExtension
    29     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
    30     public JOSMTestRules test = new JOSMTestRules();
    31 
    32     /**
    33      * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/14868">Bug #14868</a>.
    34      * @throws IOException if an error occurs
    35      */
    36     @Test
    37     void testTicket14868() throws IOException {
    38         List<File> files = new ArrayList<>();
    39         JpgImporter.addRecursiveFiles(files, new HashSet<>(), Arrays.asList(
    40                 new File("foo.jpg"), new File("foo.jpeg")
    41                 ), NullProgressMonitor.INSTANCE);
    42         assertEquals(2, files.size());
    43         assertEquals("foo.jpg", files.get(0).getName());
    44         assertEquals("foo.jpeg", files.get(1).getName());
    45     }
    46 }