Ignore:
Timestamp:
2017-03-19T01:16:39+01:00 (7 years ago)
Author:
Don-vip
Message:

fix #14536 - Improved ExifReader.readTime(), Refactored ImageEntry.extractExif() (patch by holgermappt)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/tools/ExifReader.java

    r11514 r11745  
    99
    1010import org.openstreetmap.josm.Main;
     11import org.openstreetmap.josm.data.SystemOfMeasurement;
    1112import org.openstreetmap.josm.data.coor.LatLon;
    1213import org.openstreetmap.josm.tools.date.DateUtils;
     
    4243    public static Date readTime(File filename) {
    4344        try {
    44             Metadata metadata = JpegMetadataReader.readMetadata(filename);
    45             String dateStr = null;
     45            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
     46            return readTime(metadata);
     47        } catch (JpegProcessingException | IOException e) {
     48            Main.error(e);
     49        }
     50        return null;
     51    }
     52
     53    /**
     54     * Returns the date/time from the given JPEG file.
     55     * @param metadata The EXIF metadata
     56     * @return The date/time read in the EXIF section, or {@code null} if not found
     57     * @since 11745
     58     */
     59    public static Date readTime(Metadata metadata) {
     60        try {
     61            String dateTimeOrig = null;
    4662            String dateTime = null;
    47             String subSeconds = null;
     63            String dateTimeDig = null;
     64            String subSecOrig = null;
     65            String subSec = null;
     66            String subSecDig = null;
     67            // The date fields are preferred in this order: DATETIME_ORIGINAL
     68            // (0x9003), DATETIME (0x0132), DATETIME_DIGITIZED (0x9004).  Some
     69            // cameras store the fields in the wrong directory, so all
     70            // directories are searched.  Assume that the order of the fields
     71            // in the directories is random.
    4872            for (Directory dirIt : metadata.getDirectories()) {
    4973                if (!(dirIt instanceof ExifDirectoryBase)) {
     
    5377                    if (tag.getTagType() == ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL /* 0x9003 */ &&
    5478                            !tag.getDescription().matches("\\[[0-9]+ .+\\]")) {
    55                         // prefer DATETIME_ORIGINAL
    56                         dateStr = tag.getDescription();
     79                        dateTimeOrig = tag.getDescription();
     80                    } else if (tag.getTagType() == ExifIFD0Directory.TAG_DATETIME /* 0x0132 */) {
     81                        dateTime = tag.getDescription();
     82                    } else if (tag.getTagType() == ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED /* 0x9004 */) {
     83                        dateTimeDig = tag.getDescription();
     84                    } else if (tag.getTagType() == ExifSubIFDDirectory.TAG_SUBSECOND_TIME_ORIGINAL /* 0x9291 */) {
     85                        subSecOrig = tag.getDescription();
     86                    } else if (tag.getTagType() == ExifSubIFDDirectory.TAG_SUBSECOND_TIME /* 0x9290 */) {
     87                        subSec = tag.getDescription();
     88                    } else if (tag.getTagType() == ExifSubIFDDirectory.TAG_SUBSECOND_TIME_DIGITIZED /* 0x9292 */) {
     89                        subSecDig = tag.getDescription();
    5790                    }
    58                     if (tag.getTagType() == ExifIFD0Directory.TAG_DATETIME /* 0x0132 */) {
    59                         // prefer DATETIME over DATETIME_DIGITIZED
    60                         dateTime = tag.getDescription();
    61                     }
    62                     if (tag.getTagType() == ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED /* 0x9004 */ && dateTime == null) {
    63                         dateTime = tag.getDescription();
    64                     }
    65                     if (tag.getTagType() == ExifIFD0Directory.TAG_SUBSECOND_TIME_ORIGINAL) {
    66                         subSeconds = tag.getDescription();
    67                     }
    68                 }
    69             }
    70             if (dateStr == null) {
     91                }
     92            }
     93            String dateStr = null;
     94            String subSeconds = null;
     95            if (dateTimeOrig != null) {
     96                // prefer TAG_DATETIME_ORIGINAL
     97                dateStr = dateTimeOrig;
     98                subSeconds = subSecOrig;
     99            } else if (dateTime != null) {
     100                // TAG_DATETIME is second choice, see #14209
    71101                dateStr = dateTime;
     102                subSeconds = subSec;
     103            } else if (dateTimeDig != null) {
     104                dateStr = dateTimeDig;
     105                subSeconds = subSecDig;
    72106            }
    73107            if (dateStr != null) {
     
    84118                return date;
    85119            }
    86         } catch (UncheckedParseException | JpegProcessingException | IOException e) {
     120        } catch (UncheckedParseException e) {
    87121            Main.error(e);
    88122        }
     
    154188     * @param filename The JPEG file to read
    155189     * @return The direction of the image when it was captures (in degrees between 0.0 and 359.99),
    156      * or {@code null} if missing or if {@code dirGps} is null
     190     * or {@code null} if not found
    157191     * @since 6209
    158192     */
     
    171205     * Returns the direction of the given EXIF GPS directory.
    172206     * @param dirGps The EXIF GPS directory
    173      * @return The direction of the image when it was captures (in degrees between 0.0 and 359.99),
     207     * @return The direction of the image when it was captured (in degrees between 0.0 and 359.99),
    174208     * or {@code null} if missing or if {@code dirGps} is null
    175209     * @since 6209
     
    206240        }
    207241        return value;
     242    }
     243
     244    /**
     245     * Returns the speed of the given JPEG file.
     246     * @param filename The JPEG file to read
     247     * @return The speed of the camera when the image was captured (in km/h),
     248     *         or {@code null} if not found
     249     * @since 11745
     250     */
     251    public static Double readSpeed(File filename) {
     252        try {
     253            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
     254            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
     255            return readSpeed(dirGps);
     256        } catch (JpegProcessingException | IOException e) {
     257            Main.error(e);
     258        }
     259        return null;
     260    }
     261
     262    /**
     263     * Returns the speed of the given EXIF GPS directory.
     264     * @param dirGps The EXIF GPS directory
     265     * @return The speed of the camera when the image was captured (in km/h),
     266     *         or {@code null} if missing or if {@code dirGps} is null
     267     * @since 11745
     268     */
     269    public static Double readSpeed(GpsDirectory dirGps) {
     270        if (dirGps != null) {
     271            Double speed = dirGps.getDoubleObject(GpsDirectory.TAG_SPEED);
     272            if (speed != null) {
     273                final String speedRef = dirGps.getString(GpsDirectory.TAG_SPEED_REF);
     274                if ("M".equalsIgnoreCase(speedRef)) {
     275                    // miles per hour
     276                    speed *= SystemOfMeasurement.IMPERIAL.bValue / 1000;
     277                } else if ("N".equalsIgnoreCase(speedRef)) {
     278                    // knots == nautical miles per hour
     279                    speed *= SystemOfMeasurement.NAUTICAL_MILE.bValue / 1000;
     280                }
     281                // default is K (km/h)
     282                return speed;
     283            }
     284        }
     285        return null;
     286    }
     287
     288    /**
     289     * Returns the elevation of the given JPEG file.
     290     * @param filename The JPEG file to read
     291     * @return The elevation of the camera when the image was captured (in m),
     292     *         or {@code null} if not found
     293     * @since 11745
     294     */
     295    public static Double readElevation(File filename) {
     296        try {
     297            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
     298            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
     299            return readElevation(dirGps);
     300        } catch (JpegProcessingException | IOException e) {
     301            Main.error(e);
     302        }
     303        return null;
     304    }
     305
     306    /**
     307     * Returns the elevation of the given EXIF GPS directory.
     308     * @param dirGps The EXIF GPS directory
     309     * @return The elevation of the camera when the image was captured (in m),
     310     *         or {@code null} if missing or if {@code dirGps} is null
     311     * @since 11745
     312     */
     313    public static Double readElevation(GpsDirectory dirGps) {
     314        if (dirGps != null) {
     315            Double ele = dirGps.getDoubleObject(GpsDirectory.TAG_ALTITUDE);
     316            if (ele != null) {
     317                final Integer d = dirGps.getInteger(GpsDirectory.TAG_ALTITUDE_REF);
     318                if (d != null && d.intValue() == 1) {
     319                    ele *= -1;
     320                }
     321                return ele;
     322            }
     323        }
     324        return null;
    208325    }
    209326
Note: See TracChangeset for help on using the changeset viewer.