package net.sourceforge.gpstools.exif;
/* gpsdings
* Copyright (C) 2006 Moritz Ringler
* $Id: AbstractExecExifWriter.java 441 2010-12-13 20:04:20Z ringler $
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.io.File;
import java.text.ChoiceFormat;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import net.sourceforge.gpstools.gpx.Wpt;
import de.mospace.lang.ProcessRunnable;
/** Base class for a GpsExifWriter that uses an external executable to write
GPS information to Exif headers of digital photographs. This class also
provides some Exif-related parsing and formatting.
**/
public abstract class AbstractExecExifWriter implements GpsExifWriter{
/** This ExifWriter's external executable. It is initialized from the
constructor argument. **/
protected final String executable;
/** Calculates the correct Exif.AltitudeRef based on the sign of a decimal altitude. **/
private static final NumberFormat FORMAT_ALT_REF
= new ChoiceFormat(new double[]{Double.NEGATIVE_INFINITY, 0}, new String[]{"-1", "0"});
/** Formats the date part of a java.util.Date as an Exif date stamp string. */
private static final DateFormat FORMAT_DATE =
new SimpleDateFormat("yyyy:MM:dd");
/** Formats the time part of a java.util.Date as a second precision Exif Rational Triple. */
private static final DateFormat FORMAT_TIME =
new SimpleDateFormat("HH'/1 'mm'/1 'ss'/1'");
/** Formats the given date as an EXIF date string. **/
public static String formatAsExifDate(Date d){
synchronized(FORMAT_DATE){
return FORMAT_DATE.format(d);
}
}
/** Parses the specified EXIF date string. **/
public static Date parseExifDate(String s) throws java.text.ParseException{
synchronized(FORMAT_DATE){
return FORMAT_DATE.parse(s);
}
}
/** Formats the time part of <code>dateTime</code> as an EXIF
Rational triple string. **/
public static String formatAsExifTime(Date dateTime){
synchronized(FORMAT_TIME){
return FORMAT_TIME.format(dateTime);
}
}
/** Returns a suitable Exif GPS Altitude Reference for the signed
altitude value <code>n</code>.
@return "-1" if <code>n</code> is less than zero and "0" otherwise.
**/
public static String formatAsExifAltRef(Number n){
synchronized(FORMAT_ALT_REF){
return FORMAT_ALT_REF.format(n);
}
}
static final TimeZone UTC = TimeZone.getTimeZone("UTC");
static{
FORMAT_TIME.setTimeZone(UTC);
FORMAT_DATE.setTimeZone(UTC);
FORMAT_DATE.setLenient(false);
}
/** Constructs a new ExifWriter that uses the external executable
<code>executable</code>.
@param executable typically the path of the executable
**/
public AbstractExecExifWriter(String executable){
if(executable == null){
throw new NullPointerException("You must specify an executable for this writer type: " + getClass().getName());
}
this.executable = executable;
}
@Override
public boolean writeExifGpsInfo(File jpeg, Wpt wpt, boolean overwrite){
String[] cmd = buildCommand(jpeg, wpt);
ProcessRunnable ps = new ProcessRunnable(cmd);
ps.redirectErrorsTo(System.err);
ps.redirectOutputTo(System.err);
ps.run();
return true;
}
/** Returns whether this GpsExifWriter writer will or will not
* overwrite existing gps information regardless of the <code>overwrite</code>
* parameter passed to {@link #writeExifGpsInfo writeExifGpsInfo}.
* @return <code>true</code>
*/
@Override
public boolean isAlwaysOverwrite(){
return true;
}
/** Builds the command that writes the GPS information
from <code>wpt</code> to <code>jpeg</code>.
@return the command array
@see de.mospace.lang.ProcessRunnable#ProcessRunnable(String[])
@see java.lang.Runtime#exec(String[])
**/
protected abstract String[] buildCommand(File jpeg, Wpt wpt);
}