import java.io.*; import java.text.*; import java.util.*; import com.drew.imaging.jpeg.*; import com.drew.metadata.*; import com.drew.metadata.exif.*; public class InsertRecord { public static void main(String[] args) { new InsertRecord().realMain(args); } private boolean verbose; final static String DATE_TIME = "Date/Time"; final static String PERL_PROGRAM = "use Image::ExifTool qw(:Public);" + "my ($image,$lat,$lat_ref,$lng,$lng_ref,$outfile) = @ARGV;" + "my $exifTool = new Image::ExifTool;" + "$info = $exifTool->ImageInfo($image);" + "$exifTool->SetNewValue('GPSLatitude',$lat);" + "$exifTool->SetNewValue('GPSLongitude',$lng);" + "$exifTool->SetNewValue('GPSLatitudeRef',$lat_ref);" + "$exifTool->SetNewValue('GPSLongitudeRef',$lng_ref);" + "$exifTool->WriteInfo($image,$outfile);" ; static class Point { final double lat; final double lng; Point(double lat, double lng) { this.lat = lat; this.lng = lng; } public String toString() { return "<" + lat + "," + lng + ">"; } } static class Coord { final int degrees; final int minutes; final float seconds; final boolean isNeg; Coord(int degrees, int minutes, float seconds) { this.degrees = Math.abs(degrees); this.minutes = minutes; this.seconds = seconds; this.isNeg = degrees<0; } public String getLatitudeRef() { return isNeg ? "S" : "N"; } public String getLatitudeRefFull() { return isNeg ? "South" : "North"; } public String getLongitudeRef() { return isNeg ? "W" : "E"; } public String getLongitudeRefFull() { return isNeg ? "West" : "East"; } public String toString() { return degrees + "\"" + minutes + "'" + seconds; } public String toPerlString() { // 40 deg 44' 39.00" N return degrees + " deg " + minutes + "' " + seconds + "\""; } } public void realMain(String[] args) { List imageFiles = new ArrayList(); Map imageFiles2metadata = new HashMap(); Map dates2points = new HashMap(); String outDirName = "out"; for (int i=0; i e : imageFiles2metadata.entrySet()) { String file = e.getKey(); Metadata meta = e.getValue(); Point p = getClosestPoint(dates2points,meta); Coord lat = getLatitudeCoord(p); Coord lng = getLongitudeCoord(p); note(p + " -> " + lat.toPerlString() + lat.getLatitudeRefFull() + "," + lng.toPerlString() + lng.getLongitudeRefFull()); File outDir = new File(outDirName); outDir.mkdirs(); File outFile = new File(outDir,file); String[] cmd = { "perl", "-e", PERL_PROGRAM, file, lat.toPerlString(), lat.getLatitudeRefFull(), lng.toPerlString(), lng.getLongitudeRefFull(), outFile.getAbsolutePath(), }; try { Runtime.getRuntime().exec(cmd); } catch (IOException ioe) { handle(ioe); } } } private Coord getLatitudeCoord(Point p) { return getCoord(p.lat); } private Coord getLongitudeCoord(Point p) { return getCoord(p.lng); } private Coord getCoord(double val) { String s = String.valueOf(val); int idot; String rest; int degrees = 0; int minutes = 0; float seconds = 0; idot = s.indexOf("."); if (idot == -1) { degrees = Integer.parseInt(s); } else { degrees = Integer.parseInt(s.substring(0,idot)); rest = String.valueOf(Double.parseDouble(s.substring(idot)) * 60); idot = rest.indexOf("."); if (idot == -1) { minutes = Integer.parseInt(rest); } else { minutes = Integer.parseInt(rest.substring(0,idot)); seconds = Float.parseFloat(rest.substring(idot)) * 60; } } return new Coord(degrees,minutes,seconds); } private void handle(Exception e) { e.printStackTrace(); } private void dump(Metadata metadata) { Iterator directories = metadata.getDirectoryIterator(); while (directories.hasNext()) { Directory directory = (Directory)directories.next(); Iterator tags = directory.getTagIterator(); while (tags.hasNext()) { Tag tag = (Tag)tags.next(); try { System.out.println(tag.getTagName() + ":" + tag.getDescription()); } catch (Exception e) {e.printStackTrace();} } } } private Point getClosestPoint(Map dates2points, Metadata metadata) { // // Find the date string // String dateString = null; Iterator directories = metadata.getDirectoryIterator(); while (directories.hasNext()) { Directory directory = (Directory)directories.next(); Iterator tags = directory.getTagIterator(); while (tags.hasNext()) { Tag tag = (Tag)tags.next(); try { if (tag.getTagName().equals(DATE_TIME)) { dateString = tag.getDescription(); break; } } catch (Exception e) {handle(e);} } } Date d = convertToDate(dateString); Point p = null; long minDiff = Integer.MAX_VALUE; for (Map.Entry e : dates2points.entrySet()) { Date d2 = e.getKey(); long diff = Math.abs(d2.getTime()-d.getTime()); if (p == null || diff dates2points) throws IOException { BufferedReader in = new BufferedReader(new FileReader(fileName)); String line; while ((line = in.readLine()) != null) { if (line.startsWith("#")) continue; String[] parts = line.split(","); if (parts.length<3) continue; try { // // 1256213027352,40.75,-73.997 // Date d = new Date(Long.parseLong(parts[0])); double lat = Double.parseDouble(parts[1]); double lng = Double.parseDouble(parts[2]); dates2points.put(d,new Point(lat,lng)); } catch (NumberFormatException e) { e.printStackTrace(); } } in.close(); } /** * Returns image meta data or null if it's not an image. */ private Metadata getMetadata(String file) { if (!file.endsWith(".jpg")) return null; try { File jpegFile = new File(file); Metadata metadata = JpegMetadataReader.readMetadata(jpegFile); new ExifReader(jpegFile).extract(metadata); return metadata; } catch (Exception _) {} return null; } private void note(Object msg) { if (!verbose) return; System.err.println("[" + new Date() + "] " + msg); } }