Ticket #20341: 20341-core.diff

File 20341-core.diff, 34.1 KB (added by Bjoeni, 3 years ago)
  • build.xml

     
    10371037                <exclude name="META-INF/versions/**"/>
    10381038                <exclude name="*"/>
    10391039                <exclude name="org/openstreetmap/gui/jmapviewer/Demo*"/>
    1040                 <exclude name="com/drew/imaging/FileTypeDetector*"/>
    1041                 <exclude name="com/drew/imaging/ImageMetadataReader*"/>
    1042                 <exclude name="com/drew/imaging/avi/**"/>
    1043                 <exclude name="com/drew/imaging/bmp/**"/>
    1044                 <exclude name="com/drew/imaging/eps/**"/>
    1045                 <exclude name="com/drew/imaging/gif/**"/>
    1046                 <exclude name="com/drew/imaging/heif/**"/>
    1047                 <exclude name="com/drew/imaging/ico/**"/>
    1048                 <exclude name="com/drew/imaging/mp3/**"/>
    1049                 <exclude name="com/drew/imaging/mp4/**"/>
    1050                 <exclude name="com/drew/imaging/pcx/**"/>
    1051                 <exclude name="com/drew/imaging/png/**"/>
    1052                 <exclude name="com/drew/imaging/psd/**"/>
    1053                 <exclude name="com/drew/imaging/quicktime/**"/>
    1054                 <exclude name="com/drew/imaging/raf/**"/>
    1055                 <exclude name="com/drew/imaging/riff/**"/>
    1056                 <exclude name="com/drew/imaging/wav/**"/>
    1057                 <exclude name="com/drew/imaging/webp/**"/>
    10581040                <exclude name="com/drew/metadata/avi/**"/>
    1059                 <exclude name="com/drew/metadata/bmp/**"/>
    10601041                <exclude name="com/drew/metadata/eps/**"/>
    1061                 <exclude name="com/drew/metadata/gif/**"/>
    1062                 <exclude name="com/drew/metadata/heif/**"/>
    1063                 <exclude name="com/drew/metadata/ico/**"/>
    10641042                <exclude name="com/drew/metadata/mov/**"/>
    10651043                <exclude name="com/drew/metadata/mp3/**"/>
    10661044                <exclude name="com/drew/metadata/mp4/**"/>
    1067                 <exclude name="com/drew/metadata/pcx/**"/>
    1068                 <exclude name="com/drew/metadata/png/**"/>
    10691045                <exclude name="com/drew/metadata/wav/**"/>
    1070                 <exclude name="com/drew/metadata/webp/**"/>
    10711046                <exclude name="com/drew/tools/**"/>
    10721047                <exclude name="org/apache/commons/compress/PasswordRequiredException*"/>
    10731048                <exclude name="org/apache/commons/compress/archivers/**"/>
  • 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

     
    1414import org.openstreetmap.josm.tools.JosmRuntimeException;
    1515import org.openstreetmap.josm.tools.Logging;
    1616
    17 import com.drew.imaging.jpeg.JpegMetadataReader;
     17import com.drew.imaging.ImageMetadataReader;
    1818import com.drew.lang.CompoundException;
    1919import com.drew.metadata.Directory;
    2020import com.drew.metadata.Metadata;
     
    574574        }
    575575
    576576        try {
    577             metadata = JpegMetadataReader.readMetadata(file);
     577            metadata = ImageMetadataReader.readMetadata(file);
    578578        } catch (CompoundException | IOException ex) {
    579579            Logging.error(ex);
    580580            setExifTime(null);
     
    614614            Logging.debug(ex);
    615615        }
    616616
    617         if (dirGps == null) {
     617        if (dirGps == null || dirGps.getTagCount() <= 1) {
    618618            setExifCoor(null);
    619619            setPos(null);
    620620            return;
  • 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;
     13import java.util.stream.Collectors;
     14import java.util.stream.Stream;
     15
     16import javax.imageio.ImageIO;
     17
     18import org.openstreetmap.josm.actions.ExtensionFileFilter;
     19import org.openstreetmap.josm.gui.layer.GpxLayer;
     20import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
     21import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     22import org.openstreetmap.josm.io.IllegalDataException;
     23
     24import com.drew.imaging.FileType;
     25
     26/**
     27 * File importer allowing to import geotagged images
     28 * @since xxx
     29 */
     30public class ImageImporter extends FileImporter {
     31    private GpxLayer gpx;
     32
     33    /**
     34     * The supported image file types on the current system
     35     * @since xxx
     36     */
     37    public static final List<String> SUPPORTED_FILE_TYPES = getFileTypes();
     38
     39    /**
     40     * The default file filter
     41     */
     42    public static final ExtensionFileFilter FILE_FILTER = getFileFilters(false);
     43
     44    /**
     45     * An alternate file filter that also includes folders.
     46     * @since 5438
     47     */
     48    public static final ExtensionFileFilter FILE_FILTER_WITH_FOLDERS = getFileFilters(true);
     49
     50    private static List<String> getFileTypes() {
     51        List<String> exifSupportedTypes = Arrays
     52                .stream(FileType.values())
     53                .flatMap(f -> f == null || f.getAllExtensions() == null
     54                    ? Stream.empty()
     55                    : Stream.of(f.getAllExtensions()))
     56                .collect(Collectors.toList());
     57        Stream<String> javaSupportedTypes = Arrays
     58                .stream(ImageIO.getReaderFileSuffixes());
     59        List<String> commonSupportedTypes = javaSupportedTypes
     60                .filter(ext -> exifSupportedTypes.contains(ext))
     61                .sorted()
     62                .collect(Collectors.toList());
     63
     64        return commonSupportedTypes;
     65    }
     66
     67    private static ExtensionFileFilter getFileFilters(boolean folder) {
     68        String typeStr = String.join(",", SUPPORTED_FILE_TYPES);
     69        String humanStr = tr("Image Files") + " (*." + String.join(", *.", SUPPORTED_FILE_TYPES);
     70        if (folder) {
     71            humanStr += ", " + tr("folder");
     72        }
     73        humanStr += ")";
     74
     75        return new ExtensionFileFilter(typeStr, "jpg", humanStr);
     76    }
     77
     78    /**
     79     * Constructs a new {@code ImageImporter}.
     80     */
     81    public ImageImporter() {
     82        this(false);
     83    }
     84
     85    /**
     86     * Constructs a new {@code ImageImporter} with folders selection, if wanted.
     87     * @param includeFolders If true, includes folders in the file filter
     88     * @since 5438
     89     */
     90    public ImageImporter(boolean includeFolders) {
     91        super(includeFolders ? FILE_FILTER_WITH_FOLDERS : FILE_FILTER);
     92    }
     93
     94    /**
     95     * Constructs a new {@code ImageImporter} for the given GPX layer. Folders selection is allowed.
     96     * @param gpx The GPX layer
     97     */
     98    public ImageImporter(GpxLayer gpx) {
     99        this(true);
     100        this.gpx = gpx;
     101    }
     102
     103    @Override
     104    public boolean acceptFile(File pathname) {
     105        return super.acceptFile(pathname) || pathname.isDirectory();
     106    }
     107
     108    @Override
     109    public void importData(List<File> sel, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
     110        progressMonitor.beginTask(tr("Looking for image files"), 1);
     111        try {
     112            List<File> files = new ArrayList<>();
     113            Set<String> visitedDirs = new HashSet<>();
     114            addRecursiveFiles(files, visitedDirs, sel, progressMonitor.createSubTaskMonitor(1, true));
     115
     116            if (progressMonitor.isCanceled())
     117                return;
     118
     119            if (files.isEmpty())
     120                throw new IOException(tr("No image files found."));
     121
     122            GeoImageLayer.create(files, gpx);
     123        } finally {
     124            progressMonitor.finishTask();
     125        }
     126    }
     127
     128    static void addRecursiveFiles(List<File> files, Set<String> visitedDirs, List<File> sel, ProgressMonitor progressMonitor)
     129            throws IOException {
     130
     131        if (progressMonitor.isCanceled())
     132            return;
     133
     134        progressMonitor.beginTask(null, sel.size());
     135        try {
     136            for (File f : sel) {
     137                if (f.isDirectory()) {
     138                    if (visitedDirs.add(f.getCanonicalPath())) { // Do not loop over symlinks
     139                        File[] dirFiles = f.listFiles(); // Can be null for some strange directories (like lost+found)
     140                        if (dirFiles != null) {
     141                            addRecursiveFiles(files, visitedDirs, Arrays.asList(dirFiles), progressMonitor.createSubTaskMonitor(1, true));
     142                        }
     143                    } else {
     144                        progressMonitor.worked(1);
     145                    }
     146                } else {
     147                    if (FILE_FILTER.accept(f)) {
     148                        files.add(f);
     149                    }
     150                    progressMonitor.worked(1);
     151                }
     152            }
     153        } finally {
     154            progressMonitor.finishTask();
     155        }
     156    }
     157
     158    @Override
     159    public boolean isBatchImporter() {
     160        return true;
     161    }
     162
     163    /**
     164     * Needs to be the last, to avoid problems.
     165     */
     166    @Override
     167    public double getPriority() {
     168        return -1000;
     169    }
     170}
  • 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 }