Ticket #8895: 8895.patch

File 8895.patch, 11.9 KB (added by Don-vip, 12 years ago)

work in progress (unit test to finish)

  • src/com/drew/metadata/exif/ExifReader.java

     
    2020 */
    2121package com.drew.metadata.exif;
    2222
     23import java.util.HashSet;
     24import java.util.Set;
     25
    2326import com.drew.lang.BufferBoundsException;
    2427import com.drew.lang.BufferReader;
    2528import com.drew.lang.Rational;
     
    2831import com.drew.metadata.Metadata;
    2932import com.drew.metadata.MetadataReader;
    3033
    31 import java.util.HashSet;
    32 import java.util.Set;
    33 
    3434/**
    3535 * Decodes Exif binary data, populating a {@link Metadata} object with tag values in {@link ExifSubIFDDirectory},
    3636 * {@link ExifThumbnailDirectory}, {@link ExifInteropDirectory}, {@link GpsDirectory} and one of the many camera makernote directories.
     
    233233                // This error suggests that we are processing at an incorrect index and will generate
    234234                // rubbish until we go out of bounds (which may be a while).  Exit now.
    235235                directory.addError("Invalid TIFF tag format code: " + formatCode);
    236                 return;
     236                continue; // JOSM patch to fix #8895#comment:28
    237237            }
    238238
    239239            // 4 bytes dictate the number of components in this tag's data
  • src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java

     
    541541        }
    542542
    543543        try {
    544             double ele=dirGps.getDouble(GpsDirectory.TAG_GPS_ALTITUDE);
     544            double ele = dirGps.getDouble(GpsDirectory.TAG_GPS_ALTITUDE);
    545545            int d = dirGps.getInt(GpsDirectory.TAG_GPS_ALTITUDE_REF);
    546546            if (d == 1) {
    547547                ele *= -1;
     
    551551        }
    552552
    553553        try {
    554             // longitude
    555 
    556             Rational[] components = dirGps.getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE);
    557             if (components != null) {
    558                 deg = components[0].doubleValue();
    559                 min = components[1].doubleValue();
    560                 sec = components[2].doubleValue();
    561 
    562                 if (Double.isNaN(deg) && Double.isNaN(min) && Double.isNaN(sec))
    563                     throw new IllegalArgumentException();
    564 
    565                 lon = (Double.isNaN(deg) ? 0 : deg + (Double.isNaN(min) ? 0 : (min / 60)) + (Double.isNaN(sec) ? 0 : (sec / 3600)));
    566 
    567                 if (dirGps.getString(GpsDirectory.TAG_GPS_LONGITUDE_REF).charAt(0) == 'W') {
    568                     lon = -lon;
    569                 }
    570             } else {
    571                 // Try to read lon/lat as double value (Nonstandard, created by some cameras -> #5220)
    572                 lon = dirGps.getDouble(GpsDirectory.TAG_GPS_LONGITUDE);
    573             }
    574 
    575             // latitude
    576 
    577             components = dirGps.getRationalArray(GpsDirectory.TAG_GPS_LATITUDE);
    578             if (components != null) {
    579                 deg = components[0].doubleValue();
    580                 min = components[1].doubleValue();
    581                 sec = components[2].doubleValue();
    582 
    583                 if (Double.isNaN(deg) && Double.isNaN(min) && Double.isNaN(sec))
    584                     throw new IllegalArgumentException();
    585 
    586                 lat = (Double.isNaN(deg) ? 0 : deg + (Double.isNaN(min) ? 0 : (min / 60)) + (Double.isNaN(sec) ? 0 : (sec / 3600)));
    587 
    588                 if (Double.isNaN(lat))
    589                     throw new IllegalArgumentException();
    590 
    591                 if (dirGps.getString(GpsDirectory.TAG_GPS_LATITUDE_REF).charAt(0) == 'S') {
    592                     lat = -lat;
    593                 }
    594             } else {
    595                 lat = dirGps.getDouble(GpsDirectory.TAG_GPS_LATITUDE);
    596             }
    597 
    598             // Store values
    599 
    600             e.setExifCoor(new LatLon(lat, lon));
     554            LatLon latlon = ExifReader.readLatLon(dirGps);
     555            e.setExifCoor(latlon);
    601556            e.setPos(e.getExifCoor());
    602557
    603558        } catch (Exception ex) { // (other exceptions, e.g. #5271)
  • src/org/openstreetmap/josm/tools/ExifReader.java

     
    66import java.text.ParseException;
    77import java.util.Date;
    88
     9import org.openstreetmap.josm.data.coor.LatLon;
     10
    911import com.drew.imaging.jpeg.JpegMetadataReader;
    1012import com.drew.imaging.jpeg.JpegProcessingException;
     13import com.drew.lang.Rational;
    1114import com.drew.metadata.Directory;
    1215import com.drew.metadata.Metadata;
    1316import com.drew.metadata.MetadataException;
    1417import com.drew.metadata.Tag;
    1518import com.drew.metadata.exif.ExifIFD0Directory;
    1619import com.drew.metadata.exif.ExifSubIFDDirectory;
     20import com.drew.metadata.exif.GpsDirectory;
    1721
    1822/**
    19  * Read out exif file information from a jpeg file
     23 * Read out EXIF information from a JPEG file
    2024 * @author Imi
     25 * @since 99
    2126 */
    2227public class ExifReader {
    2328
    24     @SuppressWarnings("unchecked") public static Date readTime(File filename) throws ParseException {
     29    /**
     30     * Returns the date/time from the given JPEG file.
     31     * @param filename The JPEG file to read
     32     * @return The date/time read in the EXIF section, or {@code null} if not found
     33     * @throws ParseException if {@link DateParser#parse} fails to parse date/time
     34     */
     35    public static Date readTime(File filename) throws ParseException {
    2536        try {
    2637            Metadata metadata = JpegMetadataReader.readMetadata(filename);
    2738            String dateStr = null;
     
    5061        return null;
    5162    }
    5263
    53     public static Integer readOrientation(File filename) throws ParseException {
     64    /**
     65     * Returns the image orientation of the given JPEG file.
     66     * @param filename The JPEG file to read
     67     * @return The image orientation as an {@code int}. Default value is 1. Possible values are listed in EXIF spec as follows:<br>
     68     * <ul>1. The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.</ul>
     69     * <ul>2. The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.</ul>
     70     * <ul>3. The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.</ul>
     71     * <ul>4. The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.</ul>
     72     * <ul>5. The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.</ul>
     73     * <ul>6. The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.</ul>
     74     * <ul>7. The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.</ul>
     75     * <ul>8. The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.</ul>
     76     * @see <a href="http://www.impulseadventure.com/photo/exif-orientation.html">http://www.impulseadventure.com/photo/exif-orientation.html</a>
     77     * @see <a href="http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto">http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto</a>
     78     */
     79    public static Integer readOrientation(File filename) {
    5480        Integer orientation = null;
    5581        try {
    5682            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
     
    6692        return orientation;
    6793    }
    6894
     95    /**
     96     * Returns the geolocation of the given JPEG file.
     97     * @param filename The JPEG file to read
     98     * @return The lat/lon read in the EXIF section, or {@code null} if not found
     99     * @since 6209
     100     */
     101    public static LatLon readLatLon(File filename) {
     102        LatLon latlon = null;
     103        try {
     104            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
     105            final GpsDirectory dirGps = metadata.getDirectory(GpsDirectory.class);
     106            return readLatLon(dirGps);
     107        } catch (JpegProcessingException e) {
     108            e.printStackTrace();
     109        } catch (IOException e) {
     110            e.printStackTrace();
     111        } catch (MetadataException e) {
     112            e.printStackTrace();
     113        }
     114        return latlon;
     115    }
     116
     117    /**
     118     * Returns the geolocation of the given EXIF GPS directory.
     119     * @param dirGps The EXIF GPS directory
     120     * @return The lat/lon read in the EXIF section, or {@code null} if {@code dirGps} is null
     121     * @throws MetadataException
     122     * @since 6209
     123     */
     124    public static LatLon readLatLon(GpsDirectory dirGps) throws MetadataException {
     125        LatLon latlon = null;
     126        if (dirGps != null) {
     127            double lat = readAxis(dirGps, GpsDirectory.TAG_GPS_LATITUDE, GpsDirectory.TAG_GPS_LATITUDE_REF, 'S');
     128            double lon = readAxis(dirGps, GpsDirectory.TAG_GPS_LONGITUDE, GpsDirectory.TAG_GPS_LONGITUDE_REF, 'W');
     129            latlon = new LatLon(lat, lon);
     130        }
     131        return latlon;
     132    }
     133
     134    private static double readAxis(GpsDirectory dirGps, int gpsTag, int gpsTagRef, char cRef) throws MetadataException  {
     135        double value;
     136        Rational[] components = dirGps.getRationalArray(gpsTag);
     137        if (components != null) {
     138            double deg = components[0].doubleValue();
     139            double min = components[1].doubleValue();
     140            double sec = components[2].doubleValue();
     141   
     142            if (Double.isNaN(deg) && Double.isNaN(min) && Double.isNaN(sec))
     143                throw new IllegalArgumentException();
     144   
     145            value = (Double.isNaN(deg) ? 0 : deg + (Double.isNaN(min) ? 0 : (min / 60)) + (Double.isNaN(sec) ? 0 : (sec / 3600)));
     146   
     147            if (dirGps.getString(gpsTagRef).charAt(0) == cRef) {
     148                value = -value;
     149            }
     150        } else {
     151            // Try to read lon/lat as double value (Nonstandard, created by some cameras -> #5220)
     152            value = dirGps.getDouble(gpsTag);
     153        }
     154        return value;
     155    }
    69156}
  • test/unit/org/openstreetmap/josm/tools/ExifReaderTest.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.tools;
     3
     4import static org.junit.Assert.assertNotNull;
     5
     6import java.io.File;
     7import java.text.ParseException;
     8import java.util.Date;
     9
     10import org.junit.Before;
     11import org.junit.Test;
     12import org.openstreetmap.josm.data.coor.LatLon;
     13
     14/**
     15 * EXIF metadata extraction test
     16 * @since 6209
     17 */
     18public class ExifReaderTest {
     19
     20    private File sampleFile;
     21   
     22    /**
     23     * Setup test
     24     * @throws Exception
     25     */
     26    @Before
     27    public void setUp() throws Exception {
     28        sampleFile = new File("data_nodist/exif-direction-example.jpg");
     29    }
     30
     31    /**
     32     * Test time extraction
     33     * @throws ParseException
     34     */
     35    @Test
     36    public void testReadTime() throws ParseException {
     37        Date date = ExifReader.readTime(sampleFile);
     38        assertNotNull(date);
     39        System.out.println(date);
     40    }
     41
     42    /**
     43     * Test orientation extraction
     44     */
     45    @Test
     46    public void testReadOrientation() {
     47        Integer orientation = ExifReader.readOrientation(sampleFile);
     48        assertNotNull(orientation);
     49        System.out.println(orientation);
     50    }
     51   
     52    /**
     53     * Test coordinates extraction
     54     */
     55    @Test
     56    public void testReadLatLon() {
     57        LatLon latlon = ExifReader.readLatLon(sampleFile);
     58        assertNotNull(latlon);
     59        System.out.println(latlon);
     60    }
     61}