package com.blazingfrog.backend;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import org.apache.commons.io.FileUtils;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.ImageWriteException;
import org.apache.sanselan.Sanselan;
import org.apache.sanselan.common.IImageMetadata;
import org.apache.sanselan.formats.jpeg.JpegImageMetadata;
import org.apache.sanselan.formats.jpeg.exifRewrite.ExifRewriter;
import org.apache.sanselan.formats.tiff.TiffField;
import org.apache.sanselan.formats.tiff.TiffImageMetadata;
import org.apache.sanselan.formats.tiff.constants.TiffConstants;
import org.apache.sanselan.formats.tiff.write.TiffOutputSet;
import com.blazingfrog.exceptions.NoLatitudeInfoFoundException;
import com.blazingfrog.exceptions.ProfileNotAuthorizedException;
import com.blazingfrog.gui.PrefPaneCaller;
import com.blazingfrog.imported.RotatedJLabel;
import com.blazingfrog.misc.ConsoleFile;
import com.blazingfrog.misc.DefaultOptions;
import com.blazingfrog.misc.Folder;
import com.blazingfrog.misc.ImageFile;
import com.blazingfrog.misc.Resources;
public class MainProcess implements Runnable{
private ArrayList<File> fileList;
private RotatedJLabel imgLabel;
private int nbPicsProcessed;
private String picName;
private boolean stopProcess;
private String locality;
private JLabel consoleLabel;
private boolean success = false;
private String token, tokenSecret;
private int nbUpdtPics;
public String getLocality() {
return locality;
}
public void setStopProcess(boolean stopProcess) {
this.stopProcess = stopProcess;
}
public String getPicName() {
return picName;
}
public MainProcess(ArrayList<File> fileList, RotatedJLabel imgLabel, JLabel consoleLabel, String token, String tokenSecret) {
this.fileList = fileList;
this.imgLabel = imgLabel;
this.consoleLabel = consoleLabel;
this.token = token;
this.tokenSecret = tokenSecret;
}
public void run(){
File file1 = fileList.get(0);
ConsoleFile.writeStart();
if(file1.isDirectory()) {
try {
this.exploreFileList(new Folder().getListOfFiles(file1));
} catch (IOException e) {
e.printStackTrace();
} catch (ImageWriteException e) {
e.printStackTrace();
}
}
else{
try {
this.exploreFileList(fileList);
} catch (IOException e) {
e.printStackTrace();
} catch (ImageWriteException e) {
e.printStackTrace();
}
}
imgLabel.setIcon(Resources.getIPhotoCrosshair());
imgLabel.setRotation(0);
nbPicsProcessed = 0;
}
public void exploreFileList(ArrayList<File> fileList) throws IOException, ImageWriteException {
try {
for (File picFile:fileList) {
if (picFile.isFile()){
picName = picFile.getName();
this.processGPSInfo(picFile);
if (!success){
nbPicsProcessed++;
Thread.sleep(750);
}
if (stopProcess)
break;
}
}
}
catch (ImageReadException e) {
e.printStackTrace();
}
catch (InterruptedException e) {
e.printStackTrace();
}
ConsoleFile.writeFinish(nbUpdtPics);
}
@SuppressWarnings("unused")
private void processGPSInfo(File file) throws ImageReadException, IOException, ImageWriteException{
File dst = null;
IImageMetadata metadata = null;
JpegImageMetadata jpegMetadata = null;
TiffImageMetadata exif = null;
OutputStream os = null;
TiffOutputSet outputSet = new TiffOutputSet();
long picTimestamp = 0;
BufferedImage pic = null;
success = false;
// establish metadata
try {
metadata = Sanselan.getMetadata(file);
} catch (ImageReadException e) {
ConsoleFile.write("ERROR", file.getPath() + ": File is not an image (or format is not supported). SKIPPED.");
consoleLabel.setText(file.getName() + ": File is not an image. Skipped.");
consoleLabel.setForeground(Color.RED);
imgLabel.setRotation(0);
imgLabel.setIcon(Resources.getLpNotFoundLogo());
return;
} catch (IOException e) {
e.printStackTrace();
}
// establish jpegMedatadata
if (metadata == null) {
ConsoleFile.write("ERROR", file.getPath() + ": Metadata not found. SKIPPED.");
consoleLabel.setText(file.getName() + ": Metadata not found. Picture cannot be processed. Skipped.");
consoleLabel.setForeground(Color.RED);
imgLabel.setRotation(0);
imgLabel.setIcon(Resources.getLpNotFoundLogo());
return;
}
else
{
jpegMetadata = (JpegImageMetadata) metadata;
}
int rot = 0;
// establish exif
if (jpegMetadata == null) {
ConsoleFile.write("ERROR",file.getPath() + ": JPEG METADATA not found. SKIPPED.");
consoleLabel.setText(file.getName() + ": JPEG Metadata not found. Picture cannot be processed. Skipped.");
consoleLabel.setForeground(Color.RED);
imgLabel.setRotation(0);
imgLabel.setIcon(Resources.getLpNotFoundLogo());
return;
}
else
{
exif = jpegMetadata.getExif();
// get thumbnail
pic = new ImageFile(exif).getEXIFThumbnail();
// handle thumbnail rotation
if (pic != null && jpegMetadata.findEXIFValue(TiffConstants.EXIF_TAG_ORIENTATION) != null){
switch(jpegMetadata.findEXIFValue(TiffConstants.EXIF_TAG_ORIENTATION ).getIntValue()){
case 3: rot = 180;break;
case 4: rot = 180;break;
case 5: rot = 90;break;
case 6: rot = 90;break;
case 7: rot = 270;break;
case 8: rot = 270;break;
}
}
}
// establish outputSet
if (exif == null) {
ConsoleFile.write("ERROR", file.getPath() + " : EXIF not found. SKIPPED.");
consoleLabel.setText(file.getName() + ": Picture cannot be processed.");
consoleLabel.setForeground(Color.RED);
imgLabel.setRotation(0);
imgLabel.setIcon(Resources.getLpNotFoundLogo());
return;
}
else
{
try {
outputSet = exif.getOutputSet();
/*
System.out.println("tostring: " + outputSet);
System.out.println("long ref: " + jpegMetadata.findEXIFValue(TiffConstants.GPS_TAG_GPS_LONGITUDE_REF).getStringValue());
System.out.println("long: " + jpegMetadata.findEXIFValue(TiffConstants.GPS_TAG_GPS_LONGITUDE).toString());
System.out.println("lat ref: " + jpegMetadata.findEXIFValue(TiffConstants.GPS_TAG_GPS_LATITUDE_REF).getStringValue());
System.out.println("lat: " + jpegMetadata.findEXIFValue(TiffConstants.GPS_TAG_GPS_LATITUDE).toString());
*/
} catch (ImageWriteException e) {
e.printStackTrace();
}
}
if (outputSet == null) {
ConsoleFile.write("ERROR", file.getPath() + " : OUTPUT SET not found. SKIPPED.");
consoleLabel.setText(file.getName() + ": Picture cannot be processed.");
if (pic == null){
consoleLabel.setForeground(Color.RED);
imgLabel.setRotation(0);
imgLabel.setIcon(Resources.getLpNotFoundLogo());
}
return;
}
else
{
if (outputSet.getGPSDirectory() != null && !DefaultOptions.doOverrideGPS()) {
ConsoleFile.write("WARNING", file.getPath() + " : GPS info already present. SKIPPED.");
consoleLabel.setText(file.getName() + ": GPS info already present. Picture was skipped.");
consoleLabel.setForeground(Color.DARK_GRAY);
if (pic != null){
imgLabel.setRotation(rot);
imgLabel.setIcon(new ImageIcon(pic));
}
else{
imgLabel.setIcon(Resources.getLpNotFoundLogo());
imgLabel.setRotation(0);
}
return;
}
TiffField tiffField = jpegMetadata.findEXIFValue(TiffConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
if (tiffField == null){
ConsoleFile.write("ERROR", file.getPath() + " : No Original Date tag was found, please populate and try again. SKIPPED.");
imgLabel.setRotation(0);
imgLabel.setIcon(Resources.getLpNotFoundLogo());
consoleLabel.setForeground(Color.RED);
consoleLabel.setText(file.getName() + ": No Original Date found. Fix and try again. SKIPPED.");
return;
}
Date date = null;
try {
date = new SimpleDateFormat ("yyyy:MM:dd HH:mm:ss").parse(tiffField.getStringValue());
Calendar cal = new GregorianCalendar();
cal.setTime(date);
picTimestamp = cal.getTimeInMillis();
} catch (ParseException e) {
ConsoleFile.write("ERROR", " : ERROR while parsing EXIF_TAG_DATE_TIME_ORIGINAL " + file.getPath() + ". SKIPPED.");
imgLabel.setRotation(0);
imgLabel.setIcon(Resources.getLpNotFoundLogo());
consoleLabel.setForeground(Color.RED);
consoleLabel.setText(file.getName() + ": Picture cannot be processed.");
return;
}
Latitude latitude = null;
try {
latitude = new Latitude(picTimestamp, token, tokenSecret);
} catch (NoLatitudeInfoFoundException e) {
consoleLabel.setForeground(Color.DARK_GRAY);
ConsoleFile.write("WARNING", file.getPath() + " : No Latitude history found for timestamp: " + date + ". SKIPPED");
consoleLabel.setText(file.getName() + ": No Latitude history found for timestamp: " + date);
if (pic != null){
imgLabel.setRotation(rot);
imgLabel.setIcon(new ImageIcon(pic));
}
else{
imgLabel.setIcon(Resources.getLpNotFoundLogo());
imgLabel.setRotation(0);
}
return;
}
catch (ProfileNotAuthorizedException e) {
Object[] options = {"Go To Preferences", "Cancel"};
int rc = JOptionPane.showOptionDialog(new JFrame(),
"<html><font face=\"Lucida Grande\" size=\"3\"><b>The Google ID linked to profile <b>\"" + DefaultOptions.getDefaultProfileName() +
"\"</b> doesn't seem to have granted LatiPics access to your Latitude history.</b><br><br>You can create a new profile or one with the same name in the Preferences.</font></html>",
"Profile Not Authorized",
JOptionPane.YES_NO_OPTION,
JOptionPane.ERROR_MESSAGE,
Resources.getCustAttnIcon(), //do not use a custom Icon
options, //the titles of buttons
options[0]); //default button title
if (rc == 0){
new PrefPaneCaller();
}
stopProcess = true;
return;
}
success = true;
locality = new GoogleMaps(latitude.getLongitude() , latitude.getLatitude()).getLocality();
nbPicsProcessed++;
if (pic != null){
imgLabel.setRotation(rot);
imgLabel.setIcon(new ImageIcon(pic));
consoleLabel.setText(file.getName() + ": Updating the location with \"" + locality + "\"");
consoleLabel.setForeground(Color.black);
} else{
imgLabel.setIcon(Resources.getLpNotFoundLogo());
imgLabel.setRotation(0);
consoleLabel.setForeground(Color.DARK_GRAY);
consoleLabel.setText(file.getName() + ": Updating the location with " + locality + " (no thumbnail available)");
ConsoleFile.write("WARNING", file.getPath() + ": No thumbnail found.");
}
// TEST!!!!!!!!!!!!!!!!!!
outputSet.setGPSInDegrees(latitude.getLongitude(), latitude.getLatitude());
nbUpdtPics++;
ConsoleFile.write("NORMAL", file.getPath() + " : GPS info updated to " +
latitude.getLongitude() + " / " +
latitude.getLatitude());
}
// Save last modified date
long lastModified = file.lastModified();
// create stream using temp file for dst
try {
dst = File.createTempFile("temp-" + System.currentTimeMillis(), ".jpeg");
os = new FileOutputStream(dst);
os = new BufferedOutputStream(os);
} catch (IOException e) {
e.printStackTrace();
}
// write/update EXIF metadata to output stream
try {
new ExifRewriter().updateExifMetadataLossless(file,
os, outputSet);
} catch (ImageReadException e) {e.printStackTrace();}
catch (ImageWriteException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
}
}
}
// copy temp file over original file
try {
FileUtils.copyFile(dst, file);
if (!DefaultOptions.doUpdateLastModified()){
file.setLastModified(lastModified);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public int getNbPicsProcessed(){
return nbPicsProcessed;
}
}