package esl.cuenet.algorithms.firstk.impl; import com.hp.hpl.jena.enhanced.EnhGraph; import com.hp.hpl.jena.ontology.Individual; import com.hp.hpl.jena.ontology.OntModel; import esl.cuenet.algorithms.firstk.exceptions.CorruptDatasetException; import esl.cuenet.algorithms.firstk.Dataset; import esl.cuenet.algorithms.firstk.Preprocessing; import esl.cuenet.algorithms.firstk.structs.eventgraph.Entity; import esl.cuenet.algorithms.firstk.structs.eventgraph.Event; import esl.cuenet.algorithms.firstk.structs.eventgraph.EventGraph; import esl.cuenet.algorithms.firstk.exceptions.EventGraphException; import esl.cuenet.model.Constants; import esl.datastructures.Location; import esl.datastructures.TimeInterval; import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; public class LocalFilePreprocessor implements Preprocessing<File> { private Logger logger = Logger.getLogger(ExifExtractor.class.getName()); private ExifExtractor extractor = new ExifExtractor(); private EventGraph graph = null; private OntModel model = null; // private String username = "Setareh Rad"; // private String email = "setareh.rafatirad@gmail.com"; private String username = "Ramesh Jain"; private String email = "jain49@gmail.com"; // private String username = "Arjun Satish"; // private String email = "arjun.satish@gmail.com"; public LocalFilePreprocessor(OntModel model, String username, String email) { this.model = model; this.username = username; this.email = email; } public LocalFilePreprocessor(OntModel model) { this.model = model; } @Override public EventGraph process(Dataset<File> fileDataset) throws CorruptDatasetException { if (fileDataset == null) throw new CorruptDatasetException("Dataset = NULL"); File file = fileDataset.item(); SimpleDateFormat sdformatter = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z"); if (file == null) throw new CorruptDatasetException("Dataset content = NULL"); if (!file.exists()) throw new CorruptDatasetException("File not found: " + file.getAbsolutePath()); graph = new EventGraph(model); try { Exif exif = extractor.extractExif(file.getAbsolutePath()); logger.info("Processing: " + file.getAbsolutePath()); logger.info("Timestamp: " + exif.timestamp); logger.info("Formatted Time: " + sdformatter.format(new Date(exif.timestamp))); //change to observe ranker for any photo (crude hack to disable event context). //exif.timestamp = 0L; logger.info("GPS-Lat: " + exif.GPSLatitude); logger.info("GPS-Lon: " + exif.GPSLongitude); logger.info("Image-Width: " + exif.width); logger.info("Image-Height: " + exif.height); logger.info("User name: " + username); logger.info("Email: " + email); Event io; io = graph.createEvent(Constants.PhotoCaptureEvent); io.addLiteral(model.createProperty( model.getNsPrefixMap().get(Constants.DefaultNamespace) + Constants.ImageWidth), model.createTypedLiteral(exif.width)); io.addLiteral(model.createProperty( model.getNsPrefixMap().get(Constants.DefaultNamespace) + Constants.ImageHeight), model.createTypedLiteral(exif.height)); io.addResource(model.getProperty(Constants.CuenetNamespace + Constants.OccursDuring), TimeInterval.createFromMoment(exif.timestamp, model)); io.getIndividual().addProperty(model.getProperty(Constants.CuenetNamespace + "title"), "photo-capture-event"); Entity author = null; if (username != null || email != null) { author = graph.createPerson(); } if (username != null) author.addLiteral(model.createProperty( model.getNsPrefixMap().get(Constants.DefaultNamespace) + Constants.Name), model.createTypedLiteral(username)); if (email != null) author.addLiteral(model.createProperty( model.getNsPrefixMap().get(Constants.DefaultNamespace) + Constants.Email), model.createTypedLiteral(email)); if (exif.GPSLatitude != 0 && exif.GPSLongitude != 0) { io.addResource(model.getProperty(Constants.CuenetNamespace + Constants.OccursAt), Location.createFromGPS(exif.GPSLatitude, exif.GPSLongitude, model)); } graph.addParticipant(io, author); } catch (IOException e) { e.printStackTrace(); } catch (EventGraphException e) { e.printStackTrace(); } return graph; } @Override public void associate(Individual individual, EventGraph.NodeType type) { if (graph == null) throw new RuntimeException("individual cannot be assigned to NULL graph"); graph.addIndividual(individual, type); } public static class Exif { public Integer width = null; public Integer height = null; public Long timestamp = null; public String mimetype = null; public Double GPSLatitude = null; public Double GPSLongitude = null; public String toString() { return width + "x" + height + " ; " + timestamp + " @ (" + GPSLatitude + ", " + GPSLongitude + ")"; } } public static class ExifExtractor { private String exiftoolPath = "exiftool --help"; private String args[] = {"-d \"%s\" -datetimeoriginal", "-c \"%.6f\"", "-gpslatitude", "-gpslongitude", "-imagewidth", "-imageheight", "-mimetype"}; private String command = null; private Exif exif = null; private Logger logger = Logger.getLogger(ExifExtractor.class); private HashMap<String, Exif> cache = new HashMap<String, Exif>(); private String cacheFile = "/data/test_photos/tina/highres/exif.cache"; public ExifExtractor() { StringBuilder builder = new StringBuilder(); builder.append(exiftoolPath); builder.append(' '); for (String arg : args) { builder.append(arg); builder.append(' '); } command = builder.substring(0); File file = new File(cacheFile); if ( ! file.exists() ) return; try { for (String line: FileUtils.readLines(file)) { String[] parts = line.split(" "); Exif e = new Exif(); e.timestamp = Long.parseLong(parts[1]); e.GPSLatitude = Double.parseDouble(parts[2]); e.GPSLongitude = Double.parseDouble(parts[3]); cache.put(parts[0], e); } } catch (IOException e) { e.printStackTrace(); } } public int getWidth() { return exif.width; } public int getHeight() { return exif.height; } public Double getLatitude() { return exif.GPSLatitude; } public Double getLongitude() { return exif.GPSLongitude; } public Long getTimestamp() { return exif.timestamp; } public Exif extractExif(String exifImage) throws IOException { if (cache.containsKey(exifImage)) return cache.get(exifImage); StringBuilder exifBuilder = new StringBuilder(); exif = null; if (exifImage == null) { throw new IllegalArgumentException("exifImage is null"); } if (exifImage.contains(" ")) { throw new IllegalArgumentException("Image cannot contain a whitespace"); } Process proc = null; DataInputStream exifStream = null; try { exif = new Exif(); //logger.info(command + " " + exifImage); proc = Runtime.getRuntime().exec(command + " " + exifImage); exifStream = new DataInputStream(proc.getInputStream()); while (true) { char c = (char) exifStream.readByte(); if (c != '"') exifBuilder.append(c); if (c == '\n') { parse(exifBuilder); exifBuilder = null; exifBuilder = new StringBuilder(); } } } catch (EOFException ex) { /* datainputstream reached an EOF */ } try { if (proc != null) proc.waitFor(); if (exifStream != null) exifStream.close(); if (proc != null) proc.destroy(); } catch (InterruptedException e) { e.printStackTrace(); } return exif; } private void parse(StringBuilder input) { int ix = input.indexOf(":"); if (ix == -1) { logger.info("Returning.. " + input); return; } String sequence = input.substring(0, ix).trim(); if (sequence.compareTo("Date/Time Original") == 0) { exif.timestamp = 1000 * Long.parseLong(input.substring(ix + 1).trim()); } else if (sequence.compareTo("GPS Latitude") == 0) { exif.GPSLatitude = parseCoordinate(input.substring(ix + 1).trim()); } else if (sequence.compareTo("GPS Longitude") == 0) { exif.GPSLongitude = parseCoordinate(input.substring(ix + 1).trim()); } else if (sequence.compareTo("Image Width") == 0) { exif.width = Integer.parseInt(input.substring(ix + 1).trim()); } else if (sequence.compareTo("Image Height") == 0) { exif.height = Integer.parseInt(input.substring(ix + 1).trim()); } else if (sequence.compareTo("MIME Type") == 0) { exif.mimetype = input.substring(ix + 1).trim(); } } private Double parseCoordinate(String a) { Double decimal = 0.0; int ix = a.indexOf(' '); if (ix == -1) { decimal = Double.parseDouble(a); return decimal; } decimal = Double.parseDouble(a.substring(0, ix)); String s = a.substring(ix + 1); if (s.compareTo("W") == 0 || s.compareTo("S") == 0) decimal = -decimal; return decimal; } } }