    001// License: GPL. For details, see LICENSE file.
    002package org.openstreetmap.josm.plugins.streetside;
    003
    004import java.awt.image.BufferedImage;
    005import java.io.File;
    006import java.io.IOException;
    007import java.text.ParseException;
    008import java.util.Calendar;
    009
    010import javax.imageio.ImageIO;
    011
    012import org.openstreetmap.josm.data.coor.CachedLatLon;
    013import org.openstreetmap.josm.data.coor.LatLon;
    014import org.openstreetmap.josm.gui.MapView;
    015import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
    016import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry;
    017import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils;
    018
    019import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
    020
    021/**
    022 * A StreetsideImoprtedImage object represents a picture imported locally.
    023 *
    024 * @author nokutu
    025 *
    026 */
    027public class StreetsideImportedImage extends StreetsideAbstractImage {
    028
    029  /** The picture file. */
    030  protected File file;
    031
    032  /**
    033   * Creates a new StreetsideImportedImage object using as date the current date.
    034   * Using when the EXIF tags doesn't contain that info.
    035   *
    036   * @param id  The Streetside image id
    037   * @param latLon  The latitude and longitude where the picture was taken.
    038   * @param ca  Direction of the picture (0 means north).
    039   * @param file  The file containing the picture.
    040   */
    041  public StreetsideImportedImage(final String id, final LatLon latLon, final double ca, final File file) {
    042    this(id, latLon, ca, file, Calendar.getInstance().getTimeInMillis());
    043  }
    044
    045  /**
    046   * Main constructor of the class.
    047   *
    048   * @param id  The Streetside image id
    049   * @param latLon  Latitude and Longitude where the picture was taken.
    050   * @param ca  Direction of the picture (0 means north),
    051   * @param file  The file containing the picture.
    052   * @param datetimeOriginal  The date the picture was taken.
    053   */
    054  public StreetsideImportedImage(final String id, final LatLon latLon, final double ca, final File file, final String datetimeOriginal) {
    055    this(id, latLon, ca, file, parseTimestampElseCurrentTime(datetimeOriginal));
    056  }
    057
    058  /**
    059   * Constructs a new image from an image entry of a {@link GeoImageLayer}.
    060   * @param geoImage the {@link ImageEntry}, from which the corresponding fields are taken
    061   * @return new image
    062   */
    063  public static StreetsideImportedImage createInstance(final ImageEntry geoImage) {
    064    if (geoImage == null) {
    065      return null;
    066    }
    067    if (geoImage.getFile() == null) {
    068      throw new IllegalArgumentException("Can't create an imported image from an ImageEntry without associated file.");
    069    }
    070    final CachedLatLon cachedCoord = geoImage.getPos();
    071    LatLon coord = cachedCoord == null ? null : cachedCoord.getRoundedToOsmPrecision();
    072    if (coord == null) {
    073      final MapView mv = StreetsidePlugin.getMapView();
    074      coord = mv == null ? new LatLon(0, 0) : mv.getProjection().eastNorth2latlon(mv.getCenter());
    075    }
    076    final double ca = geoImage.getExifImgDir() == null ? 0 : geoImage.getExifImgDir();
    077    final long time = geoImage.hasGpsTime()
    078      ? geoImage.getGpsTime().getTime()
    079      : geoImage.hasExifTime() ? geoImage.getExifTime().getTime() : System.currentTimeMillis();
    080    return new StreetsideImportedImage(CubemapUtils.IMPORTED_ID, coord, ca, geoImage.getFile(), time);
    081  }
    082
    083  private static long parseTimestampElseCurrentTime(final String timestamp) {
    084    try {
    085      return StreetsideUtils.getEpoch(timestamp, "yyyy:MM:dd HH:mm:ss");
    086    } catch (ParseException e) {
    087      try {
    088        return StreetsideUtils.getEpoch(timestamp, "yyyy/MM/dd HH:mm:ss");
    089      } catch (ParseException e1) {
    090        return StreetsideUtils.currentTime();
    091      }
    092    }
    093  }
    094
    095  public StreetsideImportedImage(final String id, final LatLon latLon, final double he, final File file, final long ca) {
    096    super(id, latLon, he);
    097    this.file = file;
    098    this.cd = ca;
    099  }
    100
    101  /**
    102   * Returns the pictures of the file.
    103   *
    104   * @return A {@link BufferedImage} object containing the picture, or null if
    105   *         the {@link File} given in the constructor was null.
    106   * @throws IOException
    107   *           If the file parameter of the object isn't an image.
    108   */
    109  public BufferedImage getImage() throws IOException {
    110    if (file != null)
    111      return ImageIO.read(file);
    112    return null;
    113  }
    114
    115  /**
    116   * Returns the {@link File} object where the picture is located.
    117   *
    118   * @return The {@link File} object where the picture is located.
    119   */
    120  public File getFile() {
    121    return file;
    122  }
    123
    124  @Override
    125  public int compareTo(StreetsideAbstractImage image) {
    126    if (image instanceof StreetsideImportedImage)
    127      return file.compareTo(((StreetsideImportedImage) image).getFile());
    128    return hashCode() - image.hashCode();
    129  }
    130
    131  @Override
    132  public int hashCode() {
    133    final int prime = 31;
    134    int result = 1;
    135    result = prime * result + ((file == null) ? 0 : file.hashCode());
    136    return result;
    137  }
    138
    139  @Override
    140  public boolean equals(Object obj) {
    141    if (this == obj) {
    142      return true;
    143    }
    144    if (obj == null) {
    145      return false;
    146    }
    147    if (!(obj instanceof StreetsideImportedImage)) {
    148      return false;
    149    }
    150    StreetsideImportedImage other = (StreetsideImportedImage) obj;
    151    if (file == null) {
    152      if (other.file != null) {
    153        return false;
    154      }
    155    } else if (!file.equals(other.file)) {
    156      return false;
    157    }
    158    return true;
    159  }
    160}