Ticket #8895: 8895.patch
| File 8895.patch, 11.9 KB (added by , 12 years ago) |
|---|
-
src/com/drew/metadata/exif/ExifReader.java
20 20 */ 21 21 package com.drew.metadata.exif; 22 22 23 import java.util.HashSet; 24 import java.util.Set; 25 23 26 import com.drew.lang.BufferBoundsException; 24 27 import com.drew.lang.BufferReader; 25 28 import com.drew.lang.Rational; … … 28 31 import com.drew.metadata.Metadata; 29 32 import com.drew.metadata.MetadataReader; 30 33 31 import java.util.HashSet;32 import java.util.Set;33 34 34 /** 35 35 * Decodes Exif binary data, populating a {@link Metadata} object with tag values in {@link ExifSubIFDDirectory}, 36 36 * {@link ExifThumbnailDirectory}, {@link ExifInteropDirectory}, {@link GpsDirectory} and one of the many camera makernote directories. … … 233 233 // This error suggests that we are processing at an incorrect index and will generate 234 234 // rubbish until we go out of bounds (which may be a while). Exit now. 235 235 directory.addError("Invalid TIFF tag format code: " + formatCode); 236 return;236 continue; // JOSM patch to fix #8895#comment:28 237 237 } 238 238 239 239 // 4 bytes dictate the number of components in this tag's data -
src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
541 541 } 542 542 543 543 try { 544 double ele =dirGps.getDouble(GpsDirectory.TAG_GPS_ALTITUDE);544 double ele = dirGps.getDouble(GpsDirectory.TAG_GPS_ALTITUDE); 545 545 int d = dirGps.getInt(GpsDirectory.TAG_GPS_ALTITUDE_REF); 546 546 if (d == 1) { 547 547 ele *= -1; … … 551 551 } 552 552 553 553 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); 601 556 e.setPos(e.getExifCoor()); 602 557 603 558 } catch (Exception ex) { // (other exceptions, e.g. #5271) -
src/org/openstreetmap/josm/tools/ExifReader.java
6 6 import java.text.ParseException; 7 7 import java.util.Date; 8 8 9 import org.openstreetmap.josm.data.coor.LatLon; 10 9 11 import com.drew.imaging.jpeg.JpegMetadataReader; 10 12 import com.drew.imaging.jpeg.JpegProcessingException; 13 import com.drew.lang.Rational; 11 14 import com.drew.metadata.Directory; 12 15 import com.drew.metadata.Metadata; 13 16 import com.drew.metadata.MetadataException; 14 17 import com.drew.metadata.Tag; 15 18 import com.drew.metadata.exif.ExifIFD0Directory; 16 19 import com.drew.metadata.exif.ExifSubIFDDirectory; 20 import com.drew.metadata.exif.GpsDirectory; 17 21 18 22 /** 19 * Read out exif file information from a jpegfile23 * Read out EXIF information from a JPEG file 20 24 * @author Imi 25 * @since 99 21 26 */ 22 27 public class ExifReader { 23 28 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 { 25 36 try { 26 37 Metadata metadata = JpegMetadataReader.readMetadata(filename); 27 38 String dateStr = null; … … 50 61 return null; 51 62 } 52 63 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) { 54 80 Integer orientation = null; 55 81 try { 56 82 final Metadata metadata = JpegMetadataReader.readMetadata(filename); … … 66 92 return orientation; 67 93 } 68 94 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 } 69 156 } -
test/unit/org/openstreetmap/josm/tools/ExifReaderTest.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.tools; 3 4 import static org.junit.Assert.assertNotNull; 5 6 import java.io.File; 7 import java.text.ParseException; 8 import java.util.Date; 9 10 import org.junit.Before; 11 import org.junit.Test; 12 import org.openstreetmap.josm.data.coor.LatLon; 13 14 /** 15 * EXIF metadata extraction test 16 * @since 6209 17 */ 18 public 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 }
