Package geodress.model.writer

Source Code of geodress.model.writer.ExifToolWriter

/**
*
*/
package geodress.model.writer;

import geodress.exceptions.FileTypeNotSupportedException;
import geodress.exceptions.MetaDataErrorException;
import geodress.exceptions.OperationNotSupportedException;
import geodress.main.InfoConstants;
import geodress.main.Logging;
import geodress.model.PictureFilter;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* A writer for EXIF data (in JPEG files) using <a
* href="http://www.sno.phy.queensu.ca/~phil/exiftool/">ExifTool</a>.
*
* @author Stefan T.
*/
public class ExifToolWriter implements MetaDataWriter {

  /** Logger object */
  private static Logger logger = null;
  /** verbose level of ExifTool, 0 = just a few / 5 = much information */
  private final int verboseLevel = 1;
  /** TRUE if a backup should be done before writing data */
  private boolean backup = true;
  /**
   * a map with all field values that should be saved, the key contains the
   * name of the field as used by ExifTool
   */
  private Map<String, String> saveMap;
  /**
   * The path to the ExifTool executable (NULL if not available) or simple
   * <tt>exiftool</tt> if set as a system variable.
   */
  private String exifToolPath = null;

  /**
   * Initializes class.
   */
  public ExifToolWriter() {
    /* initializes logger */
    logger = Logging.getLogger(this.getClass().getName());

    saveMap = new HashMap<String, String>();

    /* try to find ExifTool */
    try {
      setExifToolPath("exiftool");
    } catch (IOException ioe) {
      logger.log(Level.FINER,
          "ExifTool is not set as an environment variable", ioe);
    }
  }

  /**
   * @see geodress.model.writer.MetaDataWriter#setData(int, java.lang.String)
   */
  @Override
  public void setData(int field, String value)
      throws OperationNotSupportedException {
    if (field < 0 || 5 < field) {
      throw new OperationNotSupportedException("writing for field "
          + field + " is not supported yet");
    }
    if (!isExifToolAvailable()) {
      logger.log(Level.CONFIG, "ExifTool is not available, "
          + "but setData(int, String) is used.");
    }

    String fieldName = "";
    switch (field) {
    case InfoConstants.GPS_LATITUDE:
      throw new OperationNotSupportedException(
          "writing latitude is not supported yet");
    case InfoConstants.GPS_LONGITUDE:
      throw new OperationNotSupportedException(
          "writing longitude is not supported yet");
    case InfoConstants.DATE_TIME:
      throw new OperationNotSupportedException(
          "writing date/time is not supported yet");
    case InfoConstants.USER_COMMENT:
      logger.log(Level.FINER, "new user comment for writing: " + value);
      fieldName = "EXIF:UserComment";
      break;
    case InfoConstants.IMAGE_DESCRIPTION:
      logger.log(Level.FINER, "new image description for writing: "
          + value);
      fieldName = "EXIF:ImageDescription";
      break;
    default:
      throw new OperationNotSupportedException("writing for field "
          + field + " is not supported yet");
    }
    saveMap.put(fieldName, value);
  }

  /**
   * @see geodress.model.writer.MetaDataWriter#write(java.io.File)
   */
  @Override
  public void write(File file) throws MetaDataErrorException, IOException,
      FileTypeNotSupportedException {
    if (!saveMap.isEmpty()) {
      /* check if file exists */
      if (!file.exists()) {
        throw new IOException("The file " + file + " does not exist.");
      }

      /* reject picture if its type is not JPEG */
      if (!new PictureFilter().accept(file)) {
        throw new FileTypeNotSupportedException("the file type of "
            + file.getAbsolutePath()
            + " is not supported for writing EXIF data");
      }

      /* check if ExifTool is available */
      if (!isExifToolAvailable()) {
        throw new MetaDataErrorException(
            "ExifTool is not available, but needed for EXIF data writing.");
      }

      List<String> command = new LinkedList<String>();
      command.add(exifToolPath);
      command.add("-v" + verboseLevel);

      if (!backup) {
        command.add("-overwrite_original");
      }

      for (String field : saveMap.keySet()) {
        command.add("-" + field + "=" + saveMap.get(field));
      }

      command.add(file.getAbsolutePath());
      logger.log(Level.FINE, "executing" + command);

      /* execute */
      ProcessBuilder pb = new ProcessBuilder(command);
      Process p = pb.start();

      String s, output = "";
      BufferedReader br = new BufferedReader(new InputStreamReader(p
          .getInputStream()));
      while ((s = br.readLine()) != null) {
        output = output + s + "\n";
      }

      /* check output if error occurred */
      try {
        p.waitFor();
      } catch (InterruptedException ie) {
        logger.log(Level.WARNING,
            "exception while waiting for ExifTool terminating", ie);
      }
      if (p.exitValue() != 0) {
        throw new IOException(
            "ExifTool execution returned exit status "
                + p.exitValue()
                + " instead of 0. Other output was: " + output);
      }

    } else {
      logger.log(Level.FINEST,
          "empty saveMap, so no writing operations in " + file);
    }
  }

  /**
   * Returns the current path to ExifTool.
   *
   * @return the exifToolPath
   */
  public String getExifToolPath() {
    return exifToolPath;
  }

  /**
   * Set the path to ExifTool
   *
   * @param exifToolPath
   *            the exifToolPath to set
   * @throws IOException
   *             thrown if ExifTool could not be found
   */
  public void setExifToolPath(String exifToolPath) throws IOException {
    /* check if it is really accessible */
    List<String> command = new LinkedList<String>();
    command.add(exifToolPath);
    new ProcessBuilder(command).start();

    /* no exception -> ExifTool accessible */
    this.exifToolPath = exifToolPath;
    logger.log(Level.FINE, "a new path for ExifTool was set: "
        + exifToolPath);
  }

  /**
   * Checks if the ExifTool is available.
   *
   * @return TRUE if ExifTool is available
   */
  public boolean isExifToolAvailable() {
    return (exifToolPath != null);
  }

  /**
   * @see geodress.model.writer.MetaDataWriter#setBackupMode(boolean)
   */
  @Override
  public void setBackupMode(boolean backup) {
    this.backup = backup;
  }
}
TOP

Related Classes of geodress.model.writer.ExifToolWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.