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